mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-11 07:11:54 +00:00
- Initial dynamic light support for softpoly
This commit is contained in:
parent
afdeed305b
commit
dd8a114bb8
8 changed files with 257 additions and 10 deletions
|
@ -55,6 +55,13 @@ struct TriVertex
|
|||
float u, v;
|
||||
};
|
||||
|
||||
struct PolyLight
|
||||
{
|
||||
uint32_t color;
|
||||
float x, y, z;
|
||||
float radius;
|
||||
};
|
||||
|
||||
class PolyDrawArgs
|
||||
{
|
||||
public:
|
||||
|
@ -73,6 +80,7 @@ public:
|
|||
void SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *texture, bool fullbright);
|
||||
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 DrawArray(PolyRenderThread *thread, const TriVertex *vertices, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles);
|
||||
|
||||
const TriMatrix *ObjectToClip() const { return mObjectToClip; }
|
||||
|
@ -119,6 +127,9 @@ public:
|
|||
bool NearestFilter() const { return mNearestFilter; }
|
||||
bool FixedLight() const { return mFixedLight; }
|
||||
|
||||
PolyLight *Lights() const { return mLights; }
|
||||
int NumLights() const { return mNumLights; }
|
||||
|
||||
private:
|
||||
const TriMatrix *mObjectToClip = nullptr;
|
||||
const TriVertex *mVertices = nullptr;
|
||||
|
@ -155,6 +166,8 @@ private:
|
|||
bool mSimpleShade = true;
|
||||
bool mNearestFilter = true;
|
||||
bool mFixedLight = false;
|
||||
PolyLight *mLights = nullptr;
|
||||
int mNumLights = 0;
|
||||
};
|
||||
|
||||
class RectDrawArgs
|
||||
|
|
|
@ -142,9 +142,64 @@ namespace TriScreenDrawerModes
|
|||
}
|
||||
}
|
||||
|
||||
template<typename ShadeModeT>
|
||||
FORCEINLINE __m128i VECTORCALL Shade32(__m128i fgcolor, __m128i mlight, unsigned int ifgcolor0, unsigned int ifgcolor1, int desaturate, __m128i inv_desaturate, __m128i shade_fade, __m128i shade_light)
|
||||
FORCEINLINE __m128i VECTORCALL AddLights(__m128i material, __m128i fgcolor, const PolyLight *lights, int num_lights, __m128 worldpos, __m128 worldnormal)
|
||||
{
|
||||
__m128i lit = _mm_setzero_si128();
|
||||
|
||||
for (int i = 0; i != num_lights; i++)
|
||||
{
|
||||
__m128 m256 = _mm_set1_ps(256.0f);
|
||||
__m128 mSignBit = _mm_set1_ps(-0.0f);
|
||||
|
||||
__m128 lightpos = _mm_loadu_ps(&lights[i].x);
|
||||
__m128 light_radius = _mm_load_ss(&lights[i].radius);
|
||||
|
||||
__m128 is_attenuated = _mm_cmpge_ss(light_radius, _mm_setzero_ps());
|
||||
is_attenuated = _mm_shuffle_ps(is_attenuated, is_attenuated, _MM_SHUFFLE(0, 0, 0, 0));
|
||||
light_radius = _mm_andnot_ps(mSignBit, light_radius);
|
||||
|
||||
// L = light-pos
|
||||
// dist = sqrt(dot(L, L))
|
||||
// distance_attenuation = 1 - MIN(dist * (1/radius), 1)
|
||||
__m128 L = _mm_sub_ps(lightpos, worldpos);
|
||||
__m128 dist2 = _mm_mul_ps(L, L);
|
||||
dist2 = _mm_add_ss(dist2, _mm_add_ss(_mm_shuffle_ps(dist2, dist2, _MM_SHUFFLE(0, 0, 0, 1)), _mm_shuffle_ps(dist2, dist2, _MM_SHUFFLE(0, 0, 0, 2))));
|
||||
__m128 rcp_dist = _mm_rsqrt_ss(dist2);
|
||||
__m128 dist = _mm_mul_ss(dist2, rcp_dist);
|
||||
__m128 distance_attenuation = _mm_sub_ss(m256, _mm_min_ss(_mm_mul_ss(dist, light_radius), m256));
|
||||
distance_attenuation = _mm_shuffle_ps(distance_attenuation, distance_attenuation, _MM_SHUFFLE(0, 0, 0, 0));
|
||||
|
||||
// The simple light type
|
||||
__m128 simple_attenuation = distance_attenuation;
|
||||
|
||||
// The point light type
|
||||
// diffuse = dot(N,L) * attenuation
|
||||
__m128 dotNL = _mm_mul_ps(worldnormal, L);
|
||||
dotNL = _mm_add_ss(dotNL, _mm_add_ss(_mm_shuffle_ps(dotNL, dotNL, _MM_SHUFFLE(0, 0, 0, 1)), _mm_shuffle_ps(dotNL, dotNL, _MM_SHUFFLE(0, 0, 0, 2))));
|
||||
__m128 point_attenuation = _mm_mul_ss(dotNL, distance_attenuation);
|
||||
point_attenuation = _mm_shuffle_ps(point_attenuation, point_attenuation, _MM_SHUFFLE(0, 0, 0, 0));
|
||||
|
||||
__m128i attenuation = _mm_cvtps_epi32(_mm_or_ps(_mm_and_ps(is_attenuated, simple_attenuation), _mm_andnot_ps(is_attenuated, point_attenuation)));
|
||||
attenuation = _mm_packs_epi32(_mm_shuffle_epi32(attenuation, _MM_SHUFFLE(0, 0, 0, 0)), _mm_shuffle_epi32(attenuation, _MM_SHUFFLE(1, 1, 1, 1)));
|
||||
|
||||
__m128i light_color = _mm_cvtsi32_si128(lights[i].color);
|
||||
light_color = _mm_unpacklo_epi8(light_color, _mm_setzero_si128());
|
||||
light_color = _mm_shuffle_epi32(light_color, _MM_SHUFFLE(1, 0, 1, 0));
|
||||
|
||||
lit = _mm_add_epi16(lit, _mm_srli_epi16(_mm_mullo_epi16(light_color, attenuation), 8));
|
||||
}
|
||||
|
||||
lit = _mm_min_epi16(lit, _mm_set1_epi16(256));
|
||||
|
||||
fgcolor = _mm_add_epi16(fgcolor, _mm_srli_epi16(_mm_mullo_epi16(material, lit), 8));
|
||||
fgcolor = _mm_min_epi16(fgcolor, _mm_set1_epi16(255));
|
||||
return fgcolor;
|
||||
}
|
||||
|
||||
template<typename ShadeModeT>
|
||||
FORCEINLINE __m128i VECTORCALL Shade32(__m128i fgcolor, __m128i mlight, unsigned int ifgcolor0, unsigned int ifgcolor1, int desaturate, __m128i inv_desaturate, __m128i shade_fade, __m128i shade_light, const PolyLight *lights, int num_lights, __m128 worldpos, __m128 worldnormal)
|
||||
{
|
||||
__m128i material = fgcolor;
|
||||
if (ShadeModeT::Mode == (int)ShadeMode::Simple)
|
||||
{
|
||||
fgcolor = _mm_srli_epi16(_mm_mullo_epi16(fgcolor, mlight), 8);
|
||||
|
@ -168,7 +223,8 @@ namespace TriScreenDrawerModes
|
|||
fgcolor = _mm_srli_epi16(_mm_add_epi16(shade_fade, fgcolor), 8);
|
||||
fgcolor = _mm_srli_epi16(_mm_mullo_epi16(fgcolor, shade_light), 8);
|
||||
}
|
||||
return fgcolor;
|
||||
|
||||
return AddLights(material, fgcolor, lights, num_lights, worldpos, worldnormal);
|
||||
}
|
||||
|
||||
template<typename BlendT>
|
||||
|
@ -333,6 +389,11 @@ private:
|
|||
|
||||
int fuzzpos = (ScreenTriangle::FuzzStart + destX * 123 + destY) % FUZZTABLE;
|
||||
|
||||
auto lights = args->uniforms->Lights();
|
||||
auto num_lights = args->uniforms->NumLights();
|
||||
__m128 worldpos = _mm_setzero_ps();
|
||||
__m128 worldnormal = _mm_setzero_ps();
|
||||
|
||||
// Calculate gradients
|
||||
const ShadedTriVertex &v1 = *args->v1;
|
||||
ScreenTriangleStepVariables gradientX = args->gradientX;
|
||||
|
@ -341,9 +402,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;
|
||||
|
@ -404,10 +471,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);
|
||||
|
||||
__m128 mrcpW = _mm_set1_ps(1.0f / blockPosY.W);
|
||||
worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosY.WorldX), mrcpW);
|
||||
|
||||
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);
|
||||
|
@ -462,7 +535,7 @@ private:
|
|||
|
||||
// Shade and blend
|
||||
__m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128());
|
||||
fgcolor = Shade32<ShadeModeT>(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light);
|
||||
fgcolor = Shade32<ShadeModeT>(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light, lights, num_lights, worldpos, worldnormal);
|
||||
__m128i outcolor = Blend32<BlendT>(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha);
|
||||
|
||||
// Store result
|
||||
|
@ -472,6 +545,9 @@ private:
|
|||
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;
|
||||
}
|
||||
|
@ -488,10 +564,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);
|
||||
|
||||
__m128 mrcpW = _mm_set1_ps(1.0f / blockPosY.W);
|
||||
worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosY.WorldX), mrcpW);
|
||||
|
||||
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);
|
||||
|
@ -551,7 +633,7 @@ private:
|
|||
|
||||
// Shade and blend
|
||||
__m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128());
|
||||
fgcolor = Shade32<ShadeModeT>(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light);
|
||||
fgcolor = Shade32<ShadeModeT>(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light, lights, num_lights, worldpos, worldnormal);
|
||||
__m128i outcolor = Blend32<BlendT>(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha);
|
||||
|
||||
// Store result
|
||||
|
@ -565,6 +647,9 @@ private:
|
|||
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;
|
||||
}
|
||||
|
@ -579,10 +664,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);
|
||||
|
||||
__m128 mrcpW = _mm_set1_ps(1.0f / blockPosY.W);
|
||||
worldpos = _mm_mul_ps(_mm_loadu_ps(&blockPosY.WorldX), mrcpW);
|
||||
|
||||
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);
|
||||
|
@ -642,7 +733,7 @@ private:
|
|||
|
||||
// Shade and blend
|
||||
__m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128());
|
||||
fgcolor = Shade32<ShadeModeT>(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light);
|
||||
fgcolor = Shade32<ShadeModeT>(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light, lights, num_lights, worldpos, worldnormal);
|
||||
__m128i outcolor = Blend32<BlendT>(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha);
|
||||
|
||||
// Store result
|
||||
|
@ -656,6 +747,9 @@ private:
|
|||
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;
|
||||
}
|
||||
|
@ -798,7 +892,7 @@ private:
|
|||
|
||||
// Shade and blend
|
||||
__m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128());
|
||||
fgcolor = Shade32<ShadeModeT>(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light);
|
||||
fgcolor = Shade32<ShadeModeT>(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light, nullptr, 0, _mm_setzero_ps(), _mm_setzero_ps());
|
||||
__m128i outcolor = Blend32<BlendT>(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha);
|
||||
|
||||
// Store result
|
||||
|
@ -826,7 +920,7 @@ private:
|
|||
|
||||
// Shade and blend
|
||||
__m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128());
|
||||
fgcolor = Shade32<ShadeModeT>(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light);
|
||||
fgcolor = Shade32<ShadeModeT>(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light, nullptr, 0, _mm_setzero_ps(), _mm_setzero_ps());
|
||||
__m128i outcolor = Blend32<BlendT>(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha);
|
||||
|
||||
// Store result
|
||||
|
|
|
@ -155,6 +155,9 @@ ShadedTriVertex PolyTriangleDrawer::shade_vertex(const PolyDrawArgs &drawargs, c
|
|||
sv.w = position.W;
|
||||
sv.u = v.u;
|
||||
sv.v = v.v;
|
||||
sv.worldX = v.x;
|
||||
sv.worldY = v.y;
|
||||
sv.worldZ = v.z;
|
||||
|
||||
// Calculate gl_ClipDistance[i]
|
||||
for (int i = 0; i < 3; i++)
|
||||
|
@ -446,6 +449,9 @@ int PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, ShadedTriVertex *
|
|||
v.w += verts[w].w * weight;
|
||||
v.u += verts[w].u * weight;
|
||||
v.v += verts[w].v * weight;
|
||||
v.worldX += verts[w].worldX * weight;
|
||||
v.worldY += verts[w].worldY * weight;
|
||||
v.worldZ += verts[w].worldZ * weight;
|
||||
}
|
||||
}
|
||||
return inputverts;
|
||||
|
|
|
@ -46,11 +46,13 @@ struct ShadedTriVertex
|
|||
float x, y, z, w;
|
||||
float u, v;
|
||||
float clipDistance[3];
|
||||
float worldX, worldY, worldZ;
|
||||
};
|
||||
|
||||
struct ScreenTriangleStepVariables
|
||||
{
|
||||
float W, U, V;
|
||||
float WorldX, WorldY, WorldZ, Padding; // Padding so it can be loaded directly into a XMM register
|
||||
};
|
||||
|
||||
struct TriDrawTriangleArgs
|
||||
|
@ -79,11 +81,19 @@ struct TriDrawTriangleArgs
|
|||
return false;
|
||||
|
||||
gradientX.W = FindGradientX(bottomX, 1.0f, 1.0f, 1.0f);
|
||||
gradientY.W = FindGradientY(bottomY, 1.0f, 1.0f, 1.0f);
|
||||
gradientX.U = FindGradientX(bottomX, v1->u, v2->u, v3->u);
|
||||
gradientY.U = FindGradientY(bottomY, v1->u, v2->u, v3->u);
|
||||
gradientX.V = FindGradientX(bottomX, v1->v, v2->v, v3->v);
|
||||
gradientX.WorldX = FindGradientX(bottomX, v1->worldX, v2->worldX, v3->worldX);
|
||||
gradientX.WorldY = FindGradientX(bottomX, v1->worldY, v2->worldY, v3->worldY);
|
||||
gradientX.WorldZ = FindGradientX(bottomX, v1->worldZ, v2->worldZ, v3->worldZ);
|
||||
|
||||
gradientY.W = FindGradientY(bottomY, 1.0f, 1.0f, 1.0f);
|
||||
gradientY.U = FindGradientY(bottomY, v1->u, v2->u, v3->u);
|
||||
gradientY.V = FindGradientY(bottomY, v1->v, v2->v, v3->v);
|
||||
gradientY.WorldX = FindGradientY(bottomY, v1->worldX, v2->worldX, v3->worldX);
|
||||
gradientY.WorldY = FindGradientY(bottomY, v1->worldY, v2->worldY, v3->worldY);
|
||||
gradientY.WorldZ = FindGradientY(bottomY, v1->worldZ, v2->worldZ, v3->worldZ);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "polyrenderer/scene/poly_light.h"
|
||||
#include "polyrenderer/poly_renderthread.h"
|
||||
#include "p_lnspec.h"
|
||||
#include "a_dynlight.h"
|
||||
|
||||
EXTERN_CVAR(Int, r_3dfloors)
|
||||
|
||||
|
@ -253,6 +254,7 @@ void RenderPolyPlane::Render(PolyRenderThread *thread, const TriMatrix &worldToC
|
|||
|
||||
if (!isSky)
|
||||
{
|
||||
SetDynLights(thread, args, sub);
|
||||
args.SetTexture(tex);
|
||||
args.SetStyle(TriBlendMode::TextureOpaque);
|
||||
args.DrawArray(thread, vertices, sub->numlines, PolyDrawMode::TriangleFan);
|
||||
|
@ -277,6 +279,64 @@ void RenderPolyPlane::Render(PolyRenderThread *thread, const TriMatrix &worldToC
|
|||
}
|
||||
}
|
||||
|
||||
void RenderPolyPlane::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub)
|
||||
{
|
||||
FLightNode *light_list = sub->lighthead;
|
||||
|
||||
auto cameraLight = PolyCameraLight::Instance();
|
||||
if ((cameraLight->FixedLightLevel() >= 0) || (cameraLight->FixedColormap() != nullptr))
|
||||
{
|
||||
args.SetLights(nullptr, 0); // [SP] Don't draw dynlights if invul/lightamp active
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate max lights that can touch the wall so we can allocate memory for the list
|
||||
int max_lights = 0;
|
||||
FLightNode *cur_node = light_list;
|
||||
while (cur_node)
|
||||
{
|
||||
if (!(cur_node->lightsource->flags2&MF2_DORMANT))
|
||||
max_lights++;
|
||||
cur_node = cur_node->nextLight;
|
||||
}
|
||||
|
||||
if (max_lights == 0)
|
||||
{
|
||||
args.SetLights(nullptr, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
int dc_num_lights = 0;
|
||||
PolyLight *dc_lights = thread->FrameMemory->AllocMemory<PolyLight>(max_lights);
|
||||
|
||||
// Setup lights
|
||||
cur_node = light_list;
|
||||
while (cur_node)
|
||||
{
|
||||
if (!(cur_node->lightsource->flags2&MF2_DORMANT))
|
||||
{
|
||||
//bool is_point_light = (cur_node->lightsource->lightflags & LF_ATTENUATE) != 0;
|
||||
|
||||
// To do: cull lights not touching subsector
|
||||
|
||||
uint32_t red = cur_node->lightsource->GetRed();
|
||||
uint32_t green = cur_node->lightsource->GetGreen();
|
||||
uint32_t blue = cur_node->lightsource->GetBlue();
|
||||
|
||||
auto &light = dc_lights[dc_num_lights++];
|
||||
light.x = (float)cur_node->lightsource->X();
|
||||
light.y = (float)cur_node->lightsource->Y();
|
||||
light.z = (float)cur_node->lightsource->Z();
|
||||
light.radius = 256.0f / cur_node->lightsource->GetRadius();
|
||||
light.color = (red << 16) | (green << 8) | blue;
|
||||
}
|
||||
|
||||
cur_node = cur_node->nextLight;
|
||||
}
|
||||
|
||||
args.SetLights(dc_lights, dc_num_lights);
|
||||
}
|
||||
|
||||
void RenderPolyPlane::RenderSkyWalls(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, sector_t *frontsector, FSectorPortal *portal, PolyDrawSectorPortal *polyportal, bool ceiling, double skyHeight, const PolyPlaneUVTransform &transform)
|
||||
{
|
||||
for (uint32_t i = 0; i < sub->numlines; i++)
|
||||
|
|
|
@ -62,6 +62,7 @@ public:
|
|||
private:
|
||||
void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector<std::unique_ptr<PolyDrawSectorPortal>> §orPortals);
|
||||
void RenderSkyWalls(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, sector_t *frontsector, FSectorPortal *portal, PolyDrawSectorPortal *polyportal, bool ceiling, double skyHeight, const PolyPlaneUVTransform &transform);
|
||||
void SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub);
|
||||
};
|
||||
|
||||
class Render3DFloorPlane
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "polyrenderer/scene/poly_light.h"
|
||||
#include "polyrenderer/poly_renderthread.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "a_dynlight.h"
|
||||
|
||||
EXTERN_CVAR(Bool, r_drawmirrors)
|
||||
EXTERN_CVAR(Bool, r_fogboundary)
|
||||
|
@ -326,6 +327,8 @@ void RenderPolyWall::Render(PolyRenderThread *thread, const TriMatrix &worldToCl
|
|||
args.SetTexture(Texture);
|
||||
args.SetClipPlane(0, clipPlane);
|
||||
|
||||
SetDynLights(thread, args);
|
||||
|
||||
if (FogBoundary)
|
||||
{
|
||||
args.SetStyle(TriBlendMode::FogBoundary);
|
||||
|
@ -365,6 +368,64 @@ void RenderPolyWall::Render(PolyRenderThread *thread, const TriMatrix &worldToCl
|
|||
RenderPolyDecal::RenderWallDecals(thread, worldToClip, clipPlane, LineSeg, StencilValue);
|
||||
}
|
||||
|
||||
void RenderPolyWall::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args)
|
||||
{
|
||||
FLightNode *light_list = (LineSeg && LineSeg->sidedef) ? LineSeg->sidedef->lighthead : nullptr;
|
||||
|
||||
auto cameraLight = PolyCameraLight::Instance();
|
||||
if ((cameraLight->FixedLightLevel() >= 0) || (cameraLight->FixedColormap() != nullptr))
|
||||
{
|
||||
args.SetLights(nullptr, 0); // [SP] Don't draw dynlights if invul/lightamp active
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate max lights that can touch the wall so we can allocate memory for the list
|
||||
int max_lights = 0;
|
||||
FLightNode *cur_node = light_list;
|
||||
while (cur_node)
|
||||
{
|
||||
if (!(cur_node->lightsource->flags2&MF2_DORMANT))
|
||||
max_lights++;
|
||||
cur_node = cur_node->nextLight;
|
||||
}
|
||||
|
||||
if (max_lights == 0)
|
||||
{
|
||||
args.SetLights(nullptr, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
int dc_num_lights = 0;
|
||||
PolyLight *dc_lights = thread->FrameMemory->AllocMemory<PolyLight>(max_lights);
|
||||
|
||||
// Setup lights
|
||||
cur_node = light_list;
|
||||
while (cur_node)
|
||||
{
|
||||
if (!(cur_node->lightsource->flags2&MF2_DORMANT))
|
||||
{
|
||||
//bool is_point_light = (cur_node->lightsource->lightflags & LF_ATTENUATE) != 0;
|
||||
|
||||
// To do: cull lights not touching wall
|
||||
|
||||
uint32_t red = cur_node->lightsource->GetRed();
|
||||
uint32_t green = cur_node->lightsource->GetGreen();
|
||||
uint32_t blue = cur_node->lightsource->GetBlue();
|
||||
|
||||
auto &light = dc_lights[dc_num_lights++];
|
||||
light.x = (float)cur_node->lightsource->X();
|
||||
light.y = (float)cur_node->lightsource->Y();
|
||||
light.z = (float)cur_node->lightsource->Z();
|
||||
light.radius = 256.0f / cur_node->lightsource->GetRadius();
|
||||
light.color = (red << 16) | (green << 8) | blue;
|
||||
}
|
||||
|
||||
cur_node = cur_node->nextLight;
|
||||
}
|
||||
|
||||
args.SetLights(dc_lights, dc_num_lights);
|
||||
}
|
||||
|
||||
void RenderPolyWall::DrawStripes(PolyRenderThread *thread, PolyDrawArgs &args, TriVertex *vertices)
|
||||
{
|
||||
const auto &lightlist = Line->frontsector->e->XFloor.lightlist;
|
||||
|
|
|
@ -68,6 +68,8 @@ private:
|
|||
int GetLightLevel();
|
||||
void DrawStripes(PolyRenderThread *thread, PolyDrawArgs &args, TriVertex *vertices);
|
||||
|
||||
void SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args);
|
||||
|
||||
static bool IsFogBoundary(sector_t *front, sector_t *back);
|
||||
static FTexture *GetTexture(const line_t *Line, const side_t *Side, side_t::ETexpart texpart);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue