From 7670c8c3afdbafa1d9c52191d2a49dfb84c1be2f Mon Sep 17 00:00:00 2001 From: mrq Date: Thu, 6 May 2021 00:00:00 -0500 Subject: [PATCH] Commit for 2021.05.06.7z --- bin/data/shaders/display/subpass.frag.glsl | 2 +- .../shaders/display/subpass.vxgi.frag.glsl | 163 ++++++------------ bin/data/shaders/display/vxgi.comp.glsl | 20 +-- bin/data/shaders/gltf/baking/bake.frag.glsl | 11 +- bin/data/shaders/gltf/base.frag.glsl | 11 +- bin/data/shaders/gltf/voxelize.frag.glsl | 9 +- bin/data/shaders/gltf/voxelize.geom.glsl | 11 +- engine/inc/uf/ext/gltf/pod.h | 2 + engine/src/ext/gltf/graph.cpp | 4 +- .../src/ext/vulkan/rendermodes/deferred.cpp | 10 +- .../ext/vulkan/rendermodes/rendertarget.cpp | 10 +- ext/behaviors/scene/behavior.cpp | 4 +- ext/behaviors/voxelizer/behavior.cpp | 15 ++ ext/behaviors/voxelizer/behavior.h | 1 + 14 files changed, 121 insertions(+), 152 deletions(-) diff --git a/bin/data/shaders/display/subpass.frag.glsl b/bin/data/shaders/display/subpass.frag.glsl index face4f81..05d979be 100644 --- a/bin/data/shaders/display/subpass.frag.glsl +++ b/bin/data/shaders/display/subpass.frag.glsl @@ -39,7 +39,7 @@ const vec2 poissonDisk[16] = vec2[]( vec2( 0.14383161, -0.14100790 ) ); -layout (constant_id = 0) const uint TEXTURES = 256; +layout (constant_id = 0) const uint TEXTURES = 512; struct Matrices { mat4 view[2]; diff --git a/bin/data/shaders/display/subpass.vxgi.frag.glsl b/bin/data/shaders/display/subpass.vxgi.frag.glsl index e8edc0e2..532a9855 100644 --- a/bin/data/shaders/display/subpass.vxgi.frag.glsl +++ b/bin/data/shaders/display/subpass.vxgi.frag.glsl @@ -1,5 +1,6 @@ #version 450 #extension GL_EXT_samplerless_texture_functions : require +#extension GL_EXT_nonuniform_qualifier : enable #define MULTISAMPLING 1 #define DEFERRED_SAMPLING 1 @@ -21,7 +22,7 @@ const float PI = 3.14159265359; const float EPSILON = 0.00001; const float SQRT2 = 1.41421356237; -const float LIGHT_POWER_CUTOFF = 0.005; +const float LIGHT_POWER_CUTOFF = 0.0005; const vec2 poissonDisk[16] = vec2[]( vec2( -0.94201624, -0.39906216 ), @@ -42,9 +43,8 @@ const vec2 poissonDisk[16] = vec2[]( vec2( 0.14383161, -0.14100790 ) ); -#define MAX_CASCADES 4 -layout (constant_id = 0) const uint CASCADES = MAX_CASCADES; -layout (constant_id = 1) const uint TEXTURES = 256; +layout (constant_id = 0) const uint CASCADES = 16; +layout (constant_id = 1) const uint TEXTURES = 512; struct Matrices { mat4 view[2]; @@ -213,7 +213,7 @@ layout (binding = 4) uniform UBO { float exposure; uint msaa; uint shadowSamples; - uint padding1; + float cascadePower; } ubo; layout (std140, binding = 5) readonly buffer Lights { @@ -425,10 +425,10 @@ float shadowFactor( const Light light, float def ) { const float bias = light.depthBias; const float eyeDepth = positionClip.z; const int samples = int(ubo.shadowSamples); - if ( samples < 1 ) return eyeDepth < texture(samplerTextures[light.mapIndex], uv).r - bias ? 0.0 : factor; + if ( samples < 1 ) return eyeDepth < texture(samplerTextures[nonuniformEXT(light.mapIndex)], uv).r - bias ? 0.0 : factor; for ( int i = 0; i < samples; ++i ) { const int index = int( float(samples) * random(floor(surface.position.world.xyz * 1000.0), i)) % samples; - const float lightDepth = texture(samplerTextures[light.mapIndex], uv + poissonDisk[index] / 700.0 ).r; + const float lightDepth = texture(samplerTextures[nonuniformEXT(light.mapIndex)], uv + poissonDisk[index] / 700.0 ).r; if ( eyeDepth < lightDepth - bias ) factor -= 1.0 / samples; } return factor; @@ -452,71 +452,64 @@ vec4 postProcess() { return vec4(surface.fragment.rgb,1); } -uint BIASED_ROUND( float x ) { - return uint( x < 255.0 / 256.0 ? floor(x) : ceil(x)); -} -#define CASCADE_POWER 2 -uint SCALE_CASCADE( uint x ) { - return uint(pow(1 + x, CASCADE_POWER)); -} - struct VoxelInfo { vec3 min; vec3 max; float mipmapLevels; float radianceSize; - float voxelSize; - float radianceSizeRecip; - float voxelSizeRecip; } voxelInfo; +uint BIASED_ROUND( float x ) { + return uint( (x < 1 - voxelInfo.radianceSizeRecip) ? floor(x) : ceil(x)); +} +float SCALE_CASCADE( uint x ) { + return pow(1 + x, ubo.cascadePower); +} + vec4 voxelTrace( inout Ray ray, float aperture, float maxDistance ) { - uint CASCADE = 1; + uint CASCADE = 0; #if VXGI_NDC ray.origin = vec3( ubo.matrices.vxgi * vec4( ray.origin, 1.0 ) ); ray.direction = vec3( ubo.matrices.vxgi * vec4( ray.direction, 0.0 ) ); - const float granularity = 1.0f / 32.0f; - const uint maxSteps = uint(voxelInfo.radianceSize * 2 * CASCADES); CASCADE = BIASED_ROUND(clamp( max( max( abs(ray.origin.x), abs(ray.origin.y) ), abs(ray.origin.z) ), 0, CASCADES - 1 )); #else - const float granularity = 16.0f; - const uint maxSteps = uint(voxelInfo.radianceSize * granularity * CASCADES); - { - vec3 uvw = vec3( ubo.matrices.vxgi * vec4( ray.origin, 1.0 ) ); - CASCADE = BIASED_ROUND(clamp( max( max( abs(uvw.x), abs(uvw.y) ), abs(uvw.z) ), 0, CASCADES - 1 )); - } +{ + vec3 uvw = vec3( ubo.matrices.vxgi * vec4( ray.origin, 1.0 ) ); + CASCADE = BIASED_ROUND(clamp( max( max( abs(uvw.x), abs(uvw.y) ), abs(uvw.z) ), 0, CASCADES - 1 )); +} #endif - const float granularityRecip = 1.0f / granularity; + const float granularityRecip = 12.0f; + const float granularity = 1.0f / granularityRecip; + const float occlusionFalloff = 128.0f; + + const vec3 voxelBounds = voxelInfo.max - voxelInfo.min; + const vec3 voxelBoundsRecip = 1.0f / voxelBounds; + + const float coneCoefficient = 2.0 * tan(aperture * 0.5); + const uint maxSteps = uint(voxelInfo.radianceSize * CASCADES * granularityRecip); // box const vec2 rayBoxInfoA = rayBoxDst( voxelInfo.min * SCALE_CASCADE(CASCADE), voxelInfo.max * SCALE_CASCADE(CASCADE), ray ); const vec2 rayBoxInfoB = rayBoxDst( voxelInfo.min * SCALE_CASCADE(CASCADES), voxelInfo.max * SCALE_CASCADE(CASCADES), ray ); + const float tStart = rayBoxInfoA.x; const float tEnd = maxDistance > 0 ? min(maxDistance, rayBoxInfoB.y * SCALE_CASCADE(CASCADES)) : rayBoxInfoB.y * SCALE_CASCADE(CASCADES); - // steps - const float tDelta = voxelInfo.voxelSize * granularityRecip; + const float tDelta = voxelInfo.radianceSizeRecip * granularityRecip; // marcher -#if VXGI_NDC - ray.distance = tStart + tDelta * granularityRecip * 0.25; -#else - ray.distance = tStart + tDelta * granularity; -#endif + ray.distance = tStart + tDelta * 4 * (1 + CASCADE); ray.position = vec3(0); + vec4 radiance = vec4(0); vec3 uvw = vec3(0); - // cone mipmap shit - const float coneCoefficient = 2.0 * tan(aperture * 0.5); + float coneDiameter = coneCoefficient * ray.distance; float level = aperture > 0 ? log2( coneDiameter ) : 0; - // results + vec4 color = vec4(0); float occlusion = 0.0; uint stepCounter = 0; - const float falloff = 128.0f; // maxDistance > 0.0 ? 0.0f : 256.0f; - const vec3 voxelBounds = voxelInfo.max - voxelInfo.min; - const vec3 voxelBoundsRecip = 1.0f / voxelBounds; #if VXGI_NDC while ( ray.distance < tEnd && color.a < 1.0 && occlusion < 1.0 && stepCounter++ < maxSteps ) { #else @@ -541,52 +534,10 @@ vec4 voxelTrace( inout Ray ray, float aperture, float maxDistance ) { if ( level >= voxelInfo.mipmapLevels ) break; - // radiance = textureLod(voxelRadiance[CASCADE], uvw.xzy, level); - #define C 0 - #if C < MAX_CASCADES - if ( CASCADE == C && C < CASCADES ) radiance = textureLod(voxelRadiance[C], uvw.xzy, level); - #endif - #undef C - #define C 1 - #if C < MAX_CASCADES - if ( CASCADE == C && C < CASCADES ) radiance = textureLod(voxelRadiance[C], uvw.xzy, level); - #endif - #undef C - #define C 2 - #if C < MAX_CASCADES - if ( CASCADE == C && C < CASCADES ) radiance = textureLod(voxelRadiance[C], uvw.xzy, level); - #endif - #undef C - #define C 3 - #if C < MAX_CASCADES - if ( CASCADE == C && C < CASCADES ) radiance = textureLod(voxelRadiance[C], uvw.xzy, level); - #endif - #undef C - #define C 4 - #if C < MAX_CASCADES - if ( CASCADE == C && C < CASCADES ) radiance = textureLod(voxelRadiance[C], uvw.xzy, level); - #endif - #undef C - #define C 5 - #if C < MAX_CASCADES - if ( CASCADE == C && C < CASCADES ) radiance = textureLod(voxelRadiance[C], uvw.xzy, level); - #endif - #undef C - #define C 6 - #if C < MAX_CASCADES - if ( CASCADE == C && C < CASCADES ) radiance = textureLod(voxelRadiance[C], uvw.xzy, level); - #endif - #undef C - #define C 7 - #if C < MAX_CASCADES - if ( CASCADE == C && C < CASCADES ) radiance = textureLod(voxelRadiance[C], uvw.xzy, level); - #endif - #undef C - - // else radiance = textureLod(voxelRadiance[CASCADE], uvw.xzy, level); + radiance = textureLod(voxelRadiance[nonuniformEXT(CASCADE)], uvw.xzy, level); color += (1.0 - color.a) * radiance; - occlusion += ((1.0f - occlusion) * radiance.a) / (1.0f + falloff * coneDiameter); + occlusion += ((1.0f - occlusion) * radiance.a) / (1.0f + occlusionFalloff * coneDiameter); } return maxDistance > 0 ? color : vec4(color.rgb, occlusion); // return vec4(color.rgb, occlusion); @@ -604,13 +555,8 @@ float shadowFactor( const Light light, float def ) { const float DEPTH_BIAS = 0.0; Ray ray; - ray.origin = surface.position.world; ray.direction = normalize( light.position - surface.position.world ); -#if VXGI_NDC -// ray.origin -= ray.direction * 0.125; -#else - ray.origin -= ray.direction * 0.5; -#endif + ray.origin = surface.position.world + ray.direction * 0.5; float z = distance( surface.position.world, light.position ) - DEPTH_BIAS; return 1.0 - voxelTrace( ray, SHADOW_APERTURE, z ).a; } @@ -694,7 +640,7 @@ void main() { if ( useAtlas ) textureAtlas = textures[drawCall.textureIndex + material.indexAtlas]; if ( validTextureIndex( drawCall.textureIndex + material.indexAlbedo ) ) { const Texture t = textures[drawCall.textureIndex + material.indexAlbedo]; - surface.material.albedo = textureLod( samplerTextures[(useAtlas)?textureAtlas.index:t.index], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, surface.uv ) : surface.uv, mip ); + surface.material.albedo = textureLod( samplerTextures[nonuniformEXT((useAtlas)?textureAtlas.index:t.index)], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, surface.uv ) : surface.uv, mip ); } // OPAQUE if ( material.modeAlpha == 0 ) { @@ -709,7 +655,7 @@ void main() { // Emissive textures if ( validTextureIndex( drawCall.textureIndex + material.indexEmissive ) ) { const Texture t = textures[drawCall.textureIndex + material.indexEmissive]; - surface.fragment += textureLod( samplerTextures[(useAtlas)?textureAtlas.index:t.index], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, surface.uv ) : surface.uv, mip ); + surface.fragment += textureLod( samplerTextures[nonuniformEXT((useAtlas)?textureAtlas.index:t.index)], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, surface.uv ) : surface.uv, mip ); } #else #if !MULTISAMPLING @@ -722,6 +668,19 @@ void main() { surface.material.roughness = material.factorRoughness; surface.material.occlusion = material.factorOcclusion; // GI + { + voxelInfo.radianceSize = textureSize( voxelRadiance[0], 0 ).x; + voxelInfo.radianceSizeRecip = 1.0 / voxelInfo.radianceSize; + voxelInfo.mipmapLevels = log2(voxelInfo.radianceSize) + 1; + #if VXGI_NDC + voxelInfo.min = vec3( -1 ); + voxelInfo.max = vec3( 1 ); + #else + const mat4 inverseOrtho = inverse( ubo.matrices.vxgi ); + voxelInfo.min = vec3( inverseOrtho * vec4( -1, -1, -1, 1 ) ); + voxelInfo.max = vec3( inverseOrtho * vec4( 1, 1, 1, 1 ) ); + #endif + } { const vec3 P = surface.position.world; const vec3 N = surface.normal.world; @@ -769,22 +728,6 @@ void main() { vec4 indirectDiffuse = vec4(0); vec4 indirectSpecular = vec4(0); - { - voxelInfo.radianceSize = textureSize( voxelRadiance[0], 0 ).x; - voxelInfo.radianceSizeRecip = 1.0 / voxelInfo.radianceSize; - voxelInfo.mipmapLevels = log2(voxelInfo.radianceSize) + 1; - #if VXGI_NDC - voxelInfo.min = vec3( -1 ); - voxelInfo.max = vec3( 1 ); - voxelInfo.voxelSize = voxelInfo.radianceSizeRecip; - #else - const mat4 inverseOrtho = inverse( ubo.matrices.vxgi ); - voxelInfo.min = vec3( inverseOrtho * vec4( -1, -1, -1, 1 ) ); - voxelInfo.max = vec3( inverseOrtho * vec4( 1, 1, 1, 1 ) ); - voxelInfo.voxelSize = 1; - #endif - voxelInfo.voxelSizeRecip = 1.0 / voxelInfo.voxelSize; - } // outFragColor.rgb = voxelConeTrace( surface.ray, 0 ).rgb; return; if ( DIFFUSE_INDIRECT_FACTOR > 0.0f ) { @@ -869,7 +812,7 @@ void main() { // point light, compute only diffuse // else if ( abs(light.type) == 1 ) surface.fragment.rgb += (diffuse) * Lr * cosLi; else surface.fragment.rgb += (diffuse + specular) * Lr * cosLi; - surface.fragment.a += light.power * La * Ls; + // surface.fragment.a += light.power * La * Ls; } } diff --git a/bin/data/shaders/display/vxgi.comp.glsl b/bin/data/shaders/display/vxgi.comp.glsl index 92433a41..c3a20196 100644 --- a/bin/data/shaders/display/vxgi.comp.glsl +++ b/bin/data/shaders/display/vxgi.comp.glsl @@ -1,5 +1,6 @@ #version 450 #extension GL_EXT_samplerless_texture_functions : require +#extension GL_EXT_nonuniform_qualifier : enable layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in; @@ -14,8 +15,8 @@ const float EPSILON = 0.00001; const float LIGHT_POWER_CUTOFF = 0.005; -layout (constant_id = 0) const uint CASCADES = 4; -layout (constant_id = 1) const uint TEXTURES = 256; +layout (constant_id = 0) const uint CASCADES = 16; +layout (constant_id = 1) const uint TEXTURES = 512; struct Matrices { mat4 view[2]; @@ -156,7 +157,7 @@ layout (binding = 4) uniform UBO { float exposure; uint msaa; uint shadowSamples; - uint padding1; + float cascadePower; } ubo; layout (std140, binding = 5) readonly buffer Lights { @@ -269,20 +270,19 @@ float shadowFactor( const Light light, float def ) { const float bias = light.depthBias; const float eyeDepth = positionClip.z; const int samples = int(ubo.shadowSamples); - return eyeDepth < texture(samplerTextures[light.mapIndex], uv).r - bias ? 0.0 : factor; + return eyeDepth < texture(samplerTextures[nonuniformEXT(light.mapIndex)], uv).r - bias ? 0.0 : factor; #if 0 for ( int i = 0; i < samples; ++i ) { const int index = int( float(samples) * random(floor(surface.position.world.xyz * 1000.0), i)) % samples; - const float lightDepth = texture(samplerTextures[light.mapIndex], uv + poissonDisk[index] / 700.0 ).r; + const float lightDepth = texture(samplerTextures[nonuniformEXT(light.mapIndex)], uv + poissonDisk[index] / 700.0 ).r; if ( eyeDepth < lightDepth - bias ) factor -= 1.0 / samples; } return factor; #endif } -#define CASCADE_POWER 2 -uint SCALE_CASCADE( uint x ) { - return uint(pow(1 + x, CASCADE_POWER)); +float SCALE_CASCADE( uint x ) { + return pow(1 + x, ubo.cascadePower); } void main() { @@ -313,7 +313,7 @@ void main() { if ( useAtlas ) textureAtlas = textures[drawCall.textureIndex + material.indexAtlas]; if ( validTextureIndex( drawCall.textureIndex + material.indexAlbedo ) ) { const Texture t = textures[drawCall.textureIndex + material.indexAlbedo]; - surface.material.albedo = texture( samplerTextures[(useAtlas)?textureAtlas.index:t.index], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, surface.uv ) : surface.uv ); + surface.material.albedo = texture( samplerTextures[nonuniformEXT((useAtlas)?textureAtlas.index:t.index)], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, surface.uv ) : surface.uv ); } // OPAQUE @@ -329,7 +329,7 @@ void main() { // Emissive textures if ( validTextureIndex( drawCall.textureIndex + material.indexEmissive ) ) { const Texture t = textures[drawCall.textureIndex + material.indexEmissive]; - surface.fragment += texture( samplerTextures[(useAtlas)?textureAtlas.index:t.index], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, surface.uv ) : surface.uv ); + surface.fragment += texture( samplerTextures[nonuniformEXT((useAtlas)?textureAtlas.index:t.index)], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, surface.uv ) : surface.uv ); } #else surface.material.albedo = imageLoad(voxelRadiance[CASCADE], ivec3(tUvw) ); diff --git a/bin/data/shaders/gltf/baking/bake.frag.glsl b/bin/data/shaders/gltf/baking/bake.frag.glsl index ca6001b7..06974b3a 100644 --- a/bin/data/shaders/gltf/baking/bake.frag.glsl +++ b/bin/data/shaders/gltf/baking/bake.frag.glsl @@ -1,4 +1,5 @@ #version 450 +#extension GL_EXT_nonuniform_qualifier : enable #define LAMBERT 1 #define PBR 0 @@ -226,10 +227,10 @@ float shadowFactor( const Light light, float def ) { const float bias = light.depthBias; const float eyeDepth = positionClip.z; const int samples = 16; //int(ubo.poissonSamples); - if ( samples <= 1 ) return eyeDepth < texture(samplerTextures[light.mapIndex], uv).r - bias ? 0.0 : factor; + if ( samples <= 1 ) return eyeDepth < texture(samplerTextures[nonuniformEXT(light.mapIndex)], uv).r - bias ? 0.0 : factor; for ( int i = 0; i < samples; ++i ) { const int index = int( float(samples) * random(floor(surface.position.world * 1000.0), i)) % samples; - const float lightDepth = texture(samplerTextures[light.mapIndex], uv + poissonDisk[index] / 700.0 ).r; + const float lightDepth = texture(samplerTextures[nonuniformEXT(light.mapIndex)], uv + poissonDisk[index] / 700.0 ).r; if ( eyeDepth < lightDepth - bias ) factor -= 1.0 / samples; } return factor; @@ -257,7 +258,7 @@ void main() { if ( !validTextureIndex( material.indexAlbedo ) ) discard; { const Texture t = textures[material.indexAlbedo]; - surface.material.albedo = textureLod( samplerTextures[(useAtlas) ? textureAtlas.index : t.index], (useAtlas) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip ); + surface.material.albedo = textureLod( samplerTextures[nonuniformEXT((useAtlas) ? textureAtlas.index : t.index)], (useAtlas) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip ); // alpha mode OPAQUE if ( material.modeAlpha == 0 ) { surface.material.albedo.a = 1; @@ -275,13 +276,13 @@ void main() { // sample normal if ( validTextureIndex( material.indexNormal ) ) { const Texture t = textures[material.indexNormal]; - surfacem.normal.world = inTBN * normalize( textureLod( samplerTextures[(useAtlas)?textureAtlas.index:t.index], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip ).xyz * 2.0 - vec3(1.0)); + surfacem.normal.world = inTBN * normalize( textureLod( samplerTextures[nonuniformEXT((useAtlas)?textureAtlas.index:t.index)], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip ).xyz * 2.0 - vec3(1.0)); } // sample emissive if ( validTextureIndex( material.indexEmissive ) ) { const Texture t = textures[material.indexEmissive]; - surface.fragment = textureLod( samplerTextures[(useAtlas) ? textureAtlas.index : t.index], (useAtlas) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip ); + surface.fragment = textureLod( samplerTextures[nonuniformEXT((useAtlas) ? textureAtlas.index : t.index)], (useAtlas) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip ); } #else surface.material.albedo = vec4(1); diff --git a/bin/data/shaders/gltf/base.frag.glsl b/bin/data/shaders/gltf/base.frag.glsl index d01abd00..47b43810 100644 --- a/bin/data/shaders/gltf/base.frag.glsl +++ b/bin/data/shaders/gltf/base.frag.glsl @@ -1,4 +1,5 @@ #version 450 +#extension GL_EXT_nonuniform_qualifier : enable #define DEFERRED_SAMPLING 1 #define CAN_DISCARD 1 @@ -100,7 +101,7 @@ void main() { if ( useAtlas ) textureAtlas = textures[material.indexAtlas]; if ( !validTextureIndex( material.indexAlbedo ) ) discard; { Texture t = textures[material.indexAlbedo]; - A = textureLod( samplerTextures[(useAtlas) ? textureAtlas.index : t.index], (useAtlas) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip ); + A = textureLod( samplerTextures[nonuniformEXT((useAtlas) ? textureAtlas.index : t.index)], (useAtlas) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip ); // alpha mode OPAQUE if ( material.modeAlpha == 0 ) { A.a = 1; @@ -121,7 +122,7 @@ void main() { #else Texture t = textures[material.indexLightmap]; const float gamma = 1.6; - const vec4 L = pow(textureLod( samplerTextures[t.index], inSt, mip ), vec4(1.0 / gamma)); + const vec4 L = pow(textureLod( samplerTextures[nonuniformEXT(t.index)], inSt, mip ), vec4(1.0 / gamma)); A *= L; #endif } @@ -131,13 +132,13 @@ void main() { // sample normal if ( validTextureIndex( material.indexNormal ) ) { Texture t = textures[material.indexNormal]; - N = inTBN * normalize( textureLod( samplerTextures[(useAtlas)?textureAtlas.index:t.index], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip ).xyz * 2.0 - vec3(1.0)); + N = inTBN * normalize( textureLod( samplerTextures[nonuniformEXT((useAtlas)?textureAtlas.index:t.index)], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip ).xyz * 2.0 - vec3(1.0)); } #if 0 // sample metallic/roughness if ( validTextureIndex( material.indexMetallicRoughness ) ) { Texture t = textures[material.indexMetallicRoughness]; - const vec4 sampled = textureLod( samplerTextures[(useAtlas)?textureAtlas.index:t.index], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip ); + const vec4 sampled = textureLod( samplerTextures[nonuniformEXT((useAtlas)?textureAtlas.index:t.index)], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip ); M = sampled.b; R = sampled.g; } @@ -145,7 +146,7 @@ void main() { AO = material.factorOcclusion; if ( validTextureIndex( material.indexOcclusion ) ) { Texture t = textures[material.indexOcclusion]; - AO = textureLod( samplerTextures[(useAtlas)?textureAtlas.index:t.index], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv ).r; + AO = textureLod( samplerTextures[nonuniformEXT((useAtlas)?textureAtlas.index:t.index)], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv ).r; } #endif outAlbedo = A * inColor; diff --git a/bin/data/shaders/gltf/voxelize.frag.glsl b/bin/data/shaders/gltf/voxelize.frag.glsl index bd357dd6..9b5e6cf9 100644 --- a/bin/data/shaders/gltf/voxelize.frag.glsl +++ b/bin/data/shaders/gltf/voxelize.frag.glsl @@ -1,12 +1,13 @@ #version 450 +#extension GL_EXT_nonuniform_qualifier : enable #define DEFERRED_SAMPLING 1 #define USE_LIGHTMAP 1 #define PI 3.1415926536f -layout (constant_id = 0) const uint CASCADES = 4; -layout (constant_id = 1) const uint TEXTURES = 256; +layout (constant_id = 0) const uint CASCADES = 16; +layout (constant_id = 1) const uint TEXTURES = 512; struct Material { vec4 colorBase; @@ -108,7 +109,7 @@ void main() { if ( useAtlas ) textureAtlas = textures[material.indexAtlas]; if ( !validTextureIndex( material.indexAlbedo ) ) discard; { Texture t = textures[material.indexAlbedo]; - A = textureLod( samplerTextures[(useAtlas) ? textureAtlas.index : t.index], (useAtlas) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip ); + A = textureLod( samplerTextures[nonuniformEXT((useAtlas) ? textureAtlas.index : t.index)], (useAtlas) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip ); // alpha mode OPAQUE if ( material.modeAlpha == 0 ) { A.a = 1; @@ -129,7 +130,7 @@ void main() { #else Texture t = textures[material.indexLightmap]; const float gamma = 1.6; - const vec4 L = pow(textureLod( samplerTextures[t.index], inSt, mip ), vec4(1.0 / gamma)); + const vec4 L = pow(textureLod( samplerTextures[nonuniformEXT(t.index)], inSt, mip ), vec4(1.0 / gamma)); A *= L; #endif } diff --git a/bin/data/shaders/gltf/voxelize.geom.glsl b/bin/data/shaders/gltf/voxelize.geom.glsl index 870a8069..e0450afa 100644 --- a/bin/data/shaders/gltf/voxelize.geom.glsl +++ b/bin/data/shaders/gltf/voxelize.geom.glsl @@ -21,11 +21,14 @@ layout (location = 8) flat out ivec4 outId; layout (binding = 6) uniform UBO { mat4 voxel; + float cascadePower; + float padding1; + float padding2; + float padding3; } ubo; -#define CASCADE_POWER 2 -uint SCALE_CASCADE( uint x ) { - return uint(pow(1 + x, CASCADE_POWER)); +float SCALE_CASCADE( uint x ) { + return pow(1 + x, ubo.cascadePower); } void main(){ @@ -61,7 +64,7 @@ void main(){ outPosition = P[i]; // + D; outId = inId[i]; - const vec3 P = outPosition + D; + const vec3 P = outPosition; // + D; #if USE_CROSS if ( N.z > N.x && N.z > N.y ) gl_Position = vec4(P.x, P.y, 0, 1); else if ( N.x > N.y && N.x > N.z ) gl_Position = vec4(P.y, P.z, 0, 1); diff --git a/engine/inc/uf/ext/gltf/pod.h b/engine/inc/uf/ext/gltf/pod.h index c6a20da9..e6a572ea 100644 --- a/engine/inc/uf/ext/gltf/pod.h +++ b/engine/inc/uf/ext/gltf/pod.h @@ -14,7 +14,9 @@ namespace pod { std::vector uv; std::vector normal; std::vector radiance; + pod::Matrix4f matrix; + float cascadePower = 2.0; } voxels; }; diff --git a/engine/src/ext/gltf/graph.cpp b/engine/src/ext/gltf/graph.cpp index 135323fe..0500ceac 100644 --- a/engine/src/ext/gltf/graph.cpp +++ b/engine/src/ext/gltf/graph.cpp @@ -93,8 +93,8 @@ namespace { { auto& shader = graphic.material.getShader("fragment", "vxgi"); struct SpecializationConstant { - uint32_t cascades = 4; - uint32_t textures = 256; + uint32_t cascades = 16; + uint32_t textures = 1; }; auto& specializationConstants = shader.specializationConstants.get(); specializationConstants.textures = texture2Ds; diff --git a/engine/src/ext/vulkan/rendermodes/deferred.cpp b/engine/src/ext/vulkan/rendermodes/deferred.cpp index aeb94dad..2205c4c9 100644 --- a/engine/src/ext/vulkan/rendermodes/deferred.cpp +++ b/engine/src/ext/vulkan/rendermodes/deferred.cpp @@ -214,14 +214,14 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { auto& shader = blitter.material.shaders.back(); auto& sceneMetadataJson = scene.getComponent(); - size_t maxLights = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["lights"]["max"].as(256); - size_t maxTextures = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"].as(256); - size_t maxCascades = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as(4); + size_t maxLights = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["lights"]["max"].as(512); + size_t maxTextures = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"].as(512); + size_t maxCascades = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as(16); if ( ext::vulkan::settings::experimental::deferredMode == "vxgi" ) { struct SpecializationConstant { - uint32_t maxCascades = 4; - uint32_t maxTextures = 256; + uint32_t maxCascades = 16; + uint32_t maxTextures = 512; }; auto& specializationConstants = shader.specializationConstants.get(); diff --git a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp index a4298f53..82fb5bcc 100644 --- a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp +++ b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp @@ -348,15 +348,15 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) { auto& shader = blitter.material.getShader("compute"); struct SpecializationConstant { - uint32_t maxCascades = 4; - uint32_t maxTextures = 256; + uint32_t maxCascades = 16; + uint32_t maxTextures = 512; }; auto& specializationConstants = shader.specializationConstants.get(); auto& sceneMetadataJson = scene.getComponent(); - size_t maxLights = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["lights"]["max"].as(256); - size_t maxTextures = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"].as(256); - size_t maxCascades = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as(4); + size_t maxLights = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["lights"]["max"].as(512); + size_t maxTextures = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"].as(512); + size_t maxCascades = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as(16); specializationConstants.maxTextures = maxTextures; specializationConstants.maxCascades = maxCascades; diff --git a/ext/behaviors/scene/behavior.cpp b/ext/behaviors/scene/behavior.cpp index 06953732..b096f63a 100644 --- a/ext/behaviors/scene/behavior.cpp +++ b/ext/behaviors/scene/behavior.cpp @@ -497,7 +497,7 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const std::string& re alignas(4) float exposure; alignas(4) uint32_t msaa; alignas(4) uint32_t shadowSamples; - alignas(4) uint32_t padding1; + alignas(4) float cascadePower; }; struct SpecializationConstant { uint32_t maxTextures = 512; @@ -659,6 +659,8 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const std::string& re } } uniforms->matrices.vxgi = sceneTextures.voxels.matrix; + uniforms->cascadePower = sceneTextures.voxels.cascadePower; + uniforms->lengths.materials = std::min( materials.size(), maxTextures ); uniforms->lengths.textures = std::min( textures.size(), maxTextures ); uniforms->lengths.drawCalls = std::min( drawCalls.size(), maxTextures ); diff --git a/ext/behaviors/voxelizer/behavior.cpp b/ext/behaviors/voxelizer/behavior.cpp index d8c8b4fa..a47acd80 100644 --- a/ext/behaviors/voxelizer/behavior.cpp +++ b/ext/behaviors/voxelizer/behavior.cpp @@ -29,6 +29,7 @@ void ext::VoxelizerBehavior::initialize( uf::Object& self ) { const float DEFAULT_VOXELIZE_LIMITER = ext::config["engine"]["scenes"]["vxgi"]["limiter"].as(0); const uint32_t DEFAULT_DISPATCH_SIZE = ext::config["engine"]["scenes"]["vxgi"]["dispatch"].as(8); const uint32_t DEFAULT_CASCADES = ext::config["engine"]["scenes"]["vxgi"]["cascades"].as(8); + const float DEFAULT_CASCADE_POWER = ext::config["engine"]["scenes"]["vxgi"]["cascadePower"].as(1.5); if ( metadata.voxelSize.x == 0 ) metadata.voxelSize.x = DEFAULT_VOXEL_SIZE; if ( metadata.voxelSize.y == 0 ) metadata.voxelSize.y = DEFAULT_VOXEL_SIZE; @@ -41,6 +42,8 @@ void ext::VoxelizerBehavior::initialize( uf::Object& self ) { if ( metadata.dispatchSize.z == 0 ) metadata.dispatchSize.z = DEFAULT_DISPATCH_SIZE; if ( metadata.cascades == 0 ) metadata.cascades = DEFAULT_CASCADES; + + if ( metadata.cascadePower == 0 ) metadata.cascadePower = DEFAULT_CASCADE_POWER; metadata.extents.min = uf::vector::decode( ext::config["engine"]["scenes"]["vxgi"]["extents"]["min"], pod::Vector3f{-32, -32, -32} ); metadata.extents.max = uf::vector::decode( ext::config["engine"]["scenes"]["vxgi"]["extents"]["max"], pod::Vector3f{ 32, 32, 32} ); @@ -106,6 +109,7 @@ void ext::VoxelizerBehavior::initialize( uf::Object& self ) { for ( auto& t : sceneTextures.voxels.uv ) vkCmdClearColorImage( commandBuffer, t.image, t.imageLayout, &clearColor, 1, &subresourceRange ); for ( auto& t : sceneTextures.voxels.radiance ) vkCmdClearColorImage( commandBuffer, t.image, t.imageLayout, &clearColor, 1, &subresourceRange ); + #if 0 for ( auto& t : sceneTextures.voxels.radiance ) { VkImageMemoryBarrier imageMemoryBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }; imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED @@ -138,6 +142,7 @@ void ext::VoxelizerBehavior::initialize( uf::Object& self ) { t.imageLayout = imageMemoryBarrier.newLayout; } } + #endif }); renderMode.bindCallback( renderMode.CALLBACK_END, [&]( VkCommandBuffer commandBuffer ){ // parse voxel lighting @@ -172,6 +177,7 @@ void ext::VoxelizerBehavior::initialize( uf::Object& self ) { ); } + #if 0 // sync for ( auto& t : sceneTextures.voxels.radiance ) { VkImageMemoryBarrier imageMemoryBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }; @@ -205,6 +211,7 @@ void ext::VoxelizerBehavior::initialize( uf::Object& self ) { t.imageLayout = imageMemoryBarrier.newLayout; } } + #endif }); } #endif @@ -243,6 +250,7 @@ void ext::VoxelizerBehavior::tick( uf::Object& self ) { pod::Vector3f min = metadata.extents.min + controllerPosition; pod::Vector3f max = metadata.extents.max + controllerPosition; sceneTextures.voxels.matrix = uf::matrix::ortho( min.x, max.x, min.y, max.y, min.z, max.z ); + sceneTextures.voxels.cascadePower = metadata.cascadePower; auto graph = uf::scene::generateGraph(); for ( auto entity : graph ) { @@ -254,10 +262,17 @@ void ext::VoxelizerBehavior::tick( uf::Object& self ) { auto& sceneTextures = scene.getComponent(); struct UniformDescriptor { alignas(16) pod::Matrix4f matrix; + alignas(4) float cascadePower; + alignas(4) float padding1; + alignas(4) float padding2; + alignas(4) float padding3; }; auto& uniform = shader.getUniform("UBO"); auto& uniforms = uniform.get(); + uniforms.matrix = sceneTextures.voxels.matrix; + uniforms.cascadePower = sceneTextures.voxels.cascadePower; + shader.updateUniform( "UBO", uniform ); } } diff --git a/ext/behaviors/voxelizer/behavior.h b/ext/behaviors/voxelizer/behavior.h index 36a26303..425dda7f 100644 --- a/ext/behaviors/voxelizer/behavior.h +++ b/ext/behaviors/voxelizer/behavior.h @@ -21,6 +21,7 @@ namespace ext { pod::Vector3ui dispatchSize = { 0, 0, 0 }; std::string renderModeName = "VXGI"; size_t cascades = 0; + float cascadePower = 0; struct { pod::Vector3f min = {}; pod::Vector3f max = {};