From eac98ac2263b2625f43614c3f3454b24907d3748 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 14 Feb 2017 06:37:06 +0100 Subject: [PATCH] Calculate sprite dynamic light contribution and pass it along to the sprite drawer --- src/swrenderer/things/r_sprite.cpp | 50 ++++++++++++++++++++++++ src/swrenderer/things/r_sprite.h | 2 + src/swrenderer/viewport/r_spritedrawer.h | 5 +++ 3 files changed, 57 insertions(+) diff --git a/src/swrenderer/things/r_sprite.cpp b/src/swrenderer/things/r_sprite.cpp index 1da377c7df..652bfcef27 100644 --- a/src/swrenderer/things/r_sprite.cpp +++ b/src/swrenderer/things/r_sprite.cpp @@ -56,6 +56,7 @@ #include "swrenderer/viewport/r_viewport.h" #include "swrenderer/r_memory.h" #include "swrenderer/r_renderthread.h" +#include "gl/dynlights/gl_dynlight.h" EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor) @@ -225,6 +226,54 @@ namespace swrenderer bool fullbright = !vis->foggy && ((renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT)); bool fadeToBlack = (vis->RenderStyle.Flags & STYLEF_FadeToBlack) != 0; + + if (r_dynlights) + { + float lit_red = 0; + float lit_green = 0; + float lit_blue = 0; + auto node = vis->sector->lighthead; + while (node != nullptr) + { + ADynamicLight *light = node->lightsource; + if (light->visibletoplayer && !(light->flags2&MF2_DORMANT) && (!(light->flags4&MF4_DONTLIGHTSELF) || light->target != thing)) + { + double lightX = light->X() - ViewPos.X; + double lightY = light->Y() - ViewPos.Y; + double lightZ = light->Z() - ViewPos.Z; + + float lx = (float)(lightX * ViewSin - lightY * ViewCos) - pos.X; + float ly = (float)(lightX * ViewTanCos + lightY * ViewTanSin) - pos.Y; + float lz = (float)lightZ - pos.Z; + + bool is_point_light = (node->lightsource->flags4 & MF4_ATTENUATE) != 0; + float LdotL = lx * lx + ly * ly + lz * lz; + float NdotL = is_point_light ? -ly : 0.0f; + + float radius = node->lightsource->GetRadius(); + if (radius * radius >= LdotL && NdotL > 0.0f) + { + uint32_t red = light->GetRed(); + uint32_t green = light->GetGreen(); + uint32_t blue = light->GetBlue(); + float distance = sqrt(LdotL); + float attenuation = distance / radius * NdotL; + lit_red += red * attenuation; + lit_red += green * attenuation; + lit_red += blue * attenuation; + } + } + node = node->nextLight; + } + lit_red = MIN(lit_red, 255.0f); + lit_green = MIN(lit_green, 255.0f); + lit_blue = MIN(lit_blue, 255.0f); + vis->dynlightcolor = (((uint32_t)lit_red) << 16) | (((uint32_t)lit_green) << 8) | ((uint32_t)lit_blue); + } + else + { + vis->dynlightcolor = 0; + } vis->Light.SetColormap(LightVisibility::Instance()->SpriteGlobVis() / MAX(tz, MINZ), spriteshade, basecolormap, fullbright, invertcolormap, fadeToBlack); @@ -250,6 +299,7 @@ namespace swrenderer SpriteDrawerArgs drawerargs; drawerargs.SetLight(vis->Light.BaseColormap, 0, vis->Light.ColormapNum << FRACBITS); + drawerargs.SetDynamicLight(dynlightcolor); FDynamicColormap *basecolormap = static_cast(vis->Light.BaseColormap); diff --git a/src/swrenderer/things/r_sprite.h b/src/swrenderer/things/r_sprite.h index 776af54fa8..678c909090 100644 --- a/src/swrenderer/things/r_sprite.h +++ b/src/swrenderer/things/r_sprite.h @@ -32,5 +32,7 @@ namespace swrenderer uint32_t Translation = 0; uint32_t FillColor = 0; + + uint32_t dynlightcolor = 0; }; } diff --git a/src/swrenderer/viewport/r_spritedrawer.h b/src/swrenderer/viewport/r_spritedrawer.h index fc5053e6e0..bca4664aa1 100644 --- a/src/swrenderer/viewport/r_spritedrawer.h +++ b/src/swrenderer/viewport/r_spritedrawer.h @@ -21,6 +21,7 @@ namespace swrenderer void SetDest(int x, int y); void SetCount(int count) { dc_count = count; } void SetSolidColor(int color) { dc_color = color; } + void SetDynamicLight(uint32_t color) { dynlightcolor = color; } void DrawMaskedColumn(RenderThread *thread, int x, fixed_t iscale, FTexture *texture, fixed_t column, double spryscale, double sprtopscreen, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, bool unmasked = false); void FillColumn(RenderThread *thread); @@ -50,6 +51,8 @@ namespace swrenderer uint32_t *DestBlend() const { return dc_destblend; } fixed_t SrcAlpha() const { return dc_srcalpha; } fixed_t DestAlpha() const { return dc_destalpha; } + + uint32_t DynamicLight() const { return dynlightcolor; } private: bool SetBlendFunc(int op, fixed_t fglevel, fixed_t bglevel, int flags); @@ -81,6 +84,8 @@ namespace swrenderer int dc_color = 0; uint32_t dc_srccolor = 0; uint32_t dc_srccolor_bgra = 0; + + uint32_t dynlightcolor = 0; typedef void(SWPixelFormatDrawers::*SpriteDrawerFunc)(const SpriteDrawerArgs &args); SpriteDrawerFunc colfunc;