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 SetTransform(const TriMatrix *objectToClip) { mObjectToClip = objectToClip; }
|
||||||
void SetColor(uint32_t bgra, uint8_t palindex);
|
void SetColor(uint32_t bgra, uint8_t palindex);
|
||||||
void SetLights(PolyLight *lights, int numLights) { mLights = lights; mNumLights = numLights; }
|
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);
|
void DrawArray(PolyRenderThread *thread, const TriVertex *vertices, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles);
|
||||||
|
|
||||||
const TriMatrix *ObjectToClip() const { return mObjectToClip; }
|
const TriMatrix *ObjectToClip() const { return mObjectToClip; }
|
||||||
|
@ -129,6 +130,7 @@ public:
|
||||||
|
|
||||||
PolyLight *Lights() const { return mLights; }
|
PolyLight *Lights() const { return mLights; }
|
||||||
int NumLights() const { return mNumLights; }
|
int NumLights() const { return mNumLights; }
|
||||||
|
uint32_t DynLightColor() const { return mDynLightColor; }
|
||||||
|
|
||||||
const FVector3 &Normal() const { return mNormal; }
|
const FVector3 &Normal() const { return mNormal; }
|
||||||
void SetNormal(const FVector3 &normal) { mNormal = normal; }
|
void SetNormal(const FVector3 &normal) { mNormal = normal; }
|
||||||
|
@ -172,6 +174,7 @@ private:
|
||||||
PolyLight *mLights = nullptr;
|
PolyLight *mLights = nullptr;
|
||||||
int mNumLights = 0;
|
int mNumLights = 0;
|
||||||
FVector3 mNormal;
|
FVector3 mNormal;
|
||||||
|
uint32_t mDynLightColor = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RectDrawArgs
|
class RectDrawArgs
|
||||||
|
|
|
@ -149,9 +149,10 @@ namespace TriScreenDrawerModes
|
||||||
return fgcolor;
|
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++)
|
for (int i = 0; i != num_lights; i++)
|
||||||
{
|
{
|
||||||
|
@ -396,6 +397,7 @@ private:
|
||||||
auto lights = args->uniforms->Lights();
|
auto lights = args->uniforms->Lights();
|
||||||
auto num_lights = args->uniforms->NumLights();
|
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);
|
__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
|
// Calculate gradients
|
||||||
const ShadedTriVertex &v1 = *args->v1;
|
const ShadedTriVertex &v1 = *args->v1;
|
||||||
|
@ -476,7 +478,7 @@ private:
|
||||||
|
|
||||||
__m128 mrcpW = _mm_set1_ps(1.0f / blockPosY.W);
|
__m128 mrcpW = _mm_set1_ps(1.0f / blockPosY.W);
|
||||||
__m128 worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosY.WorldX), mrcpW);
|
__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;
|
ScreenTriangleStepVariables blockPosX = blockPosY;
|
||||||
blockPosX.W += gradientX.W;
|
blockPosX.W += gradientX.W;
|
||||||
|
@ -498,7 +500,7 @@ private:
|
||||||
|
|
||||||
mrcpW = _mm_set1_ps(1.0f / blockPosX.W);
|
mrcpW = _mm_set1_ps(1.0f / blockPosX.W);
|
||||||
worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosX.WorldX), mrcpW);
|
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);
|
__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());
|
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);
|
dynlightstep = _mm_slli_epi16(dynlightstep, 1);
|
||||||
|
@ -579,7 +581,7 @@ private:
|
||||||
|
|
||||||
__m128 mrcpW = _mm_set1_ps(1.0f / blockPosY.W);
|
__m128 mrcpW = _mm_set1_ps(1.0f / blockPosY.W);
|
||||||
__m128 worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosY.WorldX), mrcpW);
|
__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;
|
ScreenTriangleStepVariables blockPosX = blockPosY;
|
||||||
blockPosX.W += gradientX.W;
|
blockPosX.W += gradientX.W;
|
||||||
|
@ -601,7 +603,7 @@ private:
|
||||||
|
|
||||||
mrcpW = _mm_set1_ps(1.0f / blockPosX.W);
|
mrcpW = _mm_set1_ps(1.0f / blockPosX.W);
|
||||||
worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosX.WorldX), mrcpW);
|
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);
|
__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());
|
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);
|
dynlightstep = _mm_slli_epi16(dynlightstep, 1);
|
||||||
|
@ -689,7 +691,7 @@ private:
|
||||||
|
|
||||||
__m128 mrcpW = _mm_set1_ps(1.0f / blockPosY.W);
|
__m128 mrcpW = _mm_set1_ps(1.0f / blockPosY.W);
|
||||||
__m128 worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosY.WorldX), mrcpW);
|
__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;
|
ScreenTriangleStepVariables blockPosX = blockPosY;
|
||||||
blockPosX.W += gradientX.W;
|
blockPosX.W += gradientX.W;
|
||||||
|
@ -711,7 +713,7 @@ private:
|
||||||
|
|
||||||
mrcpW = _mm_set1_ps(1.0f / blockPosX.W);
|
mrcpW = _mm_set1_ps(1.0f / blockPosX.W);
|
||||||
worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosX.WorldX), mrcpW);
|
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);
|
__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());
|
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);
|
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;
|
int lightlevel = fullbrightSprite ? 255 : thing->Sector->lightlevel + actualextralight;
|
||||||
|
|
||||||
PolyDrawArgs args;
|
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.SetLight(GetColorTable(sub->sector->Colormap, sub->sector->SpecialColors[sector_t::sprites], true), lightlevel, PolyRenderer::Instance()->Light.SpriteGlobVis(foggy), fullbrightSprite);
|
||||||
args.SetTransform(&worldToClip);
|
args.SetTransform(&worldToClip);
|
||||||
args.SetFaceCullCCW(true);
|
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 PerformSpriteClipAdjustment(AActor *thing, const DVector2 &thingpos, double spriteheight, double z);
|
||||||
static double GetSpriteFloorZ(AActor *thing, const DVector2 &thingpos);
|
static double GetSpriteFloorZ(AActor *thing, const DVector2 &thingpos);
|
||||||
static double GetSpriteCeilingZ(AActor *thing, const DVector2 &thingpos);
|
static double GetSpriteCeilingZ(AActor *thing, const DVector2 &thingpos);
|
||||||
|
static void SetDynlight(AActor *thing, PolyDrawArgs &args);
|
||||||
};
|
};
|
||||||
|
|
||||||
class PolyTranslucentThing : public PolyTranslucentObject
|
class PolyTranslucentThing : public PolyTranslucentObject
|
||||||
|
|
Loading…
Reference in a new issue