From 336b4751a3b160e5240e46210d182625584f9b65 Mon Sep 17 00:00:00 2001 From: Alexander Gauggel <agauggel@uni-koblenz.de> Date: Mon, 21 Jun 2021 17:23:15 +0200 Subject: [PATCH] [#82] Add secondary bounce --- .../voxelization/resources/shaders/brdf.inc | 7 +- .../resources/shaders/shader.frag | 63 +------- .../voxelization/resources/shaders/voxel.inc | 136 +++++++++++++++++- .../resources/shaders/voxelBufferToImage.comp | 13 +- .../resources/shaders/voxelReset.comp | 8 +- .../shaders/voxelSecondaryBounce.comp | 46 ++++++ .../resources/shaders/voxelVisualisation.vert | 2 +- .../resources/shaders/voxelization.frag | 6 +- .../resources/shaders/voxelization.vert | 2 +- projects/voxelization/src/Voxelization.cpp | 56 +++++++- projects/voxelization/src/Voxelization.hpp | 13 +- projects/voxelization/src/main.cpp | 15 +- 12 files changed, 280 insertions(+), 87 deletions(-) create mode 100644 projects/voxelization/resources/shaders/voxelSecondaryBounce.comp diff --git a/projects/voxelization/resources/shaders/brdf.inc b/projects/voxelization/resources/shaders/brdf.inc index f8f1388b..fc97b601 100644 --- a/projects/voxelization/resources/shaders/brdf.inc +++ b/projects/voxelization/resources/shaders/brdf.inc @@ -1,3 +1,6 @@ +#ifndef BRDF_INC +#define BRDF_INC + const float pi = 3.1415; vec3 lambertBRDF(vec3 albedo){ @@ -23,4 +26,6 @@ float GGXSmithShadowingPart(float r, float cosTheta){ float GGXSmithShadowing(float r, float NoV, float NoL){ return GGXSmithShadowingPart(r, NoV) * GGXSmithShadowingPart(r, NoL); -} \ No newline at end of file +} + +#endif // #ifndef BRDF_INC \ No newline at end of file diff --git a/projects/voxelization/resources/shaders/shader.frag b/projects/voxelization/resources/shaders/shader.frag index 39af585b..e189ba85 100644 --- a/projects/voxelization/resources/shaders/shader.frag +++ b/projects/voxelization/resources/shaders/shader.frag @@ -32,51 +32,6 @@ layout(set=0, binding=6) uniform VoxelInfoBuffer{ VoxelInfo voxelInfo; }; -vec3 voxelConeTrace(texture3D voxelTexture, sampler voxelSampler, vec3 direction, vec3 startPosition, float coneAngleRadian){ - - int voxelResolution = textureSize(sampler3D(voxelTexture, voxelSampler), 0).x; - float voxelSize = voxelInfo.extent / voxelResolution; - float maxMip = float(log2(voxelResolution)); - float maxStableMip = 4; // must be the same as in Voxelization::voxelizeMeshes - maxMip = min(maxMip, maxStableMip); - float d = 2 * sqrt(3 * pow(voxelSize, 2)); - vec3 color = vec3(0); - float a = 0; - - float coneAngleHalf = coneAngleRadian * 0.5f; - - int maxSamples = 128; - for(int i = 0; i < maxSamples; i++){ - - vec3 samplePos = startPosition + d * direction; - vec3 sampleUV = worldToVoxelCoordinates(samplePos, voxelInfo); - - if(a >= 0.95 || any(lessThan(sampleUV, vec3(0))) || any(greaterThan(sampleUV, vec3(1)))){ - break; - } - - float coneDiameter = 2 * tan(coneAngleHalf) * d; - float mip = log2(coneDiameter / voxelSize); - mip = min(mip, maxMip); - - vec4 voxelSample = textureLod(sampler3D(voxelTexture, voxelSampler), sampleUV , mip); - - color += (1 - a) * voxelSample.rgb; - voxelSample.a = pow(voxelSample.a, 0.6); - a += (1 - a) * voxelSample.a; - - float minStepSize = 0.15; - d += max(coneDiameter, minStepSize); - samplePos = startPosition + d * direction; - sampleUV = worldToVoxelCoordinates(samplePos, voxelInfo); - } - return color; -} - -float degreeToRadian(float d){ - return d / 180.f * pi; -} - vec3 cookTorrance(vec3 f0, float r, vec3 N, vec3 V, vec3 L){ vec3 H = normalize(L + V); @@ -135,26 +90,12 @@ void main() { up = cross(N, right); mat3 toSurface = mat3(right, up, N); - float coneAngle = degreeToRadian(60.f); - vec3 diffuseTrace = vec3(0); - { - vec3 sampleDirection = toSurface * vec3(0, 0, 1); - float weight = pi / 4.f; - diffuseTrace += weight * voxelConeTrace(voxelTexture, voxelSampler, sampleDirection, passPos, coneAngle); - } - for(int i = 0; i < 6;i++){ - float theta = 2 * pi / i; - float phi = pi / 3; // 60 degrees - vec3 sampleDirection = toSurface * vec3(cos(theta) * sin(phi), sin(theta) * sin(phi), cos(phi)); - float weight = pi * (3.f / 4.f) / i; - vec3 trace = voxelConeTrace(voxelTexture, voxelSampler, sampleDirection, passPos, coneAngle); - diffuseTrace += trace * (1 - fresnelSchlick(NoV, f0)) * (1 - fresnelSchlick(cos(phi), f0)); - } + vec3 diffuseTrace = diffuseVoxelTraceHemisphere(toSurface, passPos, voxelTexture, voxelSampler, voxelInfo); vec3 R = reflect(-V, N); float reflectionConeAngle = degreeToRadian(roughnessToConeAngle(r)); vec3 offsetTraceStart = passPos + N_geo * 0.1f; - vec3 specularTrace = voxelConeTrace(voxelTexture, voxelSampler, R, offsetTraceStart, reflectionConeAngle); + vec3 specularTrace = voxelConeTrace(R, offsetTraceStart, reflectionConeAngle, voxelTexture, voxelSampler, voxelInfo); vec3 reflectionBRDF = cookTorrance(f0, r, N, V, R); outColor = diff --git a/projects/voxelization/resources/shaders/voxel.inc b/projects/voxelization/resources/shaders/voxel.inc index 6a244113..8742473d 100644 --- a/projects/voxelization/resources/shaders/voxel.inc +++ b/projects/voxelization/resources/shaders/voxel.inc @@ -1,8 +1,16 @@ +#include "brdf.inc" + struct VoxelInfo{ vec3 offset; float extent; }; +struct PackedVoxelData{ + uint color; + uint normal; + uint albedo; +}; + uint flattenVoxelUVToIndex(ivec3 UV, ivec3 voxelImageSize){ return UV.x + UV.y * voxelImageSize.x + UV.z * voxelImageSize.x* voxelImageSize.y; } @@ -15,6 +23,10 @@ ivec3 voxelCoordinatesToUV(vec3 voxelCoordinates, ivec3 voxelImageResolution){ return ivec3(voxelCoordinates * voxelImageResolution); } +vec3 voxelCoordinatesToWorldPosition(ivec3 coord, int voxelResolution, VoxelInfo voxelInfo, float voxelHalfSize){ + return (vec3(coord) / voxelResolution - 0.5) * voxelInfo.extent + voxelHalfSize + voxelInfo.offset; +} + // packed voxel data: // 1 bit opacity // 7 bit exposure @@ -23,7 +35,7 @@ ivec3 voxelCoordinatesToUV(vec3 voxelCoordinates, ivec3 voxelImageResolution){ // 8 bit red float maxExposure = 16.f; -uint packVoxelInfo(vec3 color){ +uint packVoxelColor(vec3 color){ color = clamp(color, vec3(0), vec3(maxExposure)); float maxComponent = max(max(max(color.r, color.g), color.b), 1.f); @@ -37,7 +49,7 @@ uint packVoxelInfo(vec3 color){ return opaqueBit | exposureBits | blueBits | greenBits | redBits; } -vec4 unpackVoxelInfo(uint packed){ +vec4 unpackVoxelColor(uint packed){ vec4 rgba; rgba.r = (packed >> 0 & 0x000000FF) / 255.f; rgba.g = (packed >> 8 & 0x000000FF) / 255.f; @@ -47,4 +59,124 @@ vec4 unpackVoxelInfo(uint packed){ rgba.rgb *= (packed >> 24 & 0x0000007F) / 127.f * maxExposure; return rgba; +} + +uint packSNormInto9Bits(float x){ + uint lengthBits = 0x000000FF & uint(abs(x) * 255.f); + uint signBits = (x < 0 ? 1 : 0) << 8; + return lengthBits | signBits; +} + +float unpack9LowBitsIntoSNorm(uint bits){ + bits = (0x000001FF & bits); + float length = bits / 255.f; + float sign = (bits >> 8) == 0 ? 1 : -1; + return sign * length; +} + +// normals are packed with 9 bits each, 8 for length and 1 for sign +uint packVoxelNormal(vec3 N){ + N = clamp(N, vec3(0), vec3(1)); + uint xBits = packSNormInto9Bits(N.x) << 0; + uint yBits = packSNormInto9Bits(N.y) << 9; + uint zBits = packSNormInto9Bits(N.z) << 18; + return zBits | yBits | xBits; +} + +vec3 unpackVoxelNormal(uint packed){ + vec3 N; + N.x = unpack9LowBitsIntoSNorm(packed >> 0); + N.y = unpack9LowBitsIntoSNorm(packed >> 9); + N.z = unpack9LowBitsIntoSNorm(packed >> 18); + return normalize(N); +} + +uint packUNormInto8Bits(float x){ + return 0x000000FF & uint(abs(x) * 255.f); +} + +float unpack8LowBitsIntoUNorm(uint bits){ + bits = (0x000000FF & bits); + return bits / 255.f; +} + +// albedo is packed with 8 bits each +uint packVoxelAlbedo(vec3 albedo){ + albedo = clamp(albedo, vec3(0), vec3(1)); + uint rBits = packUNormInto8Bits(albedo.r) << 0; + uint gBits = packUNormInto8Bits(albedo.g) << 8; + uint bBits = packUNormInto8Bits(albedo.b) << 16; + return bBits | gBits | rBits; +} + +vec3 unpackVoxelAlbedo(uint packed){ + vec3 albedo; + albedo.r = unpack8LowBitsIntoUNorm(packed >> 0); + albedo.g = unpack8LowBitsIntoUNorm(packed >> 8); + albedo.b = unpack8LowBitsIntoUNorm(packed >> 16); + return albedo; +} + +vec3 voxelConeTrace(vec3 direction, vec3 startPosition, float coneAngleRadian, texture3D voxelTexture, sampler voxelSampler, VoxelInfo voxelInfo){ + + int voxelResolution = textureSize(sampler3D(voxelTexture, voxelSampler), 0).x; + float voxelSize = voxelInfo.extent / voxelResolution; + float maxMip = float(log2(voxelResolution)); + float maxStableMip = 4; // must be the same as in Voxelization::voxelizeMeshes + maxMip = min(maxMip, maxStableMip); + float d = 2 * sqrt(3 * pow(voxelSize, 2)); + vec3 color = vec3(0); + float a = 0; + + float coneAngleHalf = coneAngleRadian * 0.5f; + + int maxSamples = 128; + for(int i = 0; i < maxSamples; i++){ + + vec3 samplePos = startPosition + d * direction; + vec3 sampleUV = worldToVoxelCoordinates(samplePos, voxelInfo); + + if(a >= 0.95 || any(lessThan(sampleUV, vec3(0))) || any(greaterThan(sampleUV, vec3(1)))){ + break; + } + + float coneDiameter = 2 * tan(coneAngleHalf) * d; + float mip = log2(coneDiameter / voxelSize); + mip = min(mip, maxMip); + + vec4 voxelSample = textureLod(sampler3D(voxelTexture, voxelSampler), sampleUV , mip); + + color += (1 - a) * voxelSample.rgb; + voxelSample.a = pow(voxelSample.a, 0.6); + a += (1 - a) * voxelSample.a; + + float minStepSize = 0.15; + d += max(coneDiameter, minStepSize); + samplePos = startPosition + d * direction; + sampleUV = worldToVoxelCoordinates(samplePos, voxelInfo); + } + return color; +} + +float degreeToRadian(float d){ + return d / 180.f * pi; +} + +vec3 diffuseVoxelTraceHemisphere(mat3 toSurface, vec3 position, texture3D voxelTexture, sampler voxelSampler, VoxelInfo voxelInfo){ + float coneAngle = degreeToRadian(60.f); + vec3 diffuseTrace = vec3(0); + { + vec3 sampleDirection = toSurface * vec3(0, 0, 1); + float weight = pi / 4.f; + diffuseTrace += weight * voxelConeTrace(sampleDirection, position, coneAngle, voxelTexture, voxelSampler, voxelInfo); + } + for(int i = 0; i < 6;i++){ + float theta = 2 * pi / i; + float phi = pi / 3; // 60 degrees + vec3 sampleDirection = toSurface * vec3(cos(theta) * sin(phi), sin(theta) * sin(phi), cos(phi)); + float weight = pi * (3.f / 4.f) / i; + vec3 trace = voxelConeTrace(sampleDirection, position, coneAngle, voxelTexture, voxelSampler, voxelInfo); + diffuseTrace += trace; + } + return diffuseTrace; } \ No newline at end of file diff --git a/projects/voxelization/resources/shaders/voxelBufferToImage.comp b/projects/voxelization/resources/shaders/voxelBufferToImage.comp index 5e829888..2c2cffe8 100644 --- a/projects/voxelization/resources/shaders/voxelBufferToImage.comp +++ b/projects/voxelization/resources/shaders/voxelBufferToImage.comp @@ -3,7 +3,7 @@ #include "voxel.inc" layout(set=0, binding=0, std430) buffer voxelBuffer{ - uint packedVoxelData[]; + PackedVoxelData packedVoxelData[]; }; layout(set=0, binding=1, rgba16f) uniform image3D voxelImage; @@ -19,6 +19,15 @@ void main(){ ivec3 UV = ivec3(gl_GlobalInvocationID); uint flatIndex = flattenVoxelUVToIndex(UV, voxelImageSize); - vec4 color = unpackVoxelInfo(packedVoxelData[flatIndex]); + vec4 color = unpackVoxelColor(packedVoxelData[flatIndex].color); + + // for proper visualisation voxel secondary bounce should be disabled, otherwise it adds color + + // for debugging: write normal into image, so voxel visualisation draws normal + // color = vec4(unpackVoxelNormal(packedVoxelData[flatIndex].normal), color.a); + + // for debugging: write albedo into image, so voxel visualisation draws albedo + // color = vec4(unpackVoxelAlbedo(packedVoxelData[flatIndex].albedo), color.a); + imageStore(voxelImage, UV, vec4(color)); } \ No newline at end of file diff --git a/projects/voxelization/resources/shaders/voxelReset.comp b/projects/voxelization/resources/shaders/voxelReset.comp index 14b78d65..79eda9ec 100644 --- a/projects/voxelization/resources/shaders/voxelReset.comp +++ b/projects/voxelization/resources/shaders/voxelReset.comp @@ -1,7 +1,9 @@ #version 450 +#extension GL_GOOGLE_include_directive : enable +#include "voxel.inc" layout(set=0, binding=0) buffer voxelizationBuffer{ - uint isFilled[]; + PackedVoxelData packedVoxelData[]; }; layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; @@ -15,5 +17,7 @@ void main(){ if(gl_GlobalInvocationID.x> voxelCount){ return; } - isFilled[gl_GlobalInvocationID.x] = 0; + packedVoxelData[gl_GlobalInvocationID.x].color = 0; + packedVoxelData[gl_GlobalInvocationID.x].normal = 0; + packedVoxelData[gl_GlobalInvocationID.x].albedo = 0; } \ No newline at end of file diff --git a/projects/voxelization/resources/shaders/voxelSecondaryBounce.comp b/projects/voxelization/resources/shaders/voxelSecondaryBounce.comp new file mode 100644 index 00000000..3e10ecb8 --- /dev/null +++ b/projects/voxelization/resources/shaders/voxelSecondaryBounce.comp @@ -0,0 +1,46 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable +#include "voxel.inc" +#include "brdf.inc" + +layout(set=0, binding=0, std430) buffer voxelBuffer{ + PackedVoxelData packedVoxelData[]; +}; +layout(set=0, binding=1) uniform texture3D voxelImageIn; +layout(set=0, binding=2) uniform sampler voxelSampler; +layout(set=0, binding=3, rgba16f) uniform image3D voxelImageOut; +layout(set=0, binding=4) uniform voxelizationInfo{ + VoxelInfo voxelInfo; +}; + +layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in; + +void main(){ + + ivec3 voxelImageSize = imageSize(voxelImageOut); + if(any(greaterThanEqual(gl_GlobalInvocationID, voxelImageSize))){ + return; + } + ivec3 UV = ivec3(gl_GlobalInvocationID); + + vec4 color = texelFetch(sampler3D(voxelImageIn, voxelSampler), UV, 0); + + if(color.a > 0){ + uint flatIndex = flattenVoxelUVToIndex(UV, voxelImageSize); + vec3 N = unpackVoxelNormal(packedVoxelData[flatIndex].normal); + + float halfVoxelSize = voxelInfo.extent / float(voxelImageSize.x) * 0.5f; + vec3 pos = voxelCoordinatesToWorldPosition(UV, voxelImageSize.x, voxelInfo, halfVoxelSize); + + vec3 up = N.y >= 0.99 ? vec3(1, 0, 0) : vec3(0, 1, 0); + vec3 right = normalize(cross(up, N)); + up = cross(N, right); + mat3 toSurface = mat3(right, up, N); + + vec3 secondaryBounce = diffuseVoxelTraceHemisphere(toSurface, pos, voxelImageIn, voxelSampler, voxelInfo); + vec3 albedo = unpackVoxelAlbedo(packedVoxelData[flatIndex].albedo); + color.rgb += lambertBRDF(albedo) * secondaryBounce; + } + + imageStore(voxelImageOut, UV, color); +} \ No newline at end of file diff --git a/projects/voxelization/resources/shaders/voxelVisualisation.vert b/projects/voxelization/resources/shaders/voxelVisualisation.vert index 8377143f..e26e2209 100644 --- a/projects/voxelization/resources/shaders/voxelVisualisation.vert +++ b/projects/voxelization/resources/shaders/voxelVisualisation.vert @@ -25,7 +25,7 @@ void main() { int index2D = gl_VertexIndex % slicePixelCount; int y = index2D / voxelResolution; int x = index2D % voxelResolution; - vec3 position = (vec3(x, y, z) / voxelResolution - 0.5) * voxelInfo.extent + passCubeHalf + voxelInfo.offset; + vec3 position = voxelCoordinatesToWorldPosition(ivec3(x, y, z), voxelResolution, voxelInfo, passCubeHalf); gl_Position = vec4(position, 1.0); vec4 voxelColor = imageLoad(voxelImage, ivec3(x,y,z)); diff --git a/projects/voxelization/resources/shaders/voxelization.frag b/projects/voxelization/resources/shaders/voxelization.frag index 59cd07e1..3e5ce1fc 100644 --- a/projects/voxelization/resources/shaders/voxelization.frag +++ b/projects/voxelization/resources/shaders/voxelization.frag @@ -13,7 +13,7 @@ layout(location = 1) in vec2 passUV; layout(location = 2) in vec3 passN; layout(set=0, binding=0, std430) buffer voxelizationBuffer{ - uint packedVoxelData[]; + PackedVoxelData packedVoxelData[]; }; layout(set=0, binding=1) uniform voxelizationInfo{ @@ -46,5 +46,7 @@ void main() { vec3 color = albedo * sun; color = lambertBRDF(albedo) * sun; - atomicMax(packedVoxelData[flatIndex], packVoxelInfo(color)); + atomicMax(packedVoxelData[flatIndex].color, packVoxelColor(color)); + atomicMax(packedVoxelData[flatIndex].normal, packVoxelNormal(N)); + atomicMax(packedVoxelData[flatIndex].albedo, packVoxelAlbedo(albedo)); } \ No newline at end of file diff --git a/projects/voxelization/resources/shaders/voxelization.vert b/projects/voxelization/resources/shaders/voxelization.vert index 1302a424..221d0f6d 100644 --- a/projects/voxelization/resources/shaders/voxelization.vert +++ b/projects/voxelization/resources/shaders/voxelization.vert @@ -18,5 +18,5 @@ void main() { gl_Position = mvp * vec4(inPosition, 1.0); passPos = (model * vec4(inPosition, 1)).xyz; passUV = inUV; - passN = inNormal; + passN = mat3(model) * inNormal; } \ No newline at end of file diff --git a/projects/voxelization/src/Voxelization.cpp b/projects/voxelization/src/Voxelization.cpp index 824c3856..a14a880c 100644 --- a/projects/voxelization/src/Voxelization.cpp +++ b/projects/voxelization/src/Voxelization.cpp @@ -59,6 +59,16 @@ vkcv::ShaderProgram loadVoxelBufferToImageShader() { return shader; } +vkcv::ShaderProgram loadSecondaryBounceShader() { + vkcv::shader::GLSLCompiler compiler; + vkcv::ShaderProgram shader; + compiler.compile(vkcv::ShaderStage::COMPUTE, "resources/shaders/voxelSecondaryBounce.comp", + [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { + shader.addShader(shaderStage, path); + }); + return shader; +} + const uint32_t voxelResolution = 128; uint32_t voxelCount = voxelResolution * voxelResolution * voxelResolution; const vk::Format voxelizationDummyFormat = vk::Format::eR8Unorm; @@ -68,10 +78,12 @@ Voxelization::Voxelization( const Dependencies& dependencies, vkcv::BufferHandle lightInfoBuffer, vkcv::ImageHandle shadowMap, - vkcv::SamplerHandle shadowSampler) + vkcv::SamplerHandle shadowSampler, + vkcv::SamplerHandle voxelSampler) : m_corePtr(corePtr), m_voxelImage(m_corePtr->createImage(vk::Format::eR16G16B16A16Sfloat, voxelResolution, voxelResolution, voxelResolution, true, true)), + m_voxelImageIntermediate(m_corePtr->createImage(vk::Format::eR16G16B16A16Sfloat, voxelResolution, voxelResolution, voxelResolution, true, true)), m_dummyRenderTarget(m_corePtr->createImage(voxelizationDummyFormat, voxelResolution, voxelResolution, 1, false, false, true)), m_voxelInfoBuffer(m_corePtr->createBuffer<VoxelizationInfo>(vkcv::BufferType::UNIFORM, 1)), m_voxelBuffer(m_corePtr->createBuffer<VoxelBufferContent>(vkcv::BufferType::STORAGE, voxelCount)){ @@ -112,7 +124,7 @@ Voxelization::Voxelization( }; voxelizationDescriptorWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(4, shadowMap) }; voxelizationDescriptorWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(5, shadowSampler) }; - voxelizationDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(2, m_voxelImage.getHandle()) }; + voxelizationDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(2, m_voxelImageIntermediate.getHandle()) }; m_corePtr->writeDescriptorSet(m_voxelizationDescriptorSet, voxelizationDescriptorWrites); vkcv::ShaderProgram voxelVisualisationShader = loadVoxelVisualisationShader(); @@ -167,7 +179,7 @@ Voxelization::Voxelization( resetVoxelWrites.storageBufferWrites = { vkcv::StorageBufferDescriptorWrite(0, m_voxelBuffer.getHandle()) }; m_corePtr->writeDescriptorSet(m_voxelResetDescriptorSet, resetVoxelWrites); - + // buffer to image vkcv::ShaderProgram bufferToImageShader = loadVoxelBufferToImageShader(); m_bufferToImageDescriptorSet = m_corePtr->createDescriptorSet(bufferToImageShader.getReflectedDescriptors()[0]); @@ -177,8 +189,24 @@ Voxelization::Voxelization( vkcv::DescriptorWrites bufferToImageDescriptorWrites; bufferToImageDescriptorWrites.storageBufferWrites = { vkcv::StorageBufferDescriptorWrite(0, m_voxelBuffer.getHandle()) }; - bufferToImageDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(1, m_voxelImage.getHandle()) }; + bufferToImageDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(1, m_voxelImageIntermediate.getHandle()) }; m_corePtr->writeDescriptorSet(m_bufferToImageDescriptorSet, bufferToImageDescriptorWrites); + + // secondary bounce + vkcv::ShaderProgram secondaryBounceShader = loadSecondaryBounceShader(); + + m_secondaryBounceDescriptorSet = m_corePtr->createDescriptorSet(secondaryBounceShader.getReflectedDescriptors()[0]); + m_secondaryBouncePipe = m_corePtr->createComputePipeline( + secondaryBounceShader, + { m_corePtr->getDescriptorSet(m_secondaryBounceDescriptorSet).layout }); + + vkcv::DescriptorWrites secondaryBounceDescriptorWrites; + secondaryBounceDescriptorWrites.storageBufferWrites = { vkcv::StorageBufferDescriptorWrite(0, m_voxelBuffer.getHandle()) }; + secondaryBounceDescriptorWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(1, m_voxelImageIntermediate.getHandle()) }; + secondaryBounceDescriptorWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(2, voxelSampler) }; + secondaryBounceDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(3, m_voxelImage.getHandle()) }; + secondaryBounceDescriptorWrites.uniformBufferWrites = { vkcv::UniformBufferDescriptorWrite(4, m_voxelInfoBuffer.getHandle()) }; + m_corePtr->writeDescriptorSet(m_secondaryBounceDescriptorSet, secondaryBounceDescriptorWrites); } void Voxelization::voxelizeMeshes( @@ -229,7 +257,6 @@ void Voxelization::voxelizeMeshes( resetVoxelDispatchCount[1] = 1; resetVoxelDispatchCount[2] = 1; - m_corePtr->prepareImageForStorage(cmdStream, m_voxelImage.getHandle()); m_corePtr->recordComputeDispatchToCmdStream( cmdStream, m_voxelResetPipe, @@ -249,6 +276,7 @@ void Voxelization::voxelizeMeshes( })); } + m_corePtr->prepareImageForStorage(cmdStream, m_voxelImageIntermediate.getHandle()); m_corePtr->recordDrawcallsToCmdStream( cmdStream, m_voxelizationPass, @@ -271,8 +299,26 @@ void Voxelization::voxelizeMeshes( { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_bufferToImageDescriptorSet).vulkanHandle) }, vkcv::PushConstantData(nullptr, 0)); + m_corePtr->recordImageMemoryBarrier(cmdStream, m_voxelImageIntermediate.getHandle()); + + // intermediate image mipchain + m_voxelImageIntermediate.recordMipChainGeneration(cmdStream); + m_corePtr->prepareImageForSampling(cmdStream, m_voxelImageIntermediate.getHandle()); + + // secondary bounce + m_corePtr->prepareImageForStorage(cmdStream, m_voxelImage.getHandle()); + + m_corePtr->recordComputeDispatchToCmdStream( + cmdStream, + m_secondaryBouncePipe, + bufferToImageDispatchCount, + { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_secondaryBounceDescriptorSet).vulkanHandle) }, + vkcv::PushConstantData(nullptr, 0)); + m_voxelImage.recordMipChainGeneration(cmdStream); + m_corePtr->recordImageMemoryBarrier(cmdStream, m_voxelImage.getHandle()); + // final image mipchain m_voxelImage.recordMipChainGeneration(cmdStream); m_corePtr->prepareImageForSampling(cmdStream, m_voxelImage.getHandle()); } diff --git a/projects/voxelization/src/Voxelization.hpp b/projects/voxelization/src/Voxelization.hpp index bb0b5c5a..6f8d155d 100644 --- a/projects/voxelization/src/Voxelization.hpp +++ b/projects/voxelization/src/Voxelization.hpp @@ -14,7 +14,8 @@ public: const Dependencies& dependencies, vkcv::BufferHandle lightInfoBuffer, vkcv::ImageHandle shadowMap, - vkcv::SamplerHandle shadowSampler); + vkcv::SamplerHandle shadowSampler, + vkcv::SamplerHandle voxelSampler); void voxelizeMeshes( vkcv::CommandStreamHandle cmdStream, @@ -39,11 +40,14 @@ private: vkcv::Core* m_corePtr; struct VoxelBufferContent{ - uint32_t isFilled; + uint32_t lightEncoded; + uint32_t normalEncoded; + uint32_t albedoEncoded; }; + vkcv::Image m_voxelImageIntermediate; vkcv::Image m_voxelImage; - vkcv::Buffer<VoxelBufferContent> m_voxelBuffer; + vkcv::Buffer<VoxelBufferContent> m_voxelBuffer; vkcv::Image m_dummyRenderTarget; vkcv::PassHandle m_voxelizationPass; @@ -59,6 +63,9 @@ private: vkcv::PassHandle m_visualisationPass; vkcv::PipelineHandle m_visualisationPipe; + vkcv::PipelineHandle m_secondaryBouncePipe; + vkcv::DescriptorSetHandle m_secondaryBounceDescriptorSet; + vkcv::DescriptorSetHandle m_visualisationDescriptorSet; struct VoxelizationInfo { diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp index 57e25066..bd6bc22a 100644 --- a/projects/voxelization/src/main.cpp +++ b/projects/voxelization/src/main.cpp @@ -340,6 +340,12 @@ int main(int argc, const char** argv) { shadowDrawcalls.push_back(vkcv::DrawcallInfo(meshes[i], {})); } + vkcv::SamplerHandle voxelSampler = core.createSampler( + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerMipmapMode::LINEAR, + vkcv::SamplerAddressMode::CLAMP_TO_EDGE); + Voxelization::Dependencies voxelDependencies; voxelDependencies.colorBufferFormat = colorBufferFormat; voxelDependencies.depthBufferFormat = depthBufferFormat; @@ -349,16 +355,11 @@ int main(int argc, const char** argv) { voxelDependencies, lightBuffer.getHandle(), shadowMap.getHandle(), - shadowSampler); + shadowSampler, + voxelSampler); vkcv::Buffer<glm::vec3> cameraPosBuffer = core.createBuffer<glm::vec3>(vkcv::BufferType::UNIFORM, 1); - vkcv::SamplerHandle voxelSampler = core.createSampler( - vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerMipmapMode::LINEAR, - vkcv::SamplerAddressMode::CLAMP_TO_EDGE); - // write forward pass descriptor set vkcv::DescriptorWrites forwardDescriptorWrites; forwardDescriptorWrites.uniformBufferWrites = { -- GitLab