- Initial dynamic light support for softpoly

This commit is contained in:
Magnus Norddahl 2017-09-21 05:39:16 +02:00
parent afdeed305b
commit dd8a114bb8
8 changed files with 257 additions and 10 deletions

View File

@ -55,6 +55,13 @@ struct TriVertex
float u, v; float u, v;
}; };
struct PolyLight
{
uint32_t color;
float x, y, z;
float radius;
};
class PolyDrawArgs class PolyDrawArgs
{ {
public: public:
@ -73,6 +80,7 @@ public:
void SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *texture, bool fullbright); 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 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 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; }
@ -119,6 +127,9 @@ public:
bool NearestFilter() const { return mNearestFilter; } bool NearestFilter() const { return mNearestFilter; }
bool FixedLight() const { return mFixedLight; } bool FixedLight() const { return mFixedLight; }
PolyLight *Lights() const { return mLights; }
int NumLights() const { return mNumLights; }
private: private:
const TriMatrix *mObjectToClip = nullptr; const TriMatrix *mObjectToClip = nullptr;
const TriVertex *mVertices = nullptr; const TriVertex *mVertices = nullptr;
@ -155,6 +166,8 @@ private:
bool mSimpleShade = true; bool mSimpleShade = true;
bool mNearestFilter = true; bool mNearestFilter = true;
bool mFixedLight = false; bool mFixedLight = false;
PolyLight *mLights = nullptr;
int mNumLights = 0;
}; };
class RectDrawArgs class RectDrawArgs

View File

@ -142,9 +142,64 @@ namespace TriScreenDrawerModes
} }
} }
template<typename ShadeModeT> FORCEINLINE __m128i VECTORCALL AddLights(__m128i material, __m128i fgcolor, const PolyLight *lights, int num_lights, __m128 worldpos, __m128 worldnormal)
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)
{ {
__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) if (ShadeModeT::Mode == (int)ShadeMode::Simple)
{ {
fgcolor = _mm_srli_epi16(_mm_mullo_epi16(fgcolor, mlight), 8); 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_add_epi16(shade_fade, fgcolor), 8);
fgcolor = _mm_srli_epi16(_mm_mullo_epi16(fgcolor, shade_light), 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> template<typename BlendT>
@ -333,6 +389,11 @@ private:
int fuzzpos = (ScreenTriangle::FuzzStart + destX * 123 + destY) % FUZZTABLE; 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 // Calculate gradients
const ShadedTriVertex &v1 = *args->v1; const ShadedTriVertex &v1 = *args->v1;
ScreenTriangleStepVariables gradientX = args->gradientX; ScreenTriangleStepVariables gradientX = args->gradientX;
@ -341,9 +402,15 @@ private:
blockPosY.W = v1.w + gradientX.W * (destX - v1.x) + gradientY.W * (destY - v1.y); 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.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.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.W *= 8.0f;
gradientX.U *= 8.0f; gradientX.U *= 8.0f;
gradientX.V *= 8.0f; gradientX.V *= 8.0f;
gradientX.WorldX *= 8.0f;
gradientX.WorldY *= 8.0f;
gradientX.WorldZ *= 8.0f;
// Output // Output
uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; 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); 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); 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; ScreenTriangleStepVariables blockPosX = blockPosY;
blockPosX.W += gradientX.W; blockPosX.W += gradientX.W;
blockPosX.U += gradientX.U; blockPosX.U += gradientX.U;
blockPosX.V += gradientX.V; blockPosX.V += gradientX.V;
blockPosX.WorldX += gradientX.WorldX;
blockPosX.WorldY += gradientX.WorldY;
blockPosX.WorldZ += gradientX.WorldZ;
rcpW = 0x01000000 / blockPosX.W; rcpW = 0x01000000 / blockPosX.W;
int32_t nextU = (int32_t)(blockPosX.U * rcpW); int32_t nextU = (int32_t)(blockPosX.U * rcpW);
@ -462,7 +535,7 @@ private:
// Shade and blend // Shade and blend
__m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128()); __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); __m128i outcolor = Blend32<BlendT>(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha);
// Store result // Store result
@ -472,6 +545,9 @@ private:
blockPosY.W += gradientY.W; blockPosY.W += gradientY.W;
blockPosY.U += gradientY.U; blockPosY.U += gradientY.U;
blockPosY.V += gradientY.V; blockPosY.V += gradientY.V;
blockPosY.WorldX += gradientY.WorldX;
blockPosY.WorldY += gradientY.WorldY;
blockPosY.WorldZ += gradientY.WorldZ;
dest += pitch; 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); 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); 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; ScreenTriangleStepVariables blockPosX = blockPosY;
blockPosX.W += gradientX.W; blockPosX.W += gradientX.W;
blockPosX.U += gradientX.U; blockPosX.U += gradientX.U;
blockPosX.V += gradientX.V; blockPosX.V += gradientX.V;
blockPosX.WorldX += gradientX.WorldX;
blockPosX.WorldY += gradientX.WorldY;
blockPosX.WorldZ += gradientX.WorldZ;
rcpW = 0x01000000 / blockPosX.W; rcpW = 0x01000000 / blockPosX.W;
int32_t nextU = (int32_t)(blockPosX.U * rcpW); int32_t nextU = (int32_t)(blockPosX.U * rcpW);
@ -551,7 +633,7 @@ private:
// Shade and blend // Shade and blend
__m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128()); __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); __m128i outcolor = Blend32<BlendT>(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha);
// Store result // Store result
@ -565,6 +647,9 @@ private:
blockPosY.W += gradientY.W; blockPosY.W += gradientY.W;
blockPosY.U += gradientY.U; blockPosY.U += gradientY.U;
blockPosY.V += gradientY.V; blockPosY.V += gradientY.V;
blockPosY.WorldX += gradientY.WorldX;
blockPosY.WorldY += gradientY.WorldY;
blockPosY.WorldZ += gradientY.WorldZ;
dest += pitch; 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); 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); 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; ScreenTriangleStepVariables blockPosX = blockPosY;
blockPosX.W += gradientX.W; blockPosX.W += gradientX.W;
blockPosX.U += gradientX.U; blockPosX.U += gradientX.U;
blockPosX.V += gradientX.V; blockPosX.V += gradientX.V;
blockPosX.WorldX += gradientX.WorldX;
blockPosX.WorldY += gradientX.WorldY;
blockPosX.WorldZ += gradientX.WorldZ;
rcpW = 0x01000000 / blockPosX.W; rcpW = 0x01000000 / blockPosX.W;
int32_t nextU = (int32_t)(blockPosX.U * rcpW); int32_t nextU = (int32_t)(blockPosX.U * rcpW);
@ -642,7 +733,7 @@ private:
// Shade and blend // Shade and blend
__m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128()); __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); __m128i outcolor = Blend32<BlendT>(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha);
// Store result // Store result
@ -656,6 +747,9 @@ private:
blockPosY.W += gradientY.W; blockPosY.W += gradientY.W;
blockPosY.U += gradientY.U; blockPosY.U += gradientY.U;
blockPosY.V += gradientY.V; blockPosY.V += gradientY.V;
blockPosY.WorldX += gradientY.WorldX;
blockPosY.WorldY += gradientY.WorldY;
blockPosY.WorldZ += gradientY.WorldZ;
dest += pitch; dest += pitch;
} }
@ -798,7 +892,7 @@ private:
// Shade and blend // Shade and blend
__m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128()); __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); __m128i outcolor = Blend32<BlendT>(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha);
// Store result // Store result
@ -826,7 +920,7 @@ private:
// Shade and blend // Shade and blend
__m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128()); __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); __m128i outcolor = Blend32<BlendT>(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha);
// Store result // Store result

View File

@ -155,6 +155,9 @@ ShadedTriVertex PolyTriangleDrawer::shade_vertex(const PolyDrawArgs &drawargs, c
sv.w = position.W; sv.w = position.W;
sv.u = v.u; sv.u = v.u;
sv.v = v.v; sv.v = v.v;
sv.worldX = v.x;
sv.worldY = v.y;
sv.worldZ = v.z;
// Calculate gl_ClipDistance[i] // Calculate gl_ClipDistance[i]
for (int i = 0; i < 3; 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.w += verts[w].w * weight;
v.u += verts[w].u * weight; v.u += verts[w].u * weight;
v.v += verts[w].v * 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; return inputverts;

View File

@ -46,11 +46,13 @@ struct ShadedTriVertex
float x, y, z, w; float x, y, z, w;
float u, v; float u, v;
float clipDistance[3]; float clipDistance[3];
float worldX, worldY, worldZ;
}; };
struct ScreenTriangleStepVariables struct ScreenTriangleStepVariables
{ {
float W, U, V; float W, U, V;
float WorldX, WorldY, WorldZ, Padding; // Padding so it can be loaded directly into a XMM register
}; };
struct TriDrawTriangleArgs struct TriDrawTriangleArgs
@ -79,11 +81,19 @@ struct TriDrawTriangleArgs
return false; return false;
gradientX.W = FindGradientX(bottomX, 1.0f, 1.0f, 1.0f); 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); 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.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.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; return true;
} }

View File

@ -32,6 +32,7 @@
#include "polyrenderer/scene/poly_light.h" #include "polyrenderer/scene/poly_light.h"
#include "polyrenderer/poly_renderthread.h" #include "polyrenderer/poly_renderthread.h"
#include "p_lnspec.h" #include "p_lnspec.h"
#include "a_dynlight.h"
EXTERN_CVAR(Int, r_3dfloors) EXTERN_CVAR(Int, r_3dfloors)
@ -253,6 +254,7 @@ void RenderPolyPlane::Render(PolyRenderThread *thread, const TriMatrix &worldToC
if (!isSky) if (!isSky)
{ {
SetDynLights(thread, args, sub);
args.SetTexture(tex); args.SetTexture(tex);
args.SetStyle(TriBlendMode::TextureOpaque); args.SetStyle(TriBlendMode::TextureOpaque);
args.DrawArray(thread, vertices, sub->numlines, PolyDrawMode::TriangleFan); 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) 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++) for (uint32_t i = 0; i < sub->numlines; i++)

View File

@ -62,6 +62,7 @@ public:
private: 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>> &sectorPortals); 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>> &sectorPortals);
void RenderSkyWalls(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, sector_t *frontsector, FSectorPortal *portal, PolyDrawSectorPortal *polyportal, bool ceiling, double skyHeight, const PolyPlaneUVTransform &transform); 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 class Render3DFloorPlane

View File

@ -35,6 +35,7 @@
#include "polyrenderer/scene/poly_light.h" #include "polyrenderer/scene/poly_light.h"
#include "polyrenderer/poly_renderthread.h" #include "polyrenderer/poly_renderthread.h"
#include "g_levellocals.h" #include "g_levellocals.h"
#include "a_dynlight.h"
EXTERN_CVAR(Bool, r_drawmirrors) EXTERN_CVAR(Bool, r_drawmirrors)
EXTERN_CVAR(Bool, r_fogboundary) EXTERN_CVAR(Bool, r_fogboundary)
@ -326,6 +327,8 @@ void RenderPolyWall::Render(PolyRenderThread *thread, const TriMatrix &worldToCl
args.SetTexture(Texture); args.SetTexture(Texture);
args.SetClipPlane(0, clipPlane); args.SetClipPlane(0, clipPlane);
SetDynLights(thread, args);
if (FogBoundary) if (FogBoundary)
{ {
args.SetStyle(TriBlendMode::FogBoundary); args.SetStyle(TriBlendMode::FogBoundary);
@ -365,6 +368,64 @@ void RenderPolyWall::Render(PolyRenderThread *thread, const TriMatrix &worldToCl
RenderPolyDecal::RenderWallDecals(thread, worldToClip, clipPlane, LineSeg, StencilValue); 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) void RenderPolyWall::DrawStripes(PolyRenderThread *thread, PolyDrawArgs &args, TriVertex *vertices)
{ {
const auto &lightlist = Line->frontsector->e->XFloor.lightlist; const auto &lightlist = Line->frontsector->e->XFloor.lightlist;

View File

@ -68,6 +68,8 @@ private:
int GetLightLevel(); int GetLightLevel();
void DrawStripes(PolyRenderThread *thread, PolyDrawArgs &args, TriVertex *vertices); void DrawStripes(PolyRenderThread *thread, PolyDrawArgs &args, TriVertex *vertices);
void SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args);
static bool IsFogBoundary(sector_t *front, sector_t *back); static bool IsFogBoundary(sector_t *front, sector_t *back);
static FTexture *GetTexture(const line_t *Line, const side_t *Side, side_t::ETexpart texpart); static FTexture *GetTexture(const line_t *Line, const side_t *Side, side_t::ETexpart texpart);
}; };