mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-01-19 07:30:59 +00:00
- Add dynamic lights to the non-sse true color drawer
This commit is contained in:
parent
f3ba92f03c
commit
5ffd26abeb
1 changed files with 133 additions and 7 deletions
|
@ -154,9 +154,62 @@ namespace TriScreenDrawerModes
|
|||
}
|
||||
}
|
||||
|
||||
template<typename ShadeModeT>
|
||||
FORCEINLINE BgraColor Shade32(BgraColor fgcolor, BgraColor mlight, uint32_t desaturate, uint32_t inv_desaturate, BgraColor shade_fade, BgraColor shade_light)
|
||||
FORCEINLINE BgraColor VECTORCALL AddLights(BgraColor material, BgraColor fgcolor, BgraColor dynlight)
|
||||
{
|
||||
fgcolor.r = MIN(fgcolor.r + ((material.r * dynlight.r) >> 8), (uint32_t)255);
|
||||
fgcolor.g = MIN(fgcolor.g + ((material.g * dynlight.g) >> 8), (uint32_t)255);
|
||||
fgcolor.b = MIN(fgcolor.b + ((material.b * dynlight.b) >> 8), (uint32_t)255);
|
||||
return fgcolor;
|
||||
}
|
||||
|
||||
FORCEINLINE BgraColor VECTORCALL CalcDynamicLight(const PolyLight *lights, int num_lights, FVector3 worldpos, FVector3 worldnormal, uint32_t dynlightcolor)
|
||||
{
|
||||
BgraColor lit = dynlightcolor;
|
||||
|
||||
for (int i = 0; i != num_lights; i++)
|
||||
{
|
||||
FVector3 lightpos = { lights[i].x, lights[i].y, lights[i].z };
|
||||
float light_radius = lights[i].radius;
|
||||
|
||||
bool is_attenuated = light_radius < 0.0f;
|
||||
if (is_attenuated)
|
||||
light_radius = -light_radius;
|
||||
|
||||
// L = light-pos
|
||||
// dist = sqrt(dot(L, L))
|
||||
// distance_attenuation = 1 - MIN(dist * (1/radius), 1)
|
||||
FVector3 L = lightpos - worldpos;
|
||||
float dist2 = L | L;
|
||||
float rcp_dist = 1.0f / sqrt(dist2);
|
||||
float dist = dist2 * rcp_dist;
|
||||
float distance_attenuation = 256.0f - MIN(dist * light_radius, 256.0f);
|
||||
|
||||
// The simple light type
|
||||
float simple_attenuation = distance_attenuation;
|
||||
|
||||
// The point light type
|
||||
// diffuse = max(dot(N,normalize(L)),0) * attenuation
|
||||
float dotNL = worldnormal | (L * rcp_dist);
|
||||
float point_attenuation = MAX(dotNL, 0.0f) * distance_attenuation;
|
||||
|
||||
uint32_t attenuation = (uint32_t)(is_attenuated ? (int32_t)point_attenuation : (int32_t)simple_attenuation);
|
||||
|
||||
BgraColor light_color = lights[i].color;
|
||||
lit.r += (light_color.r * attenuation) >> 8;
|
||||
lit.g += (light_color.g * attenuation) >> 8;
|
||||
lit.b += (light_color.b * attenuation) >> 8;
|
||||
}
|
||||
|
||||
lit.r = MIN(lit.r, (uint32_t)256);
|
||||
lit.g = MIN(lit.g, (uint32_t)256);
|
||||
lit.b = MIN(lit.b, (uint32_t)256);
|
||||
return lit;
|
||||
}
|
||||
|
||||
template<typename ShadeModeT>
|
||||
FORCEINLINE BgraColor Shade32(BgraColor fgcolor, BgraColor mlight, uint32_t desaturate, uint32_t inv_desaturate, BgraColor shade_fade, BgraColor shade_light, BgraColor dynlight)
|
||||
{
|
||||
BgraColor material = fgcolor;
|
||||
if (ShadeModeT::Mode == (int)ShadeMode::Simple)
|
||||
{
|
||||
fgcolor.r = (fgcolor.r * mlight.r) >> 8;
|
||||
|
@ -170,7 +223,7 @@ namespace TriScreenDrawerModes
|
|||
fgcolor.g = (((shade_fade.g + ((fgcolor.g * inv_desaturate + intensity) >> 8) * mlight.g) >> 8) * shade_light.g) >> 8;
|
||||
fgcolor.b = (((shade_fade.b + ((fgcolor.b * inv_desaturate + intensity) >> 8) * mlight.b) >> 8) * shade_light.b) >> 8;
|
||||
}
|
||||
return fgcolor;
|
||||
return AddLights(material, fgcolor, dynlight);
|
||||
}
|
||||
|
||||
template<typename BlendT>
|
||||
|
@ -322,6 +375,11 @@ private:
|
|||
|
||||
int fuzzpos = (ScreenTriangle::FuzzStart + destX * 123 + destY) % FUZZTABLE;
|
||||
|
||||
auto lights = args->uniforms->Lights();
|
||||
auto num_lights = args->uniforms->NumLights();
|
||||
FVector3 worldnormal = args->uniforms->Normal();
|
||||
uint32_t dynlightcolor = args->uniforms->DynLightColor();
|
||||
|
||||
// Calculate gradients
|
||||
const ShadedTriVertex &v1 = *args->v1;
|
||||
ScreenTriangleStepVariables gradientX = args->gradientX;
|
||||
|
@ -330,9 +388,15 @@ private:
|
|||
blockPosY.W = v1.w + gradientX.W * (destX - v1.x) + gradientY.W * (destY - v1.y);
|
||||
blockPosY.U = v1.u * v1.w + gradientX.U * (destX - v1.x) + gradientY.U * (destY - v1.y);
|
||||
blockPosY.V = v1.v * v1.w + gradientX.V * (destX - v1.x) + gradientY.V * (destY - v1.y);
|
||||
blockPosY.WorldX = v1.worldX * v1.w + gradientX.WorldX * (destX - v1.x) + gradientY.WorldX * (destY - v1.y);
|
||||
blockPosY.WorldY = v1.worldY * v1.w + gradientX.WorldY * (destX - v1.x) + gradientY.WorldY * (destY - v1.y);
|
||||
blockPosY.WorldZ = v1.worldZ * v1.w + gradientX.WorldZ * (destX - v1.x) + gradientY.WorldZ * (destY - v1.y);
|
||||
gradientX.W *= 8.0f;
|
||||
gradientX.U *= 8.0f;
|
||||
gradientX.V *= 8.0f;
|
||||
gradientX.WorldX *= 8.0f;
|
||||
gradientX.WorldY *= 8.0f;
|
||||
gradientX.WorldZ *= 8.0f;
|
||||
|
||||
// Output
|
||||
uint32_t * RESTRICT destOrg = (uint32_t*)args->dest;
|
||||
|
@ -401,10 +465,16 @@ private:
|
|||
fixed_t lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT);
|
||||
lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask);
|
||||
|
||||
FVector3 worldpos = FVector3(blockPosY.WorldX, blockPosY.WorldY, blockPosY.WorldZ) / blockPosY.W;
|
||||
BgraColor dynlight = CalcDynamicLight(lights, num_lights, worldpos, worldnormal, dynlightcolor);
|
||||
|
||||
ScreenTriangleStepVariables blockPosX = blockPosY;
|
||||
blockPosX.W += gradientX.W;
|
||||
blockPosX.U += gradientX.U;
|
||||
blockPosX.V += gradientX.V;
|
||||
blockPosX.WorldX += gradientX.WorldX;
|
||||
blockPosX.WorldY += gradientX.WorldY;
|
||||
blockPosX.WorldZ += gradientX.WorldZ;
|
||||
|
||||
rcpW = 0x01000000 / blockPosX.W;
|
||||
int32_t nextU = (int32_t)(blockPosX.U * rcpW);
|
||||
|
@ -416,6 +486,13 @@ private:
|
|||
fixed_t lightstep = (lightnext - lightpos) / 8;
|
||||
lightstep = lightstep & lightmask;
|
||||
|
||||
worldpos = FVector3(blockPosX.WorldX, blockPosX.WorldY, blockPosX.WorldZ) / blockPosX.W;
|
||||
BgraColor dynlightnext = CalcDynamicLight(lights, num_lights, worldpos, worldnormal, dynlightcolor);
|
||||
BgraColor dynlightstep;
|
||||
dynlightstep.r = int32_t(dynlightnext.r - dynlight.r) >> 3;
|
||||
dynlightstep.g = int32_t(dynlightnext.g - dynlight.g) >> 3;
|
||||
dynlightstep.b = int32_t(dynlightnext.b - dynlight.b) >> 3;
|
||||
|
||||
for (int ix = 0; ix < 8; ix++)
|
||||
{
|
||||
// Load bgcolor
|
||||
|
@ -456,16 +533,23 @@ private:
|
|||
}
|
||||
|
||||
// Shade and blend
|
||||
BgraColor fgcolor = Shade32<ShadeModeT>(ifgcolor, mlight, desaturate, inv_desaturate, shade_fade_lit, shade_light);
|
||||
BgraColor fgcolor = Shade32<ShadeModeT>(ifgcolor, mlight, desaturate, inv_desaturate, shade_fade_lit, shade_light, dynlight);
|
||||
BgraColor outcolor = Blend32<BlendT>(fgcolor, bgcolor, ifgcolor, ifgshade, srcalpha, destalpha);
|
||||
|
||||
// Store result
|
||||
dest[ix] = outcolor;
|
||||
|
||||
dynlight.r = MAX<int32_t>(dynlight.r + dynlightstep.r, 0);
|
||||
dynlight.g = MAX<int32_t>(dynlight.g + dynlightstep.g, 0);
|
||||
dynlight.b = MAX<int32_t>(dynlight.b + dynlightstep.b, 0);
|
||||
}
|
||||
|
||||
blockPosY.W += gradientY.W;
|
||||
blockPosY.U += gradientY.U;
|
||||
blockPosY.V += gradientY.V;
|
||||
blockPosY.WorldX += gradientY.WorldX;
|
||||
blockPosY.WorldY += gradientY.WorldY;
|
||||
blockPosY.WorldZ += gradientY.WorldZ;
|
||||
|
||||
dest += pitch;
|
||||
}
|
||||
|
@ -482,10 +566,16 @@ private:
|
|||
fixed_t lightpos = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT);
|
||||
lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask);
|
||||
|
||||
FVector3 worldpos = FVector3(blockPosY.WorldX, blockPosY.WorldY, blockPosY.WorldZ) / blockPosY.W;
|
||||
BgraColor dynlight = CalcDynamicLight(lights, num_lights, worldpos, worldnormal, dynlightcolor);
|
||||
|
||||
ScreenTriangleStepVariables blockPosX = blockPosY;
|
||||
blockPosX.W += gradientX.W;
|
||||
blockPosX.U += gradientX.U;
|
||||
blockPosX.V += gradientX.V;
|
||||
blockPosX.WorldX += gradientX.WorldX;
|
||||
blockPosX.WorldY += gradientX.WorldY;
|
||||
blockPosX.WorldZ += gradientX.WorldZ;
|
||||
|
||||
rcpW = 0x01000000 / blockPosX.W;
|
||||
int32_t nextU = (int32_t)(blockPosX.U * rcpW);
|
||||
|
@ -497,6 +587,13 @@ private:
|
|||
fixed_t lightstep = (lightnext - lightpos) / 8;
|
||||
lightstep = lightstep & lightmask;
|
||||
|
||||
worldpos = FVector3(blockPosX.WorldX, blockPosX.WorldY, blockPosX.WorldZ) / blockPosX.W;
|
||||
BgraColor dynlightnext = CalcDynamicLight(lights, num_lights, worldpos, worldnormal, dynlightcolor);
|
||||
BgraColor dynlightstep;
|
||||
dynlightstep.r = int32_t(dynlightnext.r - dynlight.r) >> 3;
|
||||
dynlightstep.g = int32_t(dynlightnext.g - dynlight.g) >> 3;
|
||||
dynlightstep.b = int32_t(dynlightnext.b - dynlight.b) >> 3;
|
||||
|
||||
for (int x = 0; x < 8; x++)
|
||||
{
|
||||
// Load bgcolor
|
||||
|
@ -539,18 +636,25 @@ private:
|
|||
}
|
||||
|
||||
// Shade and blend
|
||||
BgraColor fgcolor = Shade32<ShadeModeT>(ifgcolor, mlight, desaturate, inv_desaturate, shade_fade_lit, shade_light);
|
||||
BgraColor fgcolor = Shade32<ShadeModeT>(ifgcolor, mlight, desaturate, inv_desaturate, shade_fade_lit, shade_light, dynlight);
|
||||
BgraColor outcolor = Blend32<BlendT>(fgcolor, bgcolor, ifgcolor, ifgshade, srcalpha, destalpha);
|
||||
|
||||
// Store result
|
||||
if (mask0 & (1 << 31)) dest[x] = outcolor;
|
||||
|
||||
mask0 <<= 1;
|
||||
|
||||
dynlight.r = MAX<int32_t>(dynlight.r + dynlightstep.r, 0);
|
||||
dynlight.g = MAX<int32_t>(dynlight.g + dynlightstep.g, 0);
|
||||
dynlight.b = MAX<int32_t>(dynlight.b + dynlightstep.b, 0);
|
||||
}
|
||||
|
||||
blockPosY.W += gradientY.W;
|
||||
blockPosY.U += gradientY.U;
|
||||
blockPosY.V += gradientY.V;
|
||||
blockPosY.WorldX += gradientY.WorldX;
|
||||
blockPosY.WorldY += gradientY.WorldY;
|
||||
blockPosY.WorldZ += gradientY.WorldZ;
|
||||
|
||||
dest += pitch;
|
||||
}
|
||||
|
@ -565,10 +669,16 @@ private:
|
|||
fixed_t lightpos = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT);
|
||||
lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask);
|
||||
|
||||
FVector3 worldpos = FVector3(blockPosY.WorldX, blockPosY.WorldY, blockPosY.WorldZ) / blockPosY.W;
|
||||
BgraColor dynlight = CalcDynamicLight(lights, num_lights, worldpos, worldnormal, dynlightcolor);
|
||||
|
||||
ScreenTriangleStepVariables blockPosX = blockPosY;
|
||||
blockPosX.W += gradientX.W;
|
||||
blockPosX.U += gradientX.U;
|
||||
blockPosX.V += gradientX.V;
|
||||
blockPosX.WorldX += gradientX.WorldX;
|
||||
blockPosX.WorldY += gradientX.WorldY;
|
||||
blockPosX.WorldZ += gradientX.WorldZ;
|
||||
|
||||
rcpW = 0x01000000 / blockPosX.W;
|
||||
int32_t nextU = (int32_t)(blockPosX.U * rcpW);
|
||||
|
@ -580,6 +690,13 @@ private:
|
|||
fixed_t lightstep = (lightnext - lightpos) / 8;
|
||||
lightstep = lightstep & lightmask;
|
||||
|
||||
worldpos = FVector3(blockPosX.WorldX, blockPosX.WorldY, blockPosX.WorldZ) / blockPosX.W;
|
||||
BgraColor dynlightnext = CalcDynamicLight(lights, num_lights, worldpos, worldnormal, dynlightcolor);
|
||||
BgraColor dynlightstep;
|
||||
dynlightstep.r = int32_t(dynlightnext.r - dynlight.r) >> 3;
|
||||
dynlightstep.g = int32_t(dynlightnext.g - dynlight.g) >> 3;
|
||||
dynlightstep.b = int32_t(dynlightnext.b - dynlight.b) >> 3;
|
||||
|
||||
for (int x = 0; x < 8; x++)
|
||||
{
|
||||
// Load bgcolor
|
||||
|
@ -622,18 +739,25 @@ private:
|
|||
}
|
||||
|
||||
// Shade and blend
|
||||
BgraColor fgcolor = Shade32<ShadeModeT>(ifgcolor, mlight, desaturate, inv_desaturate, shade_fade_lit, shade_light);
|
||||
BgraColor fgcolor = Shade32<ShadeModeT>(ifgcolor, mlight, desaturate, inv_desaturate, shade_fade_lit, shade_light, dynlight);
|
||||
BgraColor outcolor = Blend32<BlendT>(fgcolor, bgcolor, ifgcolor, ifgshade, srcalpha, destalpha);
|
||||
|
||||
// Store result
|
||||
if (mask1 & (1 << 31)) dest[x] = outcolor;
|
||||
|
||||
mask1 <<= 1;
|
||||
|
||||
dynlight.r = MAX<int32_t>(dynlight.r + dynlightstep.r, 0);
|
||||
dynlight.g = MAX<int32_t>(dynlight.g + dynlightstep.g, 0);
|
||||
dynlight.b = MAX<int32_t>(dynlight.b + dynlightstep.b, 0);
|
||||
}
|
||||
|
||||
blockPosY.W += gradientY.W;
|
||||
blockPosY.U += gradientY.U;
|
||||
blockPosY.V += gradientY.V;
|
||||
blockPosY.WorldX += gradientY.WorldX;
|
||||
blockPosY.WorldY += gradientY.WorldY;
|
||||
blockPosY.WorldZ += gradientY.WorldZ;
|
||||
|
||||
dest += pitch;
|
||||
}
|
||||
|
@ -707,6 +831,8 @@ private:
|
|||
lightpos += lightpos >> 7; // 255 -> 256
|
||||
BgraColor mlight;
|
||||
|
||||
BgraColor dynlight = 0;
|
||||
|
||||
// Shade constants
|
||||
int inv_desaturate;
|
||||
BgraColor shade_fade_lit, shade_light;
|
||||
|
@ -774,7 +900,7 @@ private:
|
|||
posU += stepU;
|
||||
|
||||
// Shade and blend
|
||||
BgraColor fgcolor = Shade32<ShadeModeT>(ifgcolor, mlight, desaturate, inv_desaturate, shade_fade_lit, shade_light);
|
||||
BgraColor fgcolor = Shade32<ShadeModeT>(ifgcolor, mlight, desaturate, inv_desaturate, shade_fade_lit, shade_light, dynlight);
|
||||
BgraColor outcolor = Blend32<BlendT>(fgcolor, bgcolor, ifgcolor, ifgshade, srcalpha, destalpha);
|
||||
|
||||
// Store result
|
||||
|
|
Loading…
Reference in a new issue