Add shaders for light tiles

This commit is contained in:
Magnus Norddahl 2024-09-13 20:45:36 +02:00
commit 2ba2c24f6b
7 changed files with 130 additions and 1 deletions

View file

@ -91,7 +91,7 @@ void VkDescriptorSetManager::UpdateLevelMeshSet()
.AddBuffer(LevelMesh.Set.get(), 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, rsbuffers->MatrixBuffer->UBO(), 0, sizeof(MatricesUBO))
.AddBuffer(LevelMesh.Set.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetUniformsBuffer())
.AddBuffer(LevelMesh.Set.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetLightUniformsBuffer())
.AddBuffer(LevelMesh.Set.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetDynLightBuffer())
.AddBuffer(LevelMesh.Set.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBuffers()->SceneLightTiles.get())
.AddBuffer(LevelMesh.Set.get(), 5, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, rsbuffers->Fogballbuffer.UBO.get(), 0, sizeof(FogballBufferUBO))
.AddBuffer(LevelMesh.Set.get(), 6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, rsbuffers->Bonebuffer.SSO.get())
.Execute(fb->GetDevice());

View file

@ -32,6 +32,33 @@
VkShaderManager::VkShaderManager(VulkanRenderDevice* fb) : fb(fb)
{
ZMinMax.vert = ShaderBuilder()
.Type(ShaderType::Vertex)
.DebugName("ZMinMax.vert")
.AddSource("VersionBlock", GetVersionBlock().GetChars())
.AddSource("shaders/scene/vert_zminmax.glsl", LoadPrivateShaderLump("shaders/scene/vert_zminmax.glsl").GetChars())
.Create("ZMinMax.vert", fb->GetDevice());
ZMinMax.frag[0] = ShaderBuilder()
.Type(ShaderType::Fragment)
.DebugName("ZMinMax0.frag")
.AddSource("VersionBlock", GetVersionBlock().GetChars())
.AddSource("shaders/scene/frag_zminmax0.glsl", LoadPrivateShaderLump("shaders/scene/frag_zminmax0.glsl").GetChars())
.Create("ZMinMax0.frag", fb->GetDevice());
ZMinMax.frag[1] = ShaderBuilder()
.Type(ShaderType::Fragment)
.DebugName("ZMinMax1.frag")
.AddSource("VersionBlock", GetVersionBlock().GetChars())
.AddSource("shaders/scene/frag_zminmax1.glsl", LoadPrivateShaderLump("shaders/scene/frag_zminmax1.glsl").GetChars())
.Create("ZMinMax1.frag", fb->GetDevice());
LightTiles = ShaderBuilder()
.Type(ShaderType::Compute)
.DebugName("LightTiles.comp")
.AddSource("VersionBlock", GetVersionBlock().GetChars())
.AddSource("shaders/scene/comp_lighttiles.glsl", LoadPrivateShaderLump("shaders/scene/comp_lighttiles.glsl").GetChars())
.Create("LightTiles.comp", fb->GetDevice());
}
VkShaderManager::~VkShaderManager()

View file

@ -119,6 +119,10 @@ public:
void AddVkPPShader(VkPPShader* shader);
void RemoveVkPPShader(VkPPShader* shader);
VulkanShader* GetZMinMaxVertexShader() { return ZMinMax.vert.get(); }
VulkanShader* GetZMinMaxFragmentShader(int index) { return ZMinMax.frag[index].get(); }
VulkanShader* GetLightTilesShader() { return LightTiles.get(); }
private:
std::unique_ptr<VulkanShader> LoadVertShader(FString shadername, const char *vert_lump, const char *defines, bool levelmesh);
std::unique_ptr<VulkanShader> LoadFragShader(FString shadername, const char *frag_lump, const char *material_lump, const char* mateffect_lump, const char *lightmodel_lump, const char *defines, const VkShaderKey& key);
@ -134,4 +138,12 @@ private:
std::map<VkShaderKey, VkShaderProgram> programs;
std::list<VkPPShader*> PPShaders;
struct
{
std::unique_ptr<VulkanShader> vert;
std::unique_ptr<VulkanShader> frag[2];
} ZMinMax;
std::unique_ptr<VulkanShader> LightTiles;
};

View file

@ -0,0 +1,43 @@
layout(local_size_x = 32, local_size_y = 32) in;
layout(binding = 0, rg32f) readonly uniform image2D zminmax;
layout(binding = 1) readonly buffer Lights
{
vec4 lights[];
};
layout(binding = 1) buffer Tiles
{
vec4 tiles[];
};
layout(push_constant) uniform PushConstants
{
int normalLightCount;
int modulatedLightCount;
int subtractiveLightCount;
};
void main()
{
ivec2 zminmaxSize = imageSize(zminmax);
ivec2 tilePos = ivec2(gl_GlobalInvocationID.xy);
if (tilePos.x >= zminmaxSize.x || tilePos.y >= zminmaxSize.y)
return;
const int maxLights = 16;
const int lightSize = 3;
int tileOffset = (tilePos.x + tilePos.y * zminmaxSize.x) * (1 + maxLights * lightSize);
vec2 minmax = imageLoad(zminmax, tilePos).xy;
float zmin = minmax.x;
float zmax = minmax.y;
int tileNormalCount = 0;
int tileModulatedCount = 0;
int tileSubtractiveCount = 0;
// To do: cull and add lights
tiles[tileOffset] = vec4(ivec4(tileNormalCount, tileModulatedCount, tileSubtractiveCount, 0));
}

View file

@ -0,0 +1,17 @@
layout(binding = 0) uniform sampler2D Texture;
layout(location = 0) out vec4 FragMinMax;
void main()
{
ivec2 size = textureSize(Texture, 0) - 1;
ivec2 pos = ivec2(gl_FragCoord.xy) * 2;
float z0 = texelFetch(Texture, min(pos, size), 0).w;
float z1 = texelFetch(Texture, min(pos + ivec2(1,0), size), 0).w;
float z2 = texelFetch(Texture, min(pos + ivec2(0,1), size), 0).w;
float z3 = texelFetch(Texture, min(pos + ivec2(1,1), size), 0).w;
vec2 zminmax = vec2(
min(min(min(z0, z1), z2), z3),
max(max(max(z0, z1), z2), z3));
FragMinMax = vec4(zminmax, 0, 0);
}

View file

@ -0,0 +1,16 @@
layout(binding = 0) uniform sampler2D Texture;
layout(location = 0) out vec4 FragMinMax;
void main()
{
ivec2 pos = ivec2(gl_FragCoord.xy) * 2;
vec2 z0 = texelFetch(Texture, pos, 0).xy;
vec2 z1 = texelFetch(Texture, pos + ivec2(1,0), 0).xy;
vec2 z2 = texelFetch(Texture, pos + ivec2(0,1), 0).xy;
vec2 z3 = texelFetch(Texture, pos + ivec2(1,1), 0).xy;
vec2 zminmax = vec2(
min(min(min(z0.x, z1.x), z2.x), z3.x),
max(max(max(z0.y, z1.y), z2.y), z3.y));
FragMinMax = vec4(zminmax, 0, 0);
}

View file

@ -0,0 +1,14 @@
vec2 positions[6] = vec2[](
vec2(-1.0, -1.0),
vec2( 1.0, -1.0),
vec2(-1.0, 1.0),
vec2(-1.0, 1.0),
vec2( 1.0, -1.0),
vec2( 1.0, 1.0)
);
void main()
{
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
}