diff --git a/src/r_draw_rgba.h b/src/r_draw_rgba.h index 6d16558c0..d5b269106 100644 --- a/src/r_draw_rgba.h +++ b/src/r_draw_rgba.h @@ -445,7 +445,7 @@ namespace swrenderer class DrawParticleColumnRGBACommand : public DrawerCommand { public: - DrawParticleColumnRGBACommand(uint32_t *dest, int dest_y, int pitch, int count, uint32_t fg, uint32_t alpha); + DrawParticleColumnRGBACommand(uint32_t *dest, int dest_y, int pitch, int count, uint32_t fg, uint32_t alpha, uint32_t fracposx); void Execute(DrawerThread *thread) override; FString DebugInfo() override; @@ -455,6 +455,7 @@ namespace swrenderer int _count; uint32_t _fg; uint32_t _alpha; + uint32_t _fracposx; }; ///////////////////////////////////////////////////////////////////////////// diff --git a/src/r_drawt_rgba.cpp b/src/r_drawt_rgba.cpp index 3609956fe..b5be7a9c3 100644 --- a/src/r_drawt_rgba.cpp +++ b/src/r_drawt_rgba.cpp @@ -234,13 +234,37 @@ namespace swrenderer ///////////////////////////////////////////////////////////////////////////// - DrawParticleColumnRGBACommand::DrawParticleColumnRGBACommand(uint32_t *dest, int dest_y, int pitch, int count, uint32_t fg, uint32_t alpha) + namespace + { + static uint32_t particle_texture[16 * 16] = + { + 1*1, 2*1, 3*1, 4*1, 5*1, 6*1, 7*1, 8*1, 8*1, 7*1, 6*1, 5*1, 4*1, 3*1, 2*1, 1*1, + 1*2, 2*2, 3*2, 4*2, 5*2, 6*2, 7*2, 8*2, 8*2, 7*2, 6*2, 5*2, 4*2, 3*2, 2*2, 1*2, + 1*3, 2*3, 3*3, 4*3, 5*3, 6*3, 7*3, 8*3, 8*3, 7*3, 6*3, 5*3, 4*3, 3*3, 2*3, 1*3, + 1*4, 2*4, 3*4, 4*4, 5*4, 6*4, 7*4, 8*4, 8*4, 7*4, 6*4, 5*4, 4*4, 3*4, 2*4, 1*4, + 1*5, 2*5, 3*5, 4*5, 5*5, 6*5, 7*5, 8*5, 8*5, 7*5, 6*5, 5*5, 4*5, 3*5, 2*5, 1*5, + 1*6, 2*6, 3*6, 4*6, 5*6, 6*6, 7*6, 8*6, 8*6, 7*6, 6*6, 5*6, 4*6, 3*6, 2*6, 1*6, + 1*7, 2*7, 3*7, 4*7, 5*7, 6*7, 7*7, 8*7, 8*7, 7*7, 6*7, 5*7, 4*7, 3*7, 2*7, 1*7, + 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 8*8, 7*8, 6*8, 5*8, 4*8, 3*8, 2*8, 1*8, + 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 8*8, 7*8, 6*8, 5*8, 4*8, 3*8, 2*8, 1*8, + 1*7, 2*7, 3*7, 4*7, 5*7, 6*7, 7*7, 8*7, 8*7, 7*7, 6*7, 5*7, 4*7, 3*7, 2*7, 1*7, + 1*6, 2*6, 3*6, 4*6, 5*6, 6*6, 7*6, 8*6, 8*6, 7*6, 6*6, 5*6, 4*6, 3*6, 2*6, 1*6, + 1*5, 2*5, 3*5, 4*5, 5*5, 6*5, 7*5, 8*5, 8*5, 7*5, 6*5, 5*5, 4*5, 3*5, 2*5, 1*5, + 1*4, 2*4, 3*4, 4*4, 5*4, 6*4, 7*4, 8*4, 8*4, 7*4, 6*4, 5*4, 4*4, 3*4, 2*4, 1*4, + 1*3, 2*3, 3*3, 4*3, 5*3, 6*3, 7*3, 8*3, 8*3, 7*3, 6*3, 5*3, 4*3, 3*3, 2*3, 1*3, + 1*2, 2*2, 3*2, 4*2, 5*2, 6*2, 7*2, 8*2, 8*2, 7*2, 6*2, 5*2, 4*2, 3*2, 2*2, 1*2, + 1*1, 2*1, 3*1, 4*1, 5*1, 6*1, 7*1, 8*1, 8*1, 7*1, 6*1, 5*1, 4*1, 3*1, 2*1, 1*1 + }; + } + + DrawParticleColumnRGBACommand::DrawParticleColumnRGBACommand(uint32_t *dest, int dest_y, int pitch, int count, uint32_t fg, uint32_t alpha, uint32_t fracposx) { _dest = dest; _pitch = pitch; _count = count; _fg = fg; _alpha = alpha; + _fracposx = fracposx; _dest_y = dest_y; } @@ -253,29 +277,33 @@ namespace swrenderer uint32_t *dest = thread->dest_for_thread(_dest_y, _pitch, _dest); int pitch = _pitch * thread->num_cores; - uint32_t alpha = _alpha; - uint32_t inv_alpha = 256 - alpha; + const uint32_t *source = &particle_texture[(_fracposx >> FRACBITS) * 16]; + uint32_t particle_alpha = _alpha; + + uint32_t fracstep = 16 * FRACUNIT / _count; + uint32_t fracpos = fracstep * thread->skipped_by_thread(_dest_y) + fracstep / 2; + fracstep *= thread->num_cores; uint32_t fg_red = (_fg >> 16) & 0xff; uint32_t fg_green = (_fg >> 8) & 0xff; uint32_t fg_blue = _fg & 0xff; - fg_red *= alpha; - fg_green *= alpha; - fg_blue *= alpha; - for (int y = 0; y < count; y++) { + uint32_t alpha = (source[fracpos >> FRACBITS] * particle_alpha) >> 6; + uint32_t inv_alpha = 256 - alpha; + uint32_t bg_red = (*dest >> 16) & 0xff; uint32_t bg_green = (*dest >> 8) & 0xff; uint32_t bg_blue = (*dest) & 0xff; - uint32_t red = (fg_red + bg_red * inv_alpha) / 256; - uint32_t green = (fg_green + bg_green * inv_alpha) / 256; - uint32_t blue = (fg_blue + bg_blue * inv_alpha) / 256; + uint32_t red = (fg_red * alpha + bg_red * inv_alpha) / 256; + uint32_t green = (fg_green * alpha + bg_green * inv_alpha) / 256; + uint32_t blue = (fg_blue * alpha + bg_blue * inv_alpha) / 256; *dest = 0xff000000 | (red << 16) | (green << 8) | blue; dest += pitch; + fracpos += fracstep; } } diff --git a/src/r_things.cpp b/src/r_things.cpp index bbd9eb9cf..6e6b95402 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -2863,6 +2863,9 @@ void R_DrawParticle_rgba(vissprite_t *vis) int x1 = vis->x1; int countbase = vis->x2 - x1; + if (ycount <= 0 || countbase <= 0) + return; + R_DrawMaskedSegsBehindParticle(vis); uint32_t fg = LightBgra::shade_pal_index_simple(color, LightBgra::calc_light_multiplier(LIGHTSCALE(0, vis->Style.ColormapNum << FRACBITS))); @@ -2873,13 +2876,16 @@ void R_DrawParticle_rgba(vissprite_t *vis) spacing = RenderTarget->GetPitch(); - for (int x = x1; x < (x1 + countbase); x++) + uint32_t fracstepx = 16 * FRACUNIT / countbase; + uint32_t fracposx = fracstepx / 2; + + for (int x = x1; x < (x1 + countbase); x++, fracposx += fracstepx) { dc_x = x; if (R_ClipSpriteColumnWithPortals(vis)) continue; dest = ylookup[yl] + x + (uint32_t*)dc_destorg; - DrawerCommandQueue::QueueCommand(dest, yl, spacing, ycount, fg, alpha); + DrawerCommandQueue::QueueCommand(dest, yl, spacing, ycount, fg, alpha, fracposx); } }