mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 15:21:51 +00:00
Dynamic lights on flats
This commit is contained in:
parent
fcbacf8cac
commit
4f7c1dfdf5
7 changed files with 69 additions and 9 deletions
|
@ -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)
|
||||||
|
|
|
@ -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();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue