From 4f7c1dfdf51e8ca0af6bb8590f688f9b759042e8 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Thu, 22 Dec 2016 08:42:21 +0100 Subject: [PATCH] Dynamic lights on flats --- src/r_draw_rgba.cpp | 5 +++ src/r_drawers.h | 4 ++ src/r_plane.cpp | 10 ++--- src/r_walldraw.cpp | 2 +- .../fixedfunction/drawspancodegen.cpp | 44 ++++++++++++++++++- .../drawergen/fixedfunction/drawspancodegen.h | 9 +++- tools/drawergen/llvmdrawers.cpp | 4 ++ 7 files changed, 69 insertions(+), 9 deletions(-) diff --git a/src/r_draw_rgba.cpp b/src/r_draw_rgba.cpp index 9f8a0c312..a9fc5c80e 100644 --- a/src/r_draw_rgba.cpp +++ b/src/r_draw_rgba.cpp @@ -100,6 +100,11 @@ namespace swrenderer args.flags |= DrawSpanArgs::simple_shade; if (!sampler_setup(args.source, args.xbits, args.ybits, ds_source_mipmapped)) args.flags |= DrawSpanArgs::nearest_filter; + + args.viewpos_x = dc_viewpos.X; + args.step_viewpos_x = dc_viewpos_step.X; + args.dynlights = dc_lights; + args.num_dynlights = dc_num_lights; } void DrawSpanLLVMCommand::Execute(DrawerThread *thread) diff --git a/src/r_drawers.h b/src/r_drawers.h index eff6ea370..2ff2fd087 100644 --- a/src/r_drawers.h +++ b/src/r_drawers.h @@ -139,6 +139,10 @@ struct DrawSpanArgs nearest_filter = 2 }; + float viewpos_x, step_viewpos_x; + TriLight *dynlights; + uint32_t num_dynlights; + FString ToString(); }; diff --git a/src/r_plane.cpp b/src/r_plane.cpp index bb42cadef..48a5bcb0f 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -259,11 +259,11 @@ void R_MapPlane (int y, int x1) if (r_swtruecolor) { // Find row position in view space - float zspan = (float)((CenterY - y - 0.5) * InvZtoScale / planeheight); + float zspan = planeheight / (fabs(y + 0.5 - CenterY) / InvZtoScale); dc_viewpos.X = (float)((x1 + 0.5 - CenterX) / CenterX * zspan); dc_viewpos.Y = zspan; - dc_viewpos.Z = (float)planeheight; - dc_viewpos_step.X = (float)(-zspan / InvZtoScale); + dc_viewpos.Z = (float)((CenterY - y - 0.5) / InvZtoScale * zspan); + dc_viewpos_step.X = (float)(zspan / CenterX); static TriLight lightbuffer[64 * 1024]; static int nextlightindex = 0; @@ -286,9 +286,9 @@ void R_MapPlane (int y, int x1) auto &light = dc_lights[dc_num_lights++]; light.x = (float)(lightX * ViewSin - lightY * ViewCos); light.y = (float)(lightX * ViewTanCos + lightY * ViewTanSin) - dc_viewpos.Y; - light.z = (float)(lightZ - dc_viewpos.Z); + light.z = (float)lightZ - dc_viewpos.Z; light.radius = 256.0f / cur_node->lightsource->GetRadius(); - light.color = 0xff000000 | (red << 16) | (green << 8) | blue; + light.color = (red << 16) | (green << 8) | blue; // Precalculate the constant part of the dot here so the drawer doesn't have to. light.y = light.y * light.y + light.z * light.z; diff --git a/src/r_walldraw.cpp b/src/r_walldraw.cpp index ad73c1fa5..f43b8f9d4 100644 --- a/src/r_walldraw.cpp +++ b/src/r_walldraw.cpp @@ -575,7 +575,7 @@ static void Draw1Column(int x, int y1, int y2, WallSampler &sampler, void(*draw1 light.y = (float)(lightX * ViewTanCos + lightY * ViewTanSin) - dc_viewpos.Y; light.z = (float)lightZ; light.radius = 256.0f / cur_node->lightsource->GetRadius(); - light.color = 0xff000000 | (red << 16) | (green << 8) | blue; + light.color = (red << 16) | (green << 8) | blue; // Precalculate the constant part of the dot here so the drawer doesn't have to. light.x = light.x * light.x + light.y * light.y; diff --git a/tools/drawergen/fixedfunction/drawspancodegen.cpp b/tools/drawergen/fixedfunction/drawspancodegen.cpp index c6aacc75a..ce6ce9bad 100644 --- a/tools/drawergen/fixedfunction/drawspancodegen.cpp +++ b/tools/drawergen/fixedfunction/drawspancodegen.cpp @@ -59,6 +59,10 @@ void DrawSpanCodegen::Generate(DrawSpanVariant variant, SSAValue args) SSAShort fade_blue = args[0][22].load(true); SSAShort desaturate = args[0][23].load(true); SSAInt flags = args[0][24].load(true); + start_viewpos_x = args[0][25].load(true); + step_viewpos_x = args[0][26].load(true); + dynlights = args[0][27].load(true); + num_dynlights = args[0][28].load(true); shade_constants.light = SSAVec4i(light_blue.zext_int(), light_green.zext_int(), light_red.zext_int(), light_alpha.zext_int()); shade_constants.fade = SSAVec4i(fade_blue.zext_int(), fade_green.zext_int(), fade_red.zext_int(), fade_alpha.zext_int()); shade_constants.desaturate = desaturate.zext_int(); @@ -115,6 +119,7 @@ SSAInt DrawSpanCodegen::Loop4x(DrawSpanVariant variant, bool isSimpleShade, bool { SSAInt sseLength = count / 4; stack_index.store(SSAInt(0)); + stack_viewpos_x.store(start_viewpos_x); { SSAForBlock loop; SSAInt index = stack_index.load(); @@ -136,9 +141,11 @@ SSAInt DrawSpanCodegen::Loop4x(DrawSpanVariant variant, bool isSimpleShade, bool { SSAInt xfrac = stack_xfrac.load(); SSAInt yfrac = stack_yfrac.load(); + viewpos_x = stack_viewpos_x.load(); colors[i] = Blend(Shade(Sample(xfrac, yfrac, isNearestFilter, is64x64), isSimpleShade), bgcolors[i], variant); + stack_viewpos_x.store(viewpos_x + step_viewpos_x); stack_xfrac.store(xfrac + xstep); stack_yfrac.store(yfrac + ystep); } @@ -158,6 +165,7 @@ void DrawSpanCodegen::Loop(SSAInt start, DrawSpanVariant variant, bool isSimpleS { SSAForBlock loop; SSAInt index = stack_index.load(); + viewpos_x = stack_viewpos_x.load(); loop.loop_block(index < count); SSAInt xfrac = stack_xfrac.load(); @@ -167,6 +175,7 @@ void DrawSpanCodegen::Loop(SSAInt start, DrawSpanVariant variant, bool isSimpleS SSAVec4i color = Blend(Shade(Sample(xfrac, yfrac, isNearestFilter, is64x64), isSimpleShade), bgcolor, variant); data[index * 4].store_vec4ub(color); + stack_viewpos_x.store(viewpos_x + step_viewpos_x); stack_index.store(index.add(SSAInt(1), true, true)); stack_xfrac.store(xfrac + xstep); stack_yfrac.store(yfrac + ystep); @@ -222,10 +231,41 @@ SSAVec4i DrawSpanCodegen::SampleLinear(SSAUBytePtr texture, SSAInt xfrac, SSAInt SSAVec4i DrawSpanCodegen::Shade(SSAVec4i fg, bool isSimpleShade) { + SSAVec4i c; if (isSimpleShade) - return shade_bgra_simple(fg, light); + c = shade_bgra_simple(fg, light); else - return shade_bgra_advanced(fg, light, shade_constants); + c = shade_bgra_advanced(fg, light, shade_constants); + + stack_lit_color.store(c); + stack_light_index.store(SSAInt(0)); + + SSAForBlock block; + SSAInt light_index = stack_light_index.load(); + SSAVec4i lit_color = stack_lit_color.load(); + block.loop_block(light_index < num_dynlights); + { + SSAVec4i light_color = SSAUBytePtr(dynlights[light_index][0].v).load_vec4ub(true); + SSAFloat light_x = dynlights[light_index][1].load(true); + SSAFloat light_y = dynlights[light_index][2].load(true); + //SSAFloat light_z = dynlights[light_index][3].load(true); + SSAFloat light_rcp_radius = dynlights[light_index][4].load(true); + + // L = light-pos + // dist = sqrt(dot(L, L)) + // attenuation = 1 - MIN(dist * (1/radius), 1) + SSAFloat Lyz2 = light_y; // L.y*L.y + L.z*L.z + SSAFloat Lx = light_x - viewpos_x; + SSAFloat dist = SSAFloat::sqrt(Lyz2 + Lx * Lx); + SSAInt attenuation = SSAInt(SSAFloat(256.0f) - SSAFloat::MIN(dist * light_rcp_radius, SSAFloat(256.0f)), true); + SSAVec4i contribution = (light_color * fg * attenuation) >> 16; + + stack_lit_color.store(lit_color + contribution); + stack_light_index.store(light_index + 1); + } + block.end_block(); + + return stack_lit_color.load(); } SSAVec4i DrawSpanCodegen::Blend(SSAVec4i fg, SSAVec4i bg, DrawSpanVariant variant) diff --git a/tools/drawergen/fixedfunction/drawspancodegen.h b/tools/drawergen/fixedfunction/drawspancodegen.h index 48c86040b..9e0c67c41 100644 --- a/tools/drawergen/fixedfunction/drawspancodegen.h +++ b/tools/drawergen/fixedfunction/drawspancodegen.h @@ -49,7 +49,9 @@ private: SSAVec4i Shade(SSAVec4i fg, bool isSimpleShade); SSAVec4i Blend(SSAVec4i fg, SSAVec4i bg, DrawSpanVariant variant); - SSAStack stack_index, stack_xfrac, stack_yfrac; + SSAStack stack_index, stack_xfrac, stack_yfrac, stack_light_index; + SSAStack stack_lit_color; + SSAStack stack_viewpos_x; SSAUBytePtr destorg; SSAUBytePtr source; @@ -73,4 +75,9 @@ private: SSABool is_simple_shade; SSABool is_nearest_filter; SSAShadeConstants shade_constants; + + SSAFloat start_viewpos_x, step_viewpos_x; + SSAValue dynlights; // TriLight* + SSAInt num_dynlights; + SSAFloat viewpos_x; }; diff --git a/tools/drawergen/llvmdrawers.cpp b/tools/drawergen/llvmdrawers.cpp index f8c5da875..5c3bf05a4 100644 --- a/tools/drawergen/llvmdrawers.cpp +++ b/tools/drawergen/llvmdrawers.cpp @@ -265,6 +265,10 @@ llvm::Type *LLVMDrawers::GetDrawSpanArgsStruct(llvm::LLVMContext &context) elements.push_back(llvm::Type::getInt16Ty(context)); // uint16_t fade_blue; elements.push_back(llvm::Type::getInt16Ty(context)); // uint16_t desaturate; elements.push_back(llvm::Type::getInt32Ty(context)); // uint32_t flags; + elements.push_back(llvm::Type::getFloatTy(context)); // float viewpos_x; + elements.push_back(llvm::Type::getFloatTy(context)); // float step_viewpos_x; + elements.push_back(GetTriLightStruct(context)); // TriLight *dynlights; + elements.push_back(llvm::Type::getInt32Ty(context)); // uint32_t num_dynlights; DrawSpanArgsStruct = llvm::StructType::create(context, elements, "DrawSpanArgs", false)->getPointerTo(); return DrawSpanArgsStruct; }