mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-10 23:01:50 +00:00
- Add dynamic light to sprites
This commit is contained in:
parent
abc8e4deac
commit
f3ba92f03c
4 changed files with 63 additions and 8 deletions
|
@ -81,6 +81,7 @@ public:
|
|||
void SetTransform(const TriMatrix *objectToClip) { mObjectToClip = objectToClip; }
|
||||
void SetColor(uint32_t bgra, uint8_t palindex);
|
||||
void SetLights(PolyLight *lights, int numLights) { mLights = lights; mNumLights = numLights; }
|
||||
void SetDynLightColor(uint32_t color) { mDynLightColor = color; }
|
||||
void DrawArray(PolyRenderThread *thread, const TriVertex *vertices, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles);
|
||||
|
||||
const TriMatrix *ObjectToClip() const { return mObjectToClip; }
|
||||
|
@ -129,6 +130,7 @@ public:
|
|||
|
||||
PolyLight *Lights() const { return mLights; }
|
||||
int NumLights() const { return mNumLights; }
|
||||
uint32_t DynLightColor() const { return mDynLightColor; }
|
||||
|
||||
const FVector3 &Normal() const { return mNormal; }
|
||||
void SetNormal(const FVector3 &normal) { mNormal = normal; }
|
||||
|
@ -172,6 +174,7 @@ private:
|
|||
PolyLight *mLights = nullptr;
|
||||
int mNumLights = 0;
|
||||
FVector3 mNormal;
|
||||
uint32_t mDynLightColor = 0;
|
||||
};
|
||||
|
||||
class RectDrawArgs
|
||||
|
|
|
@ -149,9 +149,10 @@ namespace TriScreenDrawerModes
|
|||
return fgcolor;
|
||||
}
|
||||
|
||||
FORCEINLINE __m128i VECTORCALL CalcDynamicLight(const PolyLight *lights, int num_lights, __m128 worldpos, __m128 worldnormal)
|
||||
FORCEINLINE __m128i VECTORCALL CalcDynamicLight(const PolyLight *lights, int num_lights, __m128 worldpos, __m128 worldnormal, uint32_t dynlightcolor)
|
||||
{
|
||||
__m128i lit = _mm_setzero_si128();
|
||||
__m128i lit = _mm_unpacklo_epi8(_mm_cvtsi32_si128(dynlightcolor), _mm_setzero_si128());
|
||||
lit = _mm_shuffle_epi32(lit, _MM_SHUFFLE(1, 0, 1, 0));
|
||||
|
||||
for (int i = 0; i != num_lights; i++)
|
||||
{
|
||||
|
@ -396,6 +397,7 @@ private:
|
|||
auto lights = args->uniforms->Lights();
|
||||
auto num_lights = args->uniforms->NumLights();
|
||||
__m128 worldnormal = _mm_setr_ps(args->uniforms->Normal().X, args->uniforms->Normal().Y, args->uniforms->Normal().Z, 0.0f);
|
||||
uint32_t dynlightcolor = args->uniforms->DynLightColor();
|
||||
|
||||
// Calculate gradients
|
||||
const ShadedTriVertex &v1 = *args->v1;
|
||||
|
@ -476,7 +478,7 @@ private:
|
|||
|
||||
__m128 mrcpW = _mm_set1_ps(1.0f / blockPosY.W);
|
||||
__m128 worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosY.WorldX), mrcpW);
|
||||
__m128i dynlight = CalcDynamicLight(lights, num_lights, worldpos, worldnormal);
|
||||
__m128i dynlight = CalcDynamicLight(lights, num_lights, worldpos, worldnormal, dynlightcolor);
|
||||
|
||||
ScreenTriangleStepVariables blockPosX = blockPosY;
|
||||
blockPosX.W += gradientX.W;
|
||||
|
@ -498,7 +500,7 @@ private:
|
|||
|
||||
mrcpW = _mm_set1_ps(1.0f / blockPosX.W);
|
||||
worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosX.WorldX), mrcpW);
|
||||
__m128i dynlightnext = CalcDynamicLight(lights, num_lights, worldpos, worldnormal);
|
||||
__m128i dynlightnext = CalcDynamicLight(lights, num_lights, worldpos, worldnormal, dynlightcolor);
|
||||
__m128i dynlightstep = _mm_srai_epi16(_mm_sub_epi16(dynlightnext, dynlight), 3);
|
||||
dynlight = _mm_max_epi16(_mm_min_epi16(_mm_add_epi16(dynlight, _mm_and_si128(dynlightstep, _mm_set_epi32(0xffff,0xffff,0,0))), _mm_set1_epi16(256)), _mm_setzero_si128());
|
||||
dynlightstep = _mm_slli_epi16(dynlightstep, 1);
|
||||
|
@ -579,7 +581,7 @@ private:
|
|||
|
||||
__m128 mrcpW = _mm_set1_ps(1.0f / blockPosY.W);
|
||||
__m128 worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosY.WorldX), mrcpW);
|
||||
__m128i dynlight = CalcDynamicLight(lights, num_lights, worldpos, worldnormal);
|
||||
__m128i dynlight = CalcDynamicLight(lights, num_lights, worldpos, worldnormal, dynlightcolor);
|
||||
|
||||
ScreenTriangleStepVariables blockPosX = blockPosY;
|
||||
blockPosX.W += gradientX.W;
|
||||
|
@ -601,7 +603,7 @@ private:
|
|||
|
||||
mrcpW = _mm_set1_ps(1.0f / blockPosX.W);
|
||||
worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosX.WorldX), mrcpW);
|
||||
__m128i dynlightnext = CalcDynamicLight(lights, num_lights, worldpos, worldnormal);
|
||||
__m128i dynlightnext = CalcDynamicLight(lights, num_lights, worldpos, worldnormal, dynlightcolor);
|
||||
__m128i dynlightstep = _mm_srai_epi16(_mm_sub_epi16(dynlightnext, dynlight), 3);
|
||||
dynlight = _mm_max_epi16(_mm_min_epi16(_mm_add_epi16(dynlight, _mm_and_si128(dynlightstep, _mm_set_epi32(0xffff, 0xffff, 0, 0))), _mm_set1_epi16(256)), _mm_setzero_si128());
|
||||
dynlightstep = _mm_slli_epi16(dynlightstep, 1);
|
||||
|
@ -689,7 +691,7 @@ private:
|
|||
|
||||
__m128 mrcpW = _mm_set1_ps(1.0f / blockPosY.W);
|
||||
__m128 worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosY.WorldX), mrcpW);
|
||||
__m128i dynlight = CalcDynamicLight(lights, num_lights, worldpos, worldnormal);
|
||||
__m128i dynlight = CalcDynamicLight(lights, num_lights, worldpos, worldnormal, dynlightcolor);
|
||||
|
||||
ScreenTriangleStepVariables blockPosX = blockPosY;
|
||||
blockPosX.W += gradientX.W;
|
||||
|
@ -711,7 +713,7 @@ private:
|
|||
|
||||
mrcpW = _mm_set1_ps(1.0f / blockPosX.W);
|
||||
worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosX.WorldX), mrcpW);
|
||||
__m128i dynlightnext = CalcDynamicLight(lights, num_lights, worldpos, worldnormal);
|
||||
__m128i dynlightnext = CalcDynamicLight(lights, num_lights, worldpos, worldnormal, dynlightcolor);
|
||||
__m128i dynlightstep = _mm_srai_epi16(_mm_sub_epi16(dynlightnext, dynlight), 3);
|
||||
dynlight = _mm_max_epi16(_mm_min_epi16(_mm_add_epi16(dynlight, _mm_and_si128(dynlightstep, _mm_set_epi32(0xffff, 0xffff, 0, 0))), _mm_set1_epi16(256)), _mm_setzero_si128());
|
||||
dynlightstep = _mm_slli_epi16(dynlightstep, 1);
|
||||
|
|
|
@ -154,6 +154,7 @@ void RenderPolySprite::Render(PolyRenderThread *thread, const TriMatrix &worldTo
|
|||
int lightlevel = fullbrightSprite ? 255 : thing->Sector->lightlevel + actualextralight;
|
||||
|
||||
PolyDrawArgs args;
|
||||
SetDynlight(thing, args);
|
||||
args.SetLight(GetColorTable(sub->sector->Colormap, sub->sector->SpecialColors[sector_t::sprites], true), lightlevel, PolyRenderer::Instance()->Light.SpriteGlobVis(foggy), fullbrightSprite);
|
||||
args.SetTransform(&worldToClip);
|
||||
args.SetFaceCullCCW(true);
|
||||
|
@ -368,3 +369,51 @@ FTexture *RenderPolySprite::GetSpriteTexture(AActor *thing, /*out*/ bool &flipX)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderPolySprite::SetDynlight(AActor *thing, PolyDrawArgs &args)
|
||||
{
|
||||
float lit_red = 0;
|
||||
float lit_green = 0;
|
||||
float lit_blue = 0;
|
||||
auto node = thing->Sector->lighthead;
|
||||
while (node != nullptr)
|
||||
{
|
||||
ADynamicLight *light = node->lightsource;
|
||||
if (light->visibletoplayer && !(light->flags2&MF2_DORMANT) && (!(light->lightflags&LF_DONTLIGHTSELF) || light->target != thing) && !(light->lightflags&LF_DONTLIGHTACTORS))
|
||||
{
|
||||
float lx = (float)(light->X() - thing->X());
|
||||
float ly = (float)(light->Y() - thing->Y());
|
||||
float lz = (float)(light->Z() - thing->Center());
|
||||
float LdotL = lx * lx + ly * ly + lz * lz;
|
||||
float radius = node->lightsource->GetRadius();
|
||||
if (radius * radius >= LdotL)
|
||||
{
|
||||
float distance = sqrt(LdotL);
|
||||
float attenuation = 1.0f - distance / radius;
|
||||
if (attenuation > 0.0f)
|
||||
{
|
||||
float red = light->GetRed() * (1.0f / 255.0f);
|
||||
float green = light->GetGreen() * (1.0f / 255.0f);
|
||||
float blue = light->GetBlue() * (1.0f / 255.0f);
|
||||
/*if (light->IsSubtractive())
|
||||
{
|
||||
float bright = FVector3(lr, lg, lb).Length();
|
||||
FVector3 lightColor(lr, lg, lb);
|
||||
red = (bright - lr) * -1;
|
||||
green = (bright - lg) * -1;
|
||||
blue = (bright - lb) * -1;
|
||||
}*/
|
||||
|
||||
lit_red += red * attenuation;
|
||||
lit_green += green * attenuation;
|
||||
lit_blue += blue * attenuation;
|
||||
}
|
||||
}
|
||||
}
|
||||
node = node->nextLight;
|
||||
}
|
||||
lit_red = clamp(lit_red * 255.0f, 0.0f, 255.0f);
|
||||
lit_green = clamp(lit_green * 255.0f, 0.0f, 255.0f);
|
||||
lit_blue = clamp(lit_blue * 255.0f, 0.0f, 255.0f);
|
||||
args.SetDynLightColor((((uint32_t)lit_red) << 16) | (((uint32_t)lit_green) << 8) | ((uint32_t)lit_blue));
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ private:
|
|||
static double PerformSpriteClipAdjustment(AActor *thing, const DVector2 &thingpos, double spriteheight, double z);
|
||||
static double GetSpriteFloorZ(AActor *thing, const DVector2 &thingpos);
|
||||
static double GetSpriteCeilingZ(AActor *thing, const DVector2 &thingpos);
|
||||
static void SetDynlight(AActor *thing, PolyDrawArgs &args);
|
||||
};
|
||||
|
||||
class PolyTranslucentThing : public PolyTranslucentObject
|
||||
|
|
Loading…
Reference in a new issue