mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-11 23:32:02 +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;
|
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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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++)
|
||||||
|
|
|
@ -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>> §orPortals);
|
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 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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue