Dynamic lights on flats

This commit is contained in:
Magnus Norddahl 2016-12-22 08:42:21 +01:00
parent fcbacf8cac
commit 4f7c1dfdf5
7 changed files with 69 additions and 9 deletions

View file

@ -100,6 +100,11 @@ namespace swrenderer
args.flags |= DrawSpanArgs::simple_shade; args.flags |= DrawSpanArgs::simple_shade;
if (!sampler_setup(args.source, args.xbits, args.ybits, ds_source_mipmapped)) if (!sampler_setup(args.source, args.xbits, args.ybits, ds_source_mipmapped))
args.flags |= DrawSpanArgs::nearest_filter; 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) void DrawSpanLLVMCommand::Execute(DrawerThread *thread)

View file

@ -139,6 +139,10 @@ struct DrawSpanArgs
nearest_filter = 2 nearest_filter = 2
}; };
float viewpos_x, step_viewpos_x;
TriLight *dynlights;
uint32_t num_dynlights;
FString ToString(); FString ToString();
}; };

View file

@ -259,11 +259,11 @@ void R_MapPlane (int y, int x1)
if (r_swtruecolor) if (r_swtruecolor)
{ {
// Find row position in view space // 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.X = (float)((x1 + 0.5 - CenterX) / CenterX * zspan);
dc_viewpos.Y = zspan; dc_viewpos.Y = zspan;
dc_viewpos.Z = (float)planeheight; dc_viewpos.Z = (float)((CenterY - y - 0.5) / InvZtoScale * zspan);
dc_viewpos_step.X = (float)(-zspan / InvZtoScale); dc_viewpos_step.X = (float)(zspan / CenterX);
static TriLight lightbuffer[64 * 1024]; static TriLight lightbuffer[64 * 1024];
static int nextlightindex = 0; static int nextlightindex = 0;
@ -286,9 +286,9 @@ void R_MapPlane (int y, int x1)
auto &light = dc_lights[dc_num_lights++]; auto &light = dc_lights[dc_num_lights++];
light.x = (float)(lightX * ViewSin - lightY * ViewCos); light.x = (float)(lightX * ViewSin - lightY * ViewCos);
light.y = (float)(lightX * ViewTanCos + lightY * ViewTanSin) - dc_viewpos.Y; 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.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. // 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; light.y = light.y * light.y + light.z * light.z;

View file

@ -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.y = (float)(lightX * ViewTanCos + lightY * ViewTanSin) - dc_viewpos.Y;
light.z = (float)lightZ; light.z = (float)lightZ;
light.radius = 256.0f / cur_node->lightsource->GetRadius(); 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. // 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; light.x = light.x * light.x + light.y * light.y;

View file

@ -59,6 +59,10 @@ void DrawSpanCodegen::Generate(DrawSpanVariant variant, SSAValue args)
SSAShort fade_blue = args[0][22].load(true); SSAShort fade_blue = args[0][22].load(true);
SSAShort desaturate = args[0][23].load(true); SSAShort desaturate = args[0][23].load(true);
SSAInt flags = args[0][24].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.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.fade = SSAVec4i(fade_blue.zext_int(), fade_green.zext_int(), fade_red.zext_int(), fade_alpha.zext_int());
shade_constants.desaturate = desaturate.zext_int(); shade_constants.desaturate = desaturate.zext_int();
@ -115,6 +119,7 @@ SSAInt DrawSpanCodegen::Loop4x(DrawSpanVariant variant, bool isSimpleShade, bool
{ {
SSAInt sseLength = count / 4; SSAInt sseLength = count / 4;
stack_index.store(SSAInt(0)); stack_index.store(SSAInt(0));
stack_viewpos_x.store(start_viewpos_x);
{ {
SSAForBlock loop; SSAForBlock loop;
SSAInt index = stack_index.load(); SSAInt index = stack_index.load();
@ -136,9 +141,11 @@ SSAInt DrawSpanCodegen::Loop4x(DrawSpanVariant variant, bool isSimpleShade, bool
{ {
SSAInt xfrac = stack_xfrac.load(); SSAInt xfrac = stack_xfrac.load();
SSAInt yfrac = stack_yfrac.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); 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_xfrac.store(xfrac + xstep);
stack_yfrac.store(yfrac + ystep); stack_yfrac.store(yfrac + ystep);
} }
@ -158,6 +165,7 @@ void DrawSpanCodegen::Loop(SSAInt start, DrawSpanVariant variant, bool isSimpleS
{ {
SSAForBlock loop; SSAForBlock loop;
SSAInt index = stack_index.load(); SSAInt index = stack_index.load();
viewpos_x = stack_viewpos_x.load();
loop.loop_block(index < count); loop.loop_block(index < count);
SSAInt xfrac = stack_xfrac.load(); 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); SSAVec4i color = Blend(Shade(Sample(xfrac, yfrac, isNearestFilter, is64x64), isSimpleShade), bgcolor, variant);
data[index * 4].store_vec4ub(color); 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_index.store(index.add(SSAInt(1), true, true));
stack_xfrac.store(xfrac + xstep); stack_xfrac.store(xfrac + xstep);
stack_yfrac.store(yfrac + ystep); 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 DrawSpanCodegen::Shade(SSAVec4i fg, bool isSimpleShade)
{ {
SSAVec4i c;
if (isSimpleShade) if (isSimpleShade)
return shade_bgra_simple(fg, light); c = shade_bgra_simple(fg, light);
else 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) SSAVec4i DrawSpanCodegen::Blend(SSAVec4i fg, SSAVec4i bg, DrawSpanVariant variant)

View file

@ -49,7 +49,9 @@ private:
SSAVec4i Shade(SSAVec4i fg, bool isSimpleShade); SSAVec4i Shade(SSAVec4i fg, bool isSimpleShade);
SSAVec4i Blend(SSAVec4i fg, SSAVec4i bg, DrawSpanVariant variant); SSAVec4i Blend(SSAVec4i fg, SSAVec4i bg, DrawSpanVariant variant);
SSAStack<SSAInt> stack_index, stack_xfrac, stack_yfrac; SSAStack<SSAInt> stack_index, stack_xfrac, stack_yfrac, stack_light_index;
SSAStack<SSAVec4i> stack_lit_color;
SSAStack<SSAFloat> stack_viewpos_x;
SSAUBytePtr destorg; SSAUBytePtr destorg;
SSAUBytePtr source; SSAUBytePtr source;
@ -73,4 +75,9 @@ private:
SSABool is_simple_shade; SSABool is_simple_shade;
SSABool is_nearest_filter; SSABool is_nearest_filter;
SSAShadeConstants shade_constants; SSAShadeConstants shade_constants;
SSAFloat start_viewpos_x, step_viewpos_x;
SSAValue dynlights; // TriLight*
SSAInt num_dynlights;
SSAFloat viewpos_x;
}; };

View file

@ -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 fade_blue;
elements.push_back(llvm::Type::getInt16Ty(context)); // uint16_t desaturate; 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::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(); DrawSpanArgsStruct = llvm::StructType::create(context, elements, "DrawSpanArgs", false)->getPointerTo();
return DrawSpanArgsStruct; return DrawSpanArgsStruct;
} }