From 4f86a0ba81428709b4549cb5a4fffce5dfa27fb7 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 4 Oct 2023 00:24:32 +0200 Subject: [PATCH] Control ambient occlusion, sunlight and softshadows via cvars --- .../vulkan/accelstructs/vk_lightmap.cpp | 76 +++++++++++++------ .../vulkan/accelstructs/vk_lightmap.h | 6 +- .../shaders/lightmap/frag_raytrace.glsl | 10 ++- .../static/shaders/lightmap/trace_light.glsl | 2 +- .../shaders/lightmap/trace_sunlight.glsl | 2 +- 5 files changed, 65 insertions(+), 31 deletions(-) diff --git a/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp b/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp index edfa978d3..4233a93e0 100644 --- a/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp +++ b/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp @@ -26,6 +26,9 @@ ADD_STAT(lightmapper) CVAR(Int, lm_background_updates, 8, CVAR_NOSAVE); CVAR(Int, lm_max_updates, 128, CVAR_NOSAVE); CVAR(Float, lm_scale, 1.0, CVAR_NOSAVE); +CVAR(Bool, lm_ao, true, 0); +CVAR(Bool, lm_softshadows, true, 0); +CVAR(Bool, lm_sunlight, true, 0); VkLightmap::VkLightmap(VulkanRenderDevice* fb) : fb(fb) { @@ -151,7 +154,7 @@ void VkLightmap::Render() VkDeviceSize offset = 0; cmdbuffer->bindVertexBuffers(0, 1, &fb->GetRaytrace()->GetVertexBuffer()->buffer, &offset); cmdbuffer->bindIndexBuffer(fb->GetRaytrace()->GetIndexBuffer()->buffer, 0, VK_INDEX_TYPE_UINT32); - cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, raytrace.pipeline.get()); + cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, raytrace.pipeline[GetRaytracePipelineIndex()].get()); cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, raytrace.pipelineLayout.get(), 0, raytrace.descriptorSet0.get()); cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, raytrace.pipelineLayout.get(), 1, raytrace.descriptorSet1.get()); cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, raytrace.pipelineLayout.get(), 2, fb->GetDescriptorSetManager()->GetBindlessDescriptorSet()); @@ -522,6 +525,7 @@ void VkLightmap::CreateShaders() std::string prefix = "#version 460\r\n"; std::string traceprefix = "#version 460\r\n"; prefix += "#extension GL_GOOGLE_include_directive : enable\n"; + traceprefix += "#extension GL_GOOGLE_include_directive : enable\n"; traceprefix += "#extension GL_EXT_nonuniform_qualifier : enable\r\n"; if (useRayQuery) @@ -564,14 +568,25 @@ void VkLightmap::CreateShaders() .DebugName("VkLightmap.VertCopy") .Create("VkLightmap.VertCopy", fb->GetDevice()); - shaders.fragRaytrace = ShaderBuilder() - .Type(ShaderType::Fragment) - .AddSource("VersionBlock", traceprefix) - .AddSource("frag_raytrace.glsl", LoadPrivateShaderLump("shaders/lightmap/frag_raytrace.glsl").GetChars()) - .OnIncludeLocal(onIncludeLocal) - .OnIncludeSystem(onIncludeSystem) - .DebugName("VkLightmap.FragRaytrace") - .Create("VkLightmap.FragRaytrace", fb->GetDevice()); + for (int i = 0; i < 8; i++) + { + std::string defines = traceprefix; + if (i & 1) + defines += "#define USE_SOFTSHADOWS\n"; + if (i & 2) + defines += "#define USE_AO\n"; + if (i & 4) + defines += "#define USE_SUNLIGHT\n"; + + shaders.fragRaytrace[i] = ShaderBuilder() + .Type(ShaderType::Fragment) + .AddSource("VersionBlock", defines) + .AddSource("frag_raytrace.glsl", LoadPrivateShaderLump("shaders/lightmap/frag_raytrace.glsl").GetChars()) + .OnIncludeLocal(onIncludeLocal) + .OnIncludeSystem(onIncludeSystem) + .DebugName("VkLightmap.FragRaytrace") + .Create("VkLightmap.FragRaytrace", fb->GetDevice()); + } shaders.fragResolve = ShaderBuilder() .Type(ShaderType::Fragment) @@ -610,6 +625,18 @@ void VkLightmap::CreateShaders() .Create("VkLightmap.FragCopy", fb->GetDevice()); } +int VkLightmap::GetRaytracePipelineIndex() +{ + int index = 0; + if (lm_softshadows && useRayQuery) + index |= 1; + if (lm_ao && useRayQuery) + index |= 2; + if (lm_sunlight && mesh->SunColor != FVector3(0.0f, 0.0f, 0.0f)) + index |= 4; + return index; +} + FString VkLightmap::LoadPrivateShaderLump(const char* lumpname) { int lump = fileSystem.CheckNumForFullName(lumpname, 0); @@ -712,20 +739,23 @@ void VkLightmap::CreateRaytracePipeline() .DebugName("raytrace.renderPass") .Create(fb->GetDevice()); - raytrace.pipeline = GraphicsPipelineBuilder() - .Layout(raytrace.pipelineLayout.get()) - .RenderPass(raytrace.renderPass.get()) - .AddVertexShader(shaders.vertRaytrace.get()) - .AddFragmentShader(shaders.fragRaytrace.get()) - .AddVertexBufferBinding(0, sizeof(SurfaceVertex)) - .AddVertexAttribute(0, 0, VK_FORMAT_R32G32B32A32_SFLOAT, 0) - .Topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST) - .AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT) - .RasterizationSamples(VK_SAMPLE_COUNT_4_BIT) - .Viewport(0.0f, 0.0f, 0.0f, 0.0f) - .Scissor(0, 0, 4096, 4096) - .DebugName("raytrace.pipeline") - .Create(fb->GetDevice()); + for (int i = 0; i < 8; i++) + { + raytrace.pipeline[i] = GraphicsPipelineBuilder() + .Layout(raytrace.pipelineLayout.get()) + .RenderPass(raytrace.renderPass.get()) + .AddVertexShader(shaders.vertRaytrace.get()) + .AddFragmentShader(shaders.fragRaytrace[i].get()) + .AddVertexBufferBinding(0, sizeof(SurfaceVertex)) + .AddVertexAttribute(0, 0, VK_FORMAT_R32G32B32A32_SFLOAT, 0) + .Topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST) + .AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT) + .RasterizationSamples(VK_SAMPLE_COUNT_4_BIT) + .Viewport(0.0f, 0.0f, 0.0f, 0.0f) + .Scissor(0, 0, 4096, 4096) + .DebugName("raytrace.pipeline") + .Create(fb->GetDevice()); + } raytrace.descriptorPool0 = DescriptorPoolBuilder() .AddPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1) diff --git a/src/common/rendering/vulkan/accelstructs/vk_lightmap.h b/src/common/rendering/vulkan/accelstructs/vk_lightmap.h index db9d0d585..c4ce51ebc 100644 --- a/src/common/rendering/vulkan/accelstructs/vk_lightmap.h +++ b/src/common/rendering/vulkan/accelstructs/vk_lightmap.h @@ -150,6 +150,8 @@ private: void CreateDrawIndexedBuffer(); void CreateBakeImage(); + int GetRaytracePipelineIndex(); + static FString LoadPrivateShaderLump(const char* lumpname); static FString LoadPublicShaderLump(const char* lumpname); static ShaderIncludeResult OnInclude(FString headerName, FString includerName, size_t depth, bool system); @@ -205,7 +207,7 @@ private: std::unique_ptr vertRaytrace; std::unique_ptr vertScreenquad; std::unique_ptr vertCopy; - std::unique_ptr fragRaytrace; + std::unique_ptr fragRaytrace[8]; std::unique_ptr fragResolve; std::unique_ptr fragBlur[2]; std::unique_ptr fragCopy; @@ -216,7 +218,7 @@ private: std::unique_ptr descriptorSetLayout0; std::unique_ptr descriptorSetLayout1; std::unique_ptr pipelineLayout; - std::unique_ptr pipeline; + std::unique_ptr pipeline[8]; std::unique_ptr renderPass; std::unique_ptr descriptorPool0; std::unique_ptr descriptorPool1; diff --git a/wadsrc/static/shaders/lightmap/frag_raytrace.glsl b/wadsrc/static/shaders/lightmap/frag_raytrace.glsl index b499cf59e..307412414 100644 --- a/wadsrc/static/shaders/lightmap/frag_raytrace.glsl +++ b/wadsrc/static/shaders/lightmap/frag_raytrace.glsl @@ -1,6 +1,4 @@ -#define USE_SOFTSHADOWS - #include #include #include @@ -30,15 +28,19 @@ void main() vec3 normal = surfaces[SurfaceIndex].Normal; vec3 origin = worldpos + normal * 0.1; +#if defined(USE_SUNLIGHT) vec3 incoming = TraceSunLight(origin); +#else + vec3 incoming = vec3(0.0); +#endif for (uint j = LightStart; j < LightEnd; j++) { incoming += TraceLight(origin, normal, lights[j], SurfaceIndex); } -#if defined(USE_RAYQUERY) // The non-rtx version of TraceFirstHitTriangle is too slow to do AO without the shader getting killed ;( - //incoming.rgb *= TraceAmbientOcclusion(origin, normal); +#if defined(USE_AO) + incoming.rgb *= TraceAmbientOcclusion(origin, normal); #endif fragcolor = vec4(incoming, 1.0); diff --git a/wadsrc/static/shaders/lightmap/trace_light.glsl b/wadsrc/static/shaders/lightmap/trace_light.glsl index bb7189df1..036556484 100644 --- a/wadsrc/static/shaders/lightmap/trace_light.glsl +++ b/wadsrc/static/shaders/lightmap/trace_light.glsl @@ -34,7 +34,7 @@ vec3 TraceLight(vec3 origin, vec3 normal, LightInfo light, int surfaceIndex) vec3 ydir = cross(dir, xdir); float lightsize = 10; - int step_count = 16; + int step_count = 10; for (int i = 0; i < step_count; i++) { vec2 gridoffset = getVogelDiskSample(i, step_count, gl_FragCoord.x + gl_FragCoord.y * 13.37) * lightsize; diff --git a/wadsrc/static/shaders/lightmap/trace_sunlight.glsl b/wadsrc/static/shaders/lightmap/trace_sunlight.glsl index 1908c55bb..6340f3e19 100644 --- a/wadsrc/static/shaders/lightmap/trace_sunlight.glsl +++ b/wadsrc/static/shaders/lightmap/trace_sunlight.glsl @@ -16,7 +16,7 @@ vec3 TraceSunLight(vec3 origin) vec3 ydir = cross(dir, xdir); float lightsize = 100; - int step_count = 16; + int step_count = 10; for (int i = 0; i < step_count; i++) { vec2 gridoffset = getVogelDiskSample(i, step_count, gl_FragCoord.x + gl_FragCoord.y * 13.37) * lightsize;