mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-11 07:11:54 +00:00
- Attenuated lights support
This commit is contained in:
parent
e15a84f062
commit
789214200c
5 changed files with 31 additions and 8 deletions
|
@ -130,6 +130,9 @@ public:
|
||||||
PolyLight *Lights() const { return mLights; }
|
PolyLight *Lights() const { return mLights; }
|
||||||
int NumLights() const { return mNumLights; }
|
int NumLights() const { return mNumLights; }
|
||||||
|
|
||||||
|
const FVector3 &Normal() const { return mNormal; }
|
||||||
|
void SetNormal(const FVector3 &normal) { mNormal = normal; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const TriMatrix *mObjectToClip = nullptr;
|
const TriMatrix *mObjectToClip = nullptr;
|
||||||
const TriVertex *mVertices = nullptr;
|
const TriVertex *mVertices = nullptr;
|
||||||
|
@ -168,6 +171,7 @@ private:
|
||||||
bool mFixedLight = false;
|
bool mFixedLight = false;
|
||||||
PolyLight *mLights = nullptr;
|
PolyLight *mLights = nullptr;
|
||||||
int mNumLights = 0;
|
int mNumLights = 0;
|
||||||
|
FVector3 mNormal;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RectDrawArgs
|
class RectDrawArgs
|
||||||
|
|
|
@ -180,9 +180,10 @@ namespace TriScreenDrawerModes
|
||||||
__m128 simple_attenuation = distance_attenuation;
|
__m128 simple_attenuation = distance_attenuation;
|
||||||
|
|
||||||
// The point light type
|
// The point light type
|
||||||
// diffuse = dot(N,L) * attenuation
|
// diffuse = max(dot(N,normalize(L)),0) * attenuation
|
||||||
__m128 dotNL = _mm_mul_ps(worldnormal, L);
|
__m128 dotNL = _mm_mul_ps(worldnormal, _mm_mul_ps(L, _mm_shuffle_ps(rcp_dist, rcp_dist, _MM_SHUFFLE(0, 0, 0, 0))));
|
||||||
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))));
|
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))));
|
||||||
|
dotNL = _mm_max_ss(dotNL, _mm_setzero_ps());
|
||||||
__m128 point_attenuation = _mm_mul_ss(dotNL, distance_attenuation);
|
__m128 point_attenuation = _mm_mul_ss(dotNL, distance_attenuation);
|
||||||
point_attenuation = _mm_shuffle_ps(point_attenuation, point_attenuation, _MM_SHUFFLE(0, 0, 0, 0));
|
point_attenuation = _mm_shuffle_ps(point_attenuation, point_attenuation, _MM_SHUFFLE(0, 0, 0, 0));
|
||||||
|
|
||||||
|
@ -394,7 +395,7 @@ private:
|
||||||
|
|
||||||
auto lights = args->uniforms->Lights();
|
auto lights = args->uniforms->Lights();
|
||||||
auto num_lights = args->uniforms->NumLights();
|
auto num_lights = args->uniforms->NumLights();
|
||||||
__m128 worldnormal = _mm_setzero_ps();
|
__m128 worldnormal = _mm_setr_ps(args->uniforms->Normal().X, args->uniforms->Normal().Y, args->uniforms->Normal().Z, 0.0f);
|
||||||
|
|
||||||
// Calculate gradients
|
// Calculate gradients
|
||||||
const ShadedTriVertex &v1 = *args->v1;
|
const ShadedTriVertex &v1 = *args->v1;
|
||||||
|
|
|
@ -254,7 +254,7 @@ void RenderPolyPlane::Render(PolyRenderThread *thread, const TriMatrix &worldToC
|
||||||
|
|
||||||
if (!isSky)
|
if (!isSky)
|
||||||
{
|
{
|
||||||
SetDynLights(thread, args, sub);
|
SetDynLights(thread, args, sub, ceiling);
|
||||||
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);
|
||||||
|
@ -279,7 +279,7 @@ void RenderPolyPlane::Render(PolyRenderThread *thread, const TriMatrix &worldToC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderPolyPlane::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub)
|
void RenderPolyPlane::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, bool ceiling)
|
||||||
{
|
{
|
||||||
FLightNode *light_list = sub->lighthead;
|
FLightNode *light_list = sub->lighthead;
|
||||||
|
|
||||||
|
@ -315,7 +315,7 @@ void RenderPolyPlane::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args,
|
||||||
{
|
{
|
||||||
if (!(cur_node->lightsource->flags2&MF2_DORMANT))
|
if (!(cur_node->lightsource->flags2&MF2_DORMANT))
|
||||||
{
|
{
|
||||||
//bool is_point_light = (cur_node->lightsource->lightflags & LF_ATTENUATE) != 0;
|
bool is_point_light = (cur_node->lightsource->lightflags & LF_ATTENUATE) != 0;
|
||||||
|
|
||||||
// To do: cull lights not touching subsector
|
// To do: cull lights not touching subsector
|
||||||
|
|
||||||
|
@ -329,12 +329,17 @@ void RenderPolyPlane::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args,
|
||||||
light.z = (float)cur_node->lightsource->Z();
|
light.z = (float)cur_node->lightsource->Z();
|
||||||
light.radius = 256.0f / cur_node->lightsource->GetRadius();
|
light.radius = 256.0f / cur_node->lightsource->GetRadius();
|
||||||
light.color = (red << 16) | (green << 8) | blue;
|
light.color = (red << 16) | (green << 8) | blue;
|
||||||
|
if (is_point_light)
|
||||||
|
light.radius = -light.radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_node = cur_node->nextLight;
|
cur_node = cur_node->nextLight;
|
||||||
}
|
}
|
||||||
|
|
||||||
args.SetLights(dc_lights, dc_num_lights);
|
args.SetLights(dc_lights, dc_num_lights);
|
||||||
|
|
||||||
|
DVector3 normal = ceiling ? sub->sector->ceilingplane.Normal() : sub->sector->floorplane.Normal();
|
||||||
|
args.SetNormal({ (float)normal.X, (float)normal.Y, (float)normal.Z });
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|
|
@ -62,7 +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);
|
void SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, bool ceiling);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Render3DFloorPlane
|
class Render3DFloorPlane
|
||||||
|
|
|
@ -404,7 +404,7 @@ void RenderPolyWall::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args)
|
||||||
{
|
{
|
||||||
if (!(cur_node->lightsource->flags2&MF2_DORMANT))
|
if (!(cur_node->lightsource->flags2&MF2_DORMANT))
|
||||||
{
|
{
|
||||||
//bool is_point_light = (cur_node->lightsource->lightflags & LF_ATTENUATE) != 0;
|
bool is_point_light = (cur_node->lightsource->lightflags & LF_ATTENUATE) != 0;
|
||||||
|
|
||||||
// To do: cull lights not touching wall
|
// To do: cull lights not touching wall
|
||||||
|
|
||||||
|
@ -418,12 +418,25 @@ void RenderPolyWall::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args)
|
||||||
light.z = (float)cur_node->lightsource->Z();
|
light.z = (float)cur_node->lightsource->Z();
|
||||||
light.radius = 256.0f / cur_node->lightsource->GetRadius();
|
light.radius = 256.0f / cur_node->lightsource->GetRadius();
|
||||||
light.color = (red << 16) | (green << 8) | blue;
|
light.color = (red << 16) | (green << 8) | blue;
|
||||||
|
if (is_point_light)
|
||||||
|
light.radius = -light.radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_node = cur_node->nextLight;
|
cur_node = cur_node->nextLight;
|
||||||
}
|
}
|
||||||
|
|
||||||
args.SetLights(dc_lights, dc_num_lights);
|
args.SetLights(dc_lights, dc_num_lights);
|
||||||
|
|
||||||
|
// Face normal:
|
||||||
|
float dx = (float)(v2.X - v1.X);
|
||||||
|
float dy = (float)(v2.Y - v1.Y);
|
||||||
|
float nx = dy;
|
||||||
|
float ny = -dx;
|
||||||
|
float lensqr = nx * nx + ny * ny;
|
||||||
|
float rcplen = 1.0f / sqrt(lensqr);
|
||||||
|
nx *= rcplen;
|
||||||
|
ny *= rcplen;
|
||||||
|
args.SetNormal({ nx, ny, 0.0f });
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderPolyWall::DrawStripes(PolyRenderThread *thread, PolyDrawArgs &args, TriVertex *vertices)
|
void RenderPolyWall::DrawStripes(PolyRenderThread *thread, PolyDrawArgs &args, TriVertex *vertices)
|
||||||
|
|
Loading…
Reference in a new issue