From 6ddd2e43ac6d4324a2305fbd009e3e280b581040 Mon Sep 17 00:00:00 2001 From: yvain Date: Mon, 22 Jul 2024 14:34:56 +0200 Subject: [PATCH] fix voxel gi --- .../deferred_light/deferred_light.frag.glsl | 2 +- Shaders/std/conetrace.glsl | 38 ++++---- Shaders/std/light.glsl | 2 +- Shaders/voxel_light/voxel_light.comp.glsl | 59 +++++++++--- .../voxel_offsetprev.comp.glsl | 8 +- .../voxel_sdf_jumpflood.comp.glsl | 4 +- .../voxel_temporal/voxel_temporal.comp.glsl | 90 +++++++------------ Sources/armory/renderpath/Inc.hx | 29 +++--- .../armory/renderpath/RenderPathDeferred.hx | 8 ++ .../armory/renderpath/RenderPathForward.hx | 8 ++ blender/arm/material/make_depth.py | 1 + blender/arm/material/make_mesh.py | 2 +- blender/arm/material/make_voxel.py | 26 ++++-- blender/arm/props_renderpath.py | 19 ---- blender/arm/props_ui.py | 4 +- 15 files changed, 159 insertions(+), 141 deletions(-) diff --git a/Shaders/deferred_light/deferred_light.frag.glsl b/Shaders/deferred_light/deferred_light.frag.glsl index 9c2acaa656..919d8d8673 100644 --- a/Shaders/deferred_light/deferred_light.frag.glsl +++ b/Shaders/deferred_light/deferred_light.frag.glsl @@ -283,7 +283,7 @@ void main() { #endif #ifdef _VoxelAOvar - envl.rgb *= 1.0 - textureLod(voxels_ao, texCoord, 0.0).r; + envl.rgb *= textureLod(voxels_ao, texCoord, 0.0).r; #endif #ifndef _VoxelGI diff --git a/Shaders/std/conetrace.glsl b/Shaders/std/conetrace.glsl index c56edae380..c6e23d3237 100644 --- a/Shaders/std/conetrace.glsl +++ b/Shaders/std/conetrace.glsl @@ -33,7 +33,7 @@ THE SOFTWARE. // http://www.seas.upenn.edu/%7Epcozzi/OpenGLInsights/OpenGLInsights-SparseVoxelization.pdf // https://research.nvidia.com/sites/default/files/publications/GIVoxels-pg2011-authors.pdf -const float MAX_DISTANCE = voxelgiRange * 100.0; +const float MAX_DISTANCE = voxelgiRange; #ifdef _VoxelGI uniform sampler3D dummy; @@ -157,7 +157,7 @@ vec4 traceDiffuse(const vec3 origin, const vec3 normal, const sampler3D voxels, if (cosTheta <= 0) continue; int precomputed_direction = 6 + i; - amount += traceCone(voxels, dummy, origin, normal, coneDir, precomputed_direction, false, DIFFUSE_CONE_APERTURE, 1, clipmaps) * cosTheta; + amount += traceCone(voxels, dummy, origin, normal, coneDir, precomputed_direction, false, DIFFUSE_CONE_APERTURE, 1.0, clipmaps) * cosTheta; sum += cosTheta; } amount /= sum; @@ -167,7 +167,7 @@ vec4 traceDiffuse(const vec3 origin, const vec3 normal, const sampler3D voxels, } vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 viewDir, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel) { - vec3 specularDir = reflect(-viewDir, normal); + vec3 specularDir = normalize(reflect(-viewDir, normal)); vec3 P = origin;// + specularDir * (BayerMatrix8[int(pixel.x) % 8][int(pixel.y) % 8] - 0.5) * voxelgiStep; vec4 amount = traceCone(voxels, voxelsSDF, P, normal, specularDir, 0, true, roughness, voxelgiStep, clipmaps); @@ -186,8 +186,8 @@ vec3 traceRefraction(const vec3 origin, const vec3 normal, sampler3D voxels, sam #endif #ifdef _VoxelAOvar -float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const vec3 dir, const int precomputed_direction, const float aperture, const float clipmaps[voxelgiClipmapCount * 10]) { - float opacity = 0.0; +float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const vec3 dir, const int precomputed_direction, const float aperture, const float step_size, const float clipmaps[voxelgiClipmapCount * 10]) { + float sampleCol = 0.0; float voxelSize0 = float(clipmaps[0]) * 2.0; float dist = voxelSize0; float step_dist = dist; @@ -205,7 +205,7 @@ float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const float coneCoefficient = 2.0 * tan(aperture * 0.5); - while (opacity < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount) { + while (sampleCol < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount) { float mipSample = 0.0; float diam = max(voxelSize0, dist * coneCoefficient); float lod = clamp(log2(diam / voxelSize0), clipmap_index0, voxelgiClipmapCount - 1); @@ -228,13 +228,12 @@ float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const mipSample = mix(mipSample, mipSampleNext, clipmap_blend); } - float a = 1.0 - opacity; - opacity += a * mipSample; + sampleCol += (1.0 - sampleCol) * mipSample; - step_dist = diam; + step_dist = diam * step_size; dist += step_dist; } - return opacity; + return sampleCol; } @@ -247,11 +246,11 @@ float traceAO(const vec3 origin, const vec3 normal, const sampler3D voxels, cons const float cosTheta = dot(normal, coneDir); if (cosTheta <= 0) continue; - amount += traceConeAO(voxels, origin, normal, coneDir, precomputed_direction, DIFFUSE_CONE_APERTURE, clipmaps) * cosTheta; + amount += traceConeAO(voxels, origin, normal, coneDir, precomputed_direction, DIFFUSE_CONE_APERTURE, voxelgiStep, clipmaps) * cosTheta; sum += cosTheta; } amount /= sum; - amount = max(0.0, amount); + amount = clamp(amount, 0.0, 1.0); return amount * voxelgiOcc; } #endif @@ -259,7 +258,7 @@ float traceAO(const vec3 origin, const vec3 normal, const sampler3D voxels, cons #ifdef _VoxelShadow float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 origin, const vec3 n, const vec3 dir, const float aperture, const float step_size, const float clipmaps[voxelgiClipmapCount * 10]) { - float opacity = 0.0; + float sampleCol = 0.0; float voxelSize0 = float(clipmaps[0]) * 2.0; float dist = voxelSize0; float step_dist = dist; @@ -275,7 +274,7 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v ) / (6 + DIFFUSE_CONE_COUNT); vec3 direction_weight = abs(dir); - while (opacity < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount) { + while (sampleCol < 1.0 && dist < MAX_DISTANCE * 100 && clipmap_index0 < voxelgiClipmapCount) { float mipSample = 0.0; float diam = max(voxelSize0, dist * 2.0 * tan(aperture * 0.5)); float lod = clamp(log2(diam / voxelSize0), clipmap_index0, voxelgiClipmapCount - 1); @@ -306,12 +305,11 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v mipSample = mix(mipSample, mipSampleNext, clipmap_blend); } - float a = 1.0 - opacity; - opacity += a * mipSample; + sampleCol += (1.0 - sampleCol) * mipSample; float stepSizeCurrent = step_size; - if (true) { + if (false) { // half texel correction is applied to avoid sampling over current clipmap: const vec3 half_texel = vec3(0.5) / voxelgiResolution; vec3 tc0 = clamp(samplePos, half_texel, 1 - half_texel); @@ -322,14 +320,14 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v step_dist = diam * stepSizeCurrent; dist += step_dist; } - return opacity; + return sampleCol; } float traceShadow(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 dir, const float clipmaps[voxelgiClipmapCount * 10]) { float amount = traceConeShadow(voxels, voxelsSDF, origin, normal, dir, DIFFUSE_CONE_APERTURE, voxelgiStep, clipmaps); - amount = max(0.0, amount); - return amount * voxelgiOcc; + amount = clamp(amount, 0.0, 1.0); + return amount; } #endif #endif // _CONETRACE_GLSL_ diff --git a/Shaders/std/light.glsl b/Shaders/std/light.glsl index b4f15e2194..6bc4b9b855 100644 --- a/Shaders/std/light.glsl +++ b/Shaders/std/light.glsl @@ -75,7 +75,7 @@ uniform sampler2D sltcMag; #endif #ifdef _Clusters uniform sampler2DShadow shadowMapSpot[maxLightsCluster]; - uniform mat4 LWVPSpotArray[maxLightsCluster]; + uniform mat4 LWVPSpot[maxLightsCluster]; #endif #endif #endif diff --git a/Shaders/voxel_light/voxel_light.comp.glsl b/Shaders/voxel_light/voxel_light.comp.glsl index 182c48f2df..2cf5df3e25 100644 --- a/Shaders/voxel_light/voxel_light.comp.glsl +++ b/Shaders/voxel_light/voxel_light.comp.glsl @@ -27,14 +27,19 @@ uniform float clipmaps[voxelgiClipmapCount * 10]; uniform int clipmapLevel; uniform layout(r32ui) uimage3D voxelsLight; +uniform layout(r32ui) uimage3D voxels; #ifdef _ShadowMap uniform sampler2DShadow shadowMap; +uniform sampler2D shadowMapTransparent; uniform sampler2DShadow shadowMapSpot; +uniform sampler2D shadowMapSpotTransparent; #ifdef _ShadowMapAtlas uniform sampler2DShadow shadowMapPoint; +uniform sampler2D shadowMapPointTransparent; #else uniform samplerCubeShadow shadowMapPoint; +uniform samplerCube shadowMapPointTransparent; #endif #endif @@ -83,7 +88,6 @@ float lpToDepth(vec3 lp, const vec2 lightProj) { void main() { int res = voxelgiResolution.x; - ivec3 dst = ivec3(gl_GlobalInvocationID.xyz); vec3 P = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution; @@ -92,13 +96,11 @@ void main() { P *= voxelgiResolution; P += vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)]); - vec4 light = vec4(0.0); - - float visibility; + vec3 visibility; vec3 lp = lightPos - P; vec3 l; - if (lightType == 0) { l = lightDir; visibility = 1.0; } - else { l = normalize(lp); visibility = attenuate(distance(P, lightPos)); } + if (lightType == 0) { l = lightDir; visibility = vec3(1.0); } + else { l = normalize(lp); visibility = vec3(attenuate(distance(P, lightPos))); } // float dotNL = max(dot(wnormal, l), 0.0); // if (dotNL == 0.0) return; @@ -107,7 +109,7 @@ void main() { if (lightShadow == 1) { vec4 lightPosition = LVP * vec4(P, 1.0); vec3 lPos = lightPosition.xyz / lightPosition.w; - visibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).r; + visibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).rrr; } else if (lightShadow == 2) { vec4 lightPosition = LVP * vec4(P, 1.0); @@ -138,8 +140,45 @@ void main() { } } - light.rgb += visibility * lightColor; - light = clamp(light, vec4(0.0), vec4(1.0)); + vec3 light = visibility * lightColor; + + for (int i = 0; i < 6; i++) { + ivec3 src = ivec3(gl_GlobalInvocationID.xyz); + src.x += i * res; + vec3 N = vec3(0.0); + N.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 7))) / 255; + N.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 8))) / 255; + N /= 2; + vec3 wnormal = decode_oct(N.rg * 2 - 1); + + vec3 coneDirection = wnormal; + vec3 aniso_direction = coneDirection; + uvec3 face_offsets = uvec3( + aniso_direction.x > 0 ? 0 : 1, + aniso_direction.y > 0 ? 2 : 3, + aniso_direction.z > 0 ? 4 : 5 + ); + vec3 direction_weights = abs(coneDirection); + + if (direction_weights.x > 0) { + vec3 light_weight = light * direction_weights.x; + imageAtomicAdd(voxelsLight, src + ivec3(face_offsets.x, 0, 0), uint(light_weight.r * 255)); + imageAtomicAdd(voxelsLight, src + ivec3(face_offsets.x, 0, voxelgiResolution.x), uint(light_weight.g * 255)); + imageAtomicAdd(voxelsLight, src + ivec3(face_offsets.x, 0, voxelgiResolution.x * 2), uint(light_weight.b * 255)); + } - imageAtomicMax(voxelsLight, dst, convVec4ToRGBA8(light)); + if (direction_weights.y > 0) { + vec3 light_weight = light * direction_weights.y; + imageAtomicAdd(voxelsLight, src + ivec3(face_offsets.y, 0, 0), uint(light_weight.r * 255)); + imageAtomicAdd(voxelsLight, src + ivec3(face_offsets.y, 0, voxelgiResolution.x), uint(light_weight.g * 255)); + imageAtomicAdd(voxelsLight, src + ivec3(face_offsets.y, 0, voxelgiResolution.x * 2), uint(light_weight.b * 255)); + } + + if (direction_weights.z > 0) { + vec3 light_weight = light * direction_weights.z; + imageAtomicAdd(voxelsLight, src + ivec3(face_offsets.z, 0, 0), uint(light_weight.r * 255)); + imageAtomicAdd(voxelsLight, src + ivec3(face_offsets.z, 0, voxelgiResolution.x), uint(light_weight.g * 255)); + imageAtomicAdd(voxelsLight, src + ivec3(face_offsets.z, 0, voxelgiResolution.x * 2), uint(light_weight.b * 255)); + } + } } diff --git a/Shaders/voxel_offsetprev/voxel_offsetprev.comp.glsl b/Shaders/voxel_offsetprev/voxel_offsetprev.comp.glsl index b93e46fda8..2983f5cc9b 100644 --- a/Shaders/voxel_offsetprev/voxel_offsetprev.comp.glsl +++ b/Shaders/voxel_offsetprev/voxel_offsetprev.comp.glsl @@ -30,11 +30,11 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in; #include "std/voxels_constants.glsl" #ifdef _VoxelGI -uniform layout(rgba8) image3D voxelsB; -uniform layout(rgba8) image3D voxelsOut; +uniform layout(rgba16) image3D voxelsB; +uniform layout(rgba16) image3D voxelsOut; #else -uniform layout(r8) image3D voxelsB; -uniform layout(r8) image3D voxelsOut; +uniform layout(r16) image3D voxelsB; +uniform layout(r16) image3D voxelsOut; #endif uniform int clipmapLevel; diff --git a/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl b/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl index 5e6a0ea729..d224df6679 100644 --- a/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl +++ b/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl @@ -23,8 +23,8 @@ THE SOFTWARE. #include "compiled.inc" -uniform layout(r8) image3D input_sdf; -uniform layout(r8) image3D output_sdf; +uniform layout(r16) image3D input_sdf; +uniform layout(r16) image3D output_sdf; uniform float jump_size; uniform int clipmapLevel; diff --git a/Shaders/voxel_temporal/voxel_temporal.comp.glsl b/Shaders/voxel_temporal/voxel_temporal.comp.glsl index 3789d5a859..eb930f9911 100644 --- a/Shaders/voxel_temporal/voxel_temporal.comp.glsl +++ b/Shaders/voxel_temporal/voxel_temporal.comp.glsl @@ -42,10 +42,12 @@ uniform float shadowsBias; uniform mat4 LVP; #endif uniform sampler3D voxelsSampler; +uniform sampler3D voxelsSDFSampler; uniform layout(r32ui) uimage3D voxels; -uniform layout(rgba8) image3D voxelsB; uniform layout(r32ui) uimage3D voxelsLight; -uniform layout(rgba8) image3D voxelsOut; +uniform layout(rgba16) image3D voxelsB; +uniform layout(rgba16) image3D voxelsOut; +uniform layout(rgba16) image3D voxelsBounce; #ifdef _ShadowMap uniform sampler2DShadow shadowMap; uniform sampler2DShadow shadowMapSpot; @@ -66,24 +68,24 @@ uniform int envmapNumMipmaps; #ifdef _EnvCol uniform vec3 backgroundCol; #endif -uniform sampler2D gbufferD; -uniform sampler2D gbuffer0; -uniform sampler2D gbuffer1; #ifdef _gbuffer2 #ifdef _Deferred uniform sampler2D gbuffer2; #endif #endif uniform vec3 eye; -uniform layout(r8) image3D SDF; +uniform vec3 eyeLook; +uniform vec3 viewRay; +uniform vec2 cameraProj; +uniform layout(r16) image3D SDF; #else #ifdef _VoxelAOvar #ifdef _VoxelShadow -uniform layout(r8) image3D SDF; +uniform layout(r16) image3D SDF; #endif uniform layout(r32ui) uimage3D voxels; -uniform layout(r8) image3D voxelsB; -uniform layout(r8) image3D voxelsOut; +uniform layout(r16) image3D voxelsB; +uniform layout(r16) image3D voxelsOut; #endif #endif @@ -94,12 +96,6 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in; void main() { int res = voxelgiResolution.x; - #ifdef _VoxelGI - vec4 aniso_colors[6]; - #else - float opac; - float aniso_colors[6]; - #endif #ifdef _VoxelGI float sdf = float(clipmaps[int(clipmapLevel * 10)]) * 2.0 * res; @@ -109,24 +105,32 @@ void main() { #endif #endif - #ifdef _VoxelGI - vec4 light = convRGBA8ToVec4(imageLoad(voxelsLight, ivec3(gl_GlobalInvocationID.xyz)).r); - #endif - for (int i = 0; i < 6 + DIFFUSE_CONE_COUNT; i++) { + #ifdef _VoxelGI + vec4 aniso_colors[6]; + #else + float aniso_colors[6]; + #endif + ivec3 src = ivec3(gl_GlobalInvocationID.xyz); src.x += i * res; ivec3 dst = src; dst.y += clipmapLevel * res; #ifdef _VoxelGI vec4 radiance = vec4(0.0); + vec4 bounce = vec4(0.0); #else float opac = 0.0; #endif if (i < 6) { #ifdef _VoxelGI + vec3 light = vec3(0.0); + light.r = float(imageLoad(voxelsLight, src)) / 255; + light.g = float(imageLoad(voxelsLight, src + ivec3(0, 0, voxelgiResolution.x))) / 255; + light.b = float(imageLoad(voxelsLight, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 255; + light /= 3; vec4 basecol = vec4(0.0); basecol.r = float(imageLoad(voxels, src)) / 255; basecol.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x))) / 255; @@ -143,6 +147,8 @@ void main() { N.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 8))) / 255; N /= 2; vec3 wnormal = decode_oct(N.rg * 2 - 1); + float roughness = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 9))) / 255; + float metallic = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 10))) / 255; //clipmap to world vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x; @@ -151,33 +157,17 @@ void main() { wposition *= voxelgiResolution.x; wposition += vec3(clipmaps[clipmapLevel * 10 + 4], clipmaps[clipmapLevel * 10 + 5], clipmaps[clipmapLevel * 10 + 6]); + vec3 albedo = surfaceAlbedo(basecol.rgb, metallic); // g1.rgb - basecolor + #ifdef _Deferred const vec2 pixel = gl_GlobalInvocationID.xy; const vec2 uv = (pixel + 0.5) / voxelgiResolution.xy; - vec4 g0 = textureLod(gbuffer0, uv, 0.0); // Normal.xy, roughness, metallic/matid - vec3 n; - n.z = 1.0 - abs(g0.x) - abs(g0.y); - n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy); - n = normalize(n); - - float roughness = g0.b; - float metallic; - uint matid; - unpackFloatInt16(g0.a, metallic, matid); - - vec4 g1 = textureLod(gbuffer1, uv, 0.0); // Basecolor.rgb, spec/occ - vec2 occspec = unpackFloat2(g1.a); - vec3 albedo = surfaceAlbedo(g1.rgb, metallic); // g1.rgb - basecolor - vec3 f0 = surfaceF0(g1.rgb, metallic); + vec3 f0 = surfaceF0(basecol.rgb, metallic); vec3 v = normalize(eye - wposition); float dotNV = max(dot(wnormal, v), 0.0); - #ifdef _gbuffer2 - vec4 g2 = textureLod(gbuffer2, uv, 0.0); - #endif - #ifdef _Brdf vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy; #endif @@ -185,15 +175,6 @@ void main() { // Envmap #ifdef _Irr vec3 envl = shIrradiance(wnormal, shirr); - - #ifdef _gbuffer2 - if (g2.b < 0.5) { - envl = envl; - } else { - envl = vec3(0.0); - } - #endif - #ifdef _EnvTex envl /= PI; #endif @@ -217,29 +198,26 @@ void main() { envl.rgb *= albedo; #ifdef _Brdf - envl.rgb *= 1.0 - (f0 * envBRDF.x + envBRDF.y); + envl.rgb += 1.0 - (f0 * envBRDF.x + envBRDF.y); #endif #ifdef _Rad // Indirect specular - envl.rgb += prefilteredColor * (f0 * envBRDF.x + envBRDF.y); + envl.rgb *= prefilteredColor * (f0 * envBRDF.x + envBRDF.y); #else #ifdef _EnvCol - envl.rgb += backgroundCol * (f0 * envBRDF.x + envBRDF.y); + envl.rgb *= backgroundCol * (f0 * envBRDF.x + envBRDF.y); #endif #endif - - envl.rgb *= envmapStrength * occspec.x; + envl *= envmapStrength; #else vec3 envl = vec3(0.0); #endif radiance = basecol; - vec4 trace = traceDiffuse(wposition, wnormal, voxelsSampler, clipmaps); - vec3 indirect = trace.rgb + envl.rgb * (1.0 - trace.a); - radiance.rgb *= light.rgb + indirect.rgb; + vec3 diffuse_indirect = trace.rgb + envl * (1.0 - trace.a); + radiance.rgb *= max(light, envmapStrength * trace.a) / PI * diffuse_indirect; radiance.rgb += emission.rgb; - #else opac = float(imageLoad(voxels, src)) / 255; #endif diff --git a/Sources/armory/renderpath/Inc.hx b/Sources/armory/renderpath/Inc.hx index a5ddb22e05..11d1039282 100644 --- a/Sources/armory/renderpath/Inc.hx +++ b/Sources/armory/renderpath/Inc.hx @@ -566,23 +566,16 @@ class Inc { var res = iron.RenderPath.getVoxelRes(); var resZ = iron.RenderPath.getVoxelResZ(); - if (t.name == "voxels_diffuse" || t.name == "voxels_specular") { + if (t.name == "voxels_diffuse" || t.name == "voxels_specular" || t.name == "voxels_ao") { t.width = 0; t.height = 0; t.displayp = getDisplayp(); t.scale = getSuperSampling(); - t.format = getHdrFormat(); - } - else if (t.name == "voxels_ao") { - t.width = 0; - t.height = 0; - t.displayp = getDisplayp(); - t.scale = getSuperSampling(); - t.format = "R8"; + t.format = t.name == "voxels_ao" ? "R8" : "RGBA32"; } else { if (t.name == "voxelsSDF" || t.name == "voxelsSDFtmp") { - t.format = "R8"; + t.format = "R16"; t.width = res; t.height = res * Main.voxelgiClipmapCount; t.depth = res; @@ -591,7 +584,7 @@ class Inc { #if (rp_voxels == "Voxel AO") { if (t.name == "voxelsOut" || t.name == "voxelsOutB") { - t.format = "R8"; + t.format = "R16"; t.width = res * (6 + 16); t.height = res * Main.voxelgiClipmapCount; t.depth = res; @@ -606,29 +599,29 @@ class Inc { #else { if (t.name == "voxelsOut" || t.name == "voxelsOutB") { + t.format = "RGBA64"; t.width = res * (6 + 16); t.height = res * Main.voxelgiClipmapCount; - t.format = "RGBA32"; t.depth = res; } else if (t.name == "voxelsLight") { - t.width = res; - t.height = res; t.format = "R32"; - t.depth = res; + t.width = res * 6; + t.height = res; + t.depth = res * 3; } else { + t.format = "R32"; t.width = res * 6; t.height = res; - t.format = "R32"; - t.depth = res * 9; + t.depth = res * 11; } } #end } } - t.mipmaps = true; t.is_image = true; + t.mipmaps = true; path.createRenderTarget(t); } #end diff --git a/Sources/armory/renderpath/RenderPathDeferred.hx b/Sources/armory/renderpath/RenderPathDeferred.hx index 9dd603afbd..5a37702087 100644 --- a/Sources/armory/renderpath/RenderPathDeferred.hx +++ b/Sources/armory/renderpath/RenderPathDeferred.hx @@ -585,7 +585,15 @@ class RenderPathDeferred { } else { + #if (rp_voxels == "Voxel GI") + path.clearImage("voxelsLight", 0x00000000); + #end path.clearImage("voxels", 0x00000000); + path.clearImage("voxelsOutB", 0x00000000); + #if (arm_voxelgi_shadows || rp_voxels == "Voxel GI") + path.clearImage("voxelsSDF", 0x00000000); + path.clearImage("voxelsSDFtmp", 0x00000000); + #end Inc.computeVoxelsOffsetPrev(); } diff --git a/Sources/armory/renderpath/RenderPathForward.hx b/Sources/armory/renderpath/RenderPathForward.hx index 87dea914f3..58ad4fb002 100644 --- a/Sources/armory/renderpath/RenderPathForward.hx +++ b/Sources/armory/renderpath/RenderPathForward.hx @@ -387,7 +387,15 @@ class RenderPathForward { } else { + #if (rp_voxels == "Voxel GI") + path.clearImage("voxelsLight", 0x00000000); + #end path.clearImage("voxels", 0x00000000); + path.clearImage("voxelsOutB", 0x00000000); + #if (arm_voxelgi_shadows || rp_voxels == "Voxel GI") + path.clearImage("voxelsSDF", 0x00000000); + path.clearImage("voxelsSDFtmp", 0x00000000); + #end Inc.computeVoxelsOffsetPrev(); } diff --git a/blender/arm/material/make_depth.py b/blender/arm/material/make_depth.py index 21e3e49b94..91a135e932 100644 --- a/blender/arm/material/make_depth.py +++ b/blender/arm/material/make_depth.py @@ -45,6 +45,7 @@ def make(context_id, rpasses, shadowmap=False): vert.write_attrib('vec4 spos = vec4(pos.xyz, 1.0);') vert.add_include('compiled.inc') + frag.add_include('compiled.inc') parse_opacity = 'translucent' in rpasses or mat_state.material.arm_discard or 'refraction' in rpasses diff --git a/blender/arm/material/make_mesh.py b/blender/arm/material/make_mesh.py index fbd1cfe851..e8822208f7 100644 --- a/blender/arm/material/make_mesh.py +++ b/blender/arm/material/make_mesh.py @@ -682,7 +682,7 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): frag.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', link='_clipmaps') if '_VoxelAOvar' in wrd.world_defs: - frag.write('indirect *= (1.0 - traceAO(wposition, n, voxels, clipmaps).r);') + frag.write('indirect *= 1.0 - traceAO(wposition, n, voxels, clipmaps);') if '_VoxelGI' in wrd.world_defs: frag.write('indirect += traceDiffuse(wposition, n, voxels, clipmaps).rgb * albedo * voxelgiDiff;') diff --git a/blender/arm/material/make_voxel.py b/blender/arm/material/make_voxel.py index 1546c65673..21b3feb65a 100644 --- a/blender/arm/material/make_voxel.py +++ b/blender/arm/material/make_voxel.py @@ -76,6 +76,7 @@ def make_gi(context_id): rpdat = arm.utils.get_rp() frag.add_uniform('layout(r32ui) uimage3D voxels') + frag.write('vec3 n;') frag.write('vec3 wposition;') frag.write('vec3 basecol;') frag.write('float roughness;') # @@ -199,19 +200,21 @@ def make_gi(context_id): frag.write('uvw = (uvw * 0.5 + 0.5);') frag.write('if(any(notEqual(uvw, clamp(uvw, 0.0, 1.0)))) return;') frag.write('vec3 writecoords = floor(uvw * voxelgiResolution);') - frag.write_attrib('vec3 n = normalize(voxnormal);') - frag.write('vec3 aniso_direction = n;') + frag.write_attrib('vec3 N = normalize(voxnormal);') + frag.write('vec3 aniso_direction = N;') frag.write('uvec3 face_offsets = uvec3(') frag.write(' aniso_direction.x > 0 ? 0 : 1,') frag.write(' aniso_direction.y > 0 ? 2 : 3,') frag.write(' aniso_direction.z > 0 ? 4 : 5') frag.write(' ) * voxelgiResolution;') - frag.write('vec3 direction_weights = abs(n);') + frag.write('vec3 direction_weights = abs(N);') frag.write('if (direction_weights.x > 0) {') frag.write(' vec4 basecol_direction = vec4(min(basecol * direction_weights.x, vec3(1.0)), opacity);') frag.write(' vec3 emission_direction = min(emissionCol * direction_weights.x, vec3(1.0));') - frag.write(' vec2 normal_direction = encode_oct(n * direction_weights.x) * 0.5 + 0.5;') + frag.write(' vec2 normal_direction = encode_oct(N * direction_weights.x) * 0.5 + 0.5;') + frag.write(' float roughness_direction = roughness * direction_weights.x;') + frag.write(' float metallic_direction = metallic * direction_weights.x;') frag.write(' imageAtomicMax(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, 0)), uint(basecol_direction.r * 255));') frag.write(' imageAtomicMax(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') frag.write(' imageAtomicMax(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') @@ -221,13 +224,16 @@ def make_gi(context_id): frag.write(' imageAtomicMax(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 6)), uint(emission_direction.b * 255));') frag.write(' imageAtomicMax(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 7)), uint(normal_direction.r * 255));') frag.write(' imageAtomicMax(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 8)), uint(normal_direction.g * 255));') + frag.write(' imageAtomicMax(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 9)), uint(roughness_direction * 255));') + frag.write(' imageAtomicMax(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 10)), uint(metallic_direction * 255));') frag.write('}') - frag.write('if (direction_weights.y > 0) {') frag.write(' vec4 basecol_direction = vec4(min(basecol * direction_weights.y, vec3(1.0)), opacity);') frag.write(' vec3 emission_direction = min(emissionCol * direction_weights.y, vec3(1.0));') - frag.write(' vec2 normal_direction = encode_oct(n * direction_weights.y) * 0.5 + 0.5;') + frag.write(' vec2 normal_direction = encode_oct(N * direction_weights.y) * 0.5 + 0.5;') + frag.write(' float roughness_direction = roughness * direction_weights.y;') + frag.write(' float metallic_direction = metallic * direction_weights.y;') frag.write(' imageAtomicMax(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, 0)), uint(basecol_direction.r * 255));') frag.write(' imageAtomicMax(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') frag.write(' imageAtomicMax(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') @@ -237,13 +243,17 @@ def make_gi(context_id): frag.write(' imageAtomicMax(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 6)), uint(emission_direction.b * 255));') frag.write(' imageAtomicMax(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 7)), uint(normal_direction.r * 255));') frag.write(' imageAtomicMax(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 8)), uint(normal_direction.g * 255));') + frag.write(' imageAtomicMax(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 9)), uint(roughness_direction * 255));') + frag.write(' imageAtomicMax(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 10)), uint(metallic_direction * 255));') frag.write('}') frag.write('if (direction_weights.z > 0) {') frag.write(' vec4 basecol_direction = vec4(min(basecol * direction_weights.z, vec3(1.0)), opacity);') frag.write(' vec3 emission_direction = min(emissionCol * direction_weights.z, vec3(1.0));') - frag.write(' vec2 normal_direction = encode_oct(n * direction_weights.z) * 0.5 + 0.5;') + frag.write(' vec2 normal_direction = encode_oct(N * direction_weights.z) * 0.5 + 0.5;') + frag.write(' float roughness_direction = roughness * direction_weights.z;') + frag.write(' float metallic_direction = metallic * direction_weights.z;') frag.write(' imageAtomicMax(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, 0)), uint(basecol_direction.r * 255));') frag.write(' imageAtomicMax(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') frag.write(' imageAtomicMax(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') @@ -253,6 +263,8 @@ def make_gi(context_id): frag.write(' imageAtomicMax(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 6)), uint(emission_direction.b * 255));') frag.write(' imageAtomicMax(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 7)), uint(normal_direction.r * 255));') frag.write(' imageAtomicMax(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 8)), uint(normal_direction.g * 255));') + frag.write(' imageAtomicMax(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 9)), uint(roughness_direction * 255));') + frag.write(' imageAtomicMax(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 10)), uint(metallic_direction * 255));') frag.write('}') return con_voxel diff --git a/blender/arm/props_renderpath.py b/blender/arm/props_renderpath.py index 7e023db1b9..1240436a39 100644 --- a/blender/arm/props_renderpath.py +++ b/blender/arm/props_renderpath.py @@ -445,25 +445,6 @@ class ArmRPListItem(bpy.types.PropertyGroup): rp_stereo: BoolProperty(name="VR", description="Stereo rendering", default=False, update=update_renderpath) rp_water: BoolProperty(name="Water", description="Enable water surface pass", default=False, update=update_renderpath) rp_pp: BoolProperty(name="Realtime postprocess", description="Realtime postprocess", default=False, update=update_renderpath) - rp_gi: EnumProperty( # TODO: remove in 0.8 - items=[('Off', 'Off', 'Off'), - ('Voxel GI', 'Voxel GI', 'Voxel GI', 'ERROR', 1), - ('Voxel AO', 'Voxel AO', 'Voxel AO') - ], - name="Global Illumination", description="Dynamic global illumination", default='Off', update=update_renderpath) - rp_voxelao: BoolProperty(name="Voxel AO", description="Voxel-based ambient occlusion", default=False, update=update_renderpath) - rp_voxelgi_resolution: EnumProperty( - items=[('32', '32', '32'), - ('64', '64', '64'), - ('128', '128', '128'), - ('256', '256', '256'), - ('512', '512', '512')], - name="Resolution", description="3D texture resolution", default='128', update=update_renderpath) - rp_voxelgi_resolution_z: EnumProperty( - items=[('1.0', '1.0', '1.0'), - ('0.5', '0.5', '0.5'), - ('0.25', '0.25', '0.25')], - name="Resolution Z", description="3D texture z resolution multiplier", default='1.0', update=update_renderpath) arm_clouds: BoolProperty(name="Clouds", description="Enable clouds pass", default=False, update=assets.invalidate_shader_cache) arm_ssrs: BoolProperty(name="SSRS", description="Screen-space ray-traced shadows", default=False, update=assets.invalidate_shader_cache) arm_micro_shadowing: BoolProperty(name="Micro Shadowing", description="Use the shaders' occlusion parameter to compute micro shadowing for the scene's sun lamp. This option is not available for render paths using mobile or solid material models", default=False, update=assets.invalidate_shader_cache) diff --git a/blender/arm/props_ui.py b/blender/arm/props_ui.py index ed5652daf9..4afdd8c91b 100644 --- a/blender/arm/props_ui.py +++ b/blender/arm/props_ui.py @@ -1710,12 +1710,13 @@ def draw(self, context): col2.enabled = rpdat.rp_voxels == 'Voxel GI' col3 = col.column() col3.enabled = rpdat.rp_voxels == 'Voxel AO' - col.prop(rpdat, 'arm_voxelgi_shadows', text='Shadows') + #col.prop(rpdat, 'arm_voxelgi_shadows', text='Shadows') #col2.prop(rpdat, 'arm_voxelgi_refraction', text='Refraction') #col2.prop(rpdat, 'arm_voxelgi_bounces') col.prop(rpdat, 'arm_voxelgi_clipmap_count') #col.prop(rpdat, 'arm_voxelgi_cones') col.prop(rpdat, 'rp_voxelgi_resolution') + col.prop(rpdat, 'arm_voxelgi_size') #col.prop(rpdat, 'rp_voxelgi_resolution_z') col2.enabled = rpdat.rp_voxels == 'Voxel GI' #col.prop(rpdat, 'arm_voxelgi_temporal') @@ -1727,7 +1728,6 @@ def draw(self, context): #col2.prop(rpdat, 'arm_voxelgi_refr') col.prop(rpdat, 'arm_voxelgi_occ') col.label(text="Ray") - col.prop(rpdat, 'arm_voxelgi_size') col.prop(rpdat, 'arm_voxelgi_step') col.prop(rpdat, 'arm_voxelgi_range') #col.prop(rpdat, 'arm_voxelgi_offset')