diff --git a/src/r_compiler/fixedfunction/drawtrianglecodegen.cpp b/src/r_compiler/fixedfunction/drawtrianglecodegen.cpp index 11bdad7e4..7368fa121 100644 --- a/src/r_compiler/fixedfunction/drawtrianglecodegen.cpp +++ b/src/r_compiler/fixedfunction/drawtrianglecodegen.cpp @@ -260,7 +260,7 @@ void DrawTriangleCodegen::LoopBlockX(TriDrawVariant variant, bool truecolor) SetStencilBlock(x / 8 + y / 8 * stencilPitch); SSABool covered = a == SSAInt(0xF) && b == SSAInt(0xF) && c == SSAInt(0xF) && !clipneeded; - if (variant != TriDrawVariant::DrawSubsector) + if (variant != TriDrawVariant::DrawSubsector && variant != TriDrawVariant::FillSubsector) { covered = covered && StencilIsSingleValue(); } @@ -287,7 +287,7 @@ void DrawTriangleCodegen::LoopBlockX(TriDrawVariant variant, bool truecolor) void DrawTriangleCodegen::LoopFullBlock(TriDrawVariant variant, bool truecolor) { SSAIfBlock branch_stenciltest; - if (variant != TriDrawVariant::DrawSubsector) + if (variant != TriDrawVariant::DrawSubsector && variant != TriDrawVariant::FillSubsector) { branch_stenciltest.if_block(StencilGetSingle() == stencilTestValue); } @@ -325,7 +325,7 @@ void DrawTriangleCodegen::LoopFullBlock(TriDrawVariant variant, bool truecolor) varying[i] = stack_varying[i].load(); loopx.loop_block(ix < SSAInt(q), q); { - if (variant == TriDrawVariant::DrawSubsector) + if (variant == TriDrawVariant::DrawSubsector || variant == TriDrawVariant::FillSubsector) { SSAIfBlock branch; branch.if_block(subsectorbuffer[ix].load(true) >= subsectorDepth); @@ -353,7 +353,7 @@ void DrawTriangleCodegen::LoopFullBlock(TriDrawVariant variant, bool truecolor) loopy.end_block(); } - if (variant != TriDrawVariant::DrawSubsector) + if (variant != TriDrawVariant::DrawSubsector && variant != TriDrawVariant::FillSubsector) { branch_stenciltest.end_block(); } @@ -404,7 +404,7 @@ void DrawTriangleCodegen::LoopPartialBlock(TriDrawVariant variant, bool truecolo SSABool visible = (ix + x >= clipleft) && (ix + x < clipright) && (cliptop <= y + iy) && (clipbottom > y + iy); SSABool covered = CX1 > SSAInt(0) && CX2 > SSAInt(0) && CX3 > SSAInt(0) && visible; - if (variant == TriDrawVariant::DrawSubsector) + if (variant == TriDrawVariant::DrawSubsector || variant == TriDrawVariant::FillSubsector) { covered = covered && subsectorbuffer[ix].load(true) >= subsectorDepth; } @@ -449,7 +449,7 @@ void DrawTriangleCodegen::LoopPartialBlock(TriDrawVariant variant, bool truecolo void DrawTriangleCodegen::ProcessPixel(SSAUBytePtr buffer, SSAIntPtr subsectorbuffer, SSAInt *varying, TriDrawVariant variant, bool truecolor) { - if (variant == TriDrawVariant::Fill) + if (variant == TriDrawVariant::Fill || variant == TriDrawVariant::FillSubsector) { if (truecolor) { @@ -459,7 +459,9 @@ void DrawTriangleCodegen::ProcessPixel(SSAUBytePtr buffer, SSAIntPtr subsectorbu { //buffer.store(solidcolor); } - subsectorbuffer.store(subsectorDepth); + + if (variant != TriDrawVariant::FillSubsector) + subsectorbuffer.store(subsectorDepth); } else { diff --git a/src/r_compiler/llvmdrawers.cpp b/src/r_compiler/llvmdrawers.cpp index b3d893153..e7b9f6e5c 100644 --- a/src/r_compiler/llvmdrawers.cpp +++ b/src/r_compiler/llvmdrawers.cpp @@ -190,6 +190,8 @@ LLVMDrawersImpl::LLVMDrawersImpl() CodegenDrawTriangle("TriDraw32", TriDrawVariant::Draw, true); CodegenDrawTriangle("TriDrawSubsector8", TriDrawVariant::DrawSubsector, false); CodegenDrawTriangle("TriDrawSubsector32", TriDrawVariant::DrawSubsector, true); + CodegenDrawTriangle("TriFillSubsector8", TriDrawVariant::FillSubsector, false); + CodegenDrawTriangle("TriFillSubsector32", TriDrawVariant::FillSubsector, true); CodegenDrawTriangle("TriFill8", TriDrawVariant::Fill, false); CodegenDrawTriangle("TriFill32", TriDrawVariant::Fill, true); CodegenDrawTriangle("TriStencil", TriDrawVariant::Stencil, false); @@ -262,6 +264,8 @@ LLVMDrawersImpl::LLVMDrawersImpl() TriDraw32 = mProgram.GetProcAddress("TriDraw32"); TriDrawSubsector8 = mProgram.GetProcAddress("TriDrawSubsector8"); TriDrawSubsector32 = mProgram.GetProcAddress("TriDrawSubsector32"); + TriFillSubsector8 = mProgram.GetProcAddress("TriFillSubsector8"); + TriFillSubsector32 = mProgram.GetProcAddress("TriFillSubsector32"); TriFill8 = mProgram.GetProcAddress("TriFill8"); TriFill32 = mProgram.GetProcAddress("TriFill32"); TriStencil = mProgram.GetProcAddress("TriStencil"); diff --git a/src/r_compiler/llvmdrawers.h b/src/r_compiler/llvmdrawers.h index 38f0f82d1..e7a34b962 100644 --- a/src/r_compiler/llvmdrawers.h +++ b/src/r_compiler/llvmdrawers.h @@ -266,6 +266,7 @@ enum class TriDrawVariant DrawMasked, Fill, DrawSubsector, + FillSubsector, Stencil, }; @@ -348,6 +349,8 @@ public: void(*TriDraw32)(const TriDrawTriangleArgs *, WorkerThreadData *) = nullptr; void(*TriDrawSubsector8)(const TriDrawTriangleArgs *, WorkerThreadData *) = nullptr; void(*TriDrawSubsector32)(const TriDrawTriangleArgs *, WorkerThreadData *) = nullptr; + void(*TriFillSubsector8)(const TriDrawTriangleArgs *, WorkerThreadData *) = nullptr; + void(*TriFillSubsector32)(const TriDrawTriangleArgs *, WorkerThreadData *) = nullptr; void(*TriFill8)(const TriDrawTriangleArgs *, WorkerThreadData *) = nullptr; void(*TriFill32)(const TriDrawTriangleArgs *, WorkerThreadData *) = nullptr; void(*TriStencil)(const TriDrawTriangleArgs *, WorkerThreadData *) = nullptr; diff --git a/src/r_poly.cpp b/src/r_poly.cpp index 919b2ff78..d4f24be59 100644 --- a/src/r_poly.cpp +++ b/src/r_poly.cpp @@ -111,6 +111,17 @@ void RenderPolyScene::RenderSubsector(subsector_t *sub) RenderLine(sub, line, frontsector, subsectorDepth); } + bool mainBSP = ((unsigned int)(sub - subsectors) < (unsigned int)numsubsectors); + if (mainBSP) + { + int subsectorIndex = (int)(sub - subsectors); + for (int i = ParticlesInSubsec[subsectorIndex]; i != NO_PARTICLE; i = Particles[i].snext) + { + particle_t *particle = Particles + i; + TranslucentObjects.push_back({ particle, sub, subsectorDepth }); + } + } + SpriteRange sprites = GetSpritesForSector(sub->sector); for (int i = 0; i < sprites.Count; i++) { @@ -176,7 +187,12 @@ void RenderPolyScene::RenderTranslucent() for (auto it = TranslucentObjects.rbegin(); it != TranslucentObjects.rend(); ++it) { auto &obj = *it; - if (!obj.thing) + if (obj.particle) + { + RenderPolyParticle spr; + spr.Render(WorldToClip, obj.particle, obj.sub, obj.subsectorDepth); + } + else if (!obj.thing) { obj.wall.Render(WorldToClip); } diff --git a/src/r_poly.h b/src/r_poly.h index 4f7eca61d..f18f8a3cd 100644 --- a/src/r_poly.h +++ b/src/r_poly.h @@ -35,6 +35,7 @@ #include "r_poly_sprite.h" #include "r_poly_wallsprite.h" #include "r_poly_playersprite.h" +#include "r_poly_particle.h" #include "r_poly_plane.h" #include "r_poly_sky.h" #include "r_poly_cull.h" @@ -53,9 +54,11 @@ public: class PolyTranslucentObject { public: + PolyTranslucentObject(particle_t *particle, subsector_t *sub, uint32_t subsectorDepth) : particle(particle), sub(sub), subsectorDepth(subsectorDepth) { } PolyTranslucentObject(AActor *thing, subsector_t *sub, uint32_t subsectorDepth) : thing(thing), sub(sub), subsectorDepth(subsectorDepth) { } PolyTranslucentObject(RenderPolyWall wall) : wall(wall) { } + particle_t *particle = nullptr; AActor *thing = nullptr; subsector_t *sub = nullptr; uint32_t subsectorDepth = 0; diff --git a/src/r_poly_particle.cpp b/src/r_poly_particle.cpp index 06b963e4f..f0b221988 100644 --- a/src/r_poly_particle.cpp +++ b/src/r_poly_particle.cpp @@ -28,6 +28,76 @@ #include "r_poly_particle.h" #include "r_poly.h" -void RenderPolyParticle::Render() +void RenderPolyParticle::Render(const TriMatrix &worldToClip, particle_t *particle, subsector_t *sub, uint32_t subsectorDepth) { + DVector3 pos = particle->Pos; + double psize = particle->size / 8.0; + double zpos = pos.Z; + + DVector2 points[2] = + { + { pos.X - ViewSin * psize, pos.Y + ViewCos * psize }, + { pos.X + ViewSin * psize, pos.Y - ViewCos * psize } + }; + + 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)(zpos + psize * (2.0 * offsets[i].second - 1.0)); + vertices[i].w = 1.0f; + vertices[i].varying[0] = (float)(offsets[i].first); + vertices[i].varying[1] = (float)(1.0f - offsets[i].second); + } + + // int color = (particle->color >> 24) & 0xff; // pal index, I think + bool fullbrightSprite = particle->bright != 0; + + TriUniforms uniforms; + uniforms.objectToClip = worldToClip; + if (fullbrightSprite || fixedlightlev >= 0 || fixedcolormap) + { + uniforms.light = 256; + uniforms.flags = TriUniforms::fixed_light; + } + else + { + uniforms.light = (uint32_t)((sub->sector->lightlevel + actualextralight) / 255.0f * 256.0f); + uniforms.flags = 0; + } + uniforms.subsectorDepth = subsectorDepth; + + uint32_t alpha = particle->trans; + + 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.solidcolor = (alpha << 24) | (particle->color & 0xffffff); + PolyTriangleDrawer::draw(args, TriDrawVariant::FillSubsector); } diff --git a/src/r_poly_particle.h b/src/r_poly_particle.h index 5573a7e48..f4218a310 100644 --- a/src/r_poly_particle.h +++ b/src/r_poly_particle.h @@ -22,8 +22,11 @@ #pragma once +#include "r_poly_triangle.h" +#include "p_effect.h" + class RenderPolyParticle { public: - void Render(); + void Render(const TriMatrix &worldToClip, particle_t *particle, subsector_t *sub, uint32_t subsectorDepth); }; diff --git a/src/r_poly_triangle.cpp b/src/r_poly_triangle.cpp index 3d444d2ad..6426bae4e 100644 --- a/src/r_poly_triangle.cpp +++ b/src/r_poly_triangle.cpp @@ -62,6 +62,7 @@ void PolyTriangleDrawer::draw_arrays(const PolyDrawArgs &drawargs, TriDrawVarian case TriDrawVariant::Draw: drawfunc = r_swtruecolor ? llvm->TriDraw32: llvm->TriDraw8; break; case TriDrawVariant::Fill: drawfunc = r_swtruecolor ? llvm->TriFill32 : llvm->TriFill8; break; case TriDrawVariant::DrawSubsector: drawfunc = r_swtruecolor ? llvm->TriDrawSubsector32 : llvm->TriDrawSubsector8; break; + case TriDrawVariant::FillSubsector: drawfunc = r_swtruecolor ? llvm->TriFillSubsector32 : llvm->TriFillSubsector8; break; case TriDrawVariant::Stencil: drawfunc = llvm->TriStencil; break; } #else @@ -69,6 +70,7 @@ void PolyTriangleDrawer::draw_arrays(const PolyDrawArgs &drawargs, TriDrawVarian { default: case TriDrawVariant::Draw: drawfunc = r_swtruecolor ? ScreenPolyTriangleDrawer::draw32 : ScreenPolyTriangleDrawer::draw; break; + case TriDrawVariant::FillSubsector: case TriDrawVariant::Fill: drawfunc = r_swtruecolor ? ScreenPolyTriangleDrawer::fill32 : ScreenPolyTriangleDrawer::fill; break; case TriDrawVariant::DrawSubsector: drawfunc = r_swtruecolor ? ScreenPolyTriangleDrawer::drawsubsector32 : llvm->TriDrawSubsector8; break; case TriDrawVariant::Stencil: drawfunc = ScreenPolyTriangleDrawer::stencil; break;