From 8a3db6c0036dc0f387afcd4c33ea1db2c87d4424 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 20 Dec 2016 23:21:34 +0100 Subject: [PATCH] Dynamic lights? Did anyone say DYNAMIC LIGHTS? --- src/gl/dynlights/a_dynlight.cpp | 5 --- src/r_draw_rgba.cpp | 25 +++++++++++ src/r_drawers.h | 11 +++++ src/r_poly_wall.cpp | 3 ++ src/r_swrenderer.cpp | 7 +++- src/r_swrenderer.h | 19 +++++++++ .../fixedfunction/drawwallcodegen.cpp | 42 ++++++++++++++++++- .../drawergen/fixedfunction/drawwallcodegen.h | 10 ++++- tools/drawergen/llvmdrawers.cpp | 18 ++++++++ tools/drawergen/llvmdrawers.h | 2 + 10 files changed, 133 insertions(+), 9 deletions(-) diff --git a/src/gl/dynlights/a_dynlight.cpp b/src/gl/dynlights/a_dynlight.cpp index 0ab834505..d2efbe991 100644 --- a/src/gl/dynlights/a_dynlight.cpp +++ b/src/gl/dynlights/a_dynlight.cpp @@ -79,7 +79,6 @@ #include "gl/utility/gl_convert.h" #include "gl/utility/gl_templates.h" -EXTERN_CVAR(Int, vid_renderer) //========================================================================== @@ -260,10 +259,6 @@ void ADynamicLight::Deactivate(AActor *activator) //========================================================================== void ADynamicLight::Tick() { - if (vid_renderer == 0) - { - return; - } if (IsOwned()) { if (!target || !target->state) diff --git a/src/r_draw_rgba.cpp b/src/r_draw_rgba.cpp index 09293d6de..7b4763855 100644 --- a/src/r_draw_rgba.cpp +++ b/src/r_draw_rgba.cpp @@ -221,6 +221,26 @@ namespace swrenderer if (args.source2[0] == nullptr) args.flags |= DrawWallArgs::nearest_filter; + args.dynlights = nullptr; + args.num_dynlights = 0; + /* + static TriLight fakelight; + static bool first = true; + if (first) + { + fakelight.x = 100.0f; + fakelight.y = 0.0f; + fakelight.z = 100.0f; + fakelight.color = 0xffffff00; + fakelight.radius = 256.0f / 1000.0f; + first = false; + } + + args.z = 0.0f; + args.step_z = 1.0f; + args.dynlights = &fakelight; + args.num_dynlights = 1; + */ DetectRangeError(args.dest, args.dest_y, args.count); } @@ -279,6 +299,11 @@ namespace swrenderer if (args.source2[0] == nullptr) args.flags |= DrawWallArgs::nearest_filter; + args.z = 0.0f; + args.step_z = 0.0f; + args.dynlights = nullptr; + args.num_dynlights = 0; + DetectRangeError(args.dest, args.dest_y, args.count); } diff --git a/src/r_drawers.h b/src/r_drawers.h index 8ac259e11..eff6ea370 100644 --- a/src/r_drawers.h +++ b/src/r_drawers.h @@ -59,6 +59,13 @@ struct WorkerThreadData int32_t StartY; }; +struct TriLight +{ + uint32_t color; + float x, y, z; + float radius; +}; + struct DrawWallArgs { uint32_t *dest; @@ -91,6 +98,10 @@ struct DrawWallArgs nearest_filter = 2 }; + float z, step_z; + TriLight *dynlights; + uint32_t num_dynlights; + FString ToString(); }; diff --git a/src/r_poly_wall.cpp b/src/r_poly_wall.cpp index ebb355431..f9d409b60 100644 --- a/src/r_poly_wall.cpp +++ b/src/r_poly_wall.cpp @@ -261,6 +261,9 @@ void RenderPolyWall::Render(const TriMatrix &worldToClip, const Vec4f &clipPlane args.SetColormap(Line->frontsector->ColorMap); args.SetClipPlane(clipPlane.x, clipPlane.y, clipPlane.z, clipPlane.w); + //if (Side && Side->lighthead) + // args.uniforms.light = 255; // Make walls touched by a light fullbright! + if (Polyportal) { args.stencilwritevalue = Polyportal->StencilValue; diff --git a/src/r_swrenderer.cpp b/src/r_swrenderer.cpp index a0f90f5cc..5d94e0442 100644 --- a/src/r_swrenderer.cpp +++ b/src/r_swrenderer.cpp @@ -47,6 +47,9 @@ #include "r_poly.h" #include "p_setup.h" +void gl_ParseDefs(); +void gl_InitData(); + EXTERN_CVAR(Bool, r_shadercolormaps) EXTERN_CVAR(Float, maxviewpitch) // [SP] CVAR from GZDoom @@ -92,6 +95,8 @@ FSoftwareRenderer::~FSoftwareRenderer() void FSoftwareRenderer::Init() { + gl_ParseDefs(); + r_swtruecolor = screen->IsBgra(); R_InitRenderer(); } @@ -310,7 +315,7 @@ int FSoftwareRenderer::GetMaxViewPitch(bool down) bool FSoftwareRenderer::RequireGLNodes() { - return r_polyrenderer; + return true; } //========================================================================== diff --git a/src/r_swrenderer.h b/src/r_swrenderer.h index 5b205b852..812ec32b5 100644 --- a/src/r_swrenderer.h +++ b/src/r_swrenderer.h @@ -3,6 +3,10 @@ #include "r_renderer.h" +void gl_SetActorLights(AActor *); +void gl_PreprocessLevel(); +void gl_CleanLevelData(); + struct FSoftwareRenderer : public FRenderer { FSoftwareRenderer(); @@ -40,6 +44,21 @@ struct FSoftwareRenderer : public FRenderer void RenderTextureView (FCanvasTexture *tex, AActor *viewpoint, int fov) override; sector_t *FakeFlat(sector_t *sec, sector_t *tempsec, int *floorlightlevel, int *ceilinglightlevel, bool back) override; + void StateChanged(AActor *actor) override + { + gl_SetActorLights(actor); + } + + void PreprocessLevel() override + { + gl_PreprocessLevel(); + } + + void CleanLevelData() override + { + gl_CleanLevelData(); + } + }; diff --git a/tools/drawergen/fixedfunction/drawwallcodegen.cpp b/tools/drawergen/fixedfunction/drawwallcodegen.cpp index 94b807f40..1ec00df76 100644 --- a/tools/drawergen/fixedfunction/drawwallcodegen.cpp +++ b/tools/drawergen/fixedfunction/drawwallcodegen.cpp @@ -78,6 +78,10 @@ void DrawWallCodegen::Generate(DrawWallVariant variant, bool fourColumns, SSAVal SSAShort fade_blue = args[0][41].load(true); SSAShort desaturate = args[0][42].load(true); SSAInt flags = args[0][43].load(true); + start_z = args[0][44].load(true); + step_z = args[0][45].load(true); + dynlights = args[0][46].load(true); + num_dynlights = args[0][47].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(); @@ -129,9 +133,11 @@ void DrawWallCodegen::Loop(DrawWallVariant variant, bool fourColumns, bool isSim int numColumns = fourColumns ? 4 : 1; stack_index.store(SSAInt(0)); + stack_z.store(start_z); { SSAForBlock loop; SSAInt index = stack_index.load(); + z = stack_z.load(); loop.loop_block(index < count); SSAInt frac[4]; @@ -167,6 +173,7 @@ void DrawWallCodegen::Loop(DrawWallVariant variant, bool fourColumns, bool isSim dest[offset].store_vec4ub(color); } + stack_z.store(z + step_z); stack_index.store(index.add(SSAInt(1), true, true)); for (int i = 0; i < numColumns; i++) stack_frac[i].store(frac[i] + fracstep[i]); @@ -209,10 +216,41 @@ SSAVec4i DrawWallCodegen::SampleLinear(SSAUBytePtr col0, SSAUBytePtr col1, SSAIn SSAVec4i DrawWallCodegen::Shade(SSAVec4i fg, int index, bool isSimpleShade) { + SSAVec4i c; if (isSimpleShade) - return shade_bgra_simple(fg, light[index]); + c = shade_bgra_simple(fg, light[index]); else - return shade_bgra_advanced(fg, light[index], shade_constants); + c = shade_bgra_advanced(fg, light[index], 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 Lxy2 = light_x; // L.x*L.x + L.y*L.y + SSAFloat Lz = light_z - z; + SSAFloat dist = SSAFloat::sqrt(Lxy2 + Lz * Lz); + 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 DrawWallCodegen::Blend(SSAVec4i fg, SSAVec4i bg, DrawWallVariant variant) diff --git a/tools/drawergen/fixedfunction/drawwallcodegen.h b/tools/drawergen/fixedfunction/drawwallcodegen.h index 4a1599063..cb46dcd5f 100644 --- a/tools/drawergen/fixedfunction/drawwallcodegen.h +++ b/tools/drawergen/fixedfunction/drawwallcodegen.h @@ -47,7 +47,9 @@ private: SSAVec4i Shade(SSAVec4i fg, int index, bool isSimpleShade); SSAVec4i Blend(SSAVec4i fg, SSAVec4i bg, DrawWallVariant variant); - SSAStack stack_index, stack_frac[4]; + SSAStack stack_index, stack_frac[4], stack_light_index; + SSAStack stack_lit_color; + SSAStack stack_z; SSAUBytePtr dest; SSAUBytePtr source[4]; @@ -69,4 +71,10 @@ private: SSAInt fracstep[4]; SSAInt one[4]; + + SSAFloat start_z, step_z; + + SSAValue dynlights; // TriLight* + SSAInt num_dynlights; + SSAFloat z; }; diff --git a/tools/drawergen/llvmdrawers.cpp b/tools/drawergen/llvmdrawers.cpp index e68470188..706cfb79f 100644 --- a/tools/drawergen/llvmdrawers.cpp +++ b/tools/drawergen/llvmdrawers.cpp @@ -290,6 +290,11 @@ llvm::Type *LLVMDrawers::GetDrawWallArgsStruct(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 z; + elements.push_back(llvm::Type::getFloatTy(context)); // float step_z; + elements.push_back(GetTriLightStruct(context)); // TriLight *dynlights; + elements.push_back(llvm::Type::getInt32Ty(context)); // uint32_t num_dynlights; + DrawWallArgsStruct = llvm::StructType::create(context, elements, "DrawWallArgs", false)->getPointerTo(); return DrawWallArgsStruct; } @@ -326,6 +331,19 @@ llvm::Type *LLVMDrawers::GetWorkerThreadDataStruct(llvm::LLVMContext &context) return WorkerThreadDataStruct; } +llvm::Type *LLVMDrawers::GetTriLightStruct(llvm::LLVMContext &context) +{ + if (TriLightStruct) + return TriLightStruct; + + std::vector elements; + elements.push_back(llvm::Type::getInt32Ty(context)); + for (int i = 0; i < 4 + TriVertex::NumVarying; i++) + elements.push_back(llvm::Type::getFloatTy(context)); + TriLightStruct = llvm::StructType::create(context, elements, "TriLight", false)->getPointerTo(); + return TriLightStruct; +} + llvm::Type *LLVMDrawers::GetTriVertexStruct(llvm::LLVMContext &context) { if (TriVertexStruct) diff --git a/tools/drawergen/llvmdrawers.h b/tools/drawergen/llvmdrawers.h index a1b7b5361..f546d1dff 100644 --- a/tools/drawergen/llvmdrawers.h +++ b/tools/drawergen/llvmdrawers.h @@ -58,6 +58,7 @@ private: llvm::Type *GetDrawWallArgsStruct(llvm::LLVMContext &context); llvm::Type *GetDrawSkyArgsStruct(llvm::LLVMContext &context); llvm::Type *GetWorkerThreadDataStruct(llvm::LLVMContext &context); + llvm::Type *GetTriLightStruct(llvm::LLVMContext &context); llvm::Type *GetTriVertexStruct(llvm::LLVMContext &context); llvm::Type *GetTriMatrixStruct(llvm::LLVMContext &context); llvm::Type *GetTriUniformsStruct(llvm::LLVMContext &context); @@ -70,6 +71,7 @@ private: llvm::Type *DrawWallArgsStruct = nullptr; llvm::Type *DrawSkyArgsStruct = nullptr; llvm::Type *WorkerThreadDataStruct = nullptr; + llvm::Type *TriLightStruct = nullptr; llvm::Type *TriVertexStruct = nullptr; llvm::Type *TriMatrixStruct = nullptr; llvm::Type *TriUniformsStruct = nullptr;