From 59f7dedfb4e03690ef9228cce3874e424ef496f0 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 16 Nov 2016 22:31:49 +0100 Subject: [PATCH] Added wall sprite support. Unfortunately it would seem that a bullet hole is not a wall sprite.. --- src/r_poly.cpp | 2 +- src/r_poly_sprite.h | 2 +- src/r_poly_wallsprite.cpp | 96 ++++++++++++++++++++++++++++++++++++++- src/r_poly_wallsprite.h | 2 +- 4 files changed, 98 insertions(+), 4 deletions(-) diff --git a/src/r_poly.cpp b/src/r_poly.cpp index 179df248a..919b2ff78 100644 --- a/src/r_poly.cpp +++ b/src/r_poly.cpp @@ -183,7 +183,7 @@ void RenderPolyScene::RenderTranslucent() else if ((obj.thing->renderflags & RF_SPRITETYPEMASK) == RF_WALLSPRITE) { RenderPolyWallSprite wallspr; - wallspr.Render(obj.thing, obj.sub, obj.subsectorDepth); + wallspr.Render(WorldToClip, obj.thing, obj.sub, obj.subsectorDepth); } else { diff --git a/src/r_poly_sprite.h b/src/r_poly_sprite.h index d60710d04..085d9b570 100644 --- a/src/r_poly_sprite.h +++ b/src/r_poly_sprite.h @@ -30,8 +30,8 @@ public: void Render(const TriMatrix &worldToClip, AActor *thing, subsector_t *sub, uint32_t subsectorDepth); static bool IsThingCulled(AActor *thing); + static FTexture *GetSpriteTexture(AActor *thing, /*out*/ bool &flipX); private: visstyle_t GetSpriteVisStyle(AActor *thing, double z); - FTexture *GetSpriteTexture(AActor *thing, /*out*/ bool &flipX); }; diff --git a/src/r_poly_wallsprite.cpp b/src/r_poly_wallsprite.cpp index 86ddd52a9..63472e297 100644 --- a/src/r_poly_wallsprite.cpp +++ b/src/r_poly_wallsprite.cpp @@ -28,8 +28,102 @@ #include "r_poly_wallsprite.h" #include "r_poly.h" -void RenderPolyWallSprite::Render(AActor *thing, subsector_t *sub, uint32_t subsectorDepth) +void RenderPolyWallSprite::Render(const TriMatrix &worldToClip, AActor *thing, subsector_t *sub, uint32_t subsectorDepth) { if (RenderPolySprite::IsThingCulled(thing)) return; + + DVector3 pos = thing->InterpolatedPosition(r_TicFracF); + pos.Z += thing->GetBobOffset(r_TicFracF); + + bool flipTextureX = false; + FTexture *tex = RenderPolySprite::GetSpriteTexture(thing, flipTextureX); + if (tex == nullptr) + return; + + DVector2 spriteScale = thing->Scale; + double thingxscalemul = spriteScale.X / tex->Scale.X; + double thingyscalemul = spriteScale.Y / tex->Scale.Y; + double spriteHeight = thingyscalemul * tex->GetHeight(); + + DAngle ang = thing->Angles.Yaw + 90; + double angcos = ang.Cos(); + double angsin = ang.Sin(); + + // Determine left and right edges of sprite. The sprite's angle is its normal, + // so the edges are 90 degrees each side of it. + double x2 = tex->GetScaledWidth() * spriteScale.X; + double x1 = tex->GetScaledLeftOffset() * spriteScale.X; + DVector2 left, right; + left.X = pos.X - x1 * angcos; + left.Y = pos.Y - x1 * angsin; + right.X = left.X + x2 * angcos; + right.Y = right.Y + x2 * angsin; + + //int scaled_to = tex->GetScaledTopOffset(); + //int scaled_bo = scaled_to - tex->GetScaledHeight(); + //gzt = pos.Z + scale.Y * scaled_to; + //gzb = pos.Z + scale.Y * scaled_bo; + + DVector2 points[2] = { right, left }; + + TriVertex *vertices = PolyVertexBuffer::GetVertices(4); + if (!vertices) + return; + + bool foggy = false; + int actualextralight = foggy ? 0 : extralight << 4; + + std::pair offsets[4] = + { + { 0.0f, 1.0f }, + { 1.0f, 1.0f }, + { 1.0f, 0.0f }, + { 0.0f, 0.0f }, + }; + + for (int i = 0; i < 4; i++) + { + auto &p = (i == 0 || i == 3) ? points[0] : points[1]; + + vertices[i].x = (float)p.X; + vertices[i].y = (float)p.Y; + vertices[i].z = (float)(pos.Z + spriteHeight * offsets[i].second); + vertices[i].w = 1.0f; + vertices[i].varying[0] = (float)(offsets[i].first * tex->Scale.X); + vertices[i].varying[1] = (float)((1.0f - offsets[i].second) * tex->Scale.Y); + if (flipTextureX) + vertices[i].varying[0] = 1.0f - vertices[i].varying[0]; + } + + bool fullbrightSprite = ((thing->renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT)); + + TriUniforms uniforms; + uniforms.objectToClip = worldToClip; + if (fullbrightSprite || fixedlightlev >= 0 || fixedcolormap) + { + uniforms.light = 256; + uniforms.flags = TriUniforms::fixed_light; + } + else + { + uniforms.light = (uint32_t)((thing->Sector->lightlevel + actualextralight) / 255.0f * 256.0f); + uniforms.flags = 0; + } + uniforms.subsectorDepth = subsectorDepth; + + PolyDrawArgs args; + args.uniforms = uniforms; + args.vinput = vertices; + args.vcount = 4; + args.mode = TriangleDrawMode::Fan; + args.ccw = true; + args.clipleft = 0; + args.cliptop = 0; + args.clipright = viewwidth; + args.clipbottom = viewheight; + args.stenciltestvalue = 0; + args.stencilwritevalue = 1; + args.SetTexture(tex); + PolyTriangleDrawer::draw(args, TriDrawVariant::DrawSubsector); } diff --git a/src/r_poly_wallsprite.h b/src/r_poly_wallsprite.h index ce6917e58..dd4ba28da 100644 --- a/src/r_poly_wallsprite.h +++ b/src/r_poly_wallsprite.h @@ -27,5 +27,5 @@ class RenderPolyWallSprite { public: - void Render(AActor *thing, subsector_t *sub, uint32_t subsectorDepth); + void Render(const TriMatrix &worldToClip, AActor *thing, subsector_t *sub, uint32_t subsectorDepth); };