diff --git a/src/polyrenderer/drawers/poly_draw_args.h b/src/polyrenderer/drawers/poly_draw_args.h index 6417669a0..c3a685c88 100644 --- a/src/polyrenderer/drawers/poly_draw_args.h +++ b/src/polyrenderer/drawers/poly_draw_args.h @@ -130,6 +130,9 @@ public: PolyLight *Lights() const { return mLights; } int NumLights() const { return mNumLights; } + const FVector3 &Normal() const { return mNormal; } + void SetNormal(const FVector3 &normal) { mNormal = normal; } + private: const TriMatrix *mObjectToClip = nullptr; const TriVertex *mVertices = nullptr; @@ -168,6 +171,7 @@ private: bool mFixedLight = false; PolyLight *mLights = nullptr; int mNumLights = 0; + FVector3 mNormal; }; class RectDrawArgs diff --git a/src/polyrenderer/drawers/poly_drawer32_sse2.h b/src/polyrenderer/drawers/poly_drawer32_sse2.h index 0f69f5a4d..f4d3cb392 100644 --- a/src/polyrenderer/drawers/poly_drawer32_sse2.h +++ b/src/polyrenderer/drawers/poly_drawer32_sse2.h @@ -180,9 +180,10 @@ namespace TriScreenDrawerModes __m128 simple_attenuation = distance_attenuation; // The point light type - // diffuse = dot(N,L) * attenuation - __m128 dotNL = _mm_mul_ps(worldnormal, L); + // diffuse = max(dot(N,normalize(L)),0) * attenuation + __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_max_ss(dotNL, _mm_setzero_ps()); __m128 point_attenuation = _mm_mul_ss(dotNL, distance_attenuation); 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 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 const ShadedTriVertex &v1 = *args->v1; diff --git a/src/polyrenderer/scene/poly_plane.cpp b/src/polyrenderer/scene/poly_plane.cpp index 766d4260b..2ec86327e 100644 --- a/src/polyrenderer/scene/poly_plane.cpp +++ b/src/polyrenderer/scene/poly_plane.cpp @@ -254,7 +254,7 @@ void RenderPolyPlane::Render(PolyRenderThread *thread, const TriMatrix &worldToC if (!isSky) { - SetDynLights(thread, args, sub); + SetDynLights(thread, args, sub, ceiling); args.SetTexture(tex); args.SetStyle(TriBlendMode::TextureOpaque); 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; @@ -315,7 +315,7 @@ void RenderPolyPlane::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args, { 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 @@ -329,12 +329,17 @@ void RenderPolyPlane::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args, light.z = (float)cur_node->lightsource->Z(); light.radius = 256.0f / cur_node->lightsource->GetRadius(); light.color = (red << 16) | (green << 8) | blue; + if (is_point_light) + light.radius = -light.radius; } cur_node = cur_node->nextLight; } 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) diff --git a/src/polyrenderer/scene/poly_plane.h b/src/polyrenderer/scene/poly_plane.h index 2293f4f63..74db247e6 100644 --- a/src/polyrenderer/scene/poly_plane.h +++ b/src/polyrenderer/scene/poly_plane.h @@ -62,7 +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> §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); + void SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, bool ceiling); }; class Render3DFloorPlane diff --git a/src/polyrenderer/scene/poly_wall.cpp b/src/polyrenderer/scene/poly_wall.cpp index c90052b22..aba99a85a 100644 --- a/src/polyrenderer/scene/poly_wall.cpp +++ b/src/polyrenderer/scene/poly_wall.cpp @@ -404,7 +404,7 @@ void RenderPolyWall::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args) { 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 @@ -418,12 +418,25 @@ void RenderPolyWall::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args) light.z = (float)cur_node->lightsource->Z(); light.radius = 256.0f / cur_node->lightsource->GetRadius(); light.color = (red << 16) | (green << 8) | blue; + if (is_point_light) + light.radius = -light.radius; } cur_node = cur_node->nextLight; } 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)