Control ambient occlusion, sunlight and softshadows via cvars

This commit is contained in:
Magnus Norddahl 2023-10-04 00:24:32 +02:00
commit 4f86a0ba81
5 changed files with 65 additions and 31 deletions

View file

@ -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)

View file

@ -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<VulkanShader> vertRaytrace;
std::unique_ptr<VulkanShader> vertScreenquad;
std::unique_ptr<VulkanShader> vertCopy;
std::unique_ptr<VulkanShader> fragRaytrace;
std::unique_ptr<VulkanShader> fragRaytrace[8];
std::unique_ptr<VulkanShader> fragResolve;
std::unique_ptr<VulkanShader> fragBlur[2];
std::unique_ptr<VulkanShader> fragCopy;
@ -216,7 +218,7 @@ private:
std::unique_ptr<VulkanDescriptorSetLayout> descriptorSetLayout0;
std::unique_ptr<VulkanDescriptorSetLayout> descriptorSetLayout1;
std::unique_ptr<VulkanPipelineLayout> pipelineLayout;
std::unique_ptr<VulkanPipeline> pipeline;
std::unique_ptr<VulkanPipeline> pipeline[8];
std::unique_ptr<VulkanRenderPass> renderPass;
std::unique_ptr<VulkanDescriptorPool> descriptorPool0;
std::unique_ptr<VulkanDescriptorPool> descriptorPool1;

View file

@ -1,6 +1,4 @@
#define USE_SOFTSHADOWS
#include <shaders/lightmap/binding_lightmapper.glsl>
#include <shaders/lightmap/binding_raytrace.glsl>
#include <shaders/lightmap/binding_textures.glsl>
@ -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);

View file

@ -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;

View file

@ -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;