Fix misc bugs for dynamic lights in the pal slope drawer

This commit is contained in:
Magnus Norddahl 2023-02-19 01:01:24 +01:00 committed by Christoph Oelckers
parent 18bc384807
commit 99f2b5d891
3 changed files with 35 additions and 32 deletions

View file

@ -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;
}
}
}

View file

@ -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;

View file

@ -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
};
}