diff --git a/resources/shaders/VXGI/voxelization.glsl b/resources/shaders/VXGI/voxelization.glsl index fea0f79..1c67ac4 100644 --- a/resources/shaders/VXGI/voxelization.glsl +++ b/resources/shaders/VXGI/voxelization.glsl @@ -185,21 +185,24 @@ void main() { scene.lights[i].type != DIRECTIONAL_LIGHT ? normalize(scene.lights[i].worldPosition.xyz - _pos) : normalize(scene.lights[i].worldPosition.xyz), //wi //wo scene.lights[i].color * computeAttenuation(scene.lights[i].worldPosition.xyz, _pos,scene.lights[i].areaEffect,int(scene.lights[i].type)) * scene.lights[i].intensity ); - if(scene.lights[i].shadowCast == 1) { - if(scene.lights[i].shadowType == 0) //Classic - lighting *= computeShadow(shadowMap, scene.lights[i], i, _pos); - if(scene.lights[i].shadowType == 1) //VSM - lighting *= computeVarianceShadow(shadowMap, scene.lights[i], i, _pos); - if(scene.lights[i].shadowType == 2) //Raytraced - lighting *= computeRaytracedShadow( - TLAS, - blueNoiseMap, - _pos, - scene.lights[i].type != DIRECTIONAL_LIGHT ? scene.lights[i].worldPosition.xyz - _pos : scene.lights[i].shadowData.xyz, - 1, - 0.0, - 0); - } + + + //Visibility__________________________ + // if(scene.lights[i].shadowCast == 1) { + // if(scene.lights[i].shadowType == 0) //Classic + // lighting *= computeShadow(shadowMap, scene.lights[i], i, _pos); + // if(scene.lights[i].shadowType == 1) //VSM + // lighting *= computeVarianceShadow(shadowMap, scene.lights[i], i, _pos); + // if(scene.lights[i].shadowType == 2) //Raytraced + // lighting *= computeRaytracedShadow( + // TLAS, + // blueNoiseMap, + // _pos, + // scene.lights[i].type != DIRECTIONAL_LIGHT ? scene.lights[i].worldPosition.xyz - _pos : scene.lights[i].shadowData.xyz, + // 1, + // 0.0, + // 0); + // } color += lighting; } diff --git a/resources/shaders/deferred/composition.glsl b/resources/shaders/deferred/composition.glsl index aa6d91d..a2e9bf7 100644 --- a/resources/shaders/deferred/composition.glsl +++ b/resources/shaders/deferred/composition.glsl @@ -87,6 +87,7 @@ int g_isReflective; vec4 g_temp; + vec3 GI(vec3 worldPos, vec3 worldNormal){ const float VOXEL_SIZE = 1.0/float(settings.vxgi.resolution); const float ISQRT2 = 0.707106; @@ -112,35 +113,36 @@ vec3 GI(vec3 worldPos, vec3 worldNormal){ // Backward in cone direction improves GI, and forward direction removes // artifacts. const float CONE_OFFSET = -0.01; + const float CONE_SPREAD = 0.325; // Trace front cone - indirect += w[0] * traceDiffuseVoxelCone(voxelMap, C_ORIGIN + CONE_OFFSET * worldNormal, worldNormal, VOXEL_SIZE ); + indirect += w[0] * traceVoxelCone(voxelMap, C_ORIGIN + CONE_OFFSET * worldNormal, worldNormal,CONE_SPREAD, VOXEL_SIZE ); // Trace 4 side cones. const vec3 s1 = mix(worldNormal, ortho, ANGLE_MIX); - indirect += w[1] * traceDiffuseVoxelCone(voxelMap, C_ORIGIN + CONE_OFFSET * ortho, s1, VOXEL_SIZE ); + indirect += w[1] * traceVoxelCone(voxelMap, C_ORIGIN + CONE_OFFSET * ortho, s1,CONE_SPREAD, VOXEL_SIZE ); const vec3 s2 = mix(worldNormal, -ortho, ANGLE_MIX); - indirect += w[1] * traceDiffuseVoxelCone(voxelMap, C_ORIGIN - CONE_OFFSET * ortho, s2, VOXEL_SIZE ); + indirect += w[1] * traceVoxelCone(voxelMap, C_ORIGIN - CONE_OFFSET * ortho, s2,CONE_SPREAD, VOXEL_SIZE ); const vec3 s3 = mix(worldNormal, ortho2, ANGLE_MIX); - indirect += w[1] * traceDiffuseVoxelCone(voxelMap, C_ORIGIN + CONE_OFFSET * ortho2, s3, VOXEL_SIZE ); + indirect += w[1] * traceVoxelCone(voxelMap, C_ORIGIN + CONE_OFFSET * ortho2, s3,CONE_SPREAD, VOXEL_SIZE ); const vec3 s4 = mix(worldNormal, -ortho2, ANGLE_MIX); - indirect += w[1] * traceDiffuseVoxelCone(voxelMap, C_ORIGIN - CONE_OFFSET * ortho2, s4, VOXEL_SIZE ); + indirect += w[1] * traceVoxelCone(voxelMap, C_ORIGIN - CONE_OFFSET * ortho2, s4,CONE_SPREAD, VOXEL_SIZE ); // Trace 4 corner cones. const vec3 c1 = mix(worldNormal, corner, ANGLE_MIX); - indirect += w[2] * traceDiffuseVoxelCone(voxelMap, C_ORIGIN + CONE_OFFSET * corner, c1, VOXEL_SIZE ); + indirect += w[2] * traceVoxelCone(voxelMap, C_ORIGIN + CONE_OFFSET * corner, c1,CONE_SPREAD, VOXEL_SIZE ); const vec3 c2 = mix(worldNormal, -corner, ANGLE_MIX); - indirect += w[2] * traceDiffuseVoxelCone(voxelMap, C_ORIGIN - CONE_OFFSET * corner, c2, VOXEL_SIZE ); + indirect += w[2] * traceVoxelCone(voxelMap, C_ORIGIN - CONE_OFFSET * corner, c2,CONE_SPREAD, VOXEL_SIZE ); const vec3 c3 = mix(worldNormal, corner2, ANGLE_MIX); - indirect += w[2] * traceDiffuseVoxelCone(voxelMap, C_ORIGIN + CONE_OFFSET * corner2, c3, VOXEL_SIZE ); + indirect += w[2] * traceVoxelCone(voxelMap, C_ORIGIN + CONE_OFFSET * corner2, c3,CONE_SPREAD, VOXEL_SIZE ); const vec3 c4 = mix(worldNormal, -corner2, ANGLE_MIX); - indirect += w[2] * traceDiffuseVoxelCone(voxelMap, C_ORIGIN - CONE_OFFSET * corner2, c4, VOXEL_SIZE ); + indirect += w[2] * traceVoxelCone(voxelMap, C_ORIGIN - CONE_OFFSET * corner2, c4,CONE_SPREAD, VOXEL_SIZE ); // Return result. // return DIFFUSE_INDIRECT_FACTOR * material.diffuseReflectivity * acc * (material.diffuseColor + vec3(0.001f)); @@ -187,6 +189,7 @@ void main() vec3 direct = vec3(0.0); vec3 ambient = vec3(0.0); vec3 indirect = vec3(0.0); + vec3 indirect2 = vec3(0.0); vec3 modelPos = (camera.invView * vec4(g_pos.xyz, 1.0)).xyz; vec3 modelNormal = (camera.invView * vec4(g_normal.xyz, 0.0)).xyz; @@ -206,12 +209,50 @@ void main() brdf.F0 = vec3(0.04); brdf.F0 = mix(brdf.F0, brdf.albedo, brdf.metalness); brdf.emission = g_emission; - - // GI ____________________________ + // Indirect Component ____________________________ if(settings.vxgi.enabled == 1){ - indirect = GI(modelPos, modelNormal)*settings.vxgi.strength*g_albedo; + vec3 diffuseIndirect = vec3(0.0); + + const float VOXEL_SIZE = 1.0/float(settings.vxgi.resolution); + + + // Offset startPos to avoid self occlusion + vec3 startPos = modelPos + modelNormal * VOXEL_SIZE; + + float coneTraceCount = 0.0; + float cosSum = 0.0; + for (int i = 0; i < DIFFUSE_CONE_COUNT; ++i) + { + float cosTheta = dot(modelNormal, DIFFUSE_CONE_DIRECTIONS[i]); + + if (cosTheta < 0.0) + continue; + + coneTraceCount += 1.0; + diffuseIndirect += traceVoxelCone(voxelMap, startPos, DIFFUSE_CONE_DIRECTIONS[i],DIFFUSE_CONE_APERTURE , VOXEL_SIZE ); + } + + diffuseIndirect /= coneTraceCount; + // indirectContribution.a *= u_ambientOcclusionFactor; + + diffuseIndirect.rgb *= g_albedo * settings.vxgi.strength; + + + indirect = diffuseIndirect.rgb; + + + // indirect = GI(modelPos, modelNormal)*settings.vxgi.strength*g_albedo; indirect*= settings.enableAO == 1 ? (brdf.ao * SSAO) : brdf.ao; + + // vec3 specularConeDirection = reflect(normalize(camera.position.xyz-modelPos), modelNormal); + // vec3 specularIndirect = vec3(0.0); + + + // specularIndirect = traceVoxelCone(voxelMap, startPos, specularConeDirection, max(brdf.roughness, 0.05) , VOXEL_SIZE ); + // // specularIndirect = castCone(startPos, specularConeDirection, max(roughness, MIN_SPECULAR_APERTURE), MAX_TRACE_DISTANCE, minLevel).rgb * specColor.rgb * u_indirectSpecularIntensity; + // indirect2+=specularIndirect; } + //Direct Component ________________________ for(int i = 0; i < scene.numLights; i++) { @@ -232,7 +273,6 @@ void main() if(scene.lights[i].shadowType == 1) //VSM lighting *= computeVarianceShadow(shadowMap, scene.lights[i], i, modelPos); if(scene.lights[i].shadowType == 2) //Raytraced - // lighting *= traceShadowCone(voxelMap, modelPos, scene.lights[i].type != DIRECTIONAL_LIGHT ? scene.lights[i].worldPosition.xyz - modelPos : scene.lights[i].shadowData.xyz, modelNormal, 1.0/float(settings.vxgi.resolution), length(scene.lights[i].worldPosition.xyz - modelPos) ); lighting *= computeRaytracedShadow( TLAS, blueNoiseMap, @@ -263,6 +303,7 @@ void main() ambient = (scene.ambientIntensity * scene.ambientColor) * brdf.albedo; } ambient *= settings.enableAO == 1 ? (brdf.ao * SSAO) : brdf.ao; + //SSR ________________________________ vec3 fresnel = fresnelSchlick(max(dot(g_normal, normalize(g_pos)), 0.0), brdf.F0); if(settings.ssr.enabled == 1 && g_isReflective == 1){ diff --git a/resources/shaders/include/VXGI.glsl b/resources/shaders/include/VXGI.glsl index 3015016..2bd9a72 100644 --- a/resources/shaders/include/VXGI.glsl +++ b/resources/shaders/include/VXGI.glsl @@ -13,10 +13,62 @@ struct VXGI { uint enabled; }; -vec3 traceDiffuseVoxelCone(sampler3D voxelization ,const vec3 O, vec3 dir, const float VOXEL_SIZE){ +const int DIFFUSE_CONE_COUNT = 16; +const float DIFFUSE_CONE_APERTURE = 0.872665; + +const vec3 DIFFUSE_CONE_DIRECTIONS[16] = { + vec3(0.57735, 0.57735, 0.57735), + vec3(0.57735, -0.57735, -0.57735), + vec3(-0.57735, 0.57735, -0.57735), + vec3(-0.57735, -0.57735, 0.57735), + vec3(-0.903007, -0.182696, -0.388844), + vec3(-0.903007, 0.182696, 0.388844), + vec3(0.903007, -0.182696, 0.388844), + vec3(0.903007, 0.182696, -0.388844), + vec3(-0.388844, -0.903007, -0.182696), + vec3(0.388844, -0.903007, 0.182696), + vec3(0.388844, 0.903007, -0.182696), + vec3(-0.388844, 0.903007, 0.182696), + vec3(-0.182696, -0.388844, -0.903007), + vec3(0.182696, 0.388844, -0.903007), + vec3(-0.182696, 0.388844, 0.903007), + vec3(0.182696, -0.388844, 0.903007) +}; + +// vec4 traceVoxelCone(sampler3D voxelization, vec3 origin, vec3 direction, float tanHalfAngle) +// { +// float lod = 0.0f; +// vec3 color = vec3(0.0f); +// float alpha = 0.0f; +// float occlusion = 0.0f; + +// //Voxel Cube Size +// float voxelWorldSize = VoxelGridWorldSize / VoxelDimensions; +// float dist = voxelWorldSize; +// vec3 startPos = Position_world + Normal_world * voxelWorldSize; + +// while(dist < MAX_DISTANCE && alpha < MAX_ALPHA) +// { +// float diameter = max(voxelWorldSize, 2.0f * tanHalfAngle * dist); +// float lodLevel = log2(diameter / voxelWorldSize); +// vec4 voxelColor = SampleVoxels(startPos + dist * direction, lodLevel); + +// color += (1.0f - alpha) * voxelColor.rgb; +// occlusion += ((1.0f - alpha) * voxelColor.a) / (1.0f + 0.03f * diameter); +// alpha += (1.0f - alpha) * voxelColor.a; +// dist += diameter; +// } + +// return vec4(color, occlusion); +// } + +/* +FIRST TRY +*/ +vec3 traceVoxelCone(sampler3D voxelization ,const vec3 O, vec3 dir, const float CONE_SPREAD, const float VOXEL_SIZE){ dir = normalize(dir); - const float CONE_SPREAD = 0.325; + // const float CONE_SPREAD = 0.325; vec4 color = vec4(0.0); @@ -49,25 +101,28 @@ vec3 traceDiffuseVoxelCone(sampler3D voxelization ,const vec3 O, vec3 dir, const } -// Returns a soft shadow blend by using shadow cone tracing. -// Uses 2 samples per step, so it's pretty expensive. -float traceShadowCone(sampler3D voxelization , vec3 O, vec3 dir, vec3 normal, const float VOXEL_SIZE, float targetDistance){ - O += normal * 0.05; // Removes artifacts but makes self shadowing for dense meshes meh. - - float color = 0; - - float dist = 3 * VOXEL_SIZE; - // I'm using a pretty big margin here since I use an emissive light ball with a pretty big radius in my demo scenes. - const float STOP = targetDistance - 16 * VOXEL_SIZE; - - while(dist < STOP && color < 1){ - vec3 c = mapToZeroOne(O + dist * dir, scene.minCoord.xyz, scene.maxCoord.xyz); - float l = pow(dist, 2); // Experimenting with inverse square falloff for shadows. - float s1 = 0.062 * textureLod(voxelization, c, 1 + 0.75 * l).a; - float s2 = 0.135 * textureLod(voxelization, c, 4.5 * l).a; - float s = s1 + s2; - color += (1 - color) * s; - dist += 0.9 * VOXEL_SIZE * (1 + 0.05 * l); - } - return 1 - pow(smoothstep(0, 1, color * 1.4), 1.0 / 1.4); -} \ No newline at end of file +vec3 diffuseVoxelGI(sampler3D voxelMap, vec3 worldPos, vec3 worldNormal, int resolution){ +// vec3 diffuseIndirect = vec3(0.0); + +// const float VOXEL_SIZE = 1.0/float(resolution); + + +// vec3 startPos = worldPos + worldNormal * VOXEL_SIZE; + +// float coneTraceCount = 0.0; +// float cosSum = 0.0; +// for (int i = 0; i < DIFFUSE_CONE_COUNT; ++i) +// { +// float cosTheta = dot(worldNormal, DIFFUSE_CONE_DIRECTIONS[i]); +// if (cosTheta < 0.0) +// continue; +// coneTraceCount += 1.0; +// diffuseIndirect += traceVoxelCone(voxelMap, startPos, DIFFUSE_CONE_DIRECTIONS[i],DIFFUSE_CONE_APERTURE , VOXEL_SIZE ) * cosTheta; +// } + +// diffuseIndirect /= DIFFUSE_CONE_COUNT * 0.5; + +// // indirectContribution.a *= u_ambientOcclusionFactor; +// return diffuseIndirect; + +} diff --git a/resources/shaders/misc/tonemapping.glsl b/resources/shaders/misc/tonemapping.glsl index 9739ab4..acae2f5 100644 --- a/resources/shaders/misc/tonemapping.glsl +++ b/resources/shaders/misc/tonemapping.glsl @@ -27,7 +27,8 @@ layout(location = 0) out vec4 outputImage; void main() { vec3 result = texture(inputImage,v_uv).rgb; - result = vec3(1.0) - exp(-result * 1.0); + float exposure = 1.0; + result = vec3(1.0) - exp(-result * exposure); // result = result / (result + vec3(1.0)); outputImage = vec4(result,1.0); //WIP diff --git a/src/core/passes/voxelization_pass.cpp b/src/core/passes/voxelization_pass.cpp index 3b0323f..955f025 100644 --- a/src/core/passes/voxelization_pass.cpp +++ b/src/core/passes/voxelization_pass.cpp @@ -17,7 +17,8 @@ void VoxelizationPass::create_voxelization_image() { m_resourceImages[0].create_view(config); SamplerConfig samplerConfig = {}; - samplerConfig.samplerAddressMode = ADDRESS_MODE_CLAMP_TO_EDGE; + samplerConfig.samplerAddressMode = ADDRESS_MODE_CLAMP_TO_BORDER; + samplerConfig.border = BorderColor::FLOAT_OPAQUE_BLACK; m_resourceImages[0].create_sampler(samplerConfig); } diff --git a/src/core/scene/scene.cpp b/src/core/scene/scene.cpp index 7bafdb5..20f88ce 100644 --- a/src/core/scene/scene.cpp +++ b/src/core/scene/scene.cpp @@ -8,8 +8,13 @@ VKFW::Graphics::TLAS* VKFW::Core::get_TLAS(Scene* const scene) { } void VKFW::Core::Scene::update_AABB() { + m_volume.maxCoords = Vec3(0.0); + m_volume.minCoords = Vec3(INFINITY); + for (Mesh* m : m_meshes) { + if (!m->is_active()) + continue; BV const* bvolume = m->get_bounding_volume(); if (!bvolume) continue; @@ -34,5 +39,11 @@ void VKFW::Core::Scene::update_AABB() { m_volume.minCoords.z = minCoords.z; } + // Make a cube container for voxelization + float maxTerm = std::max(std::max(m_volume.maxCoords.r, m_volume.maxCoords.g), m_volume.maxCoords.b); + float minTerm = std::min(std::min(m_volume.minCoords.r, m_volume.minCoords.g), m_volume.minCoords.b); + m_volume.maxCoords = Vec3(maxTerm); + m_volume.minCoords = Vec3(minTerm); + m_volume.center = (m_volume.maxCoords + m_volume.minCoords) * 0.5f; } \ No newline at end of file