From 99f2b5d8918e82056a19700f8e7a696b132220f0 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 19 Feb 2023 01:01:24 +0100 Subject: [PATCH] Fix misc bugs for dynamic lights in the pal slope drawer --- .../swrenderer/drawers/r_draw_pal.cpp | 21 ++++++---- .../swrenderer/plane/r_slopeplane.cpp | 42 +++++++++---------- .../swrenderer/viewport/r_viewport.cpp | 4 +- 3 files changed, 35 insertions(+), 32 deletions(-) diff --git a/src/rendering/swrenderer/drawers/r_draw_pal.cpp b/src/rendering/swrenderer/drawers/r_draw_pal.cpp index 3aca6797a2..9f1b197ef1 100644 --- a/src/rendering/swrenderer/drawers/r_draw_pal.cpp +++ b/src/rendering/swrenderer/drawers/r_draw_pal.cpp @@ -1823,7 +1823,7 @@ namespace swrenderer // Screen space to view space viewpos_z = 1.0f / viewpos_z; viewpos_x *= viewpos_z; - viewpos_y *= viewpos_y; + viewpos_y *= viewpos_z; for (int i = 0; i < num_lights; i++) { @@ -1843,8 +1843,15 @@ namespace swrenderer #else float rcp_dist = _mm_cvtss_f32(_mm_rsqrt_ss(_mm_load_ss(&dist2))); #endif + Lx *= rcp_dist; + Ly *= rcp_dist; + Lz *= rcp_dist; float dist = dist2 * rcp_dist; - float distance_attenuation = (256.0f - min(dist * lights[i].radius, 256.0f)); + float radius = lights[i].radius; + bool simpleType = radius < 0.0f; + if (simpleType) + radius = -radius; + float distance_attenuation = (256.0f - min(dist * radius, 256.0f)); // The simple light type float simple_attenuation = distance_attenuation; @@ -1852,8 +1859,8 @@ namespace swrenderer // The point light type // diffuse = dot(N,L) * attenuation float dotNL = max(nx * Lx + ny * Ly + nz * Lz, 0.0f); - float point_attenuation = dotNL * rcp_dist * distance_attenuation; - uint32_t attenuation = (uint32_t)(lights[i].z == 0.0f ? simple_attenuation : point_attenuation); + float point_attenuation = dotNL * distance_attenuation; + uint32_t attenuation = (uint32_t)(simpleType ? simple_attenuation : point_attenuation); lit_r += (light_color_r * attenuation) >> 8; lit_g += (light_color_g * attenuation) >> 8; @@ -2855,7 +2862,7 @@ namespace swrenderer auto num_lights = args.dc_num_lights; auto normal = args.dc_normal; auto viewpos = args.dc_viewpos; - auto dc_viewpos_step = args.dc_viewpos_step; + auto viewpos_step = args.dc_viewpos_step; while (width >= SPANSIZE) { iz += izstep; @@ -2878,7 +2885,7 @@ namespace swrenderer x1++; u += stepu; v += stepv; - viewpos += dc_viewpos_step; + viewpos += viewpos_step; } startu = endu; startv = endv; @@ -2918,7 +2925,7 @@ namespace swrenderer x1++; u += stepu; v += stepv; - viewpos += dc_viewpos_step; + viewpos += viewpos_step; } } } diff --git a/src/rendering/swrenderer/plane/r_slopeplane.cpp b/src/rendering/swrenderer/plane/r_slopeplane.cpp index d35901a549..808a1a0b73 100644 --- a/src/rendering/swrenderer/plane/r_slopeplane.cpp +++ b/src/rendering/swrenderer/plane/r_slopeplane.cpp @@ -88,11 +88,14 @@ namespace swrenderer auto viewport = Thread->Viewport.get(); - DVector3 worldNormal = pl->height.Normal(); - planeNormal.X = worldNormal.X * viewport->viewpoint.Sin - worldNormal.Y * viewport->viewpoint.Cos; - planeNormal.Y = worldNormal.X * viewport->viewpoint.Cos + worldNormal.Y * viewport->viewpoint.Sin; - planeNormal.Z = worldNormal.Z; - planeD = -planeNormal.Z * (pl->height.ZatPoint(viewport->viewpoint.Pos.X, viewport->viewpoint.Pos.Y) - viewport->viewpoint.Pos.Z); + // Stupid way of doing it, but at least it works + DVector3 worldP0(viewport->viewpoint.Pos, pl->height.ZatPoint(viewport->viewpoint.Pos)); + DVector3 worldP1 = worldP0 + pl->height.Normal(); + DVector3 viewP0 = viewport->PointWorldToView(worldP0); + DVector3 viewP1 = viewport->PointWorldToView(worldP1); + planeNormal = viewP1 - viewP0; + planeD = -(viewP0 | planeNormal); + if (Thread->Portal->MirrorFlags & RF_XFLIP) planeNormal.X = -planeNormal.X; @@ -209,11 +212,6 @@ namespace swrenderer { if (r_dynlights) { - int tx = x1; - bool mirror = !!(Thread->Portal->MirrorFlags & RF_XFLIP); - if (mirror) - tx = viewwidth - tx - 1; - // Find row position in view space DVector3 viewposX1 = Thread->Viewport->ScreenToViewPos(x1, y, planeNormal, planeD); DVector3 viewposX2 = Thread->Viewport->ScreenToViewPos(x2, y, planeNormal, planeD); @@ -229,9 +227,9 @@ namespace swrenderer drawerargs.dc_viewpos.X = viewposX1.X; drawerargs.dc_viewpos.Y = viewposX1.Y; drawerargs.dc_viewpos.Z = viewposX1.Z; - drawerargs.dc_viewpos_step.X = viewposX2.X - viewposX1.X; - drawerargs.dc_viewpos_step.Y = viewposX2.Y - viewposX1.Y; - drawerargs.dc_viewpos_step.Z = viewposX2.Z - viewposX1.Z; + drawerargs.dc_viewpos_step.X = (viewposX2.X - viewposX1.X) / (x2 - x1); + drawerargs.dc_viewpos_step.Y = (viewposX2.Y - viewposX1.Y) / (x2 - x1); + drawerargs.dc_viewpos_step.Z = (viewposX2.Z - viewposX1.Z) / (x2 - x1); // Plane normal drawerargs.dc_normal.X = planeNormal.X; @@ -257,24 +255,22 @@ namespace swrenderer { if (cur_node->lightsource->IsActive()) { - double lightX = cur_node->lightsource->X() - Thread->Viewport->viewpoint.Pos.X; - double lightY = cur_node->lightsource->Y() - Thread->Viewport->viewpoint.Pos.Y; - double lightZ = cur_node->lightsource->Z() - Thread->Viewport->viewpoint.Pos.Z; - - float lx = (float)(lightX * Thread->Viewport->viewpoint.Sin - lightY * Thread->Viewport->viewpoint.Cos); - float ly = (float)(lightX * Thread->Viewport->viewpoint.TanCos + lightY * Thread->Viewport->viewpoint.TanSin); - float lz = (float)lightZ; + DVector3 lightPos = Thread->Viewport->PointWorldToView(cur_node->lightsource->Pos); uint32_t red = cur_node->lightsource->GetRed(); uint32_t green = cur_node->lightsource->GetGreen(); uint32_t blue = cur_node->lightsource->GetBlue(); auto& light = drawerargs.dc_lights[drawerargs.dc_num_lights++]; - light.x = lx; - light.y = ly; - light.z = lz; + light.x = lightPos.X; + light.y = lightPos.Y; + light.z = lightPos.Z; light.radius = 256.0f / cur_node->lightsource->GetRadius(); light.color = (red << 16) | (green << 8) | blue; + + bool is_point_light = cur_node->lightsource->IsAttenuated(); + if (is_point_light) + light.radius = -light.radius; } cur_node = cur_node->next; diff --git a/src/rendering/swrenderer/viewport/r_viewport.cpp b/src/rendering/swrenderer/viewport/r_viewport.cpp index 63606d4677..5778951c5e 100644 --- a/src/rendering/swrenderer/viewport/r_viewport.cpp +++ b/src/rendering/swrenderer/viewport/r_viewport.cpp @@ -254,7 +254,7 @@ namespace swrenderer double translatedY = worldPos.Y - viewpoint.Pos.Y; return { translatedX * viewpoint.Sin - translatedY * viewpoint.Cos, - translatedX * viewpoint.TanCos + translatedY * viewpoint.TanSin + translatedX * viewpoint.Cos + translatedY * viewpoint.Sin }; } @@ -266,7 +266,7 @@ namespace swrenderer return { translatedX * viewpoint.Sin - translatedY * viewpoint.Cos, translatedZ, - translatedX * viewpoint.TanCos + translatedY * viewpoint.TanSin + translatedX * viewpoint.Cos + translatedY * viewpoint.Sin }; }