diff --git a/leenkx/Shaders/deferred_light/deferred_light.frag.glsl b/leenkx/Shaders/deferred_light/deferred_light.frag.glsl index 61f94c1..7af6c9b 100644 --- a/leenkx/Shaders/deferred_light/deferred_light.frag.glsl +++ b/leenkx/Shaders/deferred_light/deferred_light.frag.glsl @@ -29,10 +29,11 @@ uniform sampler2D gbuffer1; #ifdef _VoxelGI uniform sampler2D voxels_diffuse; uniform sampler2D voxels_specular; -#endif +#else #ifdef _VoxelAOvar uniform sampler2D voxels_ao; #endif +#endif #ifdef _VoxelShadow uniform sampler3D voxels; uniform sampler3D voxelsSDF; @@ -56,6 +57,10 @@ uniform vec3 backgroundCol; #ifdef _SSAO uniform sampler2D ssaotex; +#else +#ifdef _SSGI +uniform sampler2D ssaotex; +#endif #endif #ifdef _SSS @@ -113,11 +118,15 @@ uniform vec2 cameraPlane; #ifdef _SinglePoint #ifdef _Spot //!uniform sampler2DShadow shadowMapSpot[1]; + #ifdef _ShadowMapTransparent //!uniform sampler2D shadowMapSpotTransparent[1]; + #endif //!uniform mat4 LWVPSpot[1]; #else //!uniform samplerCubeShadow shadowMapPoint[1]; + #ifdef _ShadowMapTransparent //!uniform samplerCube shadowMapPointTransparent[1]; + #endif //!uniform vec2 lightProj; #endif #endif @@ -125,30 +134,40 @@ uniform vec2 cameraPlane; #ifdef _ShadowMapAtlas #ifdef _SingleAtlas uniform sampler2DShadow shadowMapAtlas; + #ifdef _ShadowMapTransparent uniform sampler2D shadowMapAtlasTransparent; #endif + #endif #endif #ifdef _ShadowMapAtlas #ifndef _SingleAtlas //!uniform sampler2DShadow shadowMapAtlasPoint; + #ifdef _ShadowMapTransparent //!uniform sampler2D shadowMapAtlasPointTransparent; #endif - //!uniform vec4 pointLightDataArray[4]; + #endif + //!uniform vec4 pointLightDataArray[maxLightsCluster * 6]; #else //!uniform samplerCubeShadow shadowMapPoint[4]; + #ifdef _ShadowMapTransparent //!uniform samplerCube shadowMapPointTransparent[4]; + #endif #endif //!uniform vec2 lightProj; #ifdef _Spot #ifdef _ShadowMapAtlas #ifndef _SingleAtlas //!uniform sampler2DShadow shadowMapAtlasSpot; + #ifdef _ShadowMapTransparent //!uniform sampler2D shadowMapAtlasSpotTransparent; #endif + #endif #else //!uniform sampler2DShadow shadowMapSpot[4]; + #ifdef _ShadowMapTransparent //!uniform sampler2D shadowMapSpotTransparent[4]; #endif + #endif //!uniform mat4 LWVPSpotArray[maxLightsCluster]; #endif #endif @@ -161,12 +180,16 @@ uniform vec3 sunCol; #ifdef _ShadowMapAtlas #ifndef _SingleAtlas uniform sampler2DShadow shadowMapAtlasSun; + #ifdef _ShadowMapTransparent uniform sampler2D shadowMapAtlasSunTransparent; #endif + #endif #else uniform sampler2DShadow shadowMap; + #ifdef _ShadowMapTransparent uniform sampler2D shadowMapTransparent; #endif + #endif uniform float shadowsBias; #ifdef _CSM //!uniform vec4 casData[shadowmapCascades * 4 + 4]; @@ -227,17 +250,22 @@ void main() { vec4 g2 = textureLod(gbuffer2, texCoord, 0.0); #endif + #ifdef _MicroShadowing occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel #endif #ifdef _Brdf vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy; + vec3 F = f0 * envBRDF.x + envBRDF.y; +#else + vec3 F = f0; #endif +#ifndef _VoxelAOvar +#ifndef _VoxelGI // Envmap #ifdef _Irr - vec3 envl = shIrradiance(n, shirr); #ifdef _gbuffer2 @@ -271,33 +299,33 @@ void main() { envl.rgb *= albedo; #ifdef _Brdf - envl.rgb *= 1.0 - (f0 * envBRDF.x + envBRDF.y); //LV: We should take refracted light into account + envl.rgb *= 1.0 - F; //LV: We should take refracted light into account #endif #ifdef _Rad // Indirect specular - envl.rgb += prefilteredColor * (f0 * envBRDF.x + envBRDF.y); //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT + envl.rgb += prefilteredColor * F; //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT #else #ifdef _EnvCol - envl.rgb += backgroundCol * (f0 * envBRDF.x + envBRDF.y); //LV: Eh, what's the point of weighting it only by F0? + envl.rgb += backgroundCol * F; //LV: Eh, what's the point of weighting it only by F0? #endif #endif envl.rgb *= envmapStrength * occspec.x; -#ifdef _VoxelGI - vec4 indirect_diffuse = textureLod(voxels_diffuse, texCoord, 0.0); - fragColor.rgb = (indirect_diffuse.rgb * albedo + envl.rgb * (1.0 - indirect_diffuse.a)) * voxelgiDiff; - if(roughness < 1.0 && occspec.y > 0.0) - fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * occspec.y * voxelgiRefl; -#endif - -#ifdef _VoxelAOvar - envl.rgb *= textureLod(voxels_ao, texCoord, 0.0).r; -#endif - -#ifndef _VoxelGI fragColor.rgb = envl; #endif +#endif + +#ifdef _VoxelGI + fragColor.rgb = textureLod(voxels_diffuse, texCoord, 0.0).rgb * voxelgiDiff; + if(roughness < 1.0 && occspec.y > 0.0) + fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * occspec.y * voxelgiRefl; +#else +#ifdef _VoxelAOvar + fragColor.rgb = textureLod(voxels_ao, texCoord, 0.0).rgb * voxelgiOcc; +#endif +#endif + // Show voxels // vec3 origin = vec3(texCoord * 2.0 - 1.0, 0.99); // vec3 direction = vec3(0.0, 0.0, -1.0); @@ -317,6 +345,10 @@ void main() { // #else fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).r; // #endif +#else +#ifdef _SSGI + fragColor.rgb += textureLod(ssaotex, texCoord, 0.0).rgb; +#endif #endif #ifdef _EmissionShadeless @@ -349,40 +381,70 @@ void main() { #ifdef _ShadowMap #ifdef _CSM svisibility = shadowTestCascade( - #ifdef _ShadowMapAtlas - #ifndef _SingleAtlas - shadowMapAtlasSun, shadowMapAtlasSunTransparent - #else - shadowMapAtlas, shadowMapAtlasTransparent - #endif - #else - shadowMap, shadowMapTransparent - #endif - , eye, p + n * shadowsBias * 10, shadowsBias, false - ); + #ifdef _ShadowMapAtlas + #ifdef _ShadowMapTransparent + #ifndef _SingleAtlas + shadowMapAtlasSun, shadowMapAtlasSunTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + #else + #ifndef _SingleAtlas + shadowMapAtlasSun + #else + shadowMapAtlas + #endif + #endif + #else + #ifdef _ShadowMapTransparent + shadowMap, shadowMapTransparent + #else + shadowMap + #endif + #endif + , eye, p + n * shadowsBias * 10, shadowsBias + #ifdef _ShadowMapTransparent + , false + #endif + ); #else vec4 lPos = LWVP * vec4(p + n * shadowsBias * 100, 1.0); if (lPos.w > 0.0) { svisibility = shadowTest( - #ifdef _ShadowMapAtlas - #ifndef _SingleAtlas - shadowMapAtlasSun, shadowMapAtlasSunTransparent - #else - shadowMapAtlas, shadowMapAtlasTransparent - #endif - #else - shadowMap, shadowMapTransparent - #endif - , lPos.xyz / lPos.w, shadowsBias, false - ); + #ifdef _ShadowMapAtlas + #ifdef _ShadowMapTransparent + #ifndef _SingleAtlas + shadowMapAtlasSun, shadowMapAtlasSunTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + #else + #ifndef _SingleAtlas + shadowMapAtlasSun + #else + shadowMapAtlas + #endif + #endif + #else + #ifdef _ShadowMapTransparent + shadowMap, shadowMapTransparent + #else + shadowMap + #endif + #endif + , lPos.xyz / lPos.w, shadowsBias + #ifdef _ShadowMapTransparent + , false + #endif + ); } #endif #endif #ifdef _VoxelShadow - svisibility *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy).r) * voxelgiShad; + svisibility *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy, -g2.rg).r) * voxelgiShad; #endif - + #ifdef _SSRS // vec2 coords = getProjectedCoord(hitCoord); // vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy); @@ -439,13 +501,16 @@ void main() { fragColor.rgb += sampleLight( p, n, v, dotNV, pointPos, pointCol, albedo, roughness, occspec.y, f0 #ifdef _ShadowMap - , 0, pointBias, true, false + , 0, pointBias, true + #ifdef _ShadowMapTransparent + , false + #endif #endif #ifdef _Spot , true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight #endif #ifdef _VoxelShadow - , voxels, voxelsSDF, clipmaps + , voxels, voxelsSDF, clipmaps, -g2.rg #endif #ifdef _MicroShadowing , occspec.x @@ -492,7 +557,10 @@ void main() { f0 #ifdef _ShadowMap // light index, shadow bias, cast_shadows - , li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, false + , li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0 + #ifdef _ShadowMapTransparent + , false + #endif #endif #ifdef _Spot , lightsArray[li * 3 + 2].y != 0.0 @@ -503,7 +571,7 @@ void main() { , lightsArraySpot[li * 2 + 1].xyz // right #endif #ifdef _VoxelShadow - , voxels, voxelsSDF, clipmaps + , voxels, voxelsSDF, clipmaps, -g2.rg #endif #ifdef _MicroShadowing , occspec.x @@ -514,14 +582,5 @@ void main() { ); } #endif // _Clusters - -/* -#ifdef _VoxelRefract -if(opac < 1.0) { - vec3 refraction = traceRefraction(p, n, voxels, v, ior, roughness, eye) * voxelgiRefr; - fragColor.rgb = mix(refraction, fragColor.rgb, opac); -} -#endif -*/ fragColor.a = 1.0; // Mark as opaque } diff --git a/leenkx/Shaders/ssgi_pass/ssgi_pass.frag.glsl b/leenkx/Shaders/ssgi_pass/ssgi_pass.frag.glsl index 694e0f2..96de299 100644 --- a/leenkx/Shaders/ssgi_pass/ssgi_pass.frag.glsl +++ b/leenkx/Shaders/ssgi_pass/ssgi_pass.frag.glsl @@ -1,107 +1,506 @@ #version 450 #include "compiled.inc" -#include "std/math.glsl" #include "std/gbuffer.glsl" +#include "std/brdf.glsl" +#include "std/math.glsl" +#ifdef _Clusters +#include "std/clusters.glsl" +#endif +#ifdef _ShadowMap +#include "std/shadows.glsl" +#endif +#ifdef _LTC +#include "std/ltc.glsl" +#endif +#ifdef _LightIES +#include "std/ies.glsl" +#endif +#ifdef _Spot +#include "std/light_common.glsl" +#endif +#include "std/constants.glsl" +uniform sampler2D gbuffer0; +uniform sampler2D gbuffer1; uniform sampler2D gbufferD; -uniform sampler2D gbuffer0; // Normal -// #ifdef _RTGI -// uniform sampler2D gbuffer1; // Basecol -// #endif -uniform mat4 P; -uniform mat3 V3; - +#ifdef _EmissionShaded +uniform sampler2D gbufferEmission; +#endif +uniform sampler2D sveloc; uniform vec2 cameraProj; +uniform vec3 eye; +uniform vec3 eyeLook; +uniform vec2 screenSize; +uniform mat4 invVP; -const float angleMix = 0.5f; -#ifdef _SSGICone9 -const float strength = 2.0 * (1.0 / ssgiStrength); -#else -const float strength = 2.0 * (1.0 / ssgiStrength) * 1.8; +in vec2 texCoord; +in vec3 viewRay; +out vec3 fragColor; + +float metallic; +uint matid; + +#ifdef _SMSizeUniform +//!uniform vec2 smSizeUniform; #endif -in vec3 viewRay; -in vec2 texCoord; -out float fragColor; - -vec3 hitCoord; -vec2 coord; -float depth; -// #ifdef _RTGI -// vec3 col = vec3(0.0); -// #endif -vec3 vpos; - -vec2 getProjectedCoord(vec3 hitCoord) { - vec4 projectedCoord = P * vec4(hitCoord, 1.0); - projectedCoord.xy /= projectedCoord.w; - projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5; - #ifdef _InvY - projectedCoord.y = 1.0 - projectedCoord.y; +#ifdef _Clusters +uniform vec4 lightsArray[maxLights * 3]; + #ifdef _Spot + uniform vec4 lightsArraySpot[maxLights * 2]; #endif - return projectedCoord.xy; -} +uniform sampler2D clustersData; +uniform vec2 cameraPlane; +#endif -float getDeltaDepth(vec3 hitCoord) { - coord = getProjectedCoord(hitCoord); - depth = textureLod(gbufferD, coord, 0.0).r * 2.0 - 1.0; - vec3 p = getPosView(viewRay, depth, cameraProj); - return p.z - hitCoord.z; -} +#ifdef _SinglePoint // Fast path for single light +uniform vec3 pointPos; +uniform vec3 pointCol; + #ifdef _ShadowMap + uniform float pointBias; + #endif + #ifdef _Spot + uniform vec3 spotDir; + uniform vec3 spotRight; + uniform vec4 spotData; + #endif +#endif -void rayCast(vec3 dir) { - hitCoord = vpos; - dir *= ssgiRayStep * 2; - float dist = 0.15; - for (int i = 0; i < ssgiMaxSteps; i++) { - hitCoord += dir; - float delta = getDeltaDepth(hitCoord); - if (delta > 0.0 && delta < 0.2) { - dist = distance(vpos, hitCoord); - break; +#ifdef _CPostprocess + uniform vec3 PPComp12; +#endif + +#ifdef _ShadowMap + #ifdef _SinglePoint + #ifdef _Spot + #ifndef _LTC + uniform sampler2DShadow shadowMapSpot[1]; + uniform sampler2D shadowMapSpotTransparent[1]; + uniform mat4 LWVPSpot[1]; + #endif + #else + uniform samplerCubeShadow shadowMapPoint[1]; + uniform samplerCube shadowMapPointTransparent[1]; + uniform vec2 lightProj; + #endif + #endif + #ifdef _Clusters + #ifdef _SingleAtlas + uniform sampler2DShadow shadowMapAtlas; + uniform sampler2D shadowMapAtlasTransparent; + #endif + uniform vec2 lightProj; + #ifdef _ShadowMapAtlas + #ifndef _SingleAtlas + uniform sampler2DShadow shadowMapAtlasPoint; + uniform sampler2D shadowMapAtlasPointTransparent; + //!uniform vec4 pointLightDataArray[maxLightsCluster * 6]; + #else + uniform samplerCubeShadow shadowMapPoint[4]; + uniform samplerCube shadowMapPointTransparent[4]; + #endif + #endif + #ifdef _Spot + #ifdef _ShadowMapAtlas + #ifndef _SingleAtlas + uniform sampler2DShadow shadowMapAtlasSpot; + uniform sampler2D shadowMapAtlasSpotTransparent; + #endif + #else + uniform sampler2DShadow shadowMapSpot[4]; + uniform sampler2D shadowMapSpotTransparent[4]; + #endif + uniform mat4 LWVPSpotArray[maxLightsCluster]; + #endif + #endif +#endif + +#ifdef _LTC +uniform vec3 lightArea0; +uniform vec3 lightArea1; +uniform vec3 lightArea2; +uniform vec3 lightArea3; +uniform sampler2D sltcMat; +uniform sampler2D sltcMag; +#ifdef _ShadowMap +#ifndef _Spot + #ifdef _SinglePoint + uniform sampler2DShadow shadowMapSpot[1]; + uniform sampler2D shadowMapSpotTransparent[1]; + uniform mat4 LWVPSpot[1]; + #endif + #ifdef _Clusters + uniform sampler2DShadow shadowMapSpot[maxLightsCluster]; + uniform mat4 LWVPSpotArray[maxLightsCluster]; + #endif +#endif +#endif +#endif + +#ifdef _Sun +uniform vec3 sunDir; +uniform vec3 sunCol; + #ifdef _ShadowMap + #ifdef _ShadowMapAtlas + #ifndef _SingleAtlas + uniform sampler2DShadow shadowMapAtlasSun; + uniform sampler2D shadowMapAtlasSunTransparent; + #endif + #else + uniform sampler2DShadow shadowMap; + uniform sampler2D shadowMapTransparent; + #endif + uniform float shadowsBias; + #ifdef _CSM + //!uniform vec4 casData[shadowmapCascades * 4 + 4]; + #else + uniform mat4 LWVP; + #endif + #endif // _ShadowMap +#endif + +vec3 sampleLight(const vec3 p, const vec3 n, const vec3 lp, const vec3 lightCol + #ifdef _ShadowMap + , int index, float bias, bool receiveShadow, bool transparent + #endif + #ifdef _Spot + , const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right + #endif + ) { + + vec3 ld = lp - p; + vec3 l = normalize(ld); + + vec3 visibility = lightCol; + visibility *= attenuate(distance(p, lp)); + + #ifdef _LTC + #ifdef _ShadowMap + if (receiveShadow) { + #ifdef _SinglePoint + vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0); + visibility *= shadowTest(shadowMapSpot[0], + shadowMapSpotTransparent[0], + lPos.xyz / lPos.w, bias, transparent); + #endif + #ifdef _Clusters + vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); + if (index == 0) visibility *= shadowTest(shadowMapSpot[0], + shadowMapSpotTransparent[0], + lPos.xyz / lPos.w, bias, transparent); + else if (index == 1) visibility *= shadowTest(shadowMapSpot[1], + shadowMapSpotTransparent[1], + , lPos.xyz / lPos.w, bias, transparent); + else if (index == 2) visibility *= shadowTest(shadowMapSpot[2], + shadowMapSpotTransparent[2], + lPos.xyz / lPos.w, bias, transparent); + else if (index == 3) visibility *= shadowTest(shadowMapSpot[3], + shadowMapSpotTransparent[3], + lPos.xyz / lPos.w, bias, transparent); + #endif } + #endif + return visibility; + #endif + + #ifdef _Spot + if (isSpot) { + visibility *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend); + + #ifdef _ShadowMap + if (receiveShadow) { + #ifdef _SinglePoint + vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0); + visibility *= shadowTest(shadowMapSpot[0], + shadowMapSpotTransparent[0], + lPos.xyz / lPos.w, bias, transparent); + #endif + #ifdef _Clusters + vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); + #ifdef _ShadowMapAtlas + visibility *= shadowTest( + #ifndef _SingleAtlas + shadowMapAtlasSpot, shadowMapAtlasSpotTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + , lPos.xyz / lPos.w, bias, transparent + ); + #else + if (index == 0) visibility *= shadowTest(shadowMapSpot[0], + shadowMapSpotTransparent[0], + lPos.xyz / lPos.w, bias, transparent); + else if (index == 1) visibility *= shadowTest(shadowMapSpot[1], + shadowMapSpotTransparent[1], + lPos.xyz / lPos.w, bias, transparent); + else if (index == 2) visibility *= shadowTest(shadowMapSpot[2], + shadowMapSpotTransparent[2], + lPos.xyz / lPos.w, bias, transparent); + else if (index == 3) visibility *= shadowTest(shadowMapSpot[3], + shadowMapSpotTransparent[3], + lPos.xyz / lPos.w, bias, transparent); + #endif + #endif + } + #endif + return visibility; } - fragColor += dist; - // #ifdef _RTGI - // col += textureLod(gbuffer1, coord, 0.0).rgb * ((ssgiRayStep * ssgiMaxSteps) - dist); - // #endif + #endif + + #ifdef _LightIES + visibility *= iesAttenuation(-l); + #endif + + #ifdef _ShadowMap + if (receiveShadow) { + #ifdef _SinglePoint + #ifndef _Spot + visibility *= PCFCube(shadowMapPoint[0], + shadowMapPointTransparent[0], + ld, -l, bias, lightProj, n, transparent); + #endif + #endif + #ifdef _Clusters + #ifdef _ShadowMapAtlas + visibility *= PCFFakeCube( + #ifndef _SingleAtlas + shadowMapAtlasPoint, shadowMapAtlasPointTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + , ld, -l, bias, lightProj, n, index, transparent + ); + #else + if (index == 0) visibility *= PCFCube(shadowMapPoint[0], + shadowMapPointTransparent[0], + ld, -l, bias, lightProj, n, transparent); + else if (index == 1) visibility *= PCFCube(shadowMapPoint[1], + shadowMapPointTransparent[1], + ld, -l, bias, lightProj, n, transparent); + else if (index == 2) visibility *= PCFCube(shadowMapPoint[2], + shadowMapPointTransparent[2], + ld, -l, bias, lightProj, n, transparent); + else if (index == 3) visibility *= PCFCube(shadowMapPoint[3], + shadowMapPointTransparent[3], + ld, -l, bias, lightProj, n, transparent); + #endif + #endif + } + #endif + + return visibility; } -vec3 tangent(const vec3 n) { - vec3 t1 = cross(n, vec3(0, 0, 1)); - vec3 t2 = cross(n, vec3(0, 1, 0)); - if (length(t1) > length(t2)) return normalize(t1); - else return normalize(t2); +vec3 getVisibility(vec3 p, vec3 n, float depth, vec2 uv) { + vec3 visibility = vec3(0.0); +#ifdef _Sun + #ifdef _ShadowMap + #ifdef _CSM + visibility = shadowTestCascade( + #ifdef _ShadowMapAtlas + #ifndef _SingleAtlas + shadowMapAtlasSun, shadowMapAtlasSunTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + #else + shadowMap, shadowMapTransparent + #endif + , eye, p + n * shadowsBias * 10, shadowsBias, false + ); + #else + vec4 lPos = LWVP * vec4(p + n * shadowsBias * 100, 1.0); + if (lPos.w > 0.0) { + visibility = shadowTest( + #ifdef _ShadowMapAtlas + #ifndef _SingleAtlas + shadowMapAtlasSun, shadowMapAtlasSunTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + #else + shadowMap, shadowMapTransparent + #endif + , lPos.xyz / lPos.w, shadowsBias, false + ); + } + #endif + #endif +#endif + +#ifdef _SinglePoint + visibility += sampleLight( + p, n, pointPos, pointCol + #ifdef _ShadowMap + , 0, pointBias, true, false + #endif + #ifdef _Spot + , true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight + #endif + ); +#endif + +#ifdef _Clusters + float viewz = linearize(depth, cameraProj); + int clusterI = getClusterI(uv, viewz, cameraPlane); + int numLights = int(texelFetch(clustersData, ivec2(clusterI, 0), 0).r * 255); + + #ifdef HLSL + viewz += textureLod(clustersData, vec2(0.0), 0.0).r * 1e-9; // TODO: krafix bug, needs to generate sampler + #endif + + #ifdef _Spot + int numSpots = int(texelFetch(clustersData, ivec2(clusterI, 1 + maxLightsCluster), 0).r * 255); + int numPoints = numLights - numSpots; + #endif + + for (int i = 0; i < min(numLights, maxLightsCluster); i++) { + int li = int(texelFetch(clustersData, ivec2(clusterI, i + 1), 0).r * 255); + visibility += sampleLight( + p, + n, + lightsArray[li * 3].xyz, // lp + lightsArray[li * 3 + 1].xyz // lightCol + #ifdef _ShadowMap + // light index, shadow bias, cast_shadows + , li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, false + #endif + #ifdef _Spot + , lightsArray[li * 3 + 2].y != 0.0 + , lightsArray[li * 3 + 2].y // spot size (cutoff) + , lightsArraySpot[li * 2].w // spot blend (exponent) + , lightsArraySpot[li * 2].xyz // spotDir + , vec2(lightsArray[li * 3].w, lightsArray[li * 3 + 1].w) // scale + , lightsArraySpot[li * 2 + 1].xyz // right + #endif + ); + } +#endif // _Clusters + return visibility; } +vec3 getWorldPos(vec2 uv, float depth) { + vec4 pos = invVP * vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0); + return pos.xyz / pos.w; +} + +vec3 getNormal(vec2 uv) { + vec4 g0 = textureLod(gbuffer0, uv, 0.0); + vec2 enc = g0.rg; + vec3 n; + n.z = 1.0 - abs(enc.x) - abs(enc.y); + n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy); + return normalize(n); +} + +vec3 calculateIndirectLight(vec2 uv, vec3 pos, vec3 normal, float depth) { + // Simplified visibility - replace with your full visibility function if needed + vec3 sampleColor = textureLod(gbuffer1, uv, 0.0).rgb * getVisibility(pos, normal, depth, uv); + + #ifdef _EmissionShadeless + if (matid == 1) { // pure emissive material, color stored in basecol + sampleColor += textureLod(gbuffer1, uv, 0.0).rgb; + } + #endif + #ifdef _EmissionShaded + #ifdef _EmissionShadeless + else { + #endif + vec3 sampleEmission = textureLod(gbufferEmission, uv, 0.0).rgb; + sampleColor += sampleEmission; // Emission should be added directly + #ifdef _EmissionShadeless + } + #endif + #endif + + return sampleColor; +} + +// Improved sampling parameters +const float GOLDEN_ANGLE = 2.39996323; +const float MAX_DEPTH_DIFFERENCE = 0.9; // More conservative depth threshold +const float SAMPLE_BIAS = 0.01; // Small offset to avoid self-occlusion + void main() { - fragColor = 0; - vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); - float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0; + float depth = textureLod(gbufferD, texCoord, 0.0).r; + if (depth >= 1.0) { + fragColor = vec3(0.0); + return; + } + + vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); // Normal.xy, roughness, metallic/matid + unpackFloatInt16(g0.a, metallic, matid); + + vec2 velocity = -textureLod(sveloc, texCoord, 0.0).rg; - vec2 enc = g0.rg; vec3 n; - n.z = 1.0 - abs(enc.x) - abs(enc.y); - n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy); - n = normalize(V3 * 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); - vpos = getPosView(viewRay, d, cameraProj); + vec3 pos = getWorldPos(texCoord, depth); + vec3 normal = getNormal(texCoord); + vec3 centerColor = textureLod(gbuffer1, texCoord, 0.0).rgb; - rayCast(n); - vec3 o1 = normalize(tangent(n)); - vec3 o2 = (cross(o1, n)); - vec3 c1 = 0.5f * (o1 + o2); - vec3 c2 = 0.5f * (o1 - o2); - rayCast(mix(n, o1, angleMix)); - rayCast(mix(n, o2, angleMix)); - rayCast(mix(n, -c1, angleMix)); - rayCast(mix(n, -c2, angleMix)); + float radius = ssaoRadius; - #ifdef _SSGICone9 - rayCast(mix(n, -o1, angleMix)); - rayCast(mix(n, -o2, angleMix)); - rayCast(mix(n, c1, angleMix)); - rayCast(mix(n, c2, angleMix)); + vec3 gi = vec3(0.0); + float totalWeight = 0.0; + float angle = fract(sin(dot(texCoord, vec2(12.9898, 78.233))) * 100.0); + + for (int i = 0; i < ssgiSamples; i++) { + // Use quasi-random sequence for better coverage + float r = sqrt((float(i) + 0.5) / float(ssgiSamples)) * radius; + float a = (float(i) * GOLDEN_ANGLE) + angle; + + vec2 offset = vec2(cos(a), sin(a)) * r * radius; + vec2 sampleUV = clamp(texCoord + offset * (BayerMatrix8[int(gl_FragCoord.x + velocity.x) % 8][int(gl_FragCoord.y + velocity.y) % 8] - 0.5) / screenSize, vec2(0.001), vec2(0.999)); + + float sampleDepth = textureLod(gbufferD, sampleUV, 0.0).r; + if (sampleDepth >= 1.0) continue; + + vec3 samplePos = getWorldPos(sampleUV, sampleDepth); + vec3 sampleNormal = getNormal(sampleUV); + + // Apply small bias to sample position to avoid self-occlusion + samplePos += sampleNormal * SAMPLE_BIAS; + + vec3 dir = pos - samplePos; + float dist = length(dir); + + if (abs(pos.z - samplePos.z) > MAX_DEPTH_DIFFERENCE) continue;; + + vec3 sampleColor = calculateIndirectLight(sampleUV, samplePos, sampleNormal, sampleDepth); + float weight = 1.0 / (1.0 + dist * dist * 2.0) * max(dot(sampleNormal, n), 0.0); + + gi += sampleColor * weight; + totalWeight += weight; + } + + // Normalize and apply intensity + if (totalWeight > 0.0) { + gi /= totalWeight; + #ifdef _CPostprocess + gi *= PPComp12.x; + #else + gi *= ssaoStrength; + #endif + } + + #ifdef _EmissionShadeless + if (matid == 1) { // pure emissive material, color stored in basecol + gi += textureLod(gbuffer1, texCoord, 0.0).rgb; + } #endif + #ifdef _EmissionShaded + #ifdef _EmissionShadeless + else { + #endif + gi += textureLod(gbufferEmission, texCoord, 0.0).rgb; + #ifdef _EmissionShadeless + } + #endif + #endif + fragColor = gi / (gi + vec3(1.0)); // Reinhard tone mapping } diff --git a/leenkx/Shaders/ssgi_pass/ssgi_pass.json b/leenkx/Shaders/ssgi_pass/ssgi_pass.json index a249a03..24e2649 100644 --- a/leenkx/Shaders/ssgi_pass/ssgi_pass.json +++ b/leenkx/Shaders/ssgi_pass/ssgi_pass.json @@ -6,6 +6,10 @@ "compare_mode": "always", "cull_mode": "none", "links": [ + { + "name": "invVP", + "link": "_inverseViewProjectionMatrix" + }, { "name": "P", "link": "_projectionMatrix" @@ -15,16 +19,180 @@ "link": "_viewMatrix3" }, { - "name": "invP", - "link": "_inverseProjectionMatrix" + "name": "eye", + "link": "_cameraPosition" + }, + { + "name": "eyeLook", + "link": "_cameraLook" }, { "name": "cameraProj", "link": "_cameraPlaneProj" + + }, + { + "name": "screenSize", + "link": "_screenSize" + }, + { + "name": "PPComp12", + "link": "_PPComp12", + "ifdef": ["_CPostprocess"] + }, + { + "name": "lightsArraySpot", + "link": "_lightsArraySpot", + "ifdef": ["_Clusters", "_Spot"] + }, + { + "name": "lightsArray", + "link": "_lightsArray", + "ifdef": ["_Clusters"] + }, + { + "name": "clustersData", + "link": "_clustersData", + "ifdef": ["_Clusters"] + }, + { + "name": "cameraPlane", + "link": "_cameraPlane", + "ifdef": ["_Clusters"] + }, + { + "name": "sunDir", + "link": "_sunDirection", + "ifdef": ["_Sun"] + }, + { + "name": "sunCol", + "link": "_sunColor", + "ifdef": ["_Sun"] + }, + { + "name": "shadowsBias", + "link": "_sunShadowsBias", + "ifdef": ["_Sun", "_ShadowMap"] + }, + { + "name": "LWVP", + "link": "_biasLightWorldViewProjectionMatrixSun", + "ifndef": ["_CSM"], + "ifdef": ["_Sun", "_ShadowMap"] + }, + { + "name": "casData", + "link": "_cascadeData", + "ifdef": ["_Sun", "_ShadowMap", "_CSM"] + }, + { + "name": "lightArea0", + "link": "_lightArea0", + "ifdef": ["_LTC"] + }, + { + "name": "lightArea1", + "link": "_lightArea1", + "ifdef": ["_LTC"] + }, + { + "name": "lightArea2", + "link": "_lightArea2", + "ifdef": ["_LTC"] + }, + { + "name": "lightArea3", + "link": "_lightArea3", + "ifdef": ["_LTC"] + }, + { + "name": "sltcMat", + "link": "_ltcMat", + "ifdef": ["_LTC"] + }, + { + "name": "sltcMag", + "link": "_ltcMag", + "ifdef": ["_LTC"] + }, + { + "name": "smSizeUniform", + "link": "_shadowMapSize", + "ifdef": ["_SMSizeUniform"] + }, + { + "name": "lightProj", + "link": "_lightPlaneProj", + "ifdef": ["_ShadowMap"] + }, + { + "name": "pointPos", + "link": "_pointPosition", + "ifdef": ["_SinglePoint"] + }, + { + "name": "pointCol", + "link": "_pointColor", + "ifdef": ["_SinglePoint"] + }, + { + "name": "pointBias", + "link": "_pointShadowsBias", + "ifdef": ["_SinglePoint", "_ShadowMap"] + }, + { + "name": "spotDir", + "link": "_spotDirection", + "ifdef": ["_SinglePoint", "_Spot"] + }, + { + "name": "spotData", + "link": "_spotData", + "ifdef": ["_SinglePoint", "_Spot"] + }, + { + "name": "spotRight", + "link": "_spotRight", + "ifdef": ["_SinglePoint", "_Spot"] + }, + { + "name": "LWVPSpotArray", + "link": "_biasLightWorldViewProjectionMatrixSpotArray", + "ifdef": ["_Clusters", "_ShadowMap", "_Spot"] + }, + { + "name": "pointLightDataArray", + "link": "_pointLightsAtlasArray", + "ifdef": ["_Clusters", "_ShadowMap", "_ShadowMapAtlas"] + }, + { + "name": "LWVPSpot[0]", + "link": "_biasLightWorldViewProjectionMatrixSpot0", + "ifndef": ["_ShadowMapAtlas"], + "ifdef": ["_LTC", "_ShadowMap"] + }, + { + "name": "LWVPSpot[1]", + "link": "_biasLightWorldViewProjectionMatrixSpot1", + "ifndef": ["_ShadowMapAtlas"], + "ifdef": ["_LTC", "_ShadowMap"] + }, + { + "name": "LWVPSpot[2]", + "link": "_biasLightWorldViewProjectionMatrixSpot2", + "ifndef": ["_ShadowMapAtlas"], + "ifdef": ["_LTC", "_ShadowMap"] + }, + { + "name": "LWVPSpot[3]", + "link": "_biasLightWorldViewProjectionMatrixSpot3", + "ifndef": ["_ShadowMapAtlas"], + "ifdef": ["_LTC", "_ShadowMap"] } ], "texture_params": [], - "vertex_shader": "../include/pass_viewray2.vert.glsl", + "vertex_shader": "../include/pass_viewray.vert.glsl", "fragment_shader": "ssgi_pass.frag.glsl" } ] diff --git a/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl b/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl index ed70110..44a2647 100644 --- a/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl +++ b/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl @@ -72,10 +72,11 @@ void main() { float roughness = g0.z; vec4 gr = textureLod(gbuffer_refraction, texCoord, 0.0); float ior = gr.x; - float opac = gr.y; + float opac = 1.0 - gr.y; float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0; if (d == 0.0 || d == 1.0 || opac == 1.0 || ior == 1.0) { fragColor.rgb = textureLod(tex1, texCoord, 0.0).rgb; + fragColor.a = opac; return; } vec2 enc = g0.rg; @@ -98,9 +99,12 @@ void main() { clamp(-refracted.z, 0.0, 1.0) * clamp((length(viewPos - hitCoord)), 0.0, 1.0) * coords.w; intensity = clamp(intensity, 0.0, 1.0); - vec3 refractionCol = textureLod(tex1, coords.xy, 0.0).rgb; - refractionCol *= intensity; - vec3 color = textureLod(tex, texCoord.xy, 0.0).rgb; + vec4 refractionCol = textureLod(tex1, coords.xy, 0.0).rgba; + refractionCol.a = opac; + //refractionCol *= intensity; + vec4 color = textureLod(tex, texCoord.xy, 0.0).rgba; + color.a = opac; - fragColor.rgb = mix(refractionCol, color, opac); + fragColor.rgba = mix(refractionCol, color, opac); + fragColor.a = opac; } diff --git a/leenkx/Shaders/ssrefr_pass/ssrefr_pass.json b/leenkx/Shaders/ssrefr_pass/ssrefr_pass.json index 716f218..77a4f40 100644 --- a/leenkx/Shaders/ssrefr_pass/ssrefr_pass.json +++ b/leenkx/Shaders/ssrefr_pass/ssrefr_pass.json @@ -5,6 +5,12 @@ "depth_write": false, "compare_mode": "always", "cull_mode": "none", + "blend_source": "source_alpha", + "blend_destination": "inverse_source_alpha", + "blend_operation": "add", + "alpha_blend_source": "blend_one", + "alpha_blend_destination": "blend_one", + "alpha_blend_operation": "add", "links": [ { "name": "P", diff --git a/leenkx/Shaders/sss_pass/sss_pass.frag.glsl b/leenkx/Shaders/sss_pass/sss_pass.frag.glsl index 872676f..0b5296f 100644 --- a/leenkx/Shaders/sss_pass/sss_pass.frag.glsl +++ b/leenkx/Shaders/sss_pass/sss_pass.frag.glsl @@ -1,6 +1,7 @@ // // Copyright (C) 2012 Jorge Jimenez (jorge@iryoku.com) // Copyright (C) 2012 Diego Gutierrez (diegog@unizar.es) +// Copyright (C) 2025 Onek8 (info@leenkx.com) // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -33,6 +34,14 @@ // policies, either expressed or implied, of the copyright holders. // +// TODO: +// Add real sss radius +// Add real sss scale +// Move temp hash, reorganize shader utility functions +// Add compiler flag for quality presets or with samples parameter +// Clean up + Document comment + + #version 450 #include "compiled.inc" @@ -49,67 +58,93 @@ out vec4 fragColor; const float SSSS_FOVY = 108.0; -// Separable SSS Reflectance -// const float sssWidth = 0.005; +// Temp hash func - +float hash13(vec3 p3) { + p3 = fract(p3 * vec3(0.1031, 0.1030, 0.0973)); + p3 += dot(p3, p3.yzx + 33.33); + return fract((p3.x + p3.y) * p3.z); +} + vec4 SSSSBlur() { - // Quality = 0 - const int SSSS_N_SAMPLES = 11; - vec4 kernel[SSSS_N_SAMPLES]; - kernel[0] = vec4(0.560479, 0.669086, 0.784728, 0); - kernel[1] = vec4(0.00471691, 0.000184771, 5.07566e-005, -2); - kernel[2] = vec4(0.0192831, 0.00282018, 0.00084214, -1.28); - kernel[3] = vec4(0.03639, 0.0130999, 0.00643685, -0.72); - kernel[4] = vec4(0.0821904, 0.0358608, 0.0209261, -0.32); - kernel[5] = vec4(0.0771802, 0.113491, 0.0793803, -0.08); - kernel[6] = vec4(0.0771802, 0.113491, 0.0793803, 0.08); - kernel[7] = vec4(0.0821904, 0.0358608, 0.0209261, 0.32); - kernel[8] = vec4(0.03639, 0.0130999, 0.00643685, 0.72); - kernel[9] = vec4(0.0192831, 0.00282018, 0.00084214, 1.28); - kernel[10] = vec4(0.00471691, 0.000184771, 5.07565e-005, 2); + const int SSSS_N_SAMPLES = 15; + vec4 kernel[SSSS_N_SAMPLES]; + + // color neutral kernel weights to prevent color shifting + kernel[0] = vec4(0.2, 0.2, 0.2, 0.0); + kernel[1] = vec4(0.12, 0.12, 0.12, 0.2); + kernel[2] = vec4(0.09, 0.09, 0.09, 0.4); + kernel[3] = vec4(0.06, 0.06, 0.06, 0.8); + kernel[4] = vec4(0.04, 0.04, 0.04, 1.2); + kernel[5] = vec4(0.025, 0.025, 0.025, 1.6); + kernel[6] = vec4(0.015, 0.015, 0.015, 2.0); + kernel[7] = vec4(0.005, 0.005, 0.005, 2.5); + kernel[8] = vec4(0.12, 0.12, 0.12, -0.2); + kernel[9] = vec4(0.09, 0.09, 0.09, -0.4); + kernel[10] = vec4(0.06, 0.06, 0.06, -0.8); + kernel[11] = vec4(0.04, 0.04, 0.04, -1.2); + kernel[12] = vec4(0.025, 0.025, 0.025, -1.6); + kernel[13] = vec4(0.015, 0.015, 0.015, -2.0); + kernel[14] = vec4(0.005, 0.005, 0.005, -2.5); vec4 colorM = textureLod(tex, texCoord, 0.0); - // Fetch linear depth of current pixel float depth = textureLod(gbufferD, texCoord, 0.0).r; float depthM = cameraProj.y / (depth - cameraProj.x); - // Calculate the sssWidth scale (1.0 for a unit plane sitting on the projection window) float distanceToProjectionWindow = 1.0 / tan(0.5 * radians(SSSS_FOVY)); float scale = distanceToProjectionWindow / depthM; - // Calculate the final step to fetch the surrounding pixels vec2 finalStep = sssWidth * scale * dir; - finalStep *= 1.0;//SSSS_STREGTH_SOURCE; // Modulate it using the alpha channel. - finalStep *= 1.0 / 3.0; // Divide by 3 as the kernels range from -3 to 3. - finalStep *= 0.05; // + - // Accumulate the center sample: - vec4 colorBlurred = colorM; - colorBlurred.rgb *= kernel[0].rgb; - - // Accumulate the other samples + vec3 jitterSeed = vec3(texCoord.xy * 1000.0, fract(cameraProj.x * 0.0001)); + float jitterOffset = (hash13(jitterSeed) * 2.0 - 1.0) * 0.15; // 15% jitteR + + finalStep *= (1.0 + jitterOffset); + finalStep *= 0.05; + vec3 colorBlurred = vec3(0.0); + vec3 weightSum = vec3(0.0); + colorBlurred += colorM.rgb * kernel[0].rgb; + weightSum += kernel[0].rgb; + + // Accumulate the other samples with per-pixel jittering to reduce banding for (int i = 1; i < SSSS_N_SAMPLES; i++) { - // Fetch color and depth for current sample - vec2 offset = texCoord + kernel[i].a * finalStep; + float sampleJitter = hash13(vec3(texCoord.xy * 720.0, float(i) * 37.45)) * 0.1 - 0.05; + + vec2 offset = texCoord + (kernel[i].a + sampleJitter) * finalStep; vec4 color = textureLod(tex, offset, 0.0); - //#if SSSS_FOLLOW_SURFACE == 1 - // If the difference in depth is huge, we lerp color back to "colorM": - //float depth = textureLod(tex, offset, 0.0).r; - //float s = clamp(300.0f * distanceToProjectionWindow * sssWidth * abs(depthM - depth),0.0,1.0); - //color.rgb = mix(color.rgb, colorM.rgb, s); - //#endif - // Accumulate - colorBlurred.rgb += kernel[i].rgb * color.rgb; + + // ADJUST FOR SURFACE FOLLOWING + // 0.0 = disabled (maximum SSS but with bleeding), 1.0 = fully enabled (prevents bleeding but might reduce SSS effect) + const float SURFACE_FOLLOWING_STRENGTH = 0.15; // Reduced to preserve more SSS effect + + if (SURFACE_FOLLOWING_STRENGTH > 0.0) { + float sampleDepth = textureLod(gbufferD, offset, 0.0).r; + float depthScale = 5.0; + float depthDiff = abs(depth - sampleDepth) * depthScale; + if (depthDiff > 0.3) { + float blendFactor = clamp(depthDiff - 0.3, 0.0, 1.0) * SURFACE_FOLLOWING_STRENGTH; + color.rgb = mix(color.rgb, colorM.rgb, blendFactor); + } + } + + colorBlurred += color.rgb * kernel[i].rgb; + weightSum += kernel[i].rgb; } - - return colorBlurred; + vec3 normalizedColor = colorBlurred / max(weightSum, vec3(0.00001)); + float dither = hash13(vec3(texCoord * 1333.0, 0.0)) * 0.003 - 0.0015; + return vec4(normalizedColor + vec3(dither), colorM.a); } void main() { + if (textureLod(gbuffer0, texCoord, 0.0).a == 8192.0) { - fragColor = clamp(SSSSBlur(), 0.0, 1.0); - } - else { + vec4 originalColor = textureLod(tex, texCoord, 0.0); + vec4 blurredColor = SSSSBlur(); + vec4 finalColor = mix(blurredColor, originalColor, 0.15); + + fragColor = clamp(finalColor, 0.0, 1.0); + } else { fragColor = textureLod(tex, texCoord, 0.0); } } diff --git a/leenkx/Shaders/std/aabb.glsl b/leenkx/Shaders/std/aabb.glsl new file mode 100644 index 0000000..2743684 --- /dev/null +++ b/leenkx/Shaders/std/aabb.glsl @@ -0,0 +1,18 @@ +#ifndef _AABB_GLSL +#define _AABB_GLSL + +bool IntersectAABB(vec3[2] a, vec3[2] b) { + const float EPSILON = 0.001; // Small tolerance to prevent false negatives + if (abs(a[0].x - b[0].x) > (a[1].x + b[1].x + EPSILON)) return false; + if (abs(a[0].y - b[0].y) > (a[1].y + b[1].y + EPSILON)) return false; + if (abs(a[0].z - b[0].z) > (a[1].z + b[1].z + EPSILON)) return false; + return true; +} + +void AABBfromMinMax(inout vec3[2] aabb, vec3 _min, vec3 _max) +{ + aabb[0] = (_min + _max) * 0.5f; + aabb[1] = abs(_max - aabb[0]); +} + +#endif \ No newline at end of file diff --git a/leenkx/Shaders/std/conetrace.glsl b/leenkx/Shaders/std/conetrace.glsl index 9ecce8e..9aeb03b 100644 --- a/leenkx/Shaders/std/conetrace.glsl +++ b/leenkx/Shaders/std/conetrace.glsl @@ -22,7 +22,7 @@ THE SOFTWARE. #ifndef _CONETRACE_GLSL_ #define _CONETRACE_GLSL_ -#include "std/voxels_constants.glsl" +#include "std/constants.glsl" // References // https://github.com/Friduric/voxel-cone-tracing @@ -92,7 +92,7 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori float dist = voxelSize0; float step_dist = dist; vec3 samplePos; - vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset; + vec3 start_pos = origin + n * voxelSize0; int clipmap_index0 = 0; vec3 aniso_direction = -dir; @@ -125,7 +125,7 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori if(clipmap_blend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) { vec4 mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, precomputed_direction, face_offset, direction_weight); - mipSample = mix(mipSample, mipSampleNext, smoothstep(0.0, 1.0, clipmap_blend)); + mipSample = mix(mipSample, mipSampleNext, clipmap_blend); } sampleCol += (1.0 - sampleCol.a) * mipSample; @@ -148,8 +148,9 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori vec4 traceDiffuse(const vec3 origin, const vec3 normal, const sampler3D voxels, const float clipmaps[voxelgiClipmapCount * 10]) { float sum = 0.0; vec4 amount = vec4(0.0); + mat3 TBN = makeTangentBasis(normal); for (int i = 0; i < DIFFUSE_CONE_COUNT; ++i) { - vec3 coneDir = DIFFUSE_CONE_DIRECTIONS[i]; + vec3 coneDir = TBN * DIFFUSE_CONE_DIRECTIONS[i]; const float cosTheta = dot(normal, coneDir); if (cosTheta <= 0) continue; @@ -166,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, const vec2 velocity) { - vec3 specularDir = reflect(-viewDir, normal); + vec3 specularDir = reflect(normalize(-viewDir), normal); vec3 P = origin + specularDir * ((BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5)) * voxelgiStep; vec4 amount = traceCone(voxels, voxelsSDF, P, normal, specularDir, 0, true, roughness, voxelgiStep, clipmaps); @@ -176,9 +177,9 @@ vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels, return amount * voxelgiOcc; } -vec4 traceRefraction(const vec3 origin, const vec3 normal, sampler3D voxels, sampler3D voxelsSDF, const vec3 viewDir, const float ior, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) { - const float transmittance = 1.0; - vec3 refractionDir = refract(-viewDir, normal, 1.0 / ior); +vec4 traceRefraction(const vec3 origin, const vec3 normal, sampler3D voxels, sampler3D voxelsSDF, const vec3 viewDir, const float ior, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity, const float opacity) { + const float transmittance = 1.0 - opacity; + vec3 refractionDir = refract(normalize(-viewDir), normal, 1.0 / ior); vec3 P = origin + refractionDir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep; vec4 amount = transmittance * traceCone(voxels, voxelsSDF, P, normal, refractionDir, 0, true, roughness, voxelgiStep, clipmaps); @@ -196,7 +197,7 @@ float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const float dist = voxelSize0; float step_dist = dist; vec3 samplePos; - vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset; + vec3 start_pos = origin + n * voxelSize0; int clipmap_index0 = 0; vec3 aniso_direction = -dir; @@ -259,7 +260,6 @@ float traceAO(const vec3 origin, const vec3 normal, const sampler3D voxels, cons } #endif - #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 sampleCol = 0.0; @@ -267,7 +267,7 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v float dist = voxelSize0; float step_dist = dist; vec3 samplePos; - vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset; + vec3 start_pos = origin + n * voxelSize0; int clipmap_index0 = 0; vec3 aniso_direction = -dir; @@ -287,7 +287,7 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v float clipmap_blend = fract(lod); vec3 p0 = start_pos + dir * dist; - samplePos = (p0 - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution.x); + samplePos = (p0 - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution); samplePos = samplePos * 0.5 + 0.5; if ((any(notEqual(samplePos, clamp(samplePos, 0.0, 1.0))))) { @@ -328,9 +328,9 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v } -float traceShadow(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 dir, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel) { - vec3 P = origin + dir * (BayerMatrix8[int(pixel.x) % 8][int(pixel.y) % 8] - 0.5) * voxelgiStep; - float amount = traceConeShadow(voxels, voxelsSDF, P, normal, dir, DIFFUSE_CONE_APERTURE, voxelgiStep, clipmaps); +float traceShadow(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 dir, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) { + vec3 P = origin + dir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep; + float amount = traceConeShadow(voxels, voxelsSDF, P, normal, dir, SHADOW_CONE_APERTURE, voxelgiStep, clipmaps); amount = clamp(amount, 0.0, 1.0); return amount * voxelgiOcc; } diff --git a/leenkx/Shaders/std/voxels_constants.glsl b/leenkx/Shaders/std/constants.glsl similarity index 50% rename from leenkx/Shaders/std/voxels_constants.glsl rename to leenkx/Shaders/std/constants.glsl index 5b82305..caf04dc 100644 --- a/leenkx/Shaders/std/voxels_constants.glsl +++ b/leenkx/Shaders/std/constants.glsl @@ -21,29 +21,49 @@ THE SOFTWARE. */ const int DIFFUSE_CONE_COUNT = 16; -const float DIFFUSE_CONE_APERTURE = radians(45.0); -const vec3 DIFFUSE_CONE_DIRECTIONS[16] = { - vec3(0.0000, 0.0000, 1.0000), // Central direction - vec3(0.3827, 0.0000, 0.9239), // Ring 1 - vec3(-0.3827, 0.0000, 0.9239), - vec3(0.0000, 0.3827, 0.9239), - vec3(0.0000, -0.3827, 0.9239), - vec3(0.2706, 0.2706, 0.9239), // Ring 2 - vec3(-0.2706, 0.2706, 0.9239), - vec3(0.2706, -0.2706, 0.9239), - vec3(-0.2706, -0.2706, 0.9239), - vec3(0.1802, 0.3604, 0.9239), // Ring 3 - vec3(-0.1802, 0.3604, 0.9239), - vec3(0.1802, -0.3604, 0.9239), - vec3(-0.1802, -0.3604, 0.9239), - vec3(0.3604, 0.1802, 0.9239), - vec3(-0.3604, 0.1802, 0.9239), - vec3(0.3604, -0.1802, 0.9239) -}; +const float SHADOW_CONE_APERTURE = radians(15.0); +const float DIFFUSE_CONE_APERTURE = 0.872665; // 50 degrees in radians -const float BayerMatrix8[8][8] = +mat3 makeTangentBasis(const vec3 normal) { + // Create a tangent basis from normal vector + vec3 tangent; + vec3 bitangent; + + // Compute tangent (Frisvad's method) + if (abs(normal.z) < 0.999) { + tangent = normalize(cross(vec3(0, 1, 0), normal)); + } else { + tangent = normalize(cross(normal, vec3(1, 0, 0))); + } + bitangent = cross(normal, tangent); + + return mat3(tangent, bitangent, normal); +} + +// 16 optimized cone directions for hemisphere sampling (Z-up, normalized) +const vec3 DIFFUSE_CONE_DIRECTIONS[16] = vec3[]( + vec3(0.707107, 0.000000, 0.707107), // Front + vec3(-0.707107, 0.000000, 0.707107), // Back + vec3(0.000000, 0.707107, 0.707107), // Right + vec3(0.000000, -0.707107, 0.707107), // Left + vec3(0.500000, 0.500000, 0.707107), // Front-right + vec3(-0.500000, 0.500000, 0.707107), // Back-right + vec3(0.500000, -0.500000, 0.707107), // Front-left + vec3(-0.500000, -0.500000, 0.707107),// Back-left + vec3(0.353553, 0.000000, 0.935414), // Narrow front + vec3(-0.353553, 0.000000, 0.935414), // Narrow back + vec3(0.000000, 0.353553, 0.935414), // Narrow right + vec3(0.000000, -0.353553, 0.935414), // Narrow left + vec3(0.270598, 0.270598, 0.923880), // Narrow front-right + vec3(-0.270598, 0.270598, 0.923880), // Narrow back-right + vec3(0.270598, -0.270598, 0.923880), // Narrow front-left + vec3(-0.270598, -0.270598, 0.923880) // Narrow back-left +); + +// TO DO - Disabled momentarily instead of changing formulas +const float off_BayerMatrix8[8][8] = { { 1.0 / 65.0, 49.0 / 65.0, 13.0 / 65.0, 61.0 / 65.0, 4.0 / 65.0, 52.0 / 65.0, 16.0 / 65.0, 64.0 / 65.0 }, { 33.0 / 65.0, 17.0 / 65.0, 45.0 / 65.0, 29.0 / 65.0, 36.0 / 65.0, 20.0 / 65.0, 48.0 / 65.0, 32.0 / 65.0 }, @@ -54,3 +74,15 @@ const float BayerMatrix8[8][8] = { 11.0 / 65.0, 59.0 / 65.0, 7.0 / 65.0, 55.0 / 65.0, 10.0 / 65.0, 58.0 / 65.0, 6.0 / 65.0, 54.0 / 65.0 }, { 43.0 / 65.0, 27.0 / 65.0, 39.0 / 65.0, 23.0 / 65.0, 42.0 / 65.0, 26.0 / 65.0, 38.0 / 65.0, 22.0 / 65.0 } }; +const float BayerMatrix8[8][8] = +{ + { 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }, + { 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }, + { 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }, + { 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }, + { 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }, + { 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }, + { 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }, + { 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 } +}; + diff --git a/leenkx/Shaders/std/light.glsl b/leenkx/Shaders/std/light.glsl index 9e1182e..b3267fe 100644 --- a/leenkx/Shaders/std/light.glsl +++ b/leenkx/Shaders/std/light.glsl @@ -1,239 +1,679 @@ -#ifndef _LIGHT_GLSL_ -#define _LIGHT_GLSL_ - -#include "compiled.inc" -#include "std/brdf.glsl" -#include "std/math.glsl" -#ifdef _ShadowMap -#include "std/shadows.glsl" -#endif -#ifdef _VoxelShadow -#include "std/conetrace.glsl" -//!uniform sampler2D voxels_shadows; -#endif -#ifdef _LTC -#include "std/ltc.glsl" -#endif -#ifdef _LightIES -#include "std/ies.glsl" -#endif -#ifdef _SSRS -#include "std/ssrs.glsl" -#endif -#ifdef _Spot -#include "std/light_common.glsl" -#endif - -#ifdef _ShadowMap - #ifdef _SinglePoint - #ifdef _Spot - #ifndef _LTC - uniform sampler2DShadow shadowMapSpot[1]; - uniform sampler2D shadowMapSpotTransparent[1]; - uniform mat4 LWVPSpot[1]; - #endif - #else - uniform samplerCubeShadow shadowMapPoint[1]; - uniform samplerCube shadowMapPointTransparent[1]; - uniform vec2 lightProj; - #endif - #endif - #ifdef _Clusters - #ifdef _SingleAtlas - //!uniform sampler2DShadow shadowMapAtlas; - //!uniform sampler2D shadowMapAtlasTransparent; - #endif - uniform vec2 lightProj; - #ifdef _ShadowMapAtlas - #ifndef _SingleAtlas - uniform sampler2DShadow shadowMapAtlasPoint; - uniform sampler2D shadowMapAtlasPointTransparent; - #endif - #else - uniform samplerCubeShadow shadowMapPoint[4]; - uniform samplerCube shadowMapPointTransparent[4]; - #endif - #ifdef _Spot - #ifdef _ShadowMapAtlas - #ifndef _SingleAtlas - uniform sampler2DShadow shadowMapAtlasSpot; - uniform sampler2D shadowMapAtlasSpotTransparent; - #endif - #else - uniform sampler2DShadow shadowMapSpot[4]; - uniform sampler2D shadowMapSpotTransparent[4]; - #endif - uniform mat4 LWVPSpotArray[maxLightsCluster]; - #endif - #endif -#endif - -#ifdef _LTC -uniform vec3 lightArea0; -uniform vec3 lightArea1; -uniform vec3 lightArea2; -uniform vec3 lightArea3; -uniform sampler2D sltcMat; -uniform sampler2D sltcMag; -#ifdef _ShadowMap -#ifndef _Spot - #ifdef _SinglePoint - uniform sampler2DShadow shadowMapSpot[1]; - uniform sampler2D shadowMapSpotTransparent[1]; - uniform mat4 LWVPSpot[1]; - #endif - #ifdef _Clusters - uniform sampler2DShadow shadowMapSpot[maxLightsCluster]; - uniform sampler2D shadowMapSpotTransparent[maxLightsCluster]; - uniform mat4 LWVPSpotArray[maxLightsCluster]; - #endif - #endif -#endif -#endif - -vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol, - const vec3 albedo, const float rough, const float spec, const vec3 f0 - #ifdef _ShadowMap - , int index, float bias, bool receiveShadow, bool transparent - #endif - #ifdef _Spot - , const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right - #endif - #ifdef _VoxelShadow - , sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount] - #endif - #ifdef _MicroShadowing - , float occ - #endif - #ifdef _SSRS - , sampler2D gbufferD, mat4 invVP, vec3 eye - #endif - ) { - vec3 ld = lp - p; - vec3 l = normalize(ld); - vec3 h = normalize(v + l); - float dotNH = max(0.0, dot(n, h)); - float dotVH = max(0.0, dot(v, h)); - float dotNL = max(0.0, dot(n, l)); - - #ifdef _LTC - float theta = acos(dotNV); - vec2 tuv = vec2(rough, theta / (0.5 * PI)); - tuv = tuv * LUT_SCALE + LUT_BIAS; - vec4 t = textureLod(sltcMat, tuv, 0.0); - mat3 invM = mat3( - vec3(1.0, 0.0, t.y), - vec3(0.0, t.z, 0.0), - vec3(t.w, 0.0, t.x)); - float ltcspec = ltcEvaluate(n, v, dotNV, p, invM, lightArea0, lightArea1, lightArea2, lightArea3); - ltcspec *= textureLod(sltcMag, tuv, 0.0).a; - float ltcdiff = ltcEvaluate(n, v, dotNV, p, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3); - vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05; - #else - vec3 direct = lambertDiffuseBRDF(albedo, dotNL) + - specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec; - #endif - - direct *= attenuate(distance(p, lp)); - direct *= lightCol; - - #ifdef _MicroShadowing - direct *= clamp(dotNL + 2.0 * occ * occ - 1.0, 0.0, 1.0); - #endif - - #ifdef _SSRS - direct *= traceShadowSS(l, p, gbufferD, invVP, eye); - #endif - - #ifdef _VoxelShadow - direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, l, clipmaps, gl_FragCoord.xy).r) * voxelgiShad; - #endif - - #ifdef _LTC - #ifdef _ShadowMap - if (receiveShadow) { - #ifdef _SinglePoint - vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0); - direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); - #endif - #ifdef _Clusters - vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); - if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); - else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent); - else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent); - else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent); - #endif - } - #endif - return direct; - #endif - - #ifdef _Spot - if (isSpot) { - direct *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend); - - #ifdef _ShadowMap - if (receiveShadow) { - #ifdef _SinglePoint - vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0); - direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); - #endif - #ifdef _Clusters - vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); - #ifdef _ShadowMapAtlas - direct *= shadowTest( - #ifndef _SingleAtlas - shadowMapAtlasSpot, shadowMapAtlasSpotTransparent - #else - shadowMapAtlas, shadowMapAtlasTransparent - #endif - , lPos.xyz / lPos.w, bias, transparent - ); - #else - if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); - else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent); - else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent); - else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent); - #endif - #endif - } - #endif - return direct; - } - #endif - - #ifdef _LightIES - direct *= iesAttenuation(-l); - #endif - - #ifdef _ShadowMap - if (receiveShadow) { - #ifdef _SinglePoint - #ifndef _Spot - direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent); - #endif - #endif - #ifdef _Clusters - #ifdef _ShadowMapAtlas - direct *= PCFFakeCube( - #ifndef _SingleAtlas - shadowMapAtlasPoint, shadowMapAtlasPointTransparent - #else - shadowMapAtlas, shadowMapAtlasTransparent - #endif - , ld, -l, bias, lightProj, n, index, transparent - ); - #else - if (index == 0) direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent); - else if (index == 1) direct *= PCFCube(shadowMapPoint[1], shadowMapPointTransparent[1], ld, -l, bias, lightProj, n, transparent); - else if (index == 2) direct *= PCFCube(shadowMapPoint[2], shadowMapPointTransparent[2], ld, -l, bias, lightProj, n, transparent); - else if (index == 3) direct *= PCFCube(shadowMapPoint[3], shadowMapPointTransparent[3], ld, -l, bias, lightProj, n, transparent); - #endif - #endif - } - #endif - - return direct; -} - -#endif +#ifndef _LIGHT_GLSL_ +#define _LIGHT_GLSL_ + +#include "compiled.inc" +#include "std/brdf.glsl" +#include "std/math.glsl" +#ifdef _ShadowMap +#include "std/shadows.glsl" +#endif +#ifdef _VoxelShadow +#include "std/conetrace.glsl" +#endif +#ifdef _LTC +#include "std/ltc.glsl" +#endif +#ifdef _LightIES +#include "std/ies.glsl" +#endif +#ifdef _SSRS +#include "std/ssrs.glsl" +#endif +#ifdef _Spot +#include "std/light_common.glsl" +#endif +#ifdef _VoxelShadow +#include "std/conetrace.glsl" +#endif + +#ifdef _ShadowMap + #ifdef _SinglePoint + #ifdef _Spot + #ifndef _LTC + uniform sampler2DShadow shadowMapSpot[1]; + #ifdef _ShadowMapTransparent + uniform sampler2D shadowMapSpotTransparent[1]; + #endif + uniform mat4 LWVPSpotArray[1]; + #endif + #else + uniform samplerCubeShadow shadowMapPoint[1]; + #ifdef _ShadowMapTransparent + uniform samplerCube shadowMapPointTransparent[1]; + #endif + uniform vec2 lightProj; + #endif + #endif + #ifdef _Clusters + #ifdef _SingleAtlas + //!uniform sampler2DShadow shadowMapAtlas; + #ifdef _ShadowMapTransparent + //!uniform sampler2D shadowMapAtlasTransparent; + #endif + #endif + uniform vec2 lightProj; + #ifdef _ShadowMapAtlas + #ifndef _SingleAtlas + uniform sampler2DShadow shadowMapAtlasPoint; + #ifdef _ShadowMapTransparent + uniform sampler2D shadowMapAtlasPointTransparent; + #endif + #endif + #else + uniform samplerCubeShadow shadowMapPoint[4]; + #ifdef _ShadowMapTransparent + uniform samplerCube shadowMapPointTransparent[4]; + #endif + #endif + #ifdef _Spot + #ifdef _ShadowMapAtlas + #ifndef _SingleAtlas + uniform sampler2DShadow shadowMapAtlasSpot; + #ifdef _ShadowMapTransparent + uniform sampler2D shadowMapAtlasSpotTransparent; + #endif + #endif + #else + uniform sampler2DShadow shadowMapSpot[4]; + #ifdef _ShadowMapTransparent + uniform sampler2D shadowMapSpotTransparent[4]; + #endif + #endif + uniform mat4 LWVPSpotArray[maxLightsCluster]; + #endif + #endif +#endif + +#ifdef _LTC +uniform vec3 lightArea0; +uniform vec3 lightArea1; +uniform vec3 lightArea2; +uniform vec3 lightArea3; +uniform sampler2D sltcMat; +uniform sampler2D sltcMag; +#ifdef _ShadowMap +#ifndef _Spot + #ifdef _SinglePoint + uniform sampler2DShadow shadowMapSpot[1]; + #ifdef _ShadowMapTransparent + uniform sampler2D shadowMapSpotTransparent[1]; + #endif + uniform mat4 LWVPSpotArray[1]; + #endif + #ifdef _Clusters + uniform sampler2DShadow shadowMapSpot[maxLightsCluster]; + #ifdef _ShadowMapTransparent + uniform sampler2D shadowMapSpotTransparent[maxLightsCluster]; + #endif + uniform mat4 LWVPSpotArray[maxLightsCluster]; + #endif +#endif +#endif +#endif + +vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol, + const vec3 albedo, const float rough, const float spec, const vec3 f0 + #ifdef _ShadowMap + , int index, float bias, bool receiveShadow + #ifdef _ShadowMapTransparent + , bool transparent + #endif + #endif + #ifdef _Spot + , const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right + #endif + #ifdef _VoxelShadow + , sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount], vec2 velocity + #endif + #ifdef _MicroShadowing + , float occ + #endif + #ifdef _SSRS + , sampler2D gbufferD, mat4 invVP, vec3 eye + #endif + ) { + vec3 ld = lp - p; + vec3 l = normalize(ld); + vec3 h = normalize(v + l); + float dotNH = max(0.0, dot(n, h)); + float dotVH = max(0.0, dot(v, h)); + float dotNL = max(0.0, dot(n, l)); + + #ifdef _LTC + float theta = acos(dotNV); + vec2 tuv = vec2(rough, theta / (0.5 * PI)); + tuv = tuv * LUT_SCALE + LUT_BIAS; + vec4 t = textureLod(sltcMat, tuv, 0.0); + mat3 invM = mat3( + vec3(1.0, 0.0, t.y), + vec3(0.0, t.z, 0.0), + vec3(t.w, 0.0, t.x)); + float ltcspec = ltcEvaluate(n, v, dotNV, p, invM, lightArea0, lightArea1, lightArea2, lightArea3); + ltcspec *= textureLod(sltcMag, tuv, 0.0).a; + float ltcdiff = ltcEvaluate(n, v, dotNV, p, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3); + vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05; + #else + vec3 direct = lambertDiffuseBRDF(albedo, dotNL) + + specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec; + #endif + + direct *= attenuate(distance(p, lp)); + direct *= lightCol; + + #ifdef _MicroShadowing + direct *= clamp(dotNL + 2.0 * occ * occ - 1.0, 0.0, 1.0); + #endif + + #ifdef _SSRS + direct *= traceShadowSS(l, p, gbufferD, invVP, eye); + #endif + + #ifdef _VoxelShadow + vec3 lightDir = l; + #ifdef _Spot + if (isSpot) + lightDir = spotDir; + #endif + direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, lightDir, clipmaps, gl_FragCoord.xy, velocity).r) * voxelgiShad; + #endif + + #ifdef _LTC + #ifdef _ShadowMap + if (receiveShadow) { + #ifdef _SinglePoint + vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0); + direct *= shadowTest(shadowMapSpot[0], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[0], + #endif + lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + #endif + #ifdef _Clusters + vec4 lPos = LWVPSpot[index] * vec4(p + n * bias * 10, 1.0); + if (index == 0) direct *= shadowTest(shadowMapSpot[0], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[0], + #endif + lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + else if (index == 1) direct *= shadowTest(shadowMapSpot[1], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[1], + #endif + lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + else if (index == 2) direct *= shadowTest(shadowMapSpot[2], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[2], + #endif + lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + else if (index == 3) direct *= shadowTest(shadowMapSpot[3], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[3], + #endif + lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + #endif + } + #endif + return direct; + #endif + + #ifdef _Spot + if (isSpot) { + direct *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend); + + #ifdef _ShadowMap + if (receiveShadow) { + #ifdef _SinglePoint + vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0); + direct *= shadowTest(shadowMapSpot[0], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[0], + #endif + lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + #endif + #ifdef _Clusters + vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); + #ifdef _ShadowMapAtlas + direct *= shadowTest( + #ifdef _ShadowMapTransparent + #ifndef _SingleAtlas + shadowMapAtlasSpot, shadowMapAtlasSpotTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + #else + #ifndef _SingleAtlas + shadowMapAtlasSpot + #else + shadowMapAtlas + #endif + #endif + , lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + #else + if (index == 0) direct *= shadowTest(shadowMapSpot[0], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[0], + #endif + lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + else if (index == 1) direct *= shadowTest(shadowMapSpot[1], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[1], + #endif + lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + else if (index == 2) direct *= shadowTest(shadowMapSpot[2], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[2], + #endif + lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + else if (index == 3) direct *= shadowTest(shadowMapSpot[3], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[3], + #endif + lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + #endif + #endif + } + #endif + return direct; + } + #endif + + #ifdef _LightIES + direct *= iesAttenuation(-l); + #endif + + #ifdef _ShadowMap + if (receiveShadow) { + #ifdef _SinglePoint + #ifndef _Spot + direct *= PCFCube(shadowMapPoint[0], + #ifdef _ShadowMapTransparent + shadowMapPointTransparent[0], + #endif + ld, -l, bias, lightProj, n + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + #endif + #endif + #ifdef _Clusters + #ifdef _ShadowMapAtlas + direct *= PCFFakeCube( + #ifdef _ShadowMapTransparent + #ifndef _SingleAtlas + shadowMapAtlasPoint, shadowMapAtlasPointTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + #else + #ifndef _SingleAtlas + shadowMapAtlasPoint + #else + shadowMapAtlas + #endif + #endif + , ld, -l, bias, lightProj, n, index + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + #else + if (index == 0) direct *= PCFCube(shadowMapPoint[0], + #ifdef _ShadowMapTransparent + shadowMapPointTransparent[0], + #endif + ld, -l, bias, lightProj, n + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + else if (index == 1) direct *= PCFCube(shadowMapPoint[1], + #ifdef _ShadowMapTransparent + shadowMapPointTransparent[1], + #endif + ld, -l, bias, lightProj, n + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + else if (index == 2) direct *= PCFCube(shadowMapPoint[2], + #ifdef _ShadowMapTransparent + shadowMapPointTransparent[2], + #endif + ld, -l, bias, lightProj, n + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + else if (index == 3) direct *= PCFCube(shadowMapPoint[3], + #ifdef _ShadowMapTransparent + shadowMapPointTransparent[3], + #endif + ld, -l, bias, lightProj, n + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + #endif + #endif + } + #endif + + return direct; +} + +#ifdef _VoxelGI +vec3 sampleLightVoxels(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol, + const vec3 albedo, const float rough, const float spec, const vec3 f0 + #ifdef _ShadowMap + , int index, float bias, bool receiveShadow + #ifdef _ShadowMapTransparent + , bool transparent + #endif + #endif + #ifdef _Spot + , const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right + #endif + ) { + vec3 ld = lp - p; + vec3 l = normalize(ld); + vec3 h = normalize(v + l); + float dotNH = max(0.0, dot(n, h)); + float dotVH = max(0.0, dot(v, h)); + float dotNL = max(0.0, dot(n, l)); + + #ifdef _LTC + float theta = acos(dotNV); + vec2 tuv = vec2(rough, theta / (0.5 * PI)); + tuv = tuv * LUT_SCALE + LUT_BIAS; + vec4 t = textureLod(sltcMat, tuv, 0.0); + mat3 invM = mat3( + vec3(1.0, 0.0, t.y), + vec3(0.0, t.z, 0.0), + vec3(t.w, 0.0, t.x)); + float ltcspec = ltcEvaluate(n, v, dotNV, p, invM, lightArea0, lightArea1, lightArea2, lightArea3); + ltcspec *= textureLod(sltcMag, tuv, 0.0).a; + float ltcdiff = ltcEvaluate(n, v, dotNV, p, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3); + vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05; + #else + vec3 direct = lambertDiffuseBRDF(albedo, dotNL) + + specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec; + #endif + + direct *= attenuate(distance(p, lp)); + direct *= lightCol; + + #ifdef _LTC + #ifdef _ShadowMap + if (receiveShadow) { + #ifdef _SinglePoint + vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0); + direct *= shadowTest(shadowMapSpot[0], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[0], + #endif + lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + #endif + #ifdef _Clusters + vec4 lPos = LWVPSpot[index] * vec4(p + n * bias * 10, 1.0); + if (index == 0) direct *= shadowTest(shadowMapSpot[0], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[0], + #endif + lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + else if (index == 1) direct *= shadowTest(shadowMapSpot[1], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[1], + #endif + lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + else if (index == 2) direct *= shadowTest(shadowMapSpot[2], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[2], + #endif + lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + else if (index == 3) direct *= shadowTest(shadowMapSpot[3], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[3], + #endif + lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + #endif + } + #endif + return direct; + #endif + + #ifdef _Spot + if (isSpot) { + direct *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend); + + #ifdef _ShadowMap + if (receiveShadow) { + #ifdef _SinglePoint + vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0); + direct *= shadowTest(shadowMapSpot[0], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[0], + #endif + lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + #endif + #ifdef _Clusters + vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); + #ifdef _ShadowMapAtlas + direct *= shadowTest( + #ifdef _ShadowMapTransparent + #ifndef _SingleAtlas + shadowMapAtlasSpot, shadowMapAtlasSpotTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + #else + #ifndef _SingleAtlas + shadowMapAtlasSpot + #else + shadowMapAtlas + #endif + #endif + , lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + #else + if (index == 0) direct *= shadowTest(shadowMapSpot[0], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[0], + #endif + lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + else if (index == 1) direct *= shadowTest(shadowMapSpot[1], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[1], + #endif + lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + else if (index == 2) direct *= shadowTest(shadowMapSpot[2], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[2], + #endif + lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + else if (index == 3) direct *= shadowTest(shadowMapSpot[3], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[3], + #endif + lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + #endif + #endif + } + #endif + return direct; + } + #endif + + #ifdef _LightIES + direct *= iesAttenuation(-l); + #endif + + #ifdef _ShadowMap + if (receiveShadow) { + #ifdef _SinglePoint + #ifndef _Spot + direct *= PCFCube(shadowMapPoint[0], + #ifdef _ShadowMapTransparent + shadowMapPointTransparent[0], + #endif + ld, -l, bias, lightProj, n + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + #endif + #endif + #ifdef _Clusters + #ifdef _ShadowMapAtlas + direct *= PCFFakeCube( + #ifdef _ShadowMapTransparent + #ifndef _SingleAtlas + shadowMapAtlasPoint, shadowMapAtlasPointTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + #else + #ifndef _SingleAtlas + shadowMapAtlasPoint + #else + shadowMapAtlas + #endif + #endif + , ld, -l, bias, lightProj, n, index + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + #else + if (index == 0) direct *= PCFCube(shadowMapPoint[0], + #ifdef _ShadowMapTransparent + shadowMapPointTransparent[0], + #endif + ld, -l, bias, lightProj, n + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + else if (index == 1) direct *= PCFCube(shadowMapPoint[1], + #ifdef _ShadowMapTransparent + shadowMapPointTransparent[1], + #endif + ld, -l, bias, lightProj, n + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + else if (index == 2) direct *= PCFCube(shadowMapPoint[2], + #ifdef _ShadowMapTransparent + shadowMapPointTransparent[2], + #endif + ld, -l, bias, lightProj, n + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + else if (index == 3) direct *= PCFCube(shadowMapPoint[3], + #ifdef _ShadowMapTransparent + shadowMapPointTransparent[3], + #endif + ld, -l, bias, lightProj, n + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + #endif + #endif + } + #endif + + return direct; +} +#endif +#endif diff --git a/leenkx/Shaders/std/shadows.glsl b/leenkx/Shaders/std/shadows.glsl index d994eff..a1c01f4 100644 --- a/leenkx/Shaders/std/shadows.glsl +++ b/leenkx/Shaders/std/shadows.glsl @@ -58,7 +58,15 @@ vec2 sampleCube(vec3 dir, out int faceIndex) { } #endif -vec3 PCF(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec2 uv, const float compare, const vec2 smSize, const bool transparent) { +vec3 PCF(sampler2DShadow shadowMap, + #ifdef _ShadowMapTransparent + sampler2D shadowMapTransparent, + #endif + const vec2 uv, const float compare, const vec2 smSize + #ifdef _ShadowMapTransparent + , const bool transparent + #endif + ) { vec3 result = vec3(0.0); result.x = texture(shadowMap, vec3(uv + (vec2(-1.0, -1.0) / smSize), compare)); result.x += texture(shadowMap, vec3(uv + (vec2(-1.0, 0.0) / smSize), compare)); @@ -71,11 +79,13 @@ vec3 PCF(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec2 u result.x += texture(shadowMap, vec3(uv + (vec2(1.0, 1.0) / smSize), compare)); result = result.xxx / 9.0; + #ifdef _ShadowMapTransparent if (transparent == false) { vec4 shadowmap_transparent = texture(shadowMapTransparent, uv); if (shadowmap_transparent.a < compare) result *= shadowmap_transparent.rgb; } + #endif return result; } @@ -87,41 +97,15 @@ float lpToDepth(vec3 lp, const vec2 lightProj) { return zcomp * 0.5 + 0.5; } -#ifndef _ShadowMapAtlas -vec3 PCFCube(samplerCubeShadow shadowMapCube, samplerCube shadowMapCubeTransparent, vec3 lp, vec3 ml, float bias, vec2 lightProj, vec3 n, const bool transparent) { - const float s = shadowmapCubePcfSize; - float compare = lpToDepth(lp, lightProj) - bias * 1.5; - ml = ml + n * bias * 20; - #ifdef _InvY - ml.y = -ml.y; - #endif - - float shadowFactor = 0.0; - shadowFactor = texture(shadowMapCube, vec4(ml, compare)); - shadowFactor += texture(shadowMapCube, vec4(ml + vec3(s, s, s), compare)); - shadowFactor += texture(shadowMapCube, vec4(ml + vec3(-s, s, s), compare)); - shadowFactor += texture(shadowMapCube, vec4(ml + vec3(s, -s, s), compare)); - shadowFactor += texture(shadowMapCube, vec4(ml + vec3(s, s, -s), compare)); - shadowFactor += texture(shadowMapCube, vec4(ml + vec3(-s, -s, s), compare)); - shadowFactor += texture(shadowMapCube, vec4(ml + vec3(s, -s, -s), compare)); - shadowFactor += texture(shadowMapCube, vec4(ml + vec3(-s, s, -s), compare)); - shadowFactor += texture(shadowMapCube, vec4(ml + vec3(-s, -s, -s), compare)); - shadowFactor /= 9.0; - - vec3 result = vec3(shadowFactor); - - if (transparent == false) { - vec4 shadowmap_transparent = texture(shadowMapCubeTransparent, ml); - if (shadowmap_transparent.a < compare) - result *= shadowmap_transparent.rgb; - } - - return result; -} -#endif - -#ifdef _ShadowMapAtlas -vec3 PCFCube(samplerCubeShadow shadowMapCube, samplerCube shadowMapCubeTransparent, const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n, const bool transparent) { +vec3 PCFCube(samplerCubeShadow shadowMapCube, + #ifdef _ShadowMapTransparent + samplerCube shadowMapCubeTransparent, + #endif + const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n + #ifdef _ShadowMapTransparent + , const bool transparent + #endif + ) { const float s = shadowmapCubePcfSize; // TODO: incorrect... float compare = lpToDepth(lp, lightProj) - bias * 1.5; ml = ml + n * bias * 20; @@ -140,16 +124,18 @@ vec3 PCFCube(samplerCubeShadow shadowMapCube, samplerCube shadowMapCubeTranspare result.x += texture(shadowMapCube, vec4(ml + vec3(-s, -s, -s), compare)); result = result.xxx / 9.0; + #ifdef _ShadowMapTransparent if (transparent == false) { vec4 shadowmap_transparent = texture(shadowMapCubeTransparent, ml); if (shadowmap_transparent.a < compare) result *= shadowmap_transparent.rgb; } + #endif return result; } - +#ifdef _ShadowMapAtlas // transform "out-of-bounds" coordinates to the correct face/coordinate system // https://www.khronos.org/opengl/wiki/File:CubeMapAxes.png vec2 transformOffsetedUV(const int faceIndex, out int newFaceIndex, vec2 uv) { @@ -243,21 +229,31 @@ vec2 transformOffsetedUV(const int faceIndex, out int newFaceIndex, vec2 uv) { return uv; } -vec3 PCFFakeCube(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n, const int index, const bool transparent) { +vec3 PCFFakeCube(sampler2DShadow shadowMap, + #ifdef _ShadowMapTransparent + sampler2D shadowMapTransparent, + #endif + const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n, const int index + #ifdef _ShadowMapTransparent + , const bool transparent + #endif + ) { const vec2 smSize = smSizeUniform; // TODO: incorrect... const float compare = lpToDepth(lp, lightProj) - bias * 1.5; ml = ml + n * bias * 20; - int faceIndex = 0; const int lightIndex = index * 6; const vec2 uv = sampleCube(ml, faceIndex); - vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy; #ifdef _FlipY uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system #endif + if (any(lessThan(uvtiled, vec2(0.0))) || any(greaterThan(uvtiled, vec2(1.0)))) { + return vec3(1.0); // Handle edge cases by returning full light + } + vec3 result = vec3(0.0); result.x += texture(shadowMap, vec3(uvtiled, compare)); // soft shadowing @@ -270,14 +266,6 @@ vec3 PCFFakeCube(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, cons #endif result.x += texture(shadowMap, vec3(uvtiled, compare)); - uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(-1.0, 1.0) / smSize))); - pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; - uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - result.x += texture(shadowMap, vec3(uvtiled, compare)); - uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(0.0, -1.0) / smSize))); pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; @@ -334,30 +322,47 @@ vec3 PCFFakeCube(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, cons uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system #endif + #ifdef _ShadowMapTransparent if (transparent == false) { vec4 shadowmap_transparent = texture(shadowMapTransparent, uvtiled); if (shadowmap_transparent.a < compare) result *= shadowmap_transparent.rgb; } + #endif return result; } #endif -vec3 shadowTest(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec3 lPos, const float shadowsBias, const bool transparent) { +vec3 shadowTest(sampler2DShadow shadowMap, + #ifdef _ShadowMapTransparent + sampler2D shadowMapTransparent, + #endif + const vec3 lPos, const float shadowsBias + #ifdef _ShadowMapTransparent + , const bool transparent + #endif + ) { #ifdef _SMSizeUniform vec2 smSize = smSizeUniform; #else const vec2 smSize = shadowmapSize; #endif if (lPos.x < 0.0 || lPos.y < 0.0 || lPos.x > 1.0 || lPos.y > 1.0) return vec3(1.0); - return PCF(shadowMap, shadowMapTransparent, lPos.xy, lPos.z - shadowsBias, smSize, transparent); + return PCF(shadowMap, + #ifdef _ShadowMapTransparent + shadowMapTransparent, + #endif + lPos.xy, lPos.z - shadowsBias, smSize + #ifdef _ShadowMapTransparent + , transparent + #endif + ); } #ifdef _CSM mat4 getCascadeMat(const float d, out int casi, out int casIndex) { const int c = shadowmapCascades; - // Get cascade index // TODO: use bounding box slice selection instead of sphere const vec4 ci = vec4(float(c > 0), float(c > 1), float(c > 2), float(c > 3)); @@ -373,21 +378,26 @@ mat4 getCascadeMat(const float d, out int casi, out int casIndex) { float(d > casData[c * 4].z), float(d > casData[c * 4].w)); casi = int(min(dot(ci, comp), c)); - // Get cascade mat casIndex = casi * 4; - return mat4( casData[casIndex ], casData[casIndex + 1], casData[casIndex + 2], casData[casIndex + 3]); - // if (casIndex == 0) return mat4(casData[0], casData[1], casData[2], casData[3]); // .. } -vec3 shadowTestCascade(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec3 eye, const vec3 p, const float shadowsBias, const bool transparent) { +vec3 shadowTestCascade(sampler2DShadow shadowMap, + #ifdef _ShadowMapTransparent + sampler2D shadowMapTransparent, + #endif + const vec3 eye, const vec3 p, const float shadowsBias + #ifdef _ShadowMapTransparent + , const bool transparent + #endif + ) { #ifdef _SMSizeUniform vec2 smSize = smSizeUniform; #else @@ -395,16 +405,22 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap, sampler2D shadowMapTransparent #endif const int c = shadowmapCascades; float d = distance(eye, p); - int casi; int casIndex; mat4 LWVP = getCascadeMat(d, casi, casIndex); - vec4 lPos = LWVP * vec4(p, 1.0); lPos.xyz /= lPos.w; vec3 visibility = vec3(1.0); - if (lPos.w > 0.0) visibility = PCF(shadowMap, shadowMapTransparent, lPos.xy, lPos.z - shadowsBias, smSize, transparent); + if (lPos.w > 0.0) visibility = PCF(shadowMap, + #ifdef _ShadowMapTransparent + shadowMapTransparent, + #endif + lPos.xy, lPos.z - shadowsBias, smSize + #ifdef _ShadowMapTransparent + , transparent + #endif + ); // Blend cascade // https://github.com/TheRealMJP/Shadows @@ -423,13 +439,20 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap, sampler2D shadowMapTransparent vec4 lPos2 = LWVP2 * vec4(p, 1.0); lPos2.xyz /= lPos2.w; vec3 visibility2 = vec3(1.0); - if (lPos2.w > 0.0) visibility2 = PCF(shadowMap, shadowMapTransparent, lPos2.xy, lPos2.z - shadowsBias, smSize, transparent); + if (lPos2.w > 0.0) visibility2 = PCF(shadowMap, + #ifdef _ShadowMapTransparent + shadowMapTransparent, + #endif + lPos.xy, lPos.z - shadowsBias, smSize + #ifdef _ShadowMapTransparent + , transparent + #endif + ); float lerpAmt = smoothstep(0.0, blendThres, splitDist); return mix(visibility2, visibility, lerpAmt); } return visibility; - // Visualize cascades // if (ci == 0) albedo.rgb = vec3(1.0, 0.0, 0.0); // if (ci == 4) albedo.rgb = vec3(0.0, 1.0, 0.0); @@ -437,4 +460,4 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap, sampler2D shadowMapTransparent // if (ci == 12) albedo.rgb = vec3(1.0, 1.0, 0.0); } #endif -#endif +#endif \ No newline at end of file diff --git a/leenkx/Shaders/voxel_light/voxel_light.comp.glsl b/leenkx/Shaders/voxel_light/voxel_light.comp.glsl index 8d4515f..3fbdd82 100644 --- a/leenkx/Shaders/voxel_light/voxel_light.comp.glsl +++ b/leenkx/Shaders/voxel_light/voxel_light.comp.glsl @@ -33,6 +33,7 @@ uniform layout(r32ui) uimage3D voxelsLight; #ifdef _ShadowMap uniform sampler2DShadow shadowMap; +uniform sampler2D shadowMapTransparent; uniform sampler2DShadow shadowMapSpot; #ifdef _ShadowMapAtlas uniform sampler2DShadow shadowMapPoint; @@ -86,30 +87,28 @@ float lpToDepth(vec3 lp, const vec2 lightProj) { void main() { int res = voxelgiResolution.x; - ivec3 dst = ivec3(gl_GlobalInvocationID.xyz); - dst.y += clipmapLevel * res; - vec3 P = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution; - P = P * 2.0 - 1.0; - P *= clipmaps[int(clipmapLevel * 10)]; - P *= voxelgiResolution; - P += vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)]); + vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x; + wposition = wposition * 2.0 - 1.0; + wposition *= float(clipmaps[int(clipmapLevel * 10)]); + wposition *= voxelgiResolution.x; + wposition += vec3(clipmaps[clipmapLevel * 10 + 4], clipmaps[clipmapLevel * 10 + 5], clipmaps[clipmapLevel * 10 + 6]); - vec3 visibility; - vec3 lp = lightPos - P; + float visibility; + vec3 lp = lightPos -wposition; vec3 l; - if (lightType == 0) { l = lightDir; visibility = vec3(1.0); } - else { l = normalize(lp); visibility = vec3(attenuate(distance(P, lightPos))); } + if (lightType == 0) { l = lightDir; visibility = 1.0; } + else { l = normalize(lp); visibility = attenuate(distance(wposition, lightPos)); } #ifdef _ShadowMap if (lightShadow == 1) { - vec4 lightPosition = LVP * vec4(P, 1.0); + vec4 lightPosition = LVP * vec4(wposition, 1.0); vec3 lPos = lightPosition.xyz / lightPosition.w; - visibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).rrr; + visibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).r; } else if (lightShadow == 2) { - vec4 lightPosition = LVP * vec4(P, 1.0); + vec4 lightPosition = LVP * vec4(wposition, 1.0); vec3 lPos = lightPosition.xyz / lightPosition.w; visibility *= texture(shadowMapSpot, vec3(lPos.xy, lPos.z - shadowsBias)).r; } @@ -130,9 +129,7 @@ void main() { } #endif - vec3 light = visibility * lightColor; - - imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, 0), uint(light.r * 255)); - imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x), uint(light.g * 255)); - imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x * 2), uint(light.b * 255)); + imageAtomicAdd(voxelsLight, dst, uint(visibility * lightColor.r * 255)); + imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x), uint(visibility * lightColor.g * 255)); + imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x * 2), uint(visibility * lightColor.b * 255)); } diff --git a/leenkx/Shaders/voxel_offsetprev/voxel_offsetprev.comp.glsl b/leenkx/Shaders/voxel_offsetprev/voxel_offsetprev.comp.glsl index bf6ac52..3b5fe1c 100644 --- a/leenkx/Shaders/voxel_offsetprev/voxel_offsetprev.comp.glsl +++ b/leenkx/Shaders/voxel_offsetprev/voxel_offsetprev.comp.glsl @@ -27,14 +27,14 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in; #include "std/math.glsl" #include "std/gbuffer.glsl" #include "std/imageatomic.glsl" -#include "std/voxels_constants.glsl" +#include "std/constants.glsl" #ifdef _VoxelGI uniform layout(rgba8) image3D voxelsB; uniform layout(rgba8) image3D voxelsOut; #else -uniform layout(r16) image3D voxelsB; -uniform layout(r16) image3D voxelsOut; +uniform layout(r8) image3D voxelsB; +uniform layout(r8) image3D voxelsOut; #endif uniform int clipmapLevel; diff --git a/leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl b/leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl index 6abf9d1..7123f27 100644 --- a/leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl +++ b/leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl @@ -29,19 +29,38 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in; #include "std/gbuffer.glsl" #include "std/imageatomic.glsl" #include "std/conetrace.glsl" +#include "std/brdf.glsl" +#include "std/shirr.glsl" uniform sampler3D voxels; uniform sampler2D gbufferD; uniform sampler2D gbuffer0; -uniform layout(r8) image2D voxels_ao; +uniform layout(rgba8) image2D voxels_ao; uniform float clipmaps[voxelgiClipmapCount * 10]; uniform mat4 InvVP; -uniform vec2 cameraProj; uniform vec3 eye; -uniform vec3 eyeLook; uniform vec2 postprocess_resolution; +uniform sampler2D gbuffer1; +#ifdef _gbuffer2 +uniform sampler2D gbuffer2; +#endif +uniform float envmapStrength; +#ifdef _Irr +uniform float shirr[7 * 4]; +#endif +#ifdef _Brdf +uniform sampler2D senvmapBrdf; +#endif +#ifdef _Rad +uniform sampler2D senvmapRadiance; +uniform int envmapNumMipmaps; +#endif +#ifdef _EnvCol +uniform vec3 backgroundCol; +#endif + void main() { const vec2 pixel = gl_GlobalInvocationID.xy; vec2 uv = (pixel + 0.5) / postprocess_resolution; @@ -54,12 +73,11 @@ void main() { float x = uv.x * 2 - 1; float y = uv.y * 2 - 1; - vec4 v = vec4(x, y, 1.0, 1.0); - v = vec4(InvVP * v); - v.xyz /= v.w; - vec3 viewRay = v.xyz - eye; + vec4 clipPos = vec4(x, y, depth, 1.0); + vec4 worldPos = InvVP * clipPos; + vec3 P = worldPos.xyz / worldPos.w; - vec3 P = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj); + vec3 v = normalize(eye - P); vec4 g0 = textureLod(gbuffer0, uv, 0.0); vec3 n; @@ -67,7 +85,89 @@ void main() { n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy); n = normalize(n); - float occ = 1.0 - traceAO(P, n, voxels, clipmaps); + float roughness = g0.b; + float metallic; + uint matid; + unpackFloatInt16(g0.a, metallic, matid); - imageStore(voxels_ao, ivec2(pixel), vec4(occ)); + 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); + float dotNV = max(dot(n, v), 0.0); + +#ifdef _gbuffer2 + vec4 g2 = textureLod(gbuffer2, uv, 0.0); +#endif + +#ifdef _MicroShadowing + occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel +#endif + +#ifdef _Brdf + vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy; + vec3 F = f0 * envBRDF.x + envBRDF.y; +#endif + + // Envmap +#ifdef _Irr + vec4 shPacked[7]; + for (int i = 0; i < 7; i++) { + int base = i * 4; + shPacked[i] = vec4( + shirr[base], + shirr[base + 1], + shirr[base + 2], + shirr[base + 3] + ); + } + vec3 envl = shIrradiance(n, shPacked); + + #ifdef _gbuffer2 + if (g2.b < 0.5) { + envl = envl; + } else { + envl = vec3(0.0); + } + #endif + + #ifdef _EnvTex + envl /= PI; + #endif +#else + vec3 envl = vec3(0.0); +#endif + +#ifdef _Rad + vec3 reflectionWorld = reflect(-v, n); + float lod = getMipFromRoughness(roughness, envmapNumMipmaps); + vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb; +#endif + +#ifdef _EnvLDR + envl.rgb = pow(envl.rgb, vec3(2.2)); + #ifdef _Rad + prefilteredColor = pow(prefilteredColor, vec3(2.2)); + #endif +#endif + + envl.rgb *= albedo; + +#ifdef _Brdf + envl.rgb *= 1.0 - F; //LV: We should take refracted light into account +#endif + +#ifdef _Rad // Indirect specular + envl.rgb += prefilteredColor * F; //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT +#else + #ifdef _EnvCol + envl.rgb += backgroundCol * F; //LV: Eh, what's the point of weighting it only by F0? + #endif +#endif + + envl.rgb *= envmapStrength * occspec.x; + + vec3 occ = envl * (1.0 - traceAO(P, n, voxels, clipmaps)); + + imageStore(voxels_ao, ivec2(pixel), vec4(occ, 1.0)); } diff --git a/leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl b/leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl index 4d19a88..a605d79 100644 --- a/leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl +++ b/leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl @@ -29,6 +29,8 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in; #include "std/gbuffer.glsl" #include "std/imageatomic.glsl" #include "std/conetrace.glsl" +#include "std/brdf.glsl" +#include "std/shirr.glsl" uniform sampler3D voxels; uniform sampler2D gbufferD; @@ -37,29 +39,44 @@ uniform layout(rgba8) image2D voxels_diffuse; uniform float clipmaps[voxelgiClipmapCount * 10]; uniform mat4 InvVP; -uniform vec2 cameraProj; uniform vec3 eye; -uniform vec3 eyeLook; uniform vec2 postprocess_resolution; +uniform sampler2D gbuffer1; +#ifdef _gbuffer2 +uniform sampler2D gbuffer2; +#endif +uniform float envmapStrength; +#ifdef _Irr +uniform float shirr[7 * 4]; +#endif +#ifdef _Brdf +uniform sampler2D senvmapBrdf; +#endif +#ifdef _Rad +uniform sampler2D senvmapRadiance; +uniform int envmapNumMipmaps; +#endif +#ifdef _EnvCol +uniform vec3 backgroundCol; +#endif + void main() { const vec2 pixel = gl_GlobalInvocationID.xy; vec2 uv = (pixel + 0.5) / postprocess_resolution; #ifdef _InvY - uv.y = 1.0 - uv.y + uv.y = 1.0 - uv.y; #endif float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0; - if (depth == 0) return; + if (depth == 0.0) return; float x = uv.x * 2 - 1; float y = uv.y * 2 - 1; - vec4 v = vec4(x, y, 1.0, 1.0); - v = vec4(InvVP * v); - v.xyz /= v.w; - vec3 viewRay = v.xyz - eye; - - vec3 P = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj); + vec4 clipPos = vec4(x, y, depth, 1.0); + vec4 worldPos = InvVP * clipPos; + vec3 P = worldPos.xyz / worldPos.w; + vec3 v = normalize(eye - P); vec4 g0 = textureLod(gbuffer0, uv, 0.0); vec3 n; @@ -67,7 +84,94 @@ void main() { n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy); n = normalize(n); - vec4 color = traceDiffuse(P, n, voxels, clipmaps); + float roughness = g0.b; + float metallic; + uint matid; + unpackFloatInt16(g0.a, metallic, matid); - imageStore(voxels_diffuse, ivec2(pixel), color); + 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); + float dotNV = max(dot(n, v), 0.0); + +#ifdef _gbuffer2 + vec4 g2 = textureLod(gbuffer2, uv, 0.0); +#endif + +#ifdef _MicroShadowing + occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel +#endif + +#ifdef _Brdf + vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy; + vec3 F = f0 * envBRDF.x + envBRDF.y; +#else + vec3 F = f0; +#endif + + + // Envmap +#ifdef _Irr + vec4 shPacked[7]; + for (int i = 0; i < 7; i++) { + int base = i * 4; + shPacked[i] = vec4( + shirr[base], + shirr[base + 1], + shirr[base + 2], + shirr[base + 3] + ); + } + vec3 envl = shIrradiance(n, shPacked); + + #ifdef _gbuffer2 + if (g2.b < 0.5) { + envl = envl; + } else { + envl = vec3(0.0); + } + #endif + + #ifdef _EnvTex + envl /= PI; + #endif +#else + vec3 envl = vec3(0.0); +#endif + +#ifdef _Rad + vec3 reflectionWorld = reflect(-v, n); + float lod = getMipFromRoughness(roughness, envmapNumMipmaps); + vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb; +#endif + +#ifdef _EnvLDR + envl.rgb = pow(envl.rgb, vec3(2.2)); + #ifdef _Rad + prefilteredColor = pow(prefilteredColor, vec3(2.2)); + #endif +#endif + + envl.rgb *= albedo; + +#ifdef _Brdf + envl.rgb *= 1.0 - F; //LV: We should take refracted light into account +#endif + +#ifdef _Rad // Indirect specular + envl.rgb += prefilteredColor * F; //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT +#else + #ifdef _EnvCol + envl.rgb += backgroundCol * F; //LV: Eh, what's the point of weighting it only by F0? + #endif +#endif + + envl.rgb *= envmapStrength * occspec.x; + + vec4 trace = traceDiffuse(P, n, voxels, clipmaps); + vec3 color = trace.rgb * albedo * (1.0 - F); + color += envl * (1.0 - trace.a); + + imageStore(voxels_diffuse, ivec2(pixel), vec4(color, 1.0)); } diff --git a/leenkx/Shaders/voxel_resolve_refraction/voxel_resolve_refraction.comp.glsl b/leenkx/Shaders/voxel_resolve_refraction/voxel_resolve_refraction.comp.glsl deleted file mode 100644 index c74ebae..0000000 --- a/leenkx/Shaders/voxel_resolve_refraction/voxel_resolve_refraction.comp.glsl +++ /dev/null @@ -1,79 +0,0 @@ -/* -Copyright (c) 2024 Turánszki János - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - */ - -#version 450 - -layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in; - -#include "compiled.inc" -#include "std/math.glsl" -#include "std/gbuffer.glsl" -#include "std/imageatomic.glsl" -#include "std/conetrace.glsl" - -uniform sampler2D gbufferD; -uniform sampler2D gbuffer0; -uniform sampler3D voxels; -uniform sampler3D voxelsSDF; -uniform sampler2D gbuffer_refraction; -uniform layout(rgba8) image2D voxels_refraction; - -uniform float clipmaps[voxelgiClipmapCount * 10]; -uniform mat4 InvVP; -uniform vec2 cameraProj; -uniform vec3 eye; -uniform vec3 eyeLook; -uniform vec2 postprocess_resolution; - -void main() { - const vec2 pixel = gl_GlobalInvocationID.xy; - vec2 uv = (pixel + 0.5) / postprocess_resolution; - #ifdef _InvY - uv.y = 1.0 - uv.y - #endif - - float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0; - if (depth == 0) return; - - vec2 ior_opac = textureLod(gbuffer_refraction, uv, 0.0).xy; - - float x = uv.x * 2 - 1; - float y = uv.y * 2 - 1; - vec4 v = vec4(x, y, 1.0, 1.0); - v = vec4(InvVP * v); - v.xyz /= v.w; - vec3 viewRay = v.xyz - eye; - - vec3 P = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj); - - vec4 g0 = textureLod(gbuffer0, uv, 0.0); - 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); - - vec3 color = vec3(0.0); - if(ior_opac.y < 1.0) - color = traceRefraction(P, n, voxels, voxelsSDF, normalize(eye - P), ior_opac.x, g0.b, clipmaps, pixel).rgb; - - imageStore(voxels_refraction, ivec2(pixel), vec4(color, 1.0)); -} diff --git a/leenkx/Shaders/voxel_resolve_shadows/voxel_resolve_shadows.comp.glsl b/leenkx/Shaders/voxel_resolve_shadows/voxel_resolve_shadows.comp.glsl deleted file mode 100644 index d1e095f..0000000 --- a/leenkx/Shaders/voxel_resolve_shadows/voxel_resolve_shadows.comp.glsl +++ /dev/null @@ -1,75 +0,0 @@ -/* -Copyright (c) 2024 Turánszki János - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - */ - -#version 450 - -layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in; - -#include "compiled.inc" -#include "std/math.glsl" -#include "std/gbuffer.glsl" -#include "std/imageatomic.glsl" -#include "std/conetrace.glsl" - -uniform sampler3D voxels; -uniform sampler3D voxelsSDF; -uniform sampler2D gbufferD; -uniform sampler2D gbuffer0; -uniform layout(r16) image2D voxels_shadows; - -uniform float clipmaps[voxelgiClipmapCount * 10]; -uniform mat4 InvVP; -uniform vec2 cameraProj; -uniform vec3 eye; -uniform vec3 eyeLook; -uniform vec2 postprocess_resolution; -uniform vec3 lPos; - -void main() { - const vec2 pixel = gl_GlobalInvocationID.xy; - vec2 uv = (pixel + 0.5) / postprocess_resolution; - #ifdef _InvY - uv.y = 1.0 - uv.y; - #endif - - float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0; - if (depth == 0) return; - - float x = uv.x * 2 - 1; - float y = uv.y * 2 - 1; - vec4 v = vec4(x, y, 1.0, 1.0); - v = vec4(InvVP * v); - v.xyz /= v.w; - vec3 viewRay = v.xyz - eye; - - vec3 P = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj); - - vec4 g0 = textureLod(gbuffer0, uv, 0.0); - 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 occ = 1.0 - traceShadow(P, n, voxels, voxelsSDF, normalize(lPos - P), clipmaps, pixel); - - imageStore(voxels_shadows, ivec2(pixel), vec4(occ)); -} diff --git a/leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl b/leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl index 771b7a0..8cad6a1 100644 --- a/leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl +++ b/leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl @@ -29,6 +29,7 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in; #include "std/gbuffer.glsl" #include "std/imageatomic.glsl" #include "std/conetrace.glsl" +#include "std/brdf.glsl" uniform sampler2D gbufferD; uniform sampler2D gbuffer0; @@ -38,9 +39,7 @@ uniform layout(rgba8) image2D voxels_specular; uniform float clipmaps[voxelgiClipmapCount * 10]; uniform mat4 InvVP; -uniform vec2 cameraProj; uniform vec3 eye; -uniform vec3 eyeLook; uniform vec2 postprocess_resolution; uniform sampler2D sveloc; @@ -56,12 +55,10 @@ void main() { float x = uv.x * 2 - 1; float y = uv.y * 2 - 1; - vec4 v = vec4(x, y, 1.0, 1.0); - v = vec4(InvVP * v); - v.xyz /= v.w; + vec4 clipPos = vec4(x, y, depth, 1.0); + vec4 worldPos = InvVP * clipPos; + vec3 P = worldPos.xyz / worldPos.w; - vec3 viewRay = v.xyz - eye; - vec3 P = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj); vec4 g0 = textureLod(gbuffer0, uv, 0.0); vec3 n; @@ -71,7 +68,7 @@ void main() { vec2 velocity = -textureLod(sveloc, uv, 0.0).rg; - vec3 color = traceSpecular(P, n, voxels, voxelsSDF, normalize(eye - P), g0.z, clipmaps, pixel, velocity).rgb; + vec3 color = traceSpecular(P, n, voxels, voxelsSDF, normalize(eye - P), g0.z * g0.z, clipmaps, pixel, velocity).rgb; imageStore(voxels_specular, ivec2(pixel), vec4(color, 1.0)); } diff --git a/leenkx/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl b/leenkx/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl index d224df6..5e6a0ea 100644 --- a/leenkx/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl +++ b/leenkx/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl @@ -23,8 +23,8 @@ THE SOFTWARE. #include "compiled.inc" -uniform layout(r16) image3D input_sdf; -uniform layout(r16) image3D output_sdf; +uniform layout(r8) image3D input_sdf; +uniform layout(r8) image3D output_sdf; uniform float jump_size; uniform int clipmapLevel; diff --git a/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl b/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl index c62ca70..919e01a 100644 --- a/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl +++ b/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl @@ -46,15 +46,15 @@ uniform layout(r32ui) uimage3D voxels; uniform layout(r32ui) uimage3D voxelsLight; uniform layout(rgba8) image3D voxelsB; uniform layout(rgba8) image3D voxelsOut; -uniform layout(r16) image3D SDF; +uniform layout(r8) image3D SDF; #else #ifdef _VoxelAOvar #ifdef _VoxelShadow -uniform layout(r16) image3D SDF; +uniform layout(r8) image3D SDF; #endif uniform layout(r32ui) uimage3D voxels; -uniform layout(r16) image3D voxelsB; -uniform layout(r16) image3D voxelsOut; +uniform layout(r8) image3D voxelsB; +uniform layout(r8) image3D voxelsOut; #endif #endif @@ -74,14 +74,9 @@ void main() { #endif #endif - ivec3 src = ivec3(gl_GlobalInvocationID.xyz); - #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; - #endif + int nor_count = 0; + vec3 avgNormal = vec3(0.0); + mat3 TBN = mat3(0.0); for (int i = 0; i < 6 + DIFFUSE_CONE_COUNT; i++) { @@ -91,7 +86,7 @@ void main() { float aniso_colors[6]; #endif - src = ivec3(gl_GlobalInvocationID.xyz); + ivec3 src = ivec3(gl_GlobalInvocationID.xyz); src.x += i * res; ivec3 dst = src; dst.y += clipmapLevel * res; @@ -104,44 +99,67 @@ void main() { if (i < 6) { #ifdef _VoxelGI - vec4 basecol = vec4(0.0); - basecol.r = float(imageLoad(voxels, src)) / 255; - basecol.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x))) / 255; - basecol.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 255; - basecol.a = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 3))) / 255; - basecol /= 4; - vec3 emission = vec3(0.0); - emission.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 4))) / 255; - emission.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 5))) / 255; - emission.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 6))) / 255; - emission /= 3; - 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 envl = vec3(0.0); - envl.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 9))) / 255; - envl.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 10))) / 255; - envl.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 11))) / 255; - envl /= 3; - envl *= 100; + int count = int(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 15))); + if (count > 0) { + vec4 basecol = vec4(0.0); + basecol.r = float(imageLoad(voxels, src)) / 255; + basecol.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x))) / 255; + basecol.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 255; + basecol.a = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 3))) / 255; + basecol /= count; + vec3 emission = vec3(0.0); + emission.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 4))) / 255; + emission.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 5))) / 255; + emission.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 6))) / 255; + emission /= count; + 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 /= count; + N = decode_oct(N.rg * 2.0 - 1.0); - //clipmap to world - vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x; - wposition = wposition * 2.0 - 1.0; - wposition *= float(clipmaps[int(clipmapLevel * 10)]); - wposition *= voxelgiResolution.x; - wposition += vec3(clipmaps[clipmapLevel * 10 + 4], clipmaps[clipmapLevel * 10 + 5], clipmaps[clipmapLevel * 10 + 6]); + if (abs(N.x) > 0) + avgNormal.x += N.x; + if (abs(N.y) > 0) + avgNormal.y += N.y; + if (abs(N.z) > 0) + avgNormal.z += N.z; + if (i == 5) + { + avgNormal = normalize(avgNormal); + TBN = makeTangentBasis(avgNormal); + } - radiance = basecol; - vec4 trace = traceDiffuse(wposition, wnormal, voxelsSampler, clipmaps); - vec3 indirect = trace.rgb + envl.rgb * (1.0 - trace.a); - radiance.rgb *= light + indirect; - radiance.rgb += emission.rgb; + vec3 envl = vec3(0.0); + envl.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 9))) / 255; + envl.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 10))) / 255; + envl.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 11))) / 255; + envl /= count; + vec3 light = vec3(0.0); + light.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 12))) / 255; + light.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 13))) / 255; + light.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 14))) / 255; + light /= count; + //clipmap to world + vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x; + wposition = wposition * 2.0 - 1.0; + wposition *= float(clipmaps[int(clipmapLevel * 10)]); + wposition *= voxelgiResolution.x; + wposition += vec3(clipmaps[clipmapLevel * 10 + 4], clipmaps[clipmapLevel * 10 + 5], clipmaps[clipmapLevel * 10 + 6]); + + radiance = basecol; + vec4 trace = traceDiffuse(wposition, N, voxelsSampler, clipmaps); + vec3 indirect = trace.rgb + envl.rgb * (1.0 - trace.a); + radiance.rgb *= light + indirect; + radiance.rgb += emission.rgb; + } #else - opac = float(imageLoad(voxels, src)) / 255; + int count = int(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x))); + if (count > 0) { + opac = float(imageLoad(voxels, src)) / 255; + opac /= count; + } #endif #ifdef _VoxelGI @@ -195,7 +213,7 @@ void main() { } else { // precompute cone sampling: - vec3 coneDirection = DIFFUSE_CONE_DIRECTIONS[i - 6]; + vec3 coneDirection = TBN * DIFFUSE_CONE_DIRECTIONS[i - 6]; vec3 aniso_direction = -coneDirection; uvec3 face_offsets = uvec3( aniso_direction.x > 0 ? 0 : 1, @@ -236,4 +254,4 @@ void main() { imageStore(SDF, dst_sdf, vec4(sdf)); #endif #endif -} +} \ No newline at end of file diff --git a/leenkx/Shaders/water_pass/water_pass.frag.glsl b/leenkx/Shaders/water_pass/water_pass.frag.glsl index 2bf016b..cda7537 100644 --- a/leenkx/Shaders/water_pass/water_pass.frag.glsl +++ b/leenkx/Shaders/water_pass/water_pass.frag.glsl @@ -75,16 +75,17 @@ vec4 binarySearch(vec3 dir) { } vec4 rayCast(vec3 dir) { - #ifdef _CPostprocess - dir *= PPComp9.x; - #else - dir *= ssrRayStep; - #endif - for (int i = 0; i < maxSteps; i++) { - hitCoord += dir; - if (getDeltaDepth(hitCoord) > 0.0) return binarySearch(dir); - } - return vec4(0.0); + float ddepth; + dir *= ss_refractionRayStep; + for (int i = 0; i < maxSteps; i++) { + hitCoord += dir; + ddepth = getDeltaDepth(hitCoord); + if (ddepth > 0.0) + return binarySearch(dir); + } + // No hit — fallback to projecting the ray to UV space + vec2 fallbackUV = getProjectedCoord(hitCoord); + return vec4(fallbackUV, 0.0, 0.5); // We set .w lower to indicate fallback } #endif //SSR diff --git a/leenkx/Sources/leenkx/renderpath/Inc.hx b/leenkx/Sources/leenkx/renderpath/Inc.hx index 4820d63..77f4c69 100644 --- a/leenkx/Sources/leenkx/renderpath/Inc.hx +++ b/leenkx/Sources/leenkx/renderpath/Inc.hx @@ -34,10 +34,10 @@ class Inc { #if (rp_voxels == "Voxel GI") static var voxel_td1:kha.compute.TextureUnit; static var voxel_te1:kha.compute.TextureUnit; - static var voxel_tf1:kha.compute.TextureUnit; + static var voxel_cc1:kha.compute.ConstantLocation; #else #if lnx_voxelgi_shadows - static var voxel_tf1:kha.compute.TextureUnit; + static var voxel_te1:kha.compute.TextureUnit; #end #end #if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") @@ -53,12 +53,28 @@ class Inc { static var voxel_tb3:kha.compute.TextureUnit; static var voxel_tc3:kha.compute.TextureUnit; static var voxel_td3:kha.compute.TextureUnit; + static var voxel_te3:kha.compute.TextureUnit; + static var voxel_tf3:kha.compute.TextureUnit; + #if lnx_brdf + static var voxel_tg3:kha.compute.TextureUnit; + #end + #if lnx_radiance + static var voxel_th3:kha.compute.TextureUnit; + #end static var voxel_ca3:kha.compute.ConstantLocation; static var voxel_cb3:kha.compute.ConstantLocation; static var voxel_cc3:kha.compute.ConstantLocation; static var voxel_cd3:kha.compute.ConstantLocation; static var voxel_ce3:kha.compute.ConstantLocation; + #if lnx_irradiance static var voxel_cf3:kha.compute.ConstantLocation; + #end + #if lnx_radiance + static var voxel_cg3:kha.compute.ConstantLocation; + #end + #if lnx_envcol + static var voxel_ch3:kha.compute.ConstantLocation; + #end #if (rp_voxels == "Voxel GI") static var voxel_sh4:kha.compute.Shader = null; static var voxel_ta4:kha.compute.TextureUnit; @@ -71,33 +87,6 @@ class Inc { static var voxel_cb4:kha.compute.ConstantLocation; static var voxel_cc4:kha.compute.ConstantLocation; static var voxel_cd4:kha.compute.ConstantLocation; - static var voxel_ce4:kha.compute.ConstantLocation; - static var voxel_cf4:kha.compute.ConstantLocation; - #end - #if (rp_voxels == "Voxel GI") - static var voxel_sh5:kha.compute.Shader = null; - static var voxel_ta5:kha.compute.TextureUnit; - static var voxel_ca5:kha.compute.ConstantLocation; - static var voxel_cb5:kha.compute.ConstantLocation; - static var voxel_cc5:kha.compute.ConstantLocation; - static var voxel_cd5:kha.compute.ConstantLocation; - static var voxel_ce5:kha.compute.ConstantLocation; - static var voxel_cf5:kha.compute.ConstantLocation; - static var voxel_cg5:kha.compute.ConstantLocation; - #if rp_shadowmap - static var voxel_tb5:kha.compute.TextureUnit; - static var voxel_tc5:kha.compute.TextureUnit; - static var voxel_td5:kha.compute.TextureUnit; - static var voxel_ch5:kha.compute.ConstantLocation; - static var voxel_ci5:kha.compute.ConstantLocation; - static var voxel_cj5:kha.compute.ConstantLocation; - static var voxel_ck5:kha.compute.ConstantLocation; - static var voxel_cl5:kha.compute.ConstantLocation; - static var voxel_cm5:kha.compute.ConstantLocation; - #if lnx_shadowmap_atlas - static var m2 = iron.math.Mat4.identity(); - #end - #end #end #end //rp_voxels @@ -163,9 +152,11 @@ class Inc { for (atlas in ShadowMapAtlas.shadowMapAtlases) { path.bindTarget(atlas.target, atlas.target); } + #if rp_shadowmap_transparent for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { path.bindTarget(atlas.target, atlas.target); } + #end } static function getShadowMapAtlas(atlas:ShadowMapAtlas, transparent: Bool):String { @@ -206,24 +197,30 @@ class Inc { for (atlas in ShadowMapAtlas.shadowMapAtlases) { atlas.rejectedLights = []; } + #if rp_shadowmap_transparent for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { atlas.rejectedLights = []; } #end + #end for (light in iron.Scene.active.lights) { if (!light.lightInAtlas && !light.culledLight && light.visible && light.shadowMapScale > 0.0 && light.data.raw.strength > 0.0 && light.data.raw.cast_shadow) { ShadowMapAtlas.addLight(light, false); } + #if rp_shadowmap_transparent if (!light.lightInAtlasTransparent && !light.culledLight && light.visible && light.shadowMapScale > 0.0 && light.data.raw.strength > 0.0 && light.data.raw.cast_shadow) { ShadowMapAtlas.addLight(light, true); } + #end } // update point light data before rendering - updatePointLightAtlasData(true); updatePointLightAtlasData(false); + #if rp_shadowmap_transparent + updatePointLightAtlasData(true); + #end for (atlas in ShadowMapAtlas.shadowMapAtlases) { var tilesToRemove = []; @@ -301,6 +298,7 @@ class Inc { path.endStream(); } + #if rp_shadowmap_transparent for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { var tilesToRemove = []; #if lnx_shadowmap_atlas_lod @@ -395,10 +393,8 @@ class Inc { tile.freeTile(); } } - #if lnx_debug - endShadowsLogicProfile(); #end - #end // rp_shadowmap + #end } #else public static function bindShadowMap() { @@ -501,6 +497,7 @@ class Inc { else if (l.data.raw.type == "spot" || l.data.raw.type == "area") spotIndex++; } + #if rp_shadowmap_transparent pointIndex = 0; spotIndex = 0; for (l in iron.Scene.active.lights) { @@ -522,6 +519,7 @@ class Inc { if (l.data.raw.type == "point") pointIndex++; else if (l.data.raw.type == "spot" || l.data.raw.type == "area") spotIndex++; } + #end #end // rp_shadowmap } #end @@ -589,7 +587,7 @@ class Inc { t.width = 0; t.height = 0; t.displayp = getDisplayp(); - t.format = "R32"; + t.format = "R16"; t.scale = getSuperSampling(); t.depth_buffer = "main"; path.createRenderTarget(t); @@ -615,10 +613,14 @@ class Inc { #end #if (rp_voxels != "Off") - { - path.bindTarget("voxelsOut", "voxels"); - path.bindTarget("voxelsSDF", "voxelsSDF"); - } + path.bindTarget("voxelsOut", "voxels"); + #if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows) + path.bindTarget("voxelsSDF", "voxelsSDF"); + #end + #end + + #if rp_ssrs + path.bindTarget("_main", "gbufferD"); #end path.drawMeshes("translucent"); @@ -679,12 +681,11 @@ class Inc { t.width = 0; t.height = 0; t.displayp = getDisplayp(); - //t.scale = Inc.getSuperSampling(); - t.format = t.name == "voxels_ao" ? "R8" : "RGBA32"; + t.format = "RGBA32"; } else { if (t.name == "voxelsSDF" || t.name == "voxelsSDFtmp") { - t.format = "R16"; + t.format = "R8"; t.width = res; t.height = res * Main.voxelgiClipmapCount; t.depth = res; @@ -693,16 +694,16 @@ class Inc { #if (rp_voxels == "Voxel AO") { if (t.name == "voxelsOut" || t.name == "voxelsOutB") { - t.format = "R16"; + t.format = "R8"; t.width = res * (6 + 16); t.height = res * Main.voxelgiClipmapCount; t.depth = res; } else { - t.format = "R32"; + t.format = "R32UI"; t.width = res * 6; t.height = res; - t.depth = res; + t.depth = res * 2; } } #else @@ -713,17 +714,11 @@ class Inc { t.height = res * Main.voxelgiClipmapCount; t.depth = res; } - else if (t.name == "voxelsLight") { - t.format = "R32"; - t.width = res; - t.height = res; - t.depth = res * 3; - } else { - t.format = "R32"; + t.format = "R32UI"; t.width = res * 6; t.height = res; - t.depth = res * 12; + t.depth = res * 16; } } #end @@ -835,14 +830,15 @@ class Inc { voxel_ca1 = voxel_sh1.getConstantLocation("clipmaps"); voxel_cb1 = voxel_sh1.getConstantLocation("clipmapLevel"); + voxel_cc1 = voxel_sh1.getConstantLocation("envmapStrength"); #if (rp_voxels == "Voxel GI") voxel_td1 = voxel_sh1.getTextureUnit("voxelsSampler"); - voxel_te1 = voxel_sh1.getTextureUnit("voxelsLight"); - voxel_tf1 = voxel_sh1.getTextureUnit("SDF"); + voxel_te1 = voxel_sh1.getTextureUnit("SDF"); + voxel_cc1 = voxel_sh1.getConstantLocation("envmapStrength"); #else #if lnx_voxelgi_shadows - voxel_tf1 = voxel_sh1.getTextureUnit("SDF"); + voxel_te1 = voxel_sh1.getTextureUnit("SDF"); #end #end } @@ -873,12 +869,28 @@ class Inc { #else voxel_td3 = voxel_sh3.getTextureUnit("voxels_diffuse"); #end - voxel_ca3 = voxel_sh3.getConstantLocation("clipmaps"); + voxel_te3 = voxel_sh3.getTextureUnit("gbuffer1"); + voxel_tf3 = voxel_sh3.getTextureUnit("gbuffer2"); + #if lnx_brdf + voxel_tg3 = voxel_sh3.getTextureUnit("senvmapBrdf"); + #end + #if lnx_radiance + voxel_th3 = voxel_sh3.getTextureUnit("senvmapRadiance"); + #end + voxel_ca3 = voxel_sh3.getConstantLocation("clipmaps"); voxel_cb3 = voxel_sh3.getConstantLocation("InvVP"); - voxel_cc3 = voxel_sh3.getConstantLocation("cameraProj"); - voxel_cd3 = voxel_sh3.getConstantLocation("eye"); - voxel_ce3 = voxel_sh3.getConstantLocation("eyeLook"); - voxel_cf3 = voxel_sh3.getConstantLocation("postprocess_resolution"); + voxel_cc3 = voxel_sh3.getConstantLocation("eye"); + voxel_cd3 = voxel_sh3.getConstantLocation("postprocess_resolution"); + voxel_ce3 = voxel_sh3.getConstantLocation("envmapStrength"); + #if lnx_irradiance + voxel_cf3 = voxel_sh3.getConstantLocation("shirr"); + #end + #if lnx_radiance + voxel_cg3 = voxel_sh3.getConstantLocation("envmapNumMipmaps"); + #end + #if lnx_envcol + voxel_ch3 = voxel_sh3.getConstantLocation("backgroundCol"); + #end } #if (rp_voxels == "Voxel GI") if (voxel_sh4 == null) @@ -892,40 +904,8 @@ class Inc { voxel_tf4 = voxel_sh4.getTextureUnit("sveloc"); voxel_ca4 = voxel_sh4.getConstantLocation("clipmaps"); voxel_cb4 = voxel_sh4.getConstantLocation("InvVP"); - voxel_cc4 = voxel_sh4.getConstantLocation("cameraProj"); - voxel_cd4 = voxel_sh4.getConstantLocation("eye"); - voxel_ce4 = voxel_sh4.getConstantLocation("eyeLook"); - voxel_cf4 = voxel_sh4.getConstantLocation("postprocess_resolution"); - } - #end - #if (rp_voxels == "Voxel GI") - if (voxel_sh5 == null) - { - voxel_sh5 = path.getComputeShader("voxel_light"); - voxel_ta5 = voxel_sh5.getTextureUnit("voxelsLight"); - - voxel_ca5 = voxel_sh5.getConstantLocation("clipmaps"); - voxel_cb5 = voxel_sh5.getConstantLocation("clipmapLevel"); - - voxel_cc5 = voxel_sh5.getConstantLocation("lightPos"); - voxel_cd5 = voxel_sh5.getConstantLocation("lightColor"); - voxel_ce5 = voxel_sh5.getConstantLocation("lightType"); - voxel_cf5 = voxel_sh5.getConstantLocation("lightDir"); - voxel_cg5 = voxel_sh5.getConstantLocation("spotData"); - #if rp_shadowmap - voxel_tb5 = voxel_sh5.getTextureUnit("shadowMap"); - voxel_tc5 = voxel_sh5.getTextureUnit("shadowMapSpot"); - voxel_td5 = voxel_sh5.getTextureUnit("shadowMapPoint"); - - voxel_ch5 = voxel_sh5.getConstantLocation("lightShadow"); - voxel_ci5 = voxel_sh5.getConstantLocation("lightProj"); - voxel_cj5 = voxel_sh5.getConstantLocation("LVP"); - voxel_ck5 = voxel_sh5.getConstantLocation("shadowsBias"); - #if lnx_shadowmap_atlas - voxel_cl5 = voxel_sh5.getConstantLocation("index"); - voxel_cm5 = voxel_sh5.getConstantLocation("pointLightDataArray"); - #end - #end + voxel_cc4 = voxel_sh4.getConstantLocation("eye"); + voxel_cd4 = voxel_sh4.getConstantLocation("postprocess_resolution"); } #end } @@ -976,11 +956,11 @@ class Inc { kha.compute.Compute.setTexture(voxel_tc1, rts.get("voxelsOut").image, kha.compute.Access.Write); #if (rp_voxels == "Voxel GI") kha.compute.Compute.setSampledTexture(voxel_td1, rts.get("voxelsOutB").image); - kha.compute.Compute.setTexture(voxel_te1, rts.get("voxelsLight").image, kha.compute.Access.Read); - kha.compute.Compute.setTexture(voxel_tf1, rts.get("voxelsSDF").image, kha.compute.Access.Write); + kha.compute.Compute.setTexture(voxel_te1, rts.get("voxelsSDF").image, kha.compute.Access.Write); + kha.compute.Compute.setFloat(voxel_cc1, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength); #else #if lnx_voxelgi_shadows - kha.compute.Compute.setTexture(voxel_tf1, rts.get("voxelsSDF").image, kha.compute.Access.Write); + kha.compute.Compute.setTexture(voxel_te1, rts.get("voxelsSDF").image, kha.compute.Access.Write); #end #end @@ -1002,6 +982,8 @@ class Inc { kha.compute.Compute.setInt(voxel_cb1, iron.RenderPath.clipmapLevel); + kha.compute.Compute.setFloat(voxel_cc1, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength); + kha.compute.Compute.compute(Std.int(res / 8), Std.int(res / 8), Std.int(res / 8)); } @@ -1054,6 +1036,7 @@ class Inc { } } #end + #if (rp_voxels == "Voxel AO") public static function resolveAO() { var rts = path.renderTargets; @@ -1066,13 +1049,20 @@ class Inc { kha.compute.Compute.setSampledTexture(voxel_ta3, rts.get("voxelsOut").image); kha.compute.Compute.setSampledTexture(voxel_tb3, rts.get("half").image); - #if lnx_deferred kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("gbuffer0").image); - #else - kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("lbuffer1").image); - #end kha.compute.Compute.setTexture(voxel_td3, rts.get("voxels_ao").image, kha.compute.Access.Write); + kha.compute.Compute.setSampledTexture(voxel_te3, rts.get("gbuffer1").image); + #if rp_gbuffer2 + kha.compute.Compute.setSampledTexture(voxel_tf3, rts.get("gbuffer2").image); + #end + #if lnx_brdf + kha.compute.Compute.setSampledTexture(voxel_tg3, iron.Scene.active.embedded.get("brdf.png")); + #end + #if lnx_radiance + kha.compute.Compute.setSampledTexture(voxel_th3, iron.Scene.active.world.probe.radiance); + #end + var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); for (i in 0...Main.voxelgiClipmapCount) { fa[i * 10] = clipmaps[i].voxelSize; @@ -1099,18 +1089,7 @@ class Inc { kha.compute.Compute.setMatrix(voxel_cb3, m.self); - var near = camera.data.raw.near_plane; - var far = camera.data.raw.far_plane; - var v = new iron.math.Vec2(); - v.x = far / (far - near); - v.y = (-far * near) / (far - near); - - kha.compute.Compute.setFloat2(voxel_cc3, v.x, v.y); - - - kha.compute.Compute.setFloat3(voxel_cd3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); - var eyeLook = camera.lookWorld().normalize(); - kha.compute.Compute.setFloat3(voxel_ce3, eyeLook.x, eyeLook.y, eyeLook.z); + kha.compute.Compute.setFloat3(voxel_cc3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); var width = iron.App.w(); var height = iron.App.h(); @@ -1125,7 +1104,32 @@ class Inc { width = Std.int(dp * Inc.getSuperSampling()); } } - kha.compute.Compute.setFloat2(voxel_cf3, width, height); + kha.compute.Compute.setFloat2(voxel_cd3, width, height); + + kha.compute.Compute.setFloat(voxel_ce3, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength); + #if lnx_irradiance + var irradiance = iron.Scene.active.world == null ? + iron.data.WorldData.getEmptyIrradiance() : + iron.Scene.active.world.probe.irradiance; + kha.compute.Compute.setFloats(voxel_cf3, irradiance); + #end + #if lnx_radiance + kha.compute.Compute.setFloat(voxel_cg3, iron.Scene.active.world != null ? iron.Scene.active.world.probe.raw.radiance_mipmaps + 1 - 2 : 1); + #end + + #if lnx_envcol + var x: kha.FastFloat = 0.0; + var y: kha.FastFloat = 0.0; + var z: kha.FastFloat = 0.0; + + if (camera.data.raw.clear_color != null) { + x = camera.data.raw.clear_color[0]; + y = camera.data.raw.clear_color[1]; + z = camera.data.raw.clear_color[2]; + } + + kha.compute.Compute.setFloat3(voxel_ch3, x, y, z); + #end kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); } @@ -1141,12 +1145,18 @@ class Inc { kha.compute.Compute.setSampledTexture(voxel_ta3, rts.get("voxelsOut").image); kha.compute.Compute.setSampledTexture(voxel_tb3, rts.get("half").image); - #if lnx_deferred kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("gbuffer0").image); - #else - kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("lbuffer1").image); - #end kha.compute.Compute.setTexture(voxel_td3, rts.get("voxels_diffuse").image, kha.compute.Access.Write); + kha.compute.Compute.setSampledTexture(voxel_te3, rts.get("gbuffer1").image); + #if rp_gbuffer2 + kha.compute.Compute.setSampledTexture(voxel_tf3, rts.get("gbuffer2").image); + #end + #if lnx_brdf + kha.compute.Compute.setSampledTexture(voxel_tg3, iron.Scene.active.embedded.get("brdf.png")); + #end + #if lnx_radiance + kha.compute.Compute.setSampledTexture(voxel_th3, iron.Scene.active.world.probe.radiance); + #end var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); for (i in 0...Main.voxelgiClipmapCount) { @@ -1174,18 +1184,7 @@ class Inc { kha.compute.Compute.setMatrix(voxel_cb3, m.self); - var near = camera.data.raw.near_plane; - var far = camera.data.raw.far_plane; - var v = new iron.math.Vec2(); - v.x = far / (far - near); - v.y = (-far * near) / (far - near); - - kha.compute.Compute.setFloat2(voxel_cc3, v.x, v.y); - - - kha.compute.Compute.setFloat3(voxel_cd3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); - var eyeLook = camera.lookWorld().normalize(); - kha.compute.Compute.setFloat3(voxel_ce3, eyeLook.x, eyeLook.y, eyeLook.z); + kha.compute.Compute.setFloat3(voxel_cc3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); var width = iron.App.w(); var height = iron.App.h(); @@ -1200,7 +1199,32 @@ class Inc { width = Std.int(dp * Inc.getSuperSampling()); } } - kha.compute.Compute.setFloat2(voxel_cf3, width, height); + kha.compute.Compute.setFloat2(voxel_cd3, width, height); + + kha.compute.Compute.setFloat(voxel_ce3, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength); + #if lnx_irradiance + var irradiance = iron.Scene.active.world == null ? + iron.data.WorldData.getEmptyIrradiance() : + iron.Scene.active.world.probe.irradiance; + kha.compute.Compute.setFloats(voxel_cf3, irradiance); + #end + #if lnx_radiance + kha.compute.Compute.setFloat(voxel_cg3, iron.Scene.active.world != null ? iron.Scene.active.world.probe.raw.radiance_mipmaps + 1 - 2 : 1); + #end + + #if lnx_envcol + var x: kha.FastFloat = 0.0; + var y: kha.FastFloat = 0.0; + var z: kha.FastFloat = 0.0; + + if (camera.data.raw.clear_color != null) { + x = camera.data.raw.clear_color[0]; + y = camera.data.raw.clear_color[1]; + z = camera.data.raw.clear_color[2]; + } + + kha.compute.Compute.setFloat3(voxel_ch3, x, y, z); + #end kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); } @@ -1216,15 +1240,12 @@ class Inc { kha.compute.Compute.setSampledTexture(voxel_ta4, rts.get("voxelsOut").image); kha.compute.Compute.setSampledTexture(voxel_tb4, rts.get("half").image); - #if lnx_deferred kha.compute.Compute.setSampledTexture(voxel_tc4, rts.get("gbuffer0").image); - #else - kha.compute.Compute.setSampledTexture(voxel_tc4, rts.get("lbuffer1").image); - #end kha.compute.Compute.setSampledTexture(voxel_td4, rts.get("voxelsSDF").image); kha.compute.Compute.setTexture(voxel_te4, rts.get("voxels_specular").image, kha.compute.Access.Write); - - //kha.compute.Compute.setSampledTexture(voxel_tf4, rts.get("gbuffer2").image); + #if rp_gbuffer2 + kha.compute.Compute.setSampledTexture(voxel_tf4, rts.get("gbuffer2").image); + #end var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); for (i in 0...Main.voxelgiClipmapCount) { @@ -1252,18 +1273,7 @@ class Inc { kha.compute.Compute.setMatrix(voxel_cb4, m.self); - var near = camera.data.raw.near_plane; - var far = camera.data.raw.far_plane; - var v = new iron.math.Vec2(); - v.x = far / (far - near); - v.y = (-far * near) / (far - near); - - kha.compute.Compute.setFloat2(voxel_cc4, v.x, v.y); - - - kha.compute.Compute.setFloat3(voxel_cd4, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); - var eyeLook = camera.lookWorld().normalize(); - kha.compute.Compute.setFloat3(voxel_ce4, eyeLook.x, eyeLook.y, eyeLook.z); + kha.compute.Compute.setFloat3(voxel_cc4, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); var width = iron.App.w(); var height = iron.App.h(); @@ -1278,146 +1288,10 @@ class Inc { width = Std.int(dp * Inc.getSuperSampling()); } } - kha.compute.Compute.setFloat2(voxel_cf4, width, height); + kha.compute.Compute.setFloat2(voxel_cd4, width, height); kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); } - public static function computeVoxelsLight() { - var rts = path.renderTargets; - var res = iron.RenderPath.getVoxelRes(); - var camera = iron.Scene.active.camera; - var clipmaps = iron.RenderPath.clipmaps; - var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; - var lights = iron.Scene.active.lights; - - pointIndex = spotIndex = 0; - for (i in 0...lights.length) { - var l = lights[i]; - if (!l.visible) continue; - path.light = l; - - kha.compute.Compute.setShader(voxel_sh5); - - kha.compute.Compute.setTexture(voxel_ta5, rts.get("voxelsLight").image, kha.compute.Access.Write); - - var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); - for (i in 0...Main.voxelgiClipmapCount) { - fa[i * 10] = clipmaps[i].voxelSize; - fa[i * 10 + 1] = clipmaps[i].extents.x; - fa[i * 10 + 2] = clipmaps[i].extents.y; - fa[i * 10 + 3] = clipmaps[i].extents.z; - fa[i * 10 + 4] = clipmaps[i].center.x; - fa[i * 10 + 5] = clipmaps[i].center.y; - fa[i * 10 + 6] = clipmaps[i].center.z; - fa[i * 10 + 7] = clipmaps[i].offset_prev.x; - fa[i * 10 + 8] = clipmaps[i].offset_prev.y; - fa[i * 10 + 9] = clipmaps[i].offset_prev.z; - } - - kha.compute.Compute.setFloats(voxel_ca5, fa); - - kha.compute.Compute.setInt(voxel_cb5, iron.RenderPath.clipmapLevel); - - #if rp_shadowmap - if (l.data.raw.type == "sun") { - #if lnx_shadowmap_atlas - #if lnx_shadowmap_atlas_single_map - kha.compute.Compute.setSampledTexture(voxel_tb5, rts.get("shadowMapAtlas").image); - #else - kha.compute.Compute.setSampledTexture(voxel_tb5, rts.get("shadowMapAtlasSun").image); - #end - #else - kha.compute.Compute.setSampledTexture(voxel_tb5, rts.get("shadowMap").image); - #end - kha.compute.Compute.setInt(voxel_ch5, 1); // lightShadow - } - else if (l.data.raw.type == "spot" || l.data.raw.type == "area") { - #if lnx_shadowmap_atlas - #if lnx_shadowmap_atlas_single_map - kha.compute.Compute.setSampledTexture(voxel_tc5, rts.get("shadowMapAtlas").image); - #else - kha.compute.Compute.setSampledTexture(voxel_tc5, rts.get("shadowMapAtlasSpot").image); - #end - #else - kha.compute.Compute.setSampledTexture(voxel_tc5, rts.get("shadowMapSpot[" + spotIndex + "]").image); - spotIndex++; - #end - kha.compute.Compute.setInt(voxel_ch5, 2); - } - else { - #if lnx_shadowmap_atlas - #if lnx_shadowmap_atlas_single_map - kha.compute.Compute.setSampledTexture(voxel_td5, rts.get("shadowMapAtlas").image); - #else - kha.compute.Compute.setSampledTexture(voxel_td5, rts.get("shadowMapAtlasPoint").image); - kha.compute.Compute.setInt(voxel_cl5, i); - kha.compute.Compute.setFloats(voxel_cm5, iron.object.LightObject.pointLightsData); - #end - #else - kha.compute.Compute.setSampledCubeMap(voxel_td5, rts.get("shadowMapPoint[" + pointIndex + "]").cubeMap); - pointIndex++; - #end - kha.compute.Compute.setInt(voxel_ch5, 3); - } - - // lightProj - var near = l.data.raw.near_plane; - var far = l.data.raw.far_plane; - var a:kha.FastFloat = far + near; - var b:kha.FastFloat = far - near; - var f2:kha.FastFloat = 2.0; - var c:kha.FastFloat = f2 * far * near; - var vx:kha.FastFloat = a / b; - var vy:kha.FastFloat = c / b; - kha.compute.Compute.setFloat2(voxel_ci5, vx, vy); - // LVP - m.setFrom(l.VP); - m.multmat(iron.object.Uniforms.biasMat); - #if lnx_shadowmap_atlas - if (l.data.raw.type == "sun") - { - // tile matrix - m.setIdentity(); - // scale [0-1] coords to [0-tilescale] - m2._00 = l.tileScale[0]; - m2._11 = l.tileScale[0]; - // offset coordinate start from [0, 0] to [tile-start-x, tile-start-y] - m2._30 = l.tileOffsetX[0]; - m2._31 = l.tileOffsetY[0]; - m.multmat(m2); - #if (!kha_opengl) - m2.setIdentity(); - m2._11 = -1.0; - m2._31 = 1.0; - m.multmat(m2); - #end - } - #end - kha.compute.Compute.setMatrix(voxel_cj5, m.self); - // shadowsBias - kha.compute.Compute.setFloat(voxel_ck5, l.data.raw.shadows_bias); - #end // rp_shadowmap - - // lightPos - kha.compute.Compute.setFloat3(voxel_cc5, l.transform.worldx(), l.transform.worldy(), l.transform.worldz()); - // lightCol - var f = l.data.raw.strength; - kha.compute.Compute.setFloat3(voxel_cd5, l.data.raw.color[0] * f, l.data.raw.color[1] * f, l.data.raw.color[2] * f); - // lightType - kha.compute.Compute.setInt(voxel_ce5, iron.data.LightData.typeToInt(l.data.raw.type)); - // lightDir - var v = l.look(); - kha.compute.Compute.setFloat3(voxel_cf5, v.x, v.y, v.z); - // spotData - if (l.data.raw.type == "spot") { - var vx = l.data.raw.spot_size; - var vy = vx - l.data.raw.spot_blend; - kha.compute.Compute.setFloat2(voxel_cg5, vx, vy); - } - - kha.compute.Compute.compute(Std.int(res / 8), Std.int(res / 8), Std.int(res / 8)); - } - } #end // GI #end // Voxels } diff --git a/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx b/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx index 0f9a14c..9a415ef 100644 --- a/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx +++ b/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx @@ -15,6 +15,11 @@ class RenderPathDeferred { static var bloomUpsampler: Upsampler; #end + #if (rp_ssgi == "SSGI") + static var ssgitex = "singleb"; + static var ssgitexb = "singleb"; + #end + public static inline function setTargetMeshes() { //Always keep the order of render targets the same as defined in compiled.inc path.setTarget("gbuffer0", [ @@ -57,12 +62,11 @@ class RenderPathDeferred { Inc.initGI("voxels"); Inc.initGI("voxelsOut"); Inc.initGI("voxelsOutB"); - #if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") + #if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows) Inc.initGI("voxelsSDF"); Inc.initGI("voxelsSDFtmp"); #end #if (rp_voxels == "Voxel GI") - Inc.initGI("voxelsLight"); Inc.initGI("voxels_diffuse"); Inc.initGI("voxels_specular"); #else @@ -195,24 +199,94 @@ class RenderPathDeferred { path.loadShader("shader_datas/blur_edge_pass/blur_edge_pass_x"); path.loadShader("shader_datas/blur_edge_pass/blur_edge_pass_y"); } + #elseif (rp_ssgi == "SSGI") + { + path.loadShader("shader_datas/ssgi_pass/ssgi_pass"); + path.loadShader("shader_datas/blur_edge_pass/blur_edge_pass_x"); + path.loadShader("shader_datas/blur_edge_pass/blur_edge_pass_y"); + } #end - #if ((rp_ssgi != "Off") || rp_volumetriclight) + #if (rp_ssgi != "Off") { var t = new RenderTargetRaw(); t.name = "singlea"; t.width = 0; t.height = 0; t.displayp = Inc.getDisplayp(); + #if (rp_ssgi == "SSGI") + t.format = "RGBA32"; + #else + t.format = "R8"; + #end + t.scale = Inc.getSuperSampling(); + #if rp_ssgi_half + t.scale *= 0.5; + #end + path.createRenderTarget(t); + + var t = new RenderTargetRaw(); + t.name = "singleb"; + t.width = 0; + t.height = 0; + t.displayp = Inc.getDisplayp(); + #if (rp_ssgi == "SSGI") + t.format = "RGBA32"; + #else + t.format = "R8"; + #end + t.scale = Inc.getSuperSampling(); + #if rp_ssgi_half + t.scale *= 0.5; + #end + path.createRenderTarget(t); + } + #end + + #if rp_volumetriclight + { + var t = new RenderTargetRaw(); + t.name = "volumetrica"; + t.width = 0; + t.height = 0; + t.displayp = Inc.getDisplayp(); + t.format = "R8"; + t.scale = Inc.getSuperSampling(); + #if rp_ssgi_half // Do we keep this ? + t.scale *= 0.5; + #end + path.createRenderTarget(t); + + var t = new RenderTargetRaw(); + t.name = "volumetricb"; + t.width = 0; + t.height = 0; + t.displayp = Inc.getDisplayp(); t.format = "R8"; t.scale = Inc.getSuperSampling(); #if rp_ssgi_half t.scale *= 0.5; #end path.createRenderTarget(t); + } + #end + + #if rp_volumetriclight + { + var t = new RenderTargetRaw(); + t.name = "volumetrica"; + t.width = 0; + t.height = 0; + t.displayp = Inc.getDisplayp(); + t.format = "R8"; + t.scale = Inc.getSuperSampling(); + #if rp_ssgi_half // Do we keep this ? + t.scale *= 0.5; + #end + path.createRenderTarget(t); var t = new RenderTargetRaw(); - t.name = "singleb"; + t.name = "volumetricb"; t.width = 0; t.height = 0; t.displayp = Inc.getDisplayp(); @@ -368,7 +442,7 @@ class RenderPathDeferred { t.scale = Inc.getSuperSampling(); path.createRenderTarget(t); - // holds background depth + // holds background color var t = new RenderTargetRaw(); t.name = "refr"; t.width = 0; @@ -461,7 +535,7 @@ class RenderPathDeferred { #if (rp_ssrefr || lnx_voxelgi_refract) { - path.setTarget("gbuffer_refraction"); // Only clear gbuffer0 + path.setTarget("gbuffer_refraction"); path.clearTarget(0xffffff00); } #end @@ -517,30 +591,16 @@ class RenderPathDeferred { path.drawShader("shader_datas/downsample_depth/downsample_depth"); #end - #if ((rp_ssgi == "RTGI") || (rp_ssgi == "RTAO")) - { - if (leenkx.data.Config.raw.rp_ssgi != false) { - path.setTarget("singlea"); - #if rp_ssgi_half - path.bindTarget("half", "gbufferD"); - #else - path.bindTarget("_main", "gbufferD"); - #end - path.bindTarget("gbuffer0", "gbuffer0"); - path.drawShader("shader_datas/ssgi_pass/ssgi_pass"); + #if (rp_shadowmap) + // atlasing is exclusive for now + #if lnx_shadowmap_atlas + Inc.drawShadowMapAtlas(); + #else + Inc.drawShadowMap(); + #end + #end - path.setTarget("singleb"); - path.bindTarget("singlea", "tex"); - path.bindTarget("gbuffer0", "gbuffer0"); - path.drawShader("shader_datas/blur_edge_pass/blur_edge_pass_x"); - - path.setTarget("singlea"); - path.bindTarget("singleb", "tex"); - path.bindTarget("gbuffer0", "gbuffer0"); - path.drawShader("shader_datas/blur_edge_pass/blur_edge_pass_y"); - } - } - #elseif (rp_ssgi == "SSAO") + #if (rp_ssgi == "SSAO") { if (leenkx.data.Config.raw.rp_ssgi != false) { path.setTarget("singlea"); @@ -559,15 +619,43 @@ class RenderPathDeferred { path.drawShader("shader_datas/blur_edge_pass/blur_edge_pass_y"); } } - #end + #elseif (rp_ssgi == "SSGI") + { + if (leenkx.data.Config.raw.rp_ssgi != false) { + path.setTarget("singlea"); + path.bindTarget("_main", "gbufferD"); + path.bindTarget("gbuffer0", "gbuffer0"); + path.bindTarget("gbuffer1", "gbuffer1"); + #if rp_gbuffer_emission + { + path.bindTarget("gbuffer_emission", "gbufferEmission"); + } + #end + #if rp_gbuffer2 + path.bindTarget("gbuffer2", "sveloc"); + #end + #if rp_shadowmap + { + #if lnx_shadowmap_atlas + Inc.bindShadowMapAtlas(); + #else + Inc.bindShadowMap(); + #end + } + #end - #if (rp_shadowmap) - // atlasing is exclusive for now - #if lnx_shadowmap_atlas - Inc.drawShadowMapAtlas(); - #else - Inc.drawShadowMap(); - #end + path.drawShader("shader_datas/ssgi_pass/ssgi_pass"); + path.setTarget("singleb"); + path.bindTarget("singlea", "tex"); + path.bindTarget("gbuffer0", "gbuffer0"); + path.drawShader("shader_datas/blur_edge_pass/blur_edge_pass_x"); + + path.setTarget("singlea"); + path.bindTarget("singleb", "tex"); + path.bindTarget("gbuffer0", "gbuffer0"); + path.drawShader("shader_datas/blur_edge_pass/blur_edge_pass_y"); + } + } #end // Voxels @@ -580,9 +668,6 @@ class RenderPathDeferred { if (iron.RenderPath.pre_clear == true) { - #if (rp_voxels == "Voxel GI") - path.clearImage("voxelsLight", 0x00000000); - #end path.clearImage("voxels", 0x00000000); path.clearImage("voxelsOut", 0x00000000); path.clearImage("voxelsOutB", 0x00000000); @@ -594,26 +679,30 @@ class RenderPathDeferred { } else { - #if (rp_voxels == "Voxel GI") - path.clearImage("voxelsLight", 0x00000000); - #end path.clearImage("voxels", 0x00000000); Inc.computeVoxelsOffsetPrev(); } path.setTarget(""); + path.bindTarget("voxels", "voxels"); + #if rp_shadowmap + { + #if lnx_shadowmap_atlas + Inc.bindShadowMapAtlas(); + #else + Inc.bindShadowMap(); + #end + } + #end + var res = iron.RenderPath.getVoxelRes(); path.setViewport(res, res); - path.bindTarget("voxels", "voxels"); path.drawMeshes("voxel"); - #if (rp_voxels == "Voxel GI") - Inc.computeVoxelsLight(); - #end Inc.computeVoxelsTemporal(); - #if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") + #if (rp_voxels == "Voxel GI") Inc.computeVoxelsSDF(); #end @@ -628,7 +717,6 @@ class RenderPathDeferred { } } #end - // --- // Deferred light // --- @@ -760,15 +848,9 @@ class RenderPathDeferred { } #end - #if (rp_translucency && !rp_ssrefr) - { - Inc.drawTranslucency("tex"); - } - #end - #if rp_volumetriclight { - path.setTarget("singlea"); + path.setTarget("volumetrica"); path.bindTarget("_main", "gbufferD"); #if lnx_shadowmap_atlas Inc.bindShadowMapAtlas(); @@ -777,85 +859,16 @@ class RenderPathDeferred { #end path.drawShader("shader_datas/volumetric_light/volumetric_light"); - path.setTarget("singleb"); - path.bindTarget("singlea", "tex"); + path.setTarget("volumetricb"); + path.bindTarget("volumetrica", "tex"); path.drawShader("shader_datas/blur_bilat_pass/blur_bilat_pass_x"); path.setTarget("tex"); - path.bindTarget("singleb", "tex"); + path.bindTarget("volumetricb", "tex"); path.drawShader("shader_datas/blur_bilat_blend_pass/blur_bilat_blend_pass_y"); } #end - #if rp_bloom - { - inline Inc.drawBloom("tex", bloomDownsampler, bloomUpsampler); - } - #end - - #if rp_sss - { - #if (!kha_opengl) - path.setDepthFrom("tex", "gbuffer1"); // Unbind depth so we can read it - #end - - path.setTarget("buf"); - path.bindTarget("tex", "tex"); - path.bindTarget("_main", "gbufferD"); - path.bindTarget("gbuffer0", "gbuffer0"); - path.drawShader("shader_datas/sss_pass/sss_pass_x"); - - path.setTarget("tex"); - path.bindTarget("buf", "tex"); - path.bindTarget("_main", "gbufferD"); - path.bindTarget("gbuffer0", "gbuffer0"); - path.drawShader("shader_datas/sss_pass/sss_pass_y"); - - #if (!kha_opengl) - path.setDepthFrom("tex", "gbuffer0"); - #end - } - #end - - #if rp_ssrefr - { - if (leenkx.data.Config.raw.rp_ssrefr != false) - { - //save depth - path.setTarget("gbufferD1"); - path.bindTarget("_main", "tex"); - path.drawShader("shader_datas/copy_pass/copy_pass"); - - //save background color - path.setTarget("refr"); - path.bindTarget("tex", "tex"); - path.drawShader("shader_datas/copy_pass/copy_pass"); - - path.setTarget("gbuffer0", ["tex", "gbuffer_refraction"]); - - #if (rp_voxels != "Off") - { - path.bindTarget("voxelsOut", "voxels"); - path.bindTarget("voxelsSDF", "voxelsSDF"); - path.bindTarget("gbuffer2", "sveloc"); - } - #end - - path.drawMeshes("refraction"); - - path.setTarget("tex"); - path.bindTarget("tex", "tex"); - path.bindTarget("refr", "tex1"); - path.bindTarget("_main", "gbufferD"); - path.bindTarget("gbufferD1", "gbufferD1"); - path.bindTarget("gbuffer0", "gbuffer0"); - path.bindTarget("gbuffer_refraction", "gbuffer_refraction"); - - path.drawShader("shader_datas/ssrefr_pass/ssrefr_pass"); - } - } - #end - #if rp_ssr { if (leenkx.data.Config.raw.rp_ssr != false) { @@ -900,6 +913,88 @@ class RenderPathDeferred { } #end + #if rp_sss + { + #if (!kha_opengl) + path.setDepthFrom("tex", "gbuffer1"); // Unbind depth so we can read it + #end + + path.setTarget("buf"); + path.bindTarget("tex", "tex"); + path.bindTarget("_main", "gbufferD"); + path.bindTarget("gbuffer0", "gbuffer0"); + path.drawShader("shader_datas/sss_pass/sss_pass_x"); + + path.setTarget("tex"); + path.bindTarget("buf", "tex"); + path.bindTarget("_main", "gbufferD"); + path.bindTarget("gbuffer0", "gbuffer0"); + path.drawShader("shader_datas/sss_pass/sss_pass_y"); + + #if (!kha_opengl) + path.setDepthFrom("tex", "gbuffer0"); + #end + } + #end + + #if (rp_translucency && !rp_ssrefr) + { + Inc.drawTranslucency("tex"); + } + #end + + #if rp_ssrefr + { + if (leenkx.data.Config.raw.rp_ssrefr != false) + { + //save depth + path.setTarget("gbufferD1"); + path.bindTarget("_main", "tex"); + path.drawShader("shader_datas/copy_pass/copy_pass"); + + //save background color + path.setTarget("refr"); + path.bindTarget("tex", "tex"); + path.drawShader("shader_datas/copy_pass/copy_pass"); + + path.setTarget("gbuffer0", ["tex", "gbuffer_refraction"]); + + #if rp_shadowmap + { + #if lnx_shadowmap_atlas + Inc.bindShadowMapAtlas(); + #else + Inc.bindShadowMap(); + #end + } + #end + + #if (rp_voxels != "Off") + path.bindTarget("voxelsOut", "voxels"); + #if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows) + path.bindTarget("voxelsSDF", "voxelsSDF"); + #end + #end + + #if rp_ssrs + path.bindTarget("_main", "gbufferD"); + #end + + path.drawMeshes("refraction"); + + path.setTarget("tex"); + path.bindTarget("tex", "tex"); + path.bindTarget("refr", "tex1"); + path.bindTarget("_main", "gbufferD"); + path.bindTarget("gbufferD1", "gbufferD1"); + path.bindTarget("gbuffer0", "gbuffer0"); + path.bindTarget("gbuffer_refraction", "gbuffer_refraction"); + + path.drawShader("shader_datas/ssrefr_pass/ssrefr_pass"); + } + } + #end + #if ((rp_motionblur == "Camera") || (rp_motionblur == "Object")) { if (leenkx.data.Config.raw.rp_motionblur != false) { @@ -964,6 +1059,12 @@ class RenderPathDeferred { } #end + #if rp_bloom + { + inline Inc.drawBloom("tex", bloomDownsampler, bloomUpsampler); + } + #end + #if (rp_supersampling == 4) var framebuffer = "buf"; #else diff --git a/leenkx/Sources/leenkx/renderpath/RenderPathForward.hx b/leenkx/Sources/leenkx/renderpath/RenderPathForward.hx index abab814..6b8b904 100644 --- a/leenkx/Sources/leenkx/renderpath/RenderPathForward.hx +++ b/leenkx/Sources/leenkx/renderpath/RenderPathForward.hx @@ -142,16 +142,17 @@ class RenderPathForward { t.width = 0; t.height = 0; t.displayp = Inc.getDisplayp(); - t.format = "R32"; + t.format = "DEPTH24"; t.scale = Inc.getSuperSampling(); path.createRenderTarget(t); + //holds colors before refractive meshes are drawn var t = new RenderTargetRaw(); t.name = "refr"; t.width = 0; t.height = 0; t.displayp = Inc.getDisplayp(); - t.format = "RGBA64"; + t.format = Inc.getHdrFormat(); t.scale = Inc.getSuperSampling(); path.createRenderTarget(t); } @@ -200,17 +201,10 @@ class RenderPathForward { Inc.initGI("voxels"); Inc.initGI("voxelsOut"); Inc.initGI("voxelsOutB"); - #if (lnx_voxelgi_shadows || (rp_voxels == "Voxel GI")) + #if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows) Inc.initGI("voxelsSDF"); Inc.initGI("voxelsSDFtmp"); #end - #if (rp_voxels == "Voxel GI") - Inc.initGI("voxelsLight"); - Inc.initGI("voxels_diffuse"); - Inc.initGI("voxels_specular"); - #else - Inc.initGI("voxels_ao"); - #end iron.RenderPath.clipmaps = new Array(); for (i in 0...Main.voxelgiClipmapCount) { var clipmap = new iron.object.Clipmap(); @@ -257,18 +251,25 @@ class RenderPathForward { #end #end - #if rp_volumetriclight + #if (rp_volumetriclight || rp_ssgi != "Off") { + #if (rp_volumetriclight) path.loadShader("shader_datas/volumetric_light/volumetric_light"); path.loadShader("shader_datas/blur_bilat_pass/blur_bilat_pass_x"); path.loadShader("shader_datas/blur_bilat_blend_pass/blur_bilat_blend_pass_y"); + #end + var t = new RenderTargetRaw(); t.name = "singlea"; t.width = 0; t.height = 0; t.displayp = Inc.getDisplayp(); + #if (rp_ssgi == "SSGI") + t.format = "RGBA32"; + #else t.format = "R8"; + #end t.scale = Inc.getSuperSampling(); path.createRenderTarget(t); @@ -277,7 +278,11 @@ class RenderPathForward { t.width = 0; t.height = 0; t.displayp = Inc.getDisplayp(); + #if (rp_ssgi == "SSGI") + t.format = "RGBA32"; + #else t.format = "R8"; + #end t.scale = Inc.getSuperSampling(); path.createRenderTarget(t); } @@ -374,9 +379,6 @@ class RenderPathForward { if (iron.RenderPath.pre_clear == true) { - #if (rp_voxels == "Voxel GI") - path.clearImage("voxelsLight", 0x00000000); - #end path.clearImage("voxels", 0x00000000); path.clearImage("voxelsOut", 0x00000000); path.clearImage("voxelsOutB", 0x00000000); @@ -388,9 +390,6 @@ class RenderPathForward { } else { - #if (rp_voxels == "Voxel GI") - path.clearImage("voxelsLight", 0x00000000); - #end path.clearImage("voxels", 0x00000000); Inc.computeVoxelsOffsetPrev(); } @@ -400,27 +399,12 @@ class RenderPathForward { path.setViewport(res, res); path.bindTarget("voxels", "voxels"); - path.drawMeshes("voxel"); - #if (rp_voxels == "Voxel GI") - Inc.computeVoxelsLight(); - #end Inc.computeVoxelsTemporal(); #if (lnx_voxelgi_shadows || (rp_voxels == "Voxel GI")) Inc.computeVoxelsSDF(); #end - - if (iron.RenderPath.res_pre_clear == true) - { - iron.RenderPath.res_pre_clear = false; - #if (rp_voxels == "Voxel GI") - path.clearImage("voxels_diffuse", 0x00000000); - path.clearImage("voxels_specular", 0x00000000); - #else - path.clearImage("voxels_ao", 0x00000000); - #end - } } #end @@ -439,7 +423,7 @@ class RenderPathForward { #if (rp_ssrefr || lnx_voxelgi_refract) { path.setTarget("gbuffer_refraction"); // Only clear gbuffer0 - path.clearTarget(0xff000000); + path.clearTarget(0xffffff00); } #end @@ -449,13 +433,6 @@ class RenderPathForward { } #end - #if rp_ssrefr - { - path.setTarget("gbuffer_refraction"); - path.clearTarget(0xffffff00); - } - #end - RenderPathCreator.setTargetMeshes(); #if rp_shadowmap @@ -472,19 +449,12 @@ class RenderPathForward { #if (rp_voxels != "Off") if (leenkx.data.Config.raw.rp_gi != false) { - #if (rp_voxels == "Voxel AO") - Inc.resolveAO(); - path.bindTarget("voxels_ao", "voxels_ao"); - #else - Inc.resolveDiffuse(); - Inc.resolveSpecular(); - path.bindTarget("voxels_diffuse", "voxels_diffuse"); - path.bindTarget("voxels_specular", "voxels_specular"); - #end - #if lnx_voxelgi_shadows + #if (rp_voxels != "Off") path.bindTarget("voxelsOut", "voxels"); + #if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows) path.bindTarget("voxelsSDF", "voxelsSDF"); #end + #end } #end @@ -522,14 +492,31 @@ class RenderPathForward { path.setTarget("lbuffer0", ["lbuffer1", "gbuffer_refraction"]); + #if rp_shadowmap + { + #if lnx_shadowmap_atlas + Inc.bindShadowMapAtlas(); + #else + Inc.bindShadowMap(); + #end + } + #end + #if (rp_voxels != "Off") path.bindTarget("voxelsOut", "voxels"); + #if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows) path.bindTarget("voxelsSDF", "voxelsSDF"); #end + #end + + #if rp_ssrs + path.bindTarget("_main", "gbufferD"); + #end path.drawMeshes("refraction"); path.setTarget("lbuffer0"); + path.bindTarget("lbuffer0", "tex"); path.bindTarget("refr", "tex1"); path.bindTarget("_main", "gbufferD"); @@ -577,6 +564,50 @@ class RenderPathForward { } #end + #if rp_ssrefr + { + if (leenkx.data.Config.raw.rp_ssrefr != false) + { + path.setTarget("gbufferD1"); + path.bindTarget("_main", "tex"); + path.drawShader("shader_datas/copy_pass/copy_pass"); + + path.setTarget("refr"); + path.bindTarget("lbuffer0", "tex"); + path.drawShader("shader_datas/copy_pass/copy_pass"); + + path.setTarget("lbuffer0", ["lbuffer1", "gbuffer_refraction"]); + + #if rp_shadowmap + { + #if lnx_shadowmap_atlas + Inc.bindShadowMapAtlas(); + #else + Inc.bindShadowMap(); + #end + } + #end + + #if (rp_voxels != "Off") + path.bindTarget("voxelsOut", "voxels"); + path.bindTarget("voxelsSDF", "voxelsSDF"); + #end + + path.drawMeshes("refraction"); + + path.setTarget("lbuffer0"); + path.bindTarget("lbuffer0", "tex"); + path.bindTarget("refr", "tex1"); + path.bindTarget("_main", "gbufferD"); + path.bindTarget("gbufferD1", "gbufferD1"); + path.bindTarget("lbuffer1", "gbuffer0"); + path.bindTarget("gbuffer_refraction", "gbuffer_refraction"); + + path.drawShader("shader_datas/ssrefr_pass/ssrefr_pass"); + } + } + #end + #if rp_bloom { inline Inc.drawBloom("lbuffer0", bloomDownsampler, bloomUpsampler); diff --git a/leenkx/Sources/leenkx/system/Starter.hx b/leenkx/Sources/leenkx/system/Starter.hx index 7fd39ba..e8a8ca2 100644 --- a/leenkx/Sources/leenkx/system/Starter.hx +++ b/leenkx/Sources/leenkx/system/Starter.hx @@ -41,7 +41,11 @@ class Starter { try { #end - kha.System.start({title: Main.projectName, width: c.window_w, height: c.window_h, window: {mode: windowMode, windowFeatures: windowFeatures}, framebuffer: {samplesPerPixel: c.window_msaa, verticalSync: c.window_vsync}}, function(window: kha.Window) { + kha.System.start({title: Main.projectName, width: c.window_w, height: c.window_h, window: { + #if lnx_render_viewport + visible: false, + #end + mode: windowMode, windowFeatures: windowFeatures}, framebuffer: {samplesPerPixel: c.window_msaa, verticalSync: c.window_vsync}}, function(window: kha.Window) { iron.App.init(function() { #if lnx_loadscreen diff --git a/leenkx/blender/lnx/make_renderpath.py b/leenkx/blender/lnx/make_renderpath.py index fa5cb6a..bef12e2 100644 --- a/leenkx/blender/lnx/make_renderpath.py +++ b/leenkx/blender/lnx/make_renderpath.py @@ -59,6 +59,9 @@ def add_world_defs(): if rpdat.rp_shadowmap_cascades != '1': wrd.world_defs += '_CSM' assets.add_khafile_def('lnx_csm') + if rpdat.rp_shadowmap_transparent: + wrd.world_defs += '_ShadowMapTransparent' + assets.add_khafile_def('rp_shadowmap_transparent') if rpdat.rp_shadowmap_atlas: assets.add_khafile_def('lnx_shadowmap_atlas') wrd.world_defs += '_ShadowMapAtlas' @@ -119,17 +122,15 @@ def add_world_defs(): if rpdat.lnx_voxelgi_shadows and (point_lights > 0 or '_Sun' in wrd.world_defs): wrd.world_defs += '_VoxelShadow' assets.add_khafile_def('lnx_voxelgi_shadows') - #assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_resolve_shadows/voxel_resolve_shadows.comp.glsl') if voxelgi: - assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_light/voxel_light.comp.glsl') assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl') assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl') + assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_light/voxel_light.comp.glsl') wrd.world_defs += '_VoxelGI' if rpdat.lnx_voxelgi_refract: wrd.world_defs += '_VoxelRefract' assets.add_khafile_def('lnx_voxelgi_refract') - #assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_resolve_refraction/voxel_resolve_refraction.comp.glsl') elif voxelao: assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl') @@ -307,10 +308,14 @@ def build(): assets.add_khafile_def('rp_ssgi={0}'.format(rpdat.rp_ssgi)) if rpdat.rp_ssgi != 'Off': - wrd.world_defs += '_SSAO' if rpdat.rp_ssgi == 'SSAO': + wrd.world_defs += '_SSAO' assets.add_shader_pass('ssao_pass') assets.add_shader_pass('blur_edge_pass') + elif rpdat.rp_ssgi == 'SSGI': + wrd.world_defs += '_SSGI' + assets.add_shader_pass('ssgi_pass') + assets.add_shader_pass('blur_edge_pass') else: assets.add_shader_pass('ssgi_pass') assets.add_shader_pass('blur_edge_pass') @@ -457,7 +462,8 @@ def build(): if ignoreIrr: wrd.world_defs += '_IgnoreIrr' - gbuffer2 = '_Veloc' in wrd.world_defs or '_IgnoreIrr' in wrd.world_defs + gbuffer2 = '_Veloc' in wrd.world_defs or '_IgnoreIrr' in wrd.world_defs or '_VoxelGI' in wrd.world_defs or '_VoxelShadow' in wrd.world_defs or '_SSGI' in wrd.world_defs + if gbuffer2: assets.add_khafile_def('rp_gbuffer2') wrd.world_defs += '_gbuffer2' diff --git a/leenkx/blender/lnx/make_world.py b/leenkx/blender/lnx/make_world.py index 839b204..9e639a1 100644 --- a/leenkx/blender/lnx/make_world.py +++ b/leenkx/blender/lnx/make_world.py @@ -199,6 +199,7 @@ def build_node_tree(world: bpy.types.World, frag: Shader, vert: Shader, con: Sha world.lnx_envtex_color = [col[0], col[1], col[2], 1.0] world.lnx_envtex_strength = 1.0 world.world_defs += '_EnvCol' + assets.add_khafile_def("lnx_envcol") # Clouds enabled if rpdat.lnx_clouds and world.lnx_use_clouds: @@ -280,6 +281,7 @@ def parse_surface(world: bpy.types.World, node_surface: bpy.types.Node, frag: Sh # Append irradiance define if rpdat.lnx_irradiance and not solid_mat: wrd.world_defs += '_Irr' + assets.add_khafile_def("lnx_irradiance") # Extract environment strength # Todo: follow/parse strength input @@ -293,6 +295,7 @@ def parse_surface(world: bpy.types.World, node_surface: bpy.types.Node, frag: Sh solid_mat = rpdat.lnx_material_model == 'Solid' if rpdat.lnx_irradiance and not solid_mat: world.world_defs += '_Irr' + assets.add_khafile_def("lnx_irradiance") world.lnx_envtex_color = node_surface.inputs[0].default_value world.lnx_envtex_strength = 1.0 diff --git a/leenkx/blender/lnx/material/cycles_nodes/nodes_shader.py b/leenkx/blender/lnx/material/cycles_nodes/nodes_shader.py index 7934d56..c8f35bc 100644 --- a/leenkx/blender/lnx/material/cycles_nodes/nodes_shader.py +++ b/leenkx/blender/lnx/material/cycles_nodes/nodes_shader.py @@ -253,7 +253,7 @@ def parse_bsdfglass(node: bpy.types.ShaderNodeBsdfGlass, out_socket: NodeSocket, c.write_normal(node.inputs[3]) state.out_roughness = c.parse_value_input(node.inputs[1]) if state.parse_opacity: - state.out_opacity = '0.1' + state.out_opacity = '1.0' state.out_ior = c.parse_value_input(node.inputs[2]) @@ -273,7 +273,7 @@ def parse_bsdfrefraction(node: bpy.types.ShaderNodeBsdfRefraction, out_socket: N c.write_normal(node.inputs[3]) state.out_roughness = c.parse_value_input(node.inputs[1]) if state.parse_opacity: - state.out_opacity = '0.0' + state.out_opacity = '1.0' state.out_ior = c.parse_value_input(node.inputs[2]) def parse_subsurfacescattering(node: bpy.types.ShaderNodeSubsurfaceScattering, out_socket: NodeSocket, state: ParserState) -> None: diff --git a/leenkx/blender/lnx/material/cycles_nodes/nodes_texture.py b/leenkx/blender/lnx/material/cycles_nodes/nodes_texture.py index b0d3c5e..c16da81 100644 --- a/leenkx/blender/lnx/material/cycles_nodes/nodes_texture.py +++ b/leenkx/blender/lnx/material/cycles_nodes/nodes_texture.py @@ -343,9 +343,6 @@ def parse_sky_hosekwilkie(node: bpy.types.ShaderNodeTexSky, state: ParserState) world = state.world curshader = state.curshader - # Match to cycles - world.lnx_envtex_strength *= 0.1 - assets.add_khafile_def('lnx_hosek') curshader.add_uniform('vec3 A', link="_hosekA") curshader.add_uniform('vec3 B', link="_hosekB") diff --git a/leenkx/blender/lnx/material/make_cluster.py b/leenkx/blender/lnx/material/make_cluster.py index ce8ccd5..abe68f1 100644 --- a/leenkx/blender/lnx/material/make_cluster.py +++ b/leenkx/blender/lnx/material/make_cluster.py @@ -19,6 +19,7 @@ def write(vert: shader.Shader, frag: shader.Shader): parse_opacity = blend or mat_utils.is_transluc(mat_state.material) is_mobile = rpdat.lnx_material_model == 'Mobile' is_shadows = '_ShadowMap' in wrd.world_defs + is_transparent_shadows = '_ShadowMapTransparent' in wrd.world_defs is_shadows_atlas = '_ShadowMapAtlas' in wrd.world_defs is_single_atlas = '_SingleAtlas' in wrd.world_defs @@ -33,14 +34,17 @@ def write(vert: shader.Shader, frag: shader.Shader): if is_shadows_atlas: if not is_single_atlas: frag.add_uniform('sampler2DShadow shadowMapAtlasPoint', included=True) - frag.add_uniform('sampler2D shadowMapAtlasPointTransparent', included=True) + if is_transparent_shadows: + frag.add_uniform('sampler2D shadowMapAtlasPointTransparent', included=True) else: frag.add_uniform('sampler2DShadow shadowMapAtlas', top=True) - frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) + if is_transparent_shadows: + frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) frag.add_uniform('vec4 pointLightDataArray[maxLightsCluster]', link='_pointLightsAtlasArray', included=True) else: frag.add_uniform('samplerCubeShadow shadowMapPoint[4]', included=True) - frag.add_uniform('samplerCube shadowMapPointTransparent[4]', included=True) + if is_transparent_shadows: + frag.add_uniform('samplerCube shadowMapPointTransparent[4]', included=True) if not '_VoxelAOvar' in wrd.world_defs and not '_VoxelGI' in wrd.world_defs or ((parse_opacity or '_VoxelShadow' in wrd.world_defs) and ('_VoxelAOvar' in wrd.world_defs or '_VoxelGI' in wrd.world_defs)): vert.add_out('vec4 wvpposition') @@ -62,13 +66,16 @@ def write(vert: shader.Shader, frag: shader.Shader): if is_shadows_atlas: if not is_single_atlas: frag.add_uniform('sampler2DShadow shadowMapAtlasSpot', included=True) - frag.add_uniform('sampler2D shadowMapAtlasSpotTransparent', included=True) + if is_transparent_shadows: + frag.add_uniform('sampler2D shadowMapAtlasSpotTransparent', included=True) else: frag.add_uniform('sampler2DShadow shadowMapAtlas', top=True) - frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) + if is_transparent_shadows: + frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) else: frag.add_uniform('sampler2DShadow shadowMapSpot[4]', included=True) - frag.add_uniform('sampler2D shadowMapSpotTransparent[4]', included=True) + if is_transparent_shadows: + frag.add_uniform('sampler2D shadowMapSpotTransparent[4]', included=True) frag.add_uniform('mat4 LWVPSpotArray[maxLightsCluster]', link='_biasLightWorldViewProjectionMatrixSpotArray', included=True) frag.write('for (int i = 0; i < min(numLights, maxLightsCluster); i++) {') @@ -84,12 +91,10 @@ def write(vert: shader.Shader, frag: shader.Shader): frag.write(' roughness,') frag.write(' specular,') frag.write(' f0') - if is_shadows: - if parse_opacity: - frag.write('\t, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, opacity != 1.0') # bias - else: - frag.write('\t, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, false') # bias + frag.write('\t, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0') # bias + if is_transparent_shadows: + frag.write('\t, opacity != 1.0') if '_Spot' in wrd.world_defs: frag.write('\t, lightsArray[li * 3 + 2].y != 0.0') frag.write('\t, lightsArray[li * 3 + 2].y') # spot size (cutoff) @@ -98,13 +103,13 @@ def write(vert: shader.Shader, frag: shader.Shader): frag.write('\t, vec2(lightsArray[li * 3].w, lightsArray[li * 3 + 1].w)') # scale frag.write('\t, lightsArraySpot[li * 2 + 1].xyz') # right if '_VoxelShadow' in wrd.world_defs: - frag.write(', voxels, voxelsSDF, clipmaps') + frag.write(', voxels, voxelsSDF, clipmaps, velocity') if '_MicroShadowing' in wrd.world_defs and not is_mobile: frag.write('\t, occlusion') if '_SSRS' in wrd.world_defs: + frag.add_uniform('sampler2D gbufferD') frag.add_uniform('mat4 invVP', '_inverseViewProjectionMatrix') frag.add_uniform('vec3 eye', '_cameraPosition') - frag.add_uniform('sampler2D gbufferD', link='_gbufferD', top=True) frag.write(', gbufferD, invVP, eye') frag.write(');') diff --git a/leenkx/blender/lnx/material/make_finalize.py b/leenkx/blender/lnx/material/make_finalize.py index afdca57..336980f 100644 --- a/leenkx/blender/lnx/material/make_finalize.py +++ b/leenkx/blender/lnx/material/make_finalize.py @@ -1,155 +1,161 @@ -import bpy - -import lnx -import lnx.material.mat_state as mat_state -import lnx.material.make_tess as make_tess -from lnx.material.shader import ShaderContext - -if lnx.is_reload(__name__): - mat_state = lnx.reload_module(mat_state) - make_tess = lnx.reload_module(make_tess) - lnx.material.shader = lnx.reload_module(lnx.material.shader) - from lnx.material.shader import ShaderContext -else: - lnx.enable_reload(__name__) - - -def make(con_mesh: ShaderContext): - vert = con_mesh.vert - frag = con_mesh.frag - geom = con_mesh.geom - tesc = con_mesh.tesc - tese = con_mesh.tese - - # Additional values referenced in cycles - # TODO: enable from cycles.py - if frag.contains('dotNV') and not frag.contains('float dotNV'): - frag.write_init('float dotNV = max(dot(n, vVec), 0.0);') - - # n is not always defined yet (in some shadowmap shaders e.g.) - if not frag.contains('vec3 n'): - vert.add_out('vec3 wnormal') - billboard = mat_state.material.lnx_billboard - if billboard == 'spherical': - vert.add_uniform('mat3 N', '_normalMatrixSphere') - elif billboard == 'cylindrical': - vert.add_uniform('mat3 N', '_normalMatrixCylinder') - else: - vert.add_uniform('mat3 N', '_normalMatrix') - vert.write_attrib('wnormal = normalize(N * vec3(nor.xy, pos.w));') - frag.write_attrib('vec3 n = normalize(wnormal);') - - # If not yet added, add nor vertex data - vertex_elems = con_mesh.data['vertex_elements'] - has_normals = False - for elem in vertex_elems: - if elem['name'] == 'nor': - has_normals = True - break - if not has_normals: - vertex_elems.append({'name': 'nor', 'data': 'short2norm'}) - - write_wpos = False - if frag.contains('vVec') and not frag.contains('vec3 vVec'): - if tese is not None: - tese.add_out('vec3 eyeDir') - tese.add_uniform('vec3 eye', '_cameraPosition') - tese.write('eyeDir = eye - wposition;') - - else: - if not vert.contains('wposition'): - write_wpos = True - vert.add_out('vec3 eyeDir') - vert.add_uniform('vec3 eye', '_cameraPosition') - vert.write('eyeDir = eye - wposition;') - frag.write_attrib('vec3 vVec = normalize(eyeDir);') - - export_wpos = False - if frag.contains('wposition') and not frag.contains('vec3 wposition'): - export_wpos = True - if tese is not None: - export_wpos = True - if vert.contains('wposition'): - write_wpos = True - - if export_wpos: - vert.add_uniform('mat4 W', '_worldMatrix') - vert.add_out('vec3 wposition') - vert.write('wposition = vec4(W * spos).xyz;') - elif write_wpos: - vert.add_uniform('mat4 W', '_worldMatrix') - vert.write_attrib('vec3 wposition = vec4(W * spos).xyz;') - - frag_mpos = (frag.contains('mposition') and not frag.contains('vec3 mposition')) or vert.contains('mposition') - if frag_mpos: - vert.add_out('vec3 mposition') - vert.add_uniform('float posUnpack', link='_posUnpack') - vert.write_attrib('mposition = spos.xyz * posUnpack;') - - if tese is not None: - if frag_mpos: - make_tess.interpolate(tese, 'mposition', 3, declare_out=True) - elif tese.contains('mposition') and not tese.contains('vec3 mposition'): - vert.add_out('vec3 mposition') - vert.write_pre = True - vert.add_uniform('float posUnpack', link='_posUnpack') - vert.write('mposition = spos.xyz * posUnpack;') - vert.write_pre = False - make_tess.interpolate(tese, 'mposition', 3, declare_out=False) - - frag_bpos = (frag.contains('bposition') and not frag.contains('vec3 bposition')) or vert.contains('bposition') - if frag_bpos: - vert.add_out('vec3 bposition') - vert.add_uniform('vec3 dim', link='_dim') - vert.add_uniform('vec3 hdim', link='_halfDim') - vert.add_uniform('float posUnpack', link='_posUnpack') - vert.write_attrib('bposition = (spos.xyz * posUnpack + hdim) / dim;') - vert.write_attrib('if (dim.z == 0) bposition.z = 0;') - vert.write_attrib('if (dim.y == 0) bposition.y = 0;') - vert.write_attrib('if (dim.x == 0) bposition.x = 0;') - - if tese is not None: - if frag_bpos: - make_tess.interpolate(tese, 'bposition', 3, declare_out=True) - elif tese.contains('bposition') and not tese.contains('vec3 bposition'): - vert.add_out('vec3 bposition') - vert.add_uniform('vec3 dim', link='_dim') - vert.add_uniform('vec3 hdim', link='_halfDim') - vert.add_uniform('float posUnpack', link='_posUnpack') - vert.write_attrib('bposition = (spos.xyz * posUnpack + hdim) / dim;') - make_tess.interpolate(tese, 'bposition', 3, declare_out=False) - - frag_wtan = (frag.contains('wtangent') and not frag.contains('vec3 wtangent')) or vert.contains('wtangent') - if frag_wtan: - # Indicate we want tang attrib in finalizer to prevent TBN generation - con_mesh.add_elem('tex', 'short2norm') - con_mesh.add_elem('tang', 'short4norm') - vert.add_out('vec3 wtangent') - vert.write_pre = True - vert.write('wtangent = normalize(N * tang.xyz);') - vert.write_pre = False - - if tese is not None: - if frag_wtan: - make_tess.interpolate(tese, 'wtangent', 3, declare_out=True) - elif tese.contains('wtangent') and not tese.contains('vec3 wtangent'): - vert.add_out('vec3 wtangent') - vert.write_pre = True - vert.write('wtangent = normalize(N * tang.xyz);') - vert.write_pre = False - make_tess.interpolate(tese, 'wtangent', 3, declare_out=False) - - if frag.contains('vVecCam'): - vert.add_out('vec3 eyeDirCam') - vert.add_uniform('mat4 WV', '_worldViewMatrix') - vert.write('eyeDirCam = vec4(WV * spos).xyz; eyeDirCam.z *= -1;') - frag.write_attrib('vec3 vVecCam = normalize(eyeDirCam);') - - if frag.contains('nAttr'): - vert.add_out('vec3 nAttr') - vert.write_attrib('nAttr = vec3(nor.xy, pos.w);') - - wrd = bpy.data.worlds['Lnx'] - if '_Legacy' in wrd.world_defs: - frag.replace('sampler2DShadow', 'sampler2D') - frag.replace('samplerCubeShadow', 'samplerCube') +import bpy + +import lnx +import lnx.material.mat_state as mat_state +import lnx.material.make_tess as make_tess +from lnx.material.shader import ShaderContext + +if lnx.is_reload(__name__): + mat_state = lnx.reload_module(mat_state) + make_tess = lnx.reload_module(make_tess) + lnx.material.shader = lnx.reload_module(lnx.material.shader) + from lnx.material.shader import ShaderContext +else: + lnx.enable_reload(__name__) + + +def make(con_mesh: ShaderContext): + vert = con_mesh.vert + frag = con_mesh.frag + geom = con_mesh.geom + tesc = con_mesh.tesc + tese = con_mesh.tese + + # Additional values referenced in cycles + # TODO: enable from cycles.py + if frag.contains('dotNV') and not frag.contains('float dotNV'): + frag.write_init('float dotNV = max(dot(n, vVec), 0.0);') + + # n is not always defined yet (in some shadowmap shaders e.g.) + if not frag.contains('vec3 n'): + vert.add_out('vec3 wnormal') + billboard = mat_state.material.lnx_billboard + if billboard == 'spherical': + vert.add_uniform('mat3 N', '_normalMatrixSphere') + elif billboard == 'cylindrical': + vert.add_uniform('mat3 N', '_normalMatrixCylinder') + else: + vert.add_uniform('mat3 N', '_normalMatrix') + vert.write_attrib('wnormal = normalize(N * vec3(nor.xy, pos.w));') + frag.write_attrib('vec3 n = normalize(wnormal);') + + # If not yet added, add nor vertex data + vertex_elems = con_mesh.data['vertex_elements'] + has_normals = False + for elem in vertex_elems: + if elem['name'] == 'nor': + has_normals = True + break + if not has_normals: + vertex_elems.append({'name': 'nor', 'data': 'short2norm'}) + + write_wpos = False + export_wpos = False + if frag.contains('wposition') and not frag.contains('vec3 wposition'): + export_wpos = True + if tese is not None: + export_wpos = True + if vert.contains('wposition'): + write_wpos = True + + + + + if frag.contains('vVec') and not frag.contains('vec3 vVec'): + if tese is not None: + tese.add_out('vec3 eyeDir') + tese.add_uniform('vec3 eye', '_cameraPosition') + tese.write('eyeDir = eye - wposition;') + + else: + if not vert.contains('wposition'): + write_wpos = True + vert.add_out('vec3 eyeDir') + vert.add_uniform('vec3 eye', '_cameraPosition') + vert.write('eyeDir = eye - wposition;') + frag.write_attrib('vec3 vVec = normalize(eyeDir);') + + if export_wpos: + vert.add_uniform('mat4 W', '_worldMatrix') + vert.add_out('vec3 wposition') + vert.write_attrib('wposition = vec4(W * spos).xyz;') + elif write_wpos: + vert.add_uniform('mat4 W', '_worldMatrix') + vert.write_attrib('vec3 wposition = vec4(W * spos).xyz;') + + if frag.contains('dotNV') and not frag.contains('float dotNV'): + frag.write_attrib('float dotNV = max(dot(n, vVec), 0.0);') + + frag_mpos = (frag.contains('mposition') and not frag.contains('vec3 mposition')) or vert.contains('mposition') + if frag_mpos: + vert.add_out('vec3 mposition') + vert.add_uniform('float posUnpack', link='_posUnpack') + vert.write_attrib('mposition = spos.xyz * posUnpack;') + + if tese is not None: + if frag_mpos: + make_tess.interpolate(tese, 'mposition', 3, declare_out=True) + elif tese.contains('mposition') and not tese.contains('vec3 mposition'): + vert.add_out('vec3 mposition') + vert.write_pre = True + vert.add_uniform('float posUnpack', link='_posUnpack') + vert.write('mposition = spos.xyz * posUnpack;') + vert.write_pre = False + make_tess.interpolate(tese, 'mposition', 3, declare_out=False) + + frag_bpos = (frag.contains('bposition') and not frag.contains('vec3 bposition')) or vert.contains('bposition') + if frag_bpos: + vert.add_out('vec3 bposition') + vert.add_uniform('vec3 dim', link='_dim') + vert.add_uniform('vec3 hdim', link='_halfDim') + vert.add_uniform('float posUnpack', link='_posUnpack') + vert.write_attrib('bposition = (spos.xyz * posUnpack + hdim) / dim;') + vert.write_attrib('if (dim.z == 0) bposition.z = 0;') + vert.write_attrib('if (dim.y == 0) bposition.y = 0;') + vert.write_attrib('if (dim.x == 0) bposition.x = 0;') + + if tese is not None: + if frag_bpos: + make_tess.interpolate(tese, 'bposition', 3, declare_out=True) + elif tese.contains('bposition') and not tese.contains('vec3 bposition'): + vert.add_out('vec3 bposition') + vert.add_uniform('vec3 dim', link='_dim') + vert.add_uniform('vec3 hdim', link='_halfDim') + vert.add_uniform('float posUnpack', link='_posUnpack') + vert.write_attrib('bposition = (spos.xyz * posUnpack + hdim) / dim;') + make_tess.interpolate(tese, 'bposition', 3, declare_out=False) + + frag_wtan = (frag.contains('wtangent') and not frag.contains('vec3 wtangent')) or vert.contains('wtangent') + if frag_wtan: + # Indicate we want tang attrib in finalizer to prevent TBN generation + con_mesh.add_elem('tex', 'short2norm') + con_mesh.add_elem('tang', 'short4norm') + vert.add_out('vec3 wtangent') + vert.write_pre = True + vert.write('wtangent = normalize(N * tang.xyz);') + vert.write_pre = False + + if tese is not None: + if frag_wtan: + make_tess.interpolate(tese, 'wtangent', 3, declare_out=True) + elif tese.contains('wtangent') and not tese.contains('vec3 wtangent'): + vert.add_out('vec3 wtangent') + vert.write_pre = True + vert.write('wtangent = normalize(N * tang.xyz);') + vert.write_pre = False + make_tess.interpolate(tese, 'wtangent', 3, declare_out=False) + + if frag.contains('vVecCam'): + vert.add_out('vec3 eyeDirCam') + vert.add_uniform('mat4 WV', '_worldViewMatrix') + vert.write('eyeDirCam = vec4(WV * spos).xyz; eyeDirCam.z *= -1;') + frag.write_attrib('vec3 vVecCam = normalize(eyeDirCam);') + + if frag.contains('nAttr'): + vert.add_out('vec3 nAttr') + vert.write_attrib('nAttr = vec3(nor.xy, pos.w);') + + wrd = bpy.data.worlds['Lnx'] + if '_Legacy' in wrd.world_defs: + frag.replace('sampler2DShadow', 'sampler2D') + frag.replace('samplerCubeShadow', 'samplerCube') diff --git a/leenkx/blender/lnx/material/make_mesh.py b/leenkx/blender/lnx/material/make_mesh.py index c30ca74..6713f6b 100644 --- a/leenkx/blender/lnx/material/make_mesh.py +++ b/leenkx/blender/lnx/material/make_mesh.py @@ -559,7 +559,7 @@ def make_forward(con_mesh): frag.write('fragColor[0] = vec4(direct + indirect, packFloat2(occlusion, specular));') frag.write('fragColor[1] = vec4(n.xy, roughness, metallic);') if rpdat.rp_ss_refraction or rpdat.lnx_voxelgi_refract: - frag.write(f'fragColor[2] = vec4(1.0, 1.0, 0.0, 1.0);') + frag.write(f'fragColor[2] = vec4(1.0, 1.0, 0.0, 0.0);') else: frag.add_out('vec4 fragColor[1]') @@ -613,10 +613,42 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): sh = tese if tese is not None else vert sh.add_out('vec3 eyeDir') sh.add_uniform('vec3 eye', '_cameraPosition') - sh.write('eyeDir = eye - spos.xyz;') + sh.write('eyeDir = eye - wposition;') + if '_VoxelGI' in wrd.world_defs or '_VoxelShadow' in wrd.world_defs: + if '_gbuffer2' in wrd.world_defs: + if '_Veloc' in wrd.world_defs: + if tese is None: + vert.add_uniform('mat4 prevWVP', link='_prevWorldViewProjectionMatrix') + vert.add_out('vec4 wvpposition') + vert.add_out('vec4 prevwvpposition') + vert.write('wvpposition = gl_Position;') + if is_displacement: + vert.add_uniform('mat4 invW', link='_inverseWorldMatrix') + vert.write('prevwvpposition = prevWVP * (invW * vec4(wposition, 1.0));') + else: + vert.write('prevwvpposition = prevWVP * spos;') + else: + tese.add_out('vec4 wvpposition') + tese.add_out('vec4 prevwvpposition') + tese.write('wvpposition = gl_Position;') + if is_displacement: + tese.add_uniform('mat4 invW', link='_inverseWorldMatrix') + tese.add_uniform('mat4 prevWVP', '_prevWorldViewProjectionMatrix') + tese.write('prevwvpposition = prevWVP * (invW * vec4(wposition, 1.0));') + else: + vert.add_uniform('mat4 prevW', link='_prevWorldMatrix') + vert.add_out('vec3 prevwposition') + vert.write('prevwposition = vec4(prevW * spos).xyz;') + tese.add_uniform('mat4 prevVP', '_prevViewProjectionMatrix') + make_tess.interpolate(tese, 'prevwposition', 3) + tese.write('prevwvpposition = prevVP * vec4(prevwposition, 1.0);') + frag.write('vec2 posa = (wvpposition.xy / wvpposition.w) * 0.5 + 0.5;') + frag.write('vec2 posb = (prevwvpposition.xy / prevwvpposition.w) * 0.5 + 0.5;') + frag.write('vec2 velocity = -vec2(posa - posb);') frag.add_include('std/light.glsl') is_shadows = '_ShadowMap' in wrd.world_defs + is_transparent_shadows = '_ShadowMapTransparent' in wrd.world_defs is_shadows_atlas = '_ShadowMapAtlas' in wrd.world_defs is_single_atlas = is_shadows_atlas and '_SingleAtlas' in wrd.world_defs shadowmap_sun = 'shadowMap' @@ -632,7 +664,10 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): if '_Brdf' in wrd.world_defs: frag.add_uniform('sampler2D senvmapBrdf', link='$brdf.png') frag.write('vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy;') - + frag.write('vec3 F = f0 * envBRDF.x + envBRDF.y;') + else: + frag.write('vec3 F = f0;') + if '_Irr' in wrd.world_defs: frag.add_include('std/shirr.glsl') frag.add_uniform('vec4 shirr[7]', link='_envmapIrradiance') @@ -657,51 +692,37 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): frag.write('envl *= albedo;') if '_Brdf' in wrd.world_defs: - frag.write('envl.rgb *= 1.0 - (f0 * envBRDF.x + envBRDF.y);') + frag.write('envl.rgb *= 1.0 - F;') if '_Rad' in wrd.world_defs: - frag.write('envl += prefilteredColor * (f0 * envBRDF.x + envBRDF.y);') + frag.write('envl += prefilteredColor * F;') elif '_EnvCol' in wrd.world_defs: frag.add_uniform('vec3 backgroundCol', link='_backgroundCol') - frag.write('envl += backgroundCol * (f0 * envBRDF.x + envBRDF.y);') + frag.write('envl += backgroundCol * F;') frag.add_uniform('float envmapStrength', link='_envmapStrength') frag.write('envl *= envmapStrength * occlusion;') if '_VoxelAOvar' in wrd.world_defs or '_VoxelGI' in wrd.world_defs: - if parse_opacity or '_VoxelShadow' in wrd.world_defs: - frag.add_include('std/conetrace.glsl') - frag.add_uniform('sampler3D voxels') - frag.add_uniform('sampler3D voxelsSDF') - frag.add_uniform('vec3 eye', "_cameraPosition") - frag.add_uniform('float clipmaps[10 * voxelgiClipmapCount]', '_clipmaps') - vert.add_out('vec4 wvpposition') - vert.write('wvpposition = gl_Position;') - frag.write('vec2 texCoord = (wvpposition.xy / wvpposition.w) * 0.5 + 0.5;') + frag.add_include('std/conetrace.glsl') + frag.add_uniform('sampler3D voxels') + frag.add_uniform('sampler3D voxelsSDF') + frag.add_uniform('float clipmaps[10 * voxelgiClipmapCount]', '_clipmaps') - if '_VoxelAOvar' in wrd.world_defs and not parse_opacity: - frag.add_uniform("sampler2D voxels_ao"); - frag.write('envl *= textureLod(voxels_ao, texCoord, 0.0).rrr;') + if '_VoxelAOvar' in wrd.world_defs: + frag.write('envl *= (1.0 - traceAO(wposition, n, voxels, clipmaps));') if '_VoxelGI' in wrd.world_defs: frag.write('vec3 indirect = vec3(0.0);') else: frag.write('vec3 indirect = envl;') - - if '_VoxelGI' in wrd.world_defs: - if parse_opacity: - frag.write('vec4 trace = traceDiffuse(wposition, wnormal, voxels, clipmaps);') - frag.write('indirect = ((trace.rgb * albedo + envl * (1.0 - trace.a)) * voxelgiDiff);') - frag.write('if (roughness < 1.0 && specular > 0.0){') - frag.add_uniform('sampler2D sveloc') - frag.write(' vec2 velocity = -textureLod(sveloc, gl_FragCoord.xy, 0.0).rg;') - frag.write(' indirect += traceSpecular(wposition, n, voxels, voxelsSDF, vVec, roughness, clipmaps, gl_FragCoord.xy, velocity).rgb * specular * voxelgiRefl;}') - else: - frag.add_uniform("sampler2D voxels_diffuse") - frag.add_uniform("sampler2D voxels_specular") - frag.write("indirect = textureLod(voxels_diffuse, texCoord, 0.0).rgb * albedo * voxelgiDiff;") - frag.write("if (roughness < 1.0 && specular > 0.0)") - frag.write(" indirect += textureLod(voxels_specular, texCoord, 0.0).rgb * specular * voxelgiRefl;") + if '_VoxelGI' in wrd.world_defs: + frag.write('vec2 velocity = gl_FragCoord.xy;') + frag.write('vec4 diffuse_indirect = traceDiffuse(wposition, n, voxels, clipmaps);') + frag.write('indirect = (diffuse_indirect.rgb * albedo * (1.0 - F) + envl * (1.0 - diffuse_indirect.a)) * voxelgiDiff;') + frag.write('if (roughness < 1.0 && specular > 0.0) {') + frag.write(' indirect += traceSpecular(wposition, n, voxels, voxelsSDF, vVec, roughness * roughness, clipmaps, gl_FragCoord.xy, velocity).rgb * F * voxelgiRefl;') + frag.write('}') frag.write('vec3 direct = vec3(0.0);') if '_Sun' in wrd.world_defs: @@ -715,18 +736,21 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): if is_shadows: frag.add_uniform('bool receiveShadow') frag.add_uniform(f'sampler2DShadow {shadowmap_sun}', top=True) - frag.add_uniform(f'sampler2D {shadowmap_sun_tr}', top=True) + if is_transparent_shadows: + frag.add_uniform(f'sampler2D {shadowmap_sun_tr}', top=True) frag.add_uniform('float shadowsBias', '_sunShadowsBias') frag.write('if (receiveShadow) {') if '_CSM' in wrd.world_defs: frag.add_include('std/shadows.glsl') frag.add_uniform('vec4 casData[shadowmapCascades * 4 + 4]', '_cascadeData', included=True) frag.add_uniform('vec3 eye', '_cameraPosition') - if parse_opacity: - frag.write(f'svisibility = shadowTestCascade({shadowmap_sun}, {shadowmap_sun_tr}, eye, wposition + n * shadowsBias * 10, shadowsBias, true);') - else: - frag.write(f'svisibility = shadowTestCascade({shadowmap_sun}, {shadowmap_sun_tr}, eye, wposition + n * shadowsBias * 10, shadowsBias, false);') - + frag.write(f'svisibility = shadowTestCascade({shadowmap_sun},') + if is_transparent_shadows: + frag.write(f'{shadowmap_sun_tr},') + frag.write('eye, wposition + n * shadowsBias * 10, shadowsBias') + if is_transparent_shadows: + frag.write(', false') + frag.write(');') else: if tese is not None: tese.add_out('vec4 lightPosition') @@ -740,15 +764,18 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): else: vert.add_out('vec4 lightPosition') vert.add_uniform('mat4 LWVP', '_biasLightWorldViewProjectionMatrixSun') - vert.write('lightPosition = LWVP * lightPosition;') + vert.write('lightPosition = LWVP * pos;') frag.write('vec3 lPos = lightPosition.xyz / lightPosition.w;') frag.write('const vec2 smSize = shadowmapSize;') - if parse_opacity: - frag.write(f'svisibility = PCF({shadowmap_sun}, {shadowmap_sun_tr}, lPos.xy, lPos.z - shadowsBias, smSize, true);') - else: - frag.write(f'svisibility = PCF({shadowmap_sun}, {shadowmap_sun_tr}, lPos.xy, lPos.z - shadowsBias, smSize, false);') + frag.write(f'svisibility = PCF({shadowmap_sun},') + if is_transparent_shadows: + frag.write(f'{shadowmap_sun_tr},') + frag.write('lPos.xy, lPos.z - shadowsBias, smSize') + if is_transparent_shadows: + frag.write(', false') + frag.write(');') if '_VoxelShadow' in wrd.world_defs: - frag.write('svisibility *= (1.0 - traceShadow(wposition, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy).r) * voxelgiShad;') + frag.write('svisibility *= (1.0 - traceShadow(wposition, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy, velocity).r) * voxelgiShad;') frag.write('}') # receiveShadow frag.write('direct += (lambertDiffuseBRDF(albedo, sdotNL) + specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * specular) * sunCol * svisibility;') # sun @@ -767,7 +794,8 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): # Skip world matrix, already in world-space frag.add_uniform('mat4 LWVPSpot[1]', link='_biasLightViewProjectionMatrixSpotArray', included=True) frag.add_uniform('sampler2DShadow shadowMapSpot[1]', included=True) - frag.add_uniform('sampler2D shadowMapSpotTransparent[1]', included=True) + if is_transparent_shadows: + frag.add_uniform('sampler2D shadowMapSpotTransparent[1]', included=True) else: frag.add_uniform('vec2 lightProj', link='_lightPlaneProj', included=True) frag.add_uniform('samplerCubeShadow shadowMapPoint[1]', included=True) @@ -775,18 +803,19 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): frag.write('direct += sampleLight(') frag.write(' wposition, n, vVec, dotNV, pointPos, pointCol, albedo, roughness, specular, f0') if is_shadows: - if parse_opacity: - frag.write(', 0, pointBias, receiveShadow, opacity != 1.0') - else: - frag.write(', 0, pointBias, receiveShadow, false') + frag.write(', 0, pointBias, receiveShadow') + if is_transparent_shadows: + frag.write(', opacity != 1.0') if '_Spot' in wrd.world_defs: frag.write(', true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight') if '_VoxelShadow' in wrd.world_defs: frag.write(', voxels, voxelsSDF, clipmaps') + if '_Veloc' in wrd.world_defs or '_VoxelShadow' in wrd.world_defs: + frag.write(', velocity') if '_MicroShadowing' in wrd.world_defs: frag.write(', occlusion') if '_SSRS' in wrd.world_defs: - frag.add_uniform('sampler2D gbufferD', top=True) + frag.add_uniform('sampler2D gbufferD') frag.add_uniform('mat4 invVP', '_inverseViewProjectionMatrix') frag.add_uniform('vec3 eye', '_cameraPosition') frag.write(', gbufferD, invVP, eye') @@ -802,10 +831,9 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): if '_VoxelRefract' in wrd.world_defs and parse_opacity: frag.write('if (opacity < 1.0) {') - frag.write(' vec2 velocity = -textureLod(sveloc, gl_FragCoord.xy, 0.0).rg;') - frag.write(' vec3 refraction = traceRefraction(wposition, n, voxels, voxelsSDF, vVec, ior, roughness, clipmaps, gl_FragCoord.xy,velocity).rgb;') - frag.write(' indirect = mix(refraction, indirect, opacity) * voxelgiRefr;') - frag.write(' direct = mix(refraction, direct, opacity) * voxelgiRefr;') + frag.write(' vec3 refraction = traceRefraction(wposition, n, voxels, voxelsSDF, vVec, ior, roughness * roughness, clipmaps, gl_FragCoord.xy, velocity, opacity).rgb * (1.0 - F) * voxelgiRefr;') + frag.write(' indirect = mix(refraction, indirect, opacity);') + frag.write(' direct = mix(refraction, direct, opacity);') frag.write('}') def _write_material_attribs_default(frag: shader.Shader, parse_opacity: bool): @@ -819,4 +847,4 @@ def _write_material_attribs_default(frag: shader.Shader, parse_opacity: bool): frag.write('vec3 emissionCol;') if parse_opacity: frag.write('float opacity;') - frag.write('float ior;') + frag.write('float ior = 1.45;') diff --git a/leenkx/blender/lnx/material/make_refract.py b/leenkx/blender/lnx/material/make_refract.py index a4c07ea..b30f6b2 100644 --- a/leenkx/blender/lnx/material/make_refract.py +++ b/leenkx/blender/lnx/material/make_refract.py @@ -58,6 +58,7 @@ def make(context_id): frag.write('fragColor[1] = vec4(n.xy, roughness, metallic);') frag.write('fragColor[2] = vec4(ior, opacity, 0.0, 1.0);') + # frag.write('fragColor[2] = vec4(ior, opacity, packFloat2(basecol.r, basecol.g), basecol.b);') make_finalize.make(con_refract) diff --git a/leenkx/blender/lnx/material/make_refraction_buffer.py b/leenkx/blender/lnx/material/make_refraction_buffer.py deleted file mode 100644 index 06e76bc..0000000 --- a/leenkx/blender/lnx/material/make_refraction_buffer.py +++ /dev/null @@ -1,49 +0,0 @@ -import bpy - -import lnx -import lnx.material.cycles as cycles -import lnx.material.mat_state as mat_state -import lnx.material.mat_utils as mat_utils -import lnx.material.make_mesh as make_mesh -import lnx.material.make_finalize as make_finalize -import lnx.assets as assets - -if lnx.is_reload(__name__): - cycles = lnx.reload_module(cycles) - mat_state = lnx.reload_module(mat_state) - make_mesh = lnx.reload_module(make_mesh) - make_finalize = lnx.reload_module(make_finalize) - assets = lnx.reload_module(assets) -else: - lnx.enable_reload(__name__) - - -def make(context_id): - con_refraction_buffer = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'less', 'cull_mode': 'clockwise' }) - - lnx_discard = mat_state.material.lnx_discard - blend = mat_state.material.lnx_blending - parse_opacity = blend or mat_utils.is_transluc(mat_state.material) or lnx_discard - - make_mesh.make_base(con_refraction_buffer, parse_opacity) - - vert = con_refraction_buffer.vert - frag = con_refraction_buffer.frag - - frag.add_out('vec4 fragColor') - - # Remove fragColor = ...; - frag.main = frag.main[:frag.main.rfind('fragColor')] - frag.write('\n') - - if parse_opacity: - frag.write('fragColor = vec4(ior, opacity, 0.0, 1.0);') - else: - frag.write('fragColor = vec4(1.0, 1.0, 0.0, 1.0);') - - make_finalize.make(con_refraction_buffer) - - # assets.vs_equal(con_refract, assets.shader_cons['transluc_vert']) # shader_cons has no transluc yet - # assets.fs_equal(con_refract, assets.shader_cons['transluc_frag']) - - return con_refraction_buffer diff --git a/leenkx/blender/lnx/material/make_voxel.py b/leenkx/blender/lnx/material/make_voxel.py index 553df86..f589adb 100644 --- a/leenkx/blender/lnx/material/make_voxel.py +++ b/leenkx/blender/lnx/material/make_voxel.py @@ -1,508 +1,769 @@ -""" -Copyright (c) 2024 Turánszki János - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" -import bpy - -import lnx.utils -import lnx.assets as assets -import lnx.material.cycles as cycles -import lnx.material.mat_state as mat_state -import lnx.material.mat_utils as mat_utils -import lnx.material.make_particle as make_particle -import lnx.make_state as state - -if lnx.is_reload(__name__): - lnx.utils = lnx.reload_module(lnx.utils) - assets = lnx.reload_module(assets) - mat_state = lnx.reload_module(mat_state) -else: - lnx.enable_reload(__name__) - -def make(context_id): - rpdat = lnx.utils.get_rp() - if rpdat.rp_voxels == 'Voxel GI': - con = make_gi(context_id) - else: - con = make_ao(context_id) - - assets.vs_equal(con, assets.shader_cons['voxel_vert']) - assets.fs_equal(con, assets.shader_cons['voxel_frag']) - assets.gs_equal(con, assets.shader_cons['voxel_geom']) - - return con - -def make_gi(context_id): - con_voxel = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'always', 'cull_mode': 'none', 'color_write_red': False, 'color_write_green': False, 'color_write_blue': False, 'color_write_alpha': False, 'conservative_raster': True }) - wrd = bpy.data.worlds['Lnx'] - - vert = con_voxel.make_vert() - frag = con_voxel.make_frag() - geom = con_voxel.make_geom() - tesc = None - tese = None - geom.ins = vert.outs - frag.ins = geom.outs - - vert.add_include('compiled.inc') - geom.add_include('compiled.inc') - frag.add_include('compiled.inc') - frag.add_include('std/math.glsl') - frag.add_include('std/imageatomic.glsl') - frag.add_include('std/gbuffer.glsl') - frag.add_include('std/brdf.glsl') - - rpdat = lnx.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;') # - frag.write('float metallic;') # - frag.write('float occlusion;') # - frag.write('float specular;') # - frag.write('vec3 emissionCol = vec3(0.0);') - blend = mat_state.material.lnx_blending - parse_opacity = blend or mat_utils.is_transluc(mat_state.material) - if parse_opacity: - frag.write('float opacity;') - frag.write('float ior;') - else: - frag.write('float opacity = 1.0;') - - frag.write('float dotNV = 0.0;') - cycles.parse(mat_state.nodes, con_voxel, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity, parse_displacement=False, basecol_only=True) - - # Voxelized particles - particle = mat_state.material.lnx_particle_flag - if particle and rpdat.lnx_particles == 'On': - # make_particle.write(vert, particle_info=cycles.particle_info) - frag.write_pre = True - frag.write('const float p_index = 0;') - frag.write('const float p_age = 0;') - frag.write('const float p_lifetime = 0;') - frag.write('const vec3 p_location = vec3(0);') - frag.write('const float p_size = 0;') - frag.write('const vec3 p_velocity = vec3(0);') - frag.write('const vec3 p_angular_velocity = vec3(0);') - frag.write_pre = False - - export_mpos = frag.contains('mposition') and not frag.contains('vec3 mposition') - if export_mpos: - vert.add_out('vec3 mpositionGeom') - vert.write_pre = True - vert.write('mpositionGeom = pos.xyz;') - vert.write_pre = False - - export_bpos = frag.contains('bposition') and not frag.contains('vec3 bposition') - if export_bpos: - vert.add_out('vec3 bpositionGeom') - vert.add_uniform('vec3 dim', link='_dim') - vert.add_uniform('vec3 hdim', link='_halfDim') - vert.write_pre = True - vert.write('bpositionGeom = (pos.xyz + hdim) / dim;') - vert.write_pre = False - - vert.add_uniform('mat4 W', '_worldMatrix') - vert.add_uniform('mat3 N', '_normalMatrix') - vert.add_out('vec3 voxpositionGeom') - vert.add_out('vec3 voxnormalGeom') - - if con_voxel.is_elem('col'): - vert.add_out('vec3 vcolorGeom') - vert.write('vcolorGeom = col.rgb;') - - if con_voxel.is_elem('tex'): - vert.add_out('vec2 texCoordGeom') - vert.write('texCoordGeom = tex;') - - vert.write('voxpositionGeom = vec3(W * vec4(pos.xyz, 1.0));') - vert.write('voxnormalGeom = normalize(N * vec3(nor.xy, pos.w));') - - geom.add_out('vec4 voxposition[3]') - geom.add_out('vec3 P') - geom.add_out('vec3 voxnormal') - geom.add_out('vec4 lightPosition') - geom.add_out('vec4 spotPosition') - geom.add_out('vec4 wvpposition') - - if con_voxel.is_elem('col'): - geom.add_out('vec3 vcolor') - if con_voxel.is_elem('tex'): - geom.add_out('vec2 texCoord') - if export_mpos: - geom.add_out('vec3 mposition') - if export_bpos: - geom.add_out('vec3 bposition') - - geom.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') - geom.add_uniform('int clipmapLevel', '_clipmapLevel') - - geom.write('vec3 facenormal = abs(voxnormalGeom[0] + voxnormalGeom[1] + voxnormalGeom[2]);') - geom.write('uint maxi = facenormal[1] > facenormal[0] ? 1 : 0;') - geom.write('maxi = facenormal[2] > facenormal[maxi] ? 2 : maxi;') - - geom.write('for (uint i = 0; i < 3; ++i) {') - geom.write(' voxposition[i].xyz = (voxpositionGeom[i] - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]));') - geom.write(' if (maxi == 0)') - geom.write(' {') - geom.write(' voxposition[i].xyz = voxposition[i].zyx;') - geom.write(' }') - geom.write(' else if (maxi == 1)') - geom.write(' {') - geom.write(' voxposition[i].xyz = voxposition[i].xzy;') - geom.write(' }') - geom.write('}') - - geom.write('for (uint i = 0; i < 3; ++i) {') - geom.write(' voxposition[i].xy /= voxelgiResolution.xy;') - geom.write(' voxposition[i].zw = vec2(1.0);') - geom.write(' P = voxpositionGeom[i];') - geom.write(' voxnormal = voxnormalGeom[i];') - if con_voxel.is_elem('col'): - geom.write('vcolor = vcolorGeom[i];') - if con_voxel.is_elem('tex'): - geom.write('texCoord = texCoordGeom[i];') - if export_mpos: - geom.write('mposition = mpositionGeom[i];') - if export_bpos: - geom.write('bposition = bpositionGeom[i];') - geom.write(' gl_Position = voxposition[i];') - geom.write(' EmitVertex();') - geom.write('}') - geom.write('EndPrimitive();') - - frag.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') - frag.add_uniform('int clipmapLevel', '_clipmapLevel') - - frag.write('vec3 uvw = (P - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution);') - 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('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 albedo = surfaceAlbedo(basecol, metallic);') - frag.write('vec3 f0 = surfaceF0(basecol, metallic);') - - frag.add_uniform('vec3 eye', '_cameraPosition') - frag.write('vec3 eyeDir = eye - wposition;') - - if '_Brdf' in wrd.world_defs: - frag.add_uniform('sampler2D senvmapBrdf', link='$brdf.png') - frag.write('vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy;') - - if '_Irr' in wrd.world_defs: - frag.add_include('std/shirr.glsl') - frag.add_uniform('vec4 shirr[7]', link='_envmapIrradiance') - frag.write('vec3 envl = shIrradiance(n, shirr);') - if '_EnvTex' in wrd.world_defs: - frag.write('envl /= PI;') - else: - frag.write('vec3 envl = vec3(0.0);') - - if '_Rad' in wrd.world_defs: - frag.add_uniform('sampler2D senvmapRadiance', link='_envmapRadiance') - frag.add_uniform('int envmapNumMipmaps', link='_envmapNumMipmaps') - frag.write('vec3 reflectionWorld = reflect(-eyeDir, n);') - frag.write('float lod = getMipFromRoughness(roughness, envmapNumMipmaps);') - frag.write('vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;') - - if '_EnvLDR' in wrd.world_defs: - frag.write('envl = pow(envl, vec3(2.2));') - if '_Rad' in wrd.world_defs: - frag.write('prefilteredColor = pow(prefilteredColor, vec3(2.2));') - - frag.write('envl *= albedo;') - - if '_Brdf' in wrd.world_defs: - frag.write('envl.rgb *= 1.0 - (f0 * envBRDF.x + envBRDF.y);') - if '_Rad' in wrd.world_defs: - frag.write('envl += prefilteredColor * (f0 * envBRDF.x + envBRDF.y);') - elif '_EnvCol' in wrd.world_defs: - frag.add_uniform('vec3 backgroundCol', link='_backgroundCol') - frag.write('envl += backgroundCol * (f0 * envBRDF.x + envBRDF.y);') - - frag.add_uniform('float envmapStrength', link='_envmapStrength') - frag.write('envl *= envmapStrength * occlusion;') - - frag.write('if (direction_weights.x > 0) {') - frag.write(' vec4 basecol_direction = vec4(min(basecol * direction_weights.x, vec3(1.0)), 1.0);') - frag.write(' vec3 emission_direction = emissionCol * direction_weights.x;') - frag.write(' vec2 normal_direction = encode_oct(N * direction_weights.x) * 0.5 + 0.5;') - frag.write(' vec3 envl_direction = envl * direction_weights.x;') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, 0)), uint(basecol_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 3)), uint(basecol_direction.a * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 4)), uint(emission_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 5)), uint(emission_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 6)), uint(emission_direction.b * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 7)), uint(normal_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 8)), uint(normal_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') - frag.write('}') - - frag.write('if (direction_weights.y > 0) {') - frag.write(' vec4 basecol_direction = vec4(min(basecol * direction_weights.y, vec3(1.0)), 1.0);') - frag.write(' vec3 emission_direction = emissionCol * direction_weights.y;') - frag.write(' vec2 normal_direction = encode_oct(N * direction_weights.y) * 0.5 + 0.5;') - frag.write(' vec3 envl_direction = envl * direction_weights.y;') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, 0)), uint(basecol_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 3)), uint(basecol_direction.a * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 4)), uint(emission_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 5)), uint(emission_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 6)), uint(emission_direction.b * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 7)), uint(normal_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 8)), uint(normal_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') - frag.write('}') - - frag.write('if (direction_weights.z > 0) {') - frag.write(' vec4 basecol_direction = vec4(min(basecol * direction_weights.z, vec3(1.0)), 1.0);') - frag.write(' vec3 emission_direction = emissionCol * direction_weights.z;') - frag.write(' vec2 normal_direction = encode_oct(n * direction_weights.z) * 0.5 + 0.5;') - frag.write(' vec3 envl_direction = envl * direction_weights.z;') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, 0)), uint(basecol_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 3)), uint(basecol_direction.a * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 4)), uint(emission_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 5)), uint(emission_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 6)), uint(emission_direction.b * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 7)), uint(normal_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 8)), uint(normal_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') - frag.write('}') - - return con_voxel - - -def make_ao(context_id): - con_voxel = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'always', 'cull_mode': 'none', 'color_writes_red': [False], 'color_writes_green': [False], 'color_writes_blue': [False], 'color_writes_alpha': [False], 'conservative_raster': False }) - wrd = bpy.data.worlds['Lnx'] - rpdat = lnx.utils.get_rp() - - vert = con_voxel.make_vert() - frag = con_voxel.make_frag() - geom = con_voxel.make_geom() - tesc = None - tese = None - - geom.ins = vert.outs - frag.ins = geom.outs - - frag.add_include('compiled.inc') - geom.add_include('compiled.inc') - frag.add_include('std/math.glsl') - frag.add_include('std/imageatomic.glsl') - frag.write_header('#extension GL_ARB_shader_image_load_store : enable') - - vert.add_include('compiled.inc') - vert.add_uniform('mat4 W', '_worldMatrix') - vert.add_uniform('mat3 N', '_normalMatrix') - - geom.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') - geom.add_uniform('int clipmapLevel', '_clipmapLevel') - - frag.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') - frag.add_uniform('int clipmapLevel', '_clipmapLevel') - - """ - if lnx.utils.get_gapi() == 'direct3d11': - for e in con_voxel.data['vertex_elements']: - if e['name'] == 'nor': - con_voxel.data['vertex_elements'].remove(e) - break - - vert.write('uniform float4x4 W;') - vert.write('uniform float3x3 N;') - vert.write('struct SPIRV_Cross_Input {') - vert.write(' float4 pos : TEXCOORD0;') - vert.write(' float3 nor : NORMAL;') - vert.write('};') - vert.write('struct SPIRV_Cross_Output {') - vert.write(' float4 svpos : SV_POSITION;') - vert.write(' float3 svnor : NORMAL;') - vert.write('};') - vert.write('SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) {') - vert.write(' SPIRV_Cross_Output stage_output;') - vert.write(' stage_output.svpos.xyz = mul(float4(stage_input.pos.xyz, 1.0), W).xyz;') - vert.write(' stage_output.svpos.w = 1.0;') - vert.write(' stage_output.svnor.xyz = normalize(mul(float3(nor.xy, pos.w), N).xyz);') - vert.write(' return stage_output;') - vert.write('}') - - geom.write('uniform float clipmaps[voxelgiClipmapCount * 10];') - geom.write('uniform int clipmapLevel;') - geom.write('struct SPIRV_Cross_Input {') - geom.write(' float4 svpos : SV_POSITION;') - geom.write(' float3 svnor : NORMAL;') - geom.write('};') - geom.write('struct SPIRV_Cross_Output {') - geom.write(' float3 wpos : TEXCOORD0;') - geom.write(' float3 wnor : NORMAL;') - geom.write('};') - geom.write('[maxvertexcount(3)]') - geom.write('void main(triangle SPIRV_Cross_Input stage_input[3], inout TriangleStream output) {') - geom.write(' float3 p1 = stage_input[1].svpos.xyz - stage_input[0].svpos.xyz;') - geom.write(' float3 p2 = stage_input[2].svpos.xyz - stage_input[0].svpos.xyz;') - geom.write(' float3 p = abs(cross(p1, p2));') - geom.write(' for (int i = 0; i < 3; ++i) {') - geom.write(' SPIRV_Cross_Output stage_output;') - geom.write(' stage_output.wpos = (stage_input[i].svpos.xyz + float3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[clipmapLevel * 10]) * voxelgiResolution);') - geom.write(' stage_output.wnor = stage_input[i].svnor.xyz;') - geom.write(' if (p.z > p.x && p.z > p.y) {') - geom.write(' stage_output.svpos = float4(stage_input[i].svpos.x, stage_input[i].svpos.y, 0.0, 1.0);') - geom.write(' }') - geom.write(' else if (p.x > p.y && p.x > p.z) {') - geom.write(' stage_output.svpos = float4(stage_input[i].svpos.y, stage_input[i].svpos.z, 0.0, 1.0);') - geom.write(' }') - geom.write(' else {') - geom.write(' stage_output.svpos = float4(stage_input[i].svpos.x, stage_input[i].svpos.z, 0.0, 1.0);') - geom.write(' }') - geom.write(' output.Append(stage_output);') - geom.write(' }') - geom.write('}') - - frag.add_uniform('layout(r8) writeonly image3D voxels') - frag.write('RWTexture3D voxels;') - frag.write('uniform float clipmaps[voxelgiClipmapCount * 10];') - frag.write('uniform int clipmapLevel;') - - frag.write('struct SPIRV_Cross_Input {') - frag.write(' float3 wpos : TEXCOORD0;') - frag.write(' float3 wnor : NORMAL;') - frag.write('};') - frag.write('struct SPIRV_Cross_Output { float4 FragColor : SV_TARGET0; };') - frag.write('void main(SPIRV_Cross_Input stage_input) {') - frag.write(' float3 uvw = (stage_input.wpos.xyz - float3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution);') - frag.write(' uvw = uvw * 0.5 + 0.5;') - frag.write(' if(any(!saturate(uvw))) return;') - frag.write(' uvw = floor(uvw * voxelgiResolution);') - frag.write(' uint3 face_offsets = uint3(') - frag.write(' stage_input.wnor.x > 0 ? 0 : 1,') - frag.write(' stage_input.wnor.y > 0 ? 2 : 3,') - frag.write(' stage_input.wnor.z > 0 ? 4 : 5') - frag.write(' ) * voxelgiResolution;') - frag.write(' float3 direction_weights = abs(stage_input.wnor);') - - frag.write(' if (direction_weights.x > 0.0) {') - frag.write(' float opac_direction = direction_weights.x;') - frag.write(' voxels[uvw + int3(face_offsets.x, 0, 0))] = float4(opac_direction);') - frag.write(' }') - - frag.write(' if (direction_weights.y > 0.0) {') - frag.write(' float opac_direction = direction_weights.y;') - frag.write(' voxels[uvw + int3(face_offsets.y, 0, 0))] = float4(opac_direction);') - frag.write(' }') - - frag.write(' if (direction_weights.z > 0.0) {') - frag.write(' float opac_direction = direction_weights.z;') - frag.write(' voxels[uvw + int3(face_offsets.z, 0, 0))] = float4(opac_direction);') - frag.write(' }') - frag.write('}') - else: - """ - frag.add_uniform('layout(r32ui) uimage3D voxels') - - vert.add_out('vec3 voxpositionGeom') - vert.add_out('vec3 voxnormalGeom') - - vert.write('voxpositionGeom = vec3(W * vec4(pos.xyz, 1.0));') - vert.write('voxnormalGeom = normalize(N * vec3(nor.xy, pos.w));') - - geom.add_out('vec4 voxposition[3]') - geom.add_out('vec3 P') - geom.add_out('vec3 voxnormal') - geom.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') - geom.add_uniform('int clipmapLevel', '_clipmapLevel') - - geom.write('vec3 facenormal = abs(voxnormalGeom[0] + voxnormalGeom[1] + voxnormalGeom[2]);') - geom.write('uint maxi = facenormal[1] > facenormal[0] ? 1 : 0;') - geom.write('maxi = facenormal[2] > facenormal[maxi] ? 2 : maxi;') - - geom.write('for (uint i = 0; i < 3; ++i) {') - geom.write(' voxposition[i].xyz = (voxpositionGeom[i] - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]));') - geom.write(' if (maxi == 0)') - geom.write(' {') - geom.write(' voxposition[i].xyz = voxposition[i].zyx;') - geom.write(' }') - geom.write(' else if (maxi == 1)') - geom.write(' {') - geom.write(' voxposition[i].xyz = voxposition[i].xzy;') - geom.write(' }') - geom.write('}') - - geom.write('for (uint i = 0; i < 3; ++i) {') - geom.write(' voxposition[i].xy /= voxelgiResolution.xy;') - geom.write(' voxposition[i].zw = vec2(1.0);') - geom.write(' P = voxpositionGeom[i];') - geom.write(' voxnormal = voxnormalGeom[i];') - geom.write(' gl_Position = voxposition[i];') - geom.write(' EmitVertex();') - geom.write('}') - geom.write('EndPrimitive();') - - - frag.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') - frag.add_uniform('int clipmapLevel', '_clipmapLevel') - - frag.write('vec3 uvw = (P - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution);') - 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('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('if (direction_weights.x > 0) {') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, 0)), uint(direction_weights.x * 255));') - frag.write('}') - - frag.write('if (direction_weights.y > 0) {') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, 0)), uint(direction_weights.y * 255));') - frag.write('}') - - frag.write('if (direction_weights.z > 0) {') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, 0)), uint(direction_weights.z * 255));') - frag.write('}') - - return con_voxel +""" +Copyright (c) 2024 Turánszki János + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +""" +import bpy + +import lnx.utils +import lnx.assets as assets +import lnx.material.cycles as cycles +import lnx.material.mat_state as mat_state +import lnx.material.mat_utils as mat_utils +import lnx.material.make_particle as make_particle +import lnx.make_state as state + +if lnx.is_reload(__name__): + lnx.utils = lnx.reload_module(lnx.utils) + assets = lnx.reload_module(assets) + mat_state = lnx.reload_module(mat_state) +else: + lnx.enable_reload(__name__) + +def make(context_id): + rpdat = lnx.utils.get_rp() + if rpdat.rp_voxels == 'Voxel GI': + con = make_gi(context_id) + else: + con = make_ao(context_id) + + assets.vs_equal(con, assets.shader_cons['voxel_vert']) + assets.fs_equal(con, assets.shader_cons['voxel_frag']) + assets.gs_equal(con, assets.shader_cons['voxel_geom']) + + return con + +def make_gi(context_id): + con_voxel = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'always', 'cull_mode': 'none', 'color_write_red': False, 'color_write_green': False, 'color_write_blue': False, 'color_write_alpha': False, 'conservative_raster': True }) + wrd = bpy.data.worlds['Lnx'] + + vert = con_voxel.make_vert() + frag = con_voxel.make_frag() + geom = con_voxel.make_geom() + tesc = None + tese = None + geom.ins = vert.outs + frag.ins = geom.outs + + vert.add_include('compiled.inc') + geom.add_include('compiled.inc') + frag.add_include('compiled.inc') + frag.add_include('std/math.glsl') + frag.add_include('std/imageatomic.glsl') + frag.add_include('std/gbuffer.glsl') + frag.add_include('std/brdf.glsl') + frag.add_include('std/aabb.glsl') + + rpdat = lnx.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;') # + frag.write('float metallic;') # + frag.write('float occlusion;') # + frag.write('float specular;') # + frag.write('vec3 emissionCol = vec3(0.0);') + blend = mat_state.material.lnx_blending + parse_opacity = blend or mat_utils.is_transluc(mat_state.material) + if parse_opacity: + frag.write('float opacity;') + frag.write('float ior;') + else: + frag.write('float opacity = 1.0;') + + cycles.parse(mat_state.nodes, con_voxel, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity, parse_displacement=False, basecol_only=True) + + # Voxelized particles + particle = mat_state.material.lnx_particle_flag + if particle and rpdat.lnx_particles == 'On': + # make_particle.write(vert, particle_info=cycles.particle_info) + frag.write_pre = True + frag.write('const float p_index = 0;') + frag.write('const float p_age = 0;') + frag.write('const float p_lifetime = 0;') + frag.write('const vec3 p_location = vec3(0);') + frag.write('const float p_size = 0;') + frag.write('const vec3 p_velocity = vec3(0);') + frag.write('const vec3 p_angular_velocity = vec3(0);') + frag.write_pre = False + + export_mpos = frag.contains('mposition') and not frag.contains('vec3 mposition') + if export_mpos: + vert.add_out('vec3 mpositionGeom') + vert.write_pre = True + vert.write('mpositionGeom = pos.xyz;') + vert.write_pre = False + + export_bpos = frag.contains('bposition') and not frag.contains('vec3 bposition') + if export_bpos: + vert.add_out('vec3 bpositionGeom') + vert.add_uniform('vec3 dim', link='_dim') + vert.add_uniform('vec3 hdim', link='_halfDim') + vert.write_pre = True + vert.write('bpositionGeom = (pos.xyz + hdim) / dim;') + vert.write_pre = False + + vert.add_uniform('mat4 W', '_worldMatrix') + vert.add_uniform('mat3 N', '_normalMatrix') + vert.add_out('vec3 voxpositionGeom') + vert.add_out('vec3 voxnormalGeom') + + if con_voxel.is_elem('col'): + vert.add_out('vec3 vcolorGeom') + vert.write('vcolorGeom = col.rgb;') + + if con_voxel.is_elem('tex'): + vert.add_out('vec2 texCoordGeom') + vert.write('texCoordGeom = tex;') + + vert.write('voxpositionGeom = vec3(W * vec4(pos.xyz, 1.0));') + vert.write('voxnormalGeom = normalize(N * vec3(nor.xy, pos.w));') + + geom.add_out('vec4 voxposition[3]') + geom.add_out('vec3 P') + geom.add_out('vec3 wnormal') + geom.add_out('vec4 lightPosition') + geom.add_out('vec4 wvpposition') + geom.add_out('vec3 eyeDir') + geom.add_out('vec3 aabb_min') + geom.add_out('vec3 aabb_max') + + if con_voxel.is_elem('col'): + geom.add_out('vec3 vcolor') + if con_voxel.is_elem('tex'): + geom.add_out('vec2 texCoord') + if export_mpos: + geom.add_out('vec3 mposition') + if export_bpos: + geom.add_out('vec3 bposition') + + geom.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') + geom.add_uniform('int clipmapLevel', '_clipmapLevel') + + geom.write('vec3 facenormal = abs(voxnormalGeom[0] + voxnormalGeom[1] + voxnormalGeom[2]);') + geom.write('uint maxi = facenormal[1] > facenormal[0] ? 1 : 0;') + geom.write('maxi = facenormal[2] > facenormal[maxi] ? 2 : maxi;') + + geom.write('aabb_min = min(voxpositionGeom[0].xyz, min(voxpositionGeom[1].xyz, voxpositionGeom[2].xyz));') + geom.write('aabb_max = max(voxpositionGeom[0].xyz, max(voxpositionGeom[1].xyz, voxpositionGeom[2].xyz));') + + geom.write('for (uint i = 0; i < 3; ++i) {') + geom.write(' voxposition[i].xyz = (voxpositionGeom[i] - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]));') + geom.write(' if (maxi == 0)') + geom.write(' {') + geom.write(' voxposition[i].xyz = voxposition[i].zyx;') + geom.write(' }') + geom.write(' else if (maxi == 1)') + geom.write(' {') + geom.write(' voxposition[i].xyz = voxposition[i].xzy;') + geom.write(' }') + geom.write('}') + + geom.write('vec2 side0N = normalize(voxposition[1].xy - voxposition[0].xy);') + geom.write('vec2 side1N = normalize(voxposition[2].xy - voxposition[1].xy);') + geom.write('vec2 side2N = normalize(voxposition[0].xy - voxposition[2].xy);') + geom.write('voxposition[0].xy += normalize(side2N - side0N);') + geom.write('voxposition[1].xy += normalize(side0N - side1N);') + geom.write('voxposition[2].xy += normalize(side1N - side2N);') + + geom.write('for (uint i = 0; i < 3; ++i) {') + geom.write(' voxposition[i].xy /= voxelgiResolution.xy;') + geom.write(' voxposition[i].zw = vec2(1.0);') + geom.write(' P = voxpositionGeom[i];') + geom.write(' wnormal = voxnormalGeom[i];') + if con_voxel.is_elem('col'): + geom.write('vcolor = vcolorGeom[i];') + if con_voxel.is_elem('tex'): + geom.write('texCoord = texCoordGeom[i];') + if export_mpos: + geom.write('mposition = mpositionGeom[i];') + if export_bpos: + geom.write('bposition = bpositionGeom[i];') + geom.write(' eyeDir = eyeDirGeom[i];') + if '_Sun' in wrd.world_defs and not '_CSM' in wrd.world_defs and '_ShadowMap' in wrd.world_defs: + geom.write(' lightPosition = lightPositionGeom[i];') + if '_Clusters' in wrd.world_defs and '_ShadowMap' in wrd.world_defs: + geom.write(' wvpposition = wvppositionGeom[i];') + geom.write(' gl_Position = voxposition[i];') + geom.write(' EmitVertex();') + geom.write('}') + geom.write('EndPrimitive();') + + frag.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') + frag.add_uniform('int clipmapLevel', '_clipmapLevel') + + frag.write('vec3 uvw = (P - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution);') + 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(wnormal);') + 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 clipmap_pixel = uvw * voxelgiResolution;') + frag.write('vec3 clipmap_uvw_center = (clipmap_pixel + 0.5) / voxelgiResolution;') + frag.write('vec3 voxel_center = clipmap_uvw_center * 2.0 - 1.0;') + frag.write('float voxel_size = float(clipmaps[int(clipmapLevel * 10)]);') + frag.write('voxel_center *= voxel_size;') + frag.write('voxel_center *= voxelgiResolution.x;') + frag.write('voxel_center += vec3(') + frag.write(' clipmaps[clipmapLevel * 10 + 4],') + frag.write(' clipmaps[clipmapLevel * 10 + 5],') + frag.write(' clipmaps[clipmapLevel * 10 + 6]);') + + frag.write('vec3 voxel_aabb[2];') + frag.write('voxel_aabb[0] = voxel_center;') + frag.write('voxel_aabb[1] = vec3(voxel_size);') + frag.write('vec3 triangle_aabb[2];') + frag.write('AABBfromMinMax(triangle_aabb, aabb_min, aabb_max);') + frag.write('if (!IntersectAABB(voxel_aabb, triangle_aabb))') + frag.write(' return;') + + frag.write('vec3 albedo = surfaceAlbedo(basecol, metallic);') + frag.write('vec3 f0 = surfaceF0(basecol, metallic);') + + vert.add_uniform('vec3 eye', '_cameraPosition') + vert.add_out('vec3 eyeDirGeom') + vert.write('eyeDirGeom = eye - voxpositionGeom;') + frag.write_attrib('vec3 vVec = normalize(eyeDir);') + frag.write_attrib('float dotNV = max(dot(N, vVec), 0.0);') + + if '_Brdf' in wrd.world_defs: + frag.add_uniform('sampler2D senvmapBrdf', link='$brdf.png') + frag.write('vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy;') + + if '_Irr' in wrd.world_defs: + frag.add_include('std/shirr.glsl') + frag.add_uniform('vec4 shirr[7]', link='_envmapIrradiance') + frag.write('vec3 envl = shIrradiance(N, shirr);') + if '_EnvTex' in wrd.world_defs: + frag.write('envl /= PI;') + else: + frag.write('vec3 envl = vec3(0.0);') + + if '_Rad' in wrd.world_defs: + frag.add_uniform('sampler2D senvmapRadiance', link='_envmapRadiance') + frag.add_uniform('int envmapNumMipmaps', link='_envmapNumMipmaps') + frag.write('vec3 reflectionWorld = reflect(-vVec, N);') + frag.write('float lod = getMipFromRoughness(roughness, envmapNumMipmaps);') + frag.write('vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;') + + if '_EnvLDR' in wrd.world_defs: + frag.write('envl = pow(envl, vec3(2.2));') + if '_Rad' in wrd.world_defs: + frag.write('prefilteredColor = pow(prefilteredColor, vec3(2.2));') + + frag.write('envl *= albedo;') + + if '_Brdf' in wrd.world_defs: + frag.write('vec3 F = f0 + (vec3(1.0) - f0) * pow(1.0 - abs(dot(N, vVec)), 5.0);') + frag.write('envl.rgb *= 1.0 - F;') + if '_Rad' in wrd.world_defs: + frag.write('envl += prefilteredColor * F;') + elif '_EnvCol' in wrd.world_defs: + frag.add_uniform('vec3 backgroundCol', link='_backgroundCol') + frag.write('envl += backgroundCol * F;') + + frag.add_uniform('float envmapStrength', link='_envmapStrength') + frag.write('envl *= envmapStrength * occlusion;') + + frag.add_include('std/light.glsl') + is_shadows = '_ShadowMap' in wrd.world_defs + is_transparent_shadows = '_ShadowMapTransparent' in wrd.world_defs + is_shadows_atlas = '_ShadowMapAtlas' in wrd.world_defs + is_single_atlas = is_shadows_atlas and '_SingleAtlas' in wrd.world_defs + shadowmap_sun = 'shadowMap' + shadowmap_sun_tr = 'shadowMapTransparent' + if is_shadows_atlas: + shadowmap_sun = 'shadowMapAtlasSun' if not is_single_atlas else 'shadowMapAtlas' + shadowmap_sun_tr = 'shadowMapAtlasSunTransparent' if not is_single_atlas else 'shadowMapAtlasTransparent' + frag.add_uniform('vec2 smSizeUniform', '_shadowMapSize', included=True) + + frag.write('vec3 direct = vec3(0.0);') + + if '_Sun' in wrd.world_defs: + frag.add_uniform('vec3 sunCol', '_sunColor') + frag.add_uniform('vec3 sunDir', '_sunDirection') + frag.write('vec3 svisibility = vec3(1.0);') + frag.write('vec3 sh = normalize(vVec + sunDir);') + frag.write('float sdotNL = dot(N, sunDir);') + frag.write('float sdotNH = dot(N, sh);') + frag.write('float sdotVH = dot(vVec, sh);') + if is_shadows: + frag.add_uniform('bool receiveShadow') + frag.add_uniform(f'sampler2DShadow {shadowmap_sun}', top=True) + if is_transparent_shadows: + frag.add_uniform(f'sampler2D {shadowmap_sun_tr}', top=True) + frag.add_uniform('float shadowsBias', '_sunShadowsBias') + frag.write('if (receiveShadow) {') + if '_CSM' in wrd.world_defs: + frag.add_include('std/shadows.glsl') + frag.add_uniform('vec4 casData[shadowmapCascades * 4 + 4]', '_cascadeData', included=True) + frag.add_uniform('vec3 eye', '_cameraPosition') + frag.write(f'svisibility = shadowTestCascade({shadowmap_sun},') + if is_transparent_shadows: + frag.write(f'{shadowmap_sun_tr},') + frag.write('eye, P + N * shadowsBias * 10, shadowsBias') + if is_transparent_shadows: + frag.write(', false') + frag.write(');') + else: + vert.add_out('vec4 lightPositionGeom') + vert.add_uniform('mat4 LWVP', '_biasLightWorldViewProjectionMatrixSun') + vert.write('lightPositionGeom = LWVP * vec4(pos.xyz, 1.0);') + frag.write('vec3 lPos = lightPosition.xyz / lightPosition.w;') + frag.write('const vec2 smSize = shadowmapSize;') + frag.write(f'svisibility = PCF({shadowmap_sun},') + if is_transparent_shadows: + frag.write(f'{shadowmap_sun_tr},') + frag.write('lPos.xy, lPos.z - shadowsBias, smSize') + if is_transparent_shadows: + frag.write(', false') + frag.write(');') + frag.write('}') # receiveShadow + frag.write('direct += (lambertDiffuseBRDF(albedo, sdotNL) + specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * specular) * sunCol * svisibility;') + # sun + + if '_SinglePoint' in wrd.world_defs: + frag.add_uniform('vec3 pointPos', link='_pointPosition') + frag.add_uniform('vec3 pointCol', link='_pointColor') + if '_Spot' in wrd.world_defs: + frag.add_uniform('vec3 spotDir', link='_spotDirection') + frag.add_uniform('vec3 spotRight', link='_spotRight') + frag.add_uniform('vec4 spotData', link='_spotData') + if is_shadows: + frag.add_uniform('bool receiveShadow') + frag.add_uniform('float pointBias', link='_pointShadowsBias') + if '_Spot' in wrd.world_defs: + # Skip world matrix, already in world-space + frag.add_uniform('mat4 LWVPSpot[1]', link='_biasLightViewProjectionMatrixSpotArray', included=True) + frag.add_uniform('sampler2DShadow shadowMapSpot[1]', included=True) + if is_transparent_shadows: + frag.add_uniform('sampler2D shadowMapSpotTransparent[1]', included=True) + else: + frag.add_uniform('vec2 lightProj', link='_lightPlaneProj', included=True) + frag.add_uniform('samplerCubeShadow shadowMapPoint[1]', included=True) + if is_transparent_shadows: + frag.add_uniform('samplerCube shadowMapPointTransparent[1]', included=True) + frag.write('direct += sampleLight(') + frag.write(' P, N, vVec, dotNV, pointPos, pointCol, albedo, roughness, specular, f0') + if is_shadows: + frag.write(', 0, pointBias, receiveShadow') + if is_transparent_shadows: + frag.write(', opacity != 1.0') + if '_Spot' in wrd.world_defs: + frag.write(', true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight') + frag.write(');') + + if '_Clusters' in wrd.world_defs: + frag.add_include_front('std/clusters.glsl') + frag.add_uniform('vec2 cameraProj', link='_cameraPlaneProj') + frag.add_uniform('vec2 cameraPlane', link='_cameraPlane') + frag.add_uniform('vec4 lightsArray[maxLights * 3]', link='_lightsArray') + frag.add_uniform('sampler2D clustersData', link='_clustersData') + if is_shadows: + frag.add_uniform('bool receiveShadow') + frag.add_uniform('vec2 lightProj', link='_lightPlaneProj', included=True) + if is_shadows_atlas: + if not is_single_atlas: + frag.add_uniform('sampler2DShadow shadowMapAtlasPoint', included=True) + if is_transparent_shadows: + frag.add_uniform('sampler2D shadowMapAtlasPointTransparent', included=True) + else: + frag.add_uniform('sampler2DShadow shadowMapAtlas', top=True) + if is_transparent_shadows: + frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) + frag.add_uniform('vec4 pointLightDataArray[maxLightsCluster]', link='_pointLightsAtlasArray', included=True) + else: + frag.add_uniform('samplerCubeShadow shadowMapPoint[4]', included=True) + frag.add_uniform('samplerCube shadowMapPointTransparent[4]', included=True) + + vert.add_out('vec4 wvppositionGeom') + vert.add_uniform('mat4 VP', '_viewProjectionMatrix') + vert.write('wvppositionGeom = VP * vec4(voxpositionGeom, 1.0);') + # wvpposition.z / wvpposition.w + frag.write('float viewz = linearize((wvpposition.z / wvpposition.w) * 0.5 + 0.5, cameraProj);') + frag.write('int clusterI = getClusterI((wvpposition.xy / wvpposition.w) * 0.5 + 0.5, viewz, cameraPlane);') + frag.write('int numLights = int(texelFetch(clustersData, ivec2(clusterI, 0), 0).r * 255);') + + frag.write('#ifdef HLSL') + frag.write('viewz += texture(clustersData, vec2(0.0)).r * 1e-9;') # TODO: krafix bug, needs to generate sampler + frag.write('#endif') + + if '_Spot' in wrd.world_defs: + frag.add_uniform('vec4 lightsArraySpot[maxLights * 2]', link='_lightsArraySpot') + frag.write('int numSpots = int(texelFetch(clustersData, ivec2(clusterI, 1 + maxLightsCluster), 0).r * 255);') + frag.write('int numPoints = numLights - numSpots;') + if is_shadows: + if is_shadows_atlas: + if not is_single_atlas: + frag.add_uniform('sampler2DShadow shadowMapAtlasSpot', included=True) + if is_transparent_shadows: + frag.add_uniform('sampler2D shadowMapAtlasSpotTransparent', included=True) + else: + frag.add_uniform('sampler2DShadow shadowMapAtlas', top=True) + if is_transparent_shadows: + frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) + else: + frag.add_uniform('sampler2DShadow shadowMapSpot[4]', included=True) + if is_transparent_shadows: + frag.add_uniform('sampler2D shadowMapSpotTransparent[4]', included=True) + frag.add_uniform('mat4 LWVPSpotArray[maxLightsCluster]', link='_biasLightWorldViewProjectionMatrixSpotArray', included=True) + + frag.write('for (int i = 0; i < min(numLights, maxLightsCluster); i++) {') + frag.write('int li = int(texelFetch(clustersData, ivec2(clusterI, i + 1), 0).r * 255);') + frag.write('direct += sampleLightVoxels(') + frag.write(' P,') + frag.write(' N,') + frag.write(' vVec,') + frag.write(' dotNV,') + frag.write(' lightsArray[li * 3].xyz,') # lp + frag.write(' lightsArray[li * 3 + 1].xyz,') # lightCol + frag.write(' albedo,') + frag.write(' roughness,') + frag.write(' specular,') + frag.write(' f0') + if is_shadows: + frag.write('\t, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0') # bias + if is_transparent_shadows: + frag.write('\t, opacity != 1.0') + if '_Spot' in wrd.world_defs: + frag.write('\t, lightsArray[li * 3 + 2].y != 0.0') + frag.write('\t, lightsArray[li * 3 + 2].y') # spot size (cutoff) + frag.write('\t, lightsArraySpot[li * 2].w') # spot blend (exponent) + frag.write('\t, lightsArraySpot[li * 2].xyz') # spotDir + frag.write('\t, vec2(lightsArray[li * 3].w, lightsArray[li * 3 + 1].w)') # scale + frag.write('\t, lightsArraySpot[li * 2 + 1].xyz') # right + frag.write(' );') + frag.write('}') + + frag.write('if (direction_weights.x > 0.0) {') + frag.write(' vec4 basecol_direction = vec4(basecol, opacity) * direction_weights.x;') + frag.write(' vec3 emission_direction = emissionCol * direction_weights.x;') + frag.write(' vec2 normal_direction = encode_oct(N * direction_weights.x) * 0.5 + 0.5;') + frag.write(' vec3 envl_direction = envl * direction_weights.x;') + frag.write(' vec3 light_direction = direct * direction_weights.x;') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, 0)), uint(basecol_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 3)), uint(basecol_direction.a * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 4)), uint(emission_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 5)), uint(emission_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 6)), uint(emission_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 7)), uint(normal_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 8)), uint(normal_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 12)), uint(light_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 13)), uint(light_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 14)), uint(light_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 15)), uint(1));') + frag.write('}') + + frag.write('if (direction_weights.y > 0.0) {') + frag.write(' vec4 basecol_direction = vec4(basecol, opacity) * direction_weights.y;') + frag.write(' vec3 emission_direction = emissionCol * direction_weights.y;') + frag.write(' vec2 normal_direction = encode_oct(N * direction_weights.y) * 0.5 + 0.5;') + frag.write(' vec3 envl_direction = envl * direction_weights.y;') + frag.write(' vec3 light_direction = direct * direction_weights.y;') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, 0)), uint(basecol_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 3)), uint(basecol_direction.a * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 4)), uint(emission_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 5)), uint(emission_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 6)), uint(emission_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 7)), uint(normal_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 8)), uint(normal_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 12)), uint(light_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 13)), uint(light_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 14)), uint(light_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 15)), uint(1));') + frag.write('}') + + frag.write('if (direction_weights.z > 0.0) {') + frag.write(' vec4 basecol_direction = vec4(basecol, opacity) * direction_weights.z;') + frag.write(' vec3 emission_direction = emissionCol * direction_weights.z;') + frag.write(' vec2 normal_direction = encode_oct(N * direction_weights.z) * 0.5 + 0.5;') + frag.write(' vec3 envl_direction = envl * direction_weights.z;') + frag.write(' vec3 light_direction = direct * direction_weights.z;') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, 0)), uint(basecol_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 3)), uint(basecol_direction.a * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 4)), uint(emission_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 5)), uint(emission_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 6)), uint(emission_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 7)), uint(normal_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 8)), uint(normal_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 12)), uint(light_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 13)), uint(light_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 14)), uint(light_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 15)), uint(1));') + frag.write('}') + + return con_voxel + + +def make_ao(context_id): + con_voxel = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'always', 'cull_mode': 'none', 'color_writes_red': [False], 'color_writes_green': [False], 'color_writes_blue': [False], 'color_writes_alpha': [False], 'conservative_raster': False }) + wrd = bpy.data.worlds['Lnx'] + rpdat = lnx.utils.get_rp() + + vert = con_voxel.make_vert() + frag = con_voxel.make_frag() + geom = con_voxel.make_geom() + tesc = None + tese = None + + geom.ins = vert.outs + frag.ins = geom.outs + + frag.add_include('compiled.inc') + geom.add_include('compiled.inc') + frag.add_include('std/math.glsl') + frag.add_include('std/imageatomic.glsl') + frag.add_include('std/aabb.glsl') + frag.write_header('#extension GL_ARB_shader_image_load_store : enable') + + vert.add_include('compiled.inc') + vert.add_uniform('mat4 W', '_worldMatrix') + vert.add_uniform('mat3 N', '_normalMatrix') + + geom.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') + geom.add_uniform('int clipmapLevel', '_clipmapLevel') + + frag.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') + frag.add_uniform('int clipmapLevel', '_clipmapLevel') + + """ + if lnx.utils.get_gapi() == 'direct3d11': + for e in con_voxel.data['vertex_elements']: + if e['name'] == 'nor': + con_voxel.data['vertex_elements'].remove(e) + break + + vert.write('uniform float4x4 W;') + vert.write('uniform float3x3 N;') + vert.write('struct SPIRV_Cross_Input {') + vert.write(' float4 pos : TEXCOORD0;') + vert.write(' float3 nor : NORMAL;') + vert.write('};') + vert.write('struct SPIRV_Cross_Output {') + vert.write(' float4 svpos : SV_POSITION;') + vert.write(' float3 svnor : NORMAL;') + vert.write('};') + vert.write('SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) {') + vert.write(' SPIRV_Cross_Output stage_output;') + vert.write(' stage_output.svpos.xyz = mul(float4(stage_input.pos.xyz, 1.0), W).xyz;') + vert.write(' stage_output.svpos.w = 1.0;') + vert.write(' stage_output.svnor.xyz = normalize(mul(float3(nor.xy, pos.w), N).xyz);') + vert.write(' return stage_output;') + vert.write('}') + + geom.write('uniform float clipmaps[voxelgiClipmapCount * 10];') + geom.write('uniform int clipmapLevel;') + geom.write('struct SPIRV_Cross_Input {') + geom.write(' float4 svpos : SV_POSITION;') + geom.write(' float3 svnor : NORMAL;') + geom.write('};') + geom.write('struct SPIRV_Cross_Output {') + geom.write(' float3 wpos : TEXCOORD0;') + geom.write(' float3 wnor : NORMAL;') + geom.write('};') + geom.write('[maxvertexcount(3)]') + geom.write('void main(triangle SPIRV_Cross_Input stage_input[3], inout TriangleStream output) {') + geom.write(' float3 p1 = stage_input[1].svpos.xyz - stage_input[0].svpos.xyz;') + geom.write(' float3 p2 = stage_input[2].svpos.xyz - stage_input[0].svpos.xyz;') + geom.write(' float3 p = abs(cross(p1, p2));') + geom.write(' for (int i = 0; i < 3; ++i) {') + geom.write(' SPIRV_Cross_Output stage_output;') + geom.write(' stage_output.wpos = (stage_input[i].svpos.xyz + float3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[clipmapLevel * 10]) * voxelgiResolution);') + geom.write(' stage_output.wnor = stage_input[i].svnor.xyz;') + geom.write(' if (p.z > p.x && p.z > p.y) {') + geom.write(' stage_output.svpos = float4(stage_input[i].svpos.x, stage_input[i].svpos.y, 0.0, 1.0);') + geom.write(' }') + geom.write(' else if (p.x > p.y && p.x > p.z) {') + geom.write(' stage_output.svpos = float4(stage_input[i].svpos.y, stage_input[i].svpos.z, 0.0, 1.0);') + geom.write(' }') + geom.write(' else {') + geom.write(' stage_output.svpos = float4(stage_input[i].svpos.x, stage_input[i].svpos.z, 0.0, 1.0);') + geom.write(' }') + geom.write(' output.Append(stage_output);') + geom.write(' }') + geom.write('}') + + frag.add_uniform('layout(r8) writeonly image3D voxels') + frag.write('RWTexture3D voxels;') + frag.write('uniform float clipmaps[voxelgiClipmapCount * 10];') + frag.write('uniform int clipmapLevel;') + + frag.write('struct SPIRV_Cross_Input {') + frag.write(' float3 wpos : TEXCOORD0;') + frag.write(' float3 wnor : NORMAL;') + frag.write('};') + frag.write('struct SPIRV_Cross_Output { float4 FragColor : SV_TARGET0; };') + frag.write('void main(SPIRV_Cross_Input stage_input) {') + frag.write(' float3 uvw = (stage_input.wpos.xyz - float3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution);') + frag.write(' uvw = uvw * 0.5 + 0.5;') + frag.write(' if(any(!saturate(uvw))) return;') + frag.write(' uvw = floor(uvw * voxelgiResolution);') + frag.write(' uint3 face_offsets = uint3(') + frag.write(' stage_input.wnor.x > 0 ? 0 : 1,') + frag.write(' stage_input.wnor.y > 0 ? 2 : 3,') + frag.write(' stage_input.wnor.z > 0 ? 4 : 5') + frag.write(' ) * voxelgiResolution;') + frag.write(' float3 direction_weights = abs(stage_input.wnor);') + + frag.write(' if (direction_weights.x > 0.0) {') + frag.write(' float opac_direction = direction_weights.x;') + frag.write(' voxels[uvw + int3(face_offsets.x, 0, 0))] = float4(opac_direction);') + frag.write(' }') + + frag.write(' if (direction_weights.y > 0.0) {') + frag.write(' float opac_direction = direction_weights.y;') + frag.write(' voxels[uvw + int3(face_offsets.y, 0, 0))] = float4(opac_direction);') + frag.write(' }') + + frag.write(' if (direction_weights.z > 0.0) {') + frag.write(' float opac_direction = direction_weights.z;') + frag.write(' voxels[uvw + int3(face_offsets.z, 0, 0))] = float4(opac_direction);') + frag.write(' }') + frag.write('}') + else: + """ + frag.add_uniform('layout(r32ui) uimage3D voxels') + + vert.add_out('vec3 voxpositionGeom') + vert.add_out('vec3 voxnormalGeom') + + vert.write('voxpositionGeom = vec3(W * vec4(pos.xyz, 1.0));') + vert.write('voxnormalGeom = normalize(N * vec3(nor.xy, pos.w));') + + geom.add_out('vec4 voxposition[3]') + geom.add_out('vec3 P') + geom.add_out('vec3 voxnormal') + geom.add_out('vec3 aabb_min') + geom.add_out('vec3 aabb_max') + + geom.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') + geom.add_uniform('int clipmapLevel', '_clipmapLevel') + + geom.write('aabb_min = min(voxpositionGeom[0].xyz, min(voxpositionGeom[1].xyz, voxpositionGeom[2].xyz));') + geom.write('aabb_max = max(voxpositionGeom[0].xyz, max(voxpositionGeom[1].xyz, voxpositionGeom[2].xyz));') + + geom.write('vec3 facenormal = abs(voxnormalGeom[0] + voxnormalGeom[1] + voxnormalGeom[2]);') + geom.write('uint maxi = facenormal[1] > facenormal[0] ? 1 : 0;') + geom.write('maxi = facenormal[2] > facenormal[maxi] ? 2 : maxi;') + + geom.write('for (uint i = 0; i < 3; ++i) {') + geom.write(' voxposition[i].xyz = (voxpositionGeom[i] - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]));') + geom.write(' if (maxi == 0)') + geom.write(' {') + geom.write(' voxposition[i].xyz = voxposition[i].zyx;') + geom.write(' }') + geom.write(' else if (maxi == 1)') + geom.write(' {') + geom.write(' voxposition[i].xyz = voxposition[i].xzy;') + geom.write(' }') + geom.write('}') + + geom.write('vec2 side0N = normalize(voxposition[1].xy - voxposition[0].xy);') + geom.write('vec2 side1N = normalize(voxposition[2].xy - voxposition[1].xy);') + geom.write('vec2 side2N = normalize(voxposition[0].xy - voxposition[2].xy);') + geom.write('voxposition[0].xy += normalize(side2N - side0N);') + geom.write('voxposition[1].xy += normalize(side0N - side1N);') + geom.write('voxposition[2].xy += normalize(side1N - side2N);') + + geom.write('for (uint i = 0; i < 3; ++i) {') + geom.write(' voxposition[i].xy /= voxelgiResolution.xy;') + geom.write(' voxposition[i].zw = vec2(1.0);') + geom.write(' P = voxpositionGeom[i];') + geom.write(' voxnormal = voxnormalGeom[i];') + geom.write(' gl_Position = voxposition[i];') + geom.write(' EmitVertex();') + geom.write('}') + geom.write('EndPrimitive();') + + frag.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') + frag.add_uniform('int clipmapLevel', '_clipmapLevel') + + frag.write('vec3 uvw = (P - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution);') + 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('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 clipmap_pixel = uvw * voxelgiResolution;') + frag.write('vec3 clipmap_uvw_center = (clipmap_pixel + 0.5) / voxelgiResolution;') + frag.write('vec3 voxel_center = clipmap_uvw_center * 2.0 - 1.0;') + frag.write('float voxel_size = float(clipmaps[int(clipmapLevel * 10)]);') + frag.write('voxel_center *= voxel_size;') + frag.write('voxel_center *= voxelgiResolution.x;') + frag.write('voxel_center += vec3(') + frag.write(' clipmaps[clipmapLevel * 10 + 4],') + frag.write(' clipmaps[clipmapLevel * 10 + 5],') + frag.write(' clipmaps[clipmapLevel * 10 + 6]);') + + frag.write('vec3 voxel_aabb[2];') + frag.write('voxel_aabb[0] = voxel_center;') + frag.write('voxel_aabb[1] = vec3(voxel_size);') + frag.write('vec3 triangle_aabb[2];') + frag.write('AABBfromMinMax(triangle_aabb, aabb_min, aabb_max);') + frag.write('if (!IntersectAABB(voxel_aabb, triangle_aabb))') + frag.write(' return;') + + frag.write('if (direction_weights.x > 0.0) {') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, 0)), uint(direction_weights.x * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x)), uint(1));') + frag.write('}') + + frag.write('if (direction_weights.y > 0.0) {') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, 0)), uint(direction_weights.y * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x)), uint(1));') + frag.write('}') + + frag.write('if (direction_weights.z > 0.0) {') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, 0)), uint(direction_weights.z * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x)), uint(1));') + frag.write('}') + + return con_voxel diff --git a/leenkx/blender/lnx/props.py b/leenkx/blender/lnx/props.py index 7eca246..87afd2b 100644 --- a/leenkx/blender/lnx/props.py +++ b/leenkx/blender/lnx/props.py @@ -320,6 +320,7 @@ def init_properties(): name="Assertion Level", description="Ignore all assertions below this level (assertions are turned off completely for published builds)", default='Warning', update=assets.invalidate_compiler_cache) bpy.types.World.lnx_assert_quit = BoolProperty(name="Quit On Assertion Fail", description="Whether to close the game when an 'Error' level assertion fails", default=False, update=assets.invalidate_compiler_cache) bpy.types.World.lnx_live_patch = BoolProperty(name="Live Patch", description="Live patching for Krom", default=False) + bpy.types.World.lnx_render_viewport = BoolProperty(name="Viewport Render", description="Viewport rendering", default=False) bpy.types.World.lnx_clear_on_compile = BoolProperty(name="Clear Console", description="Clears the system console on compile", default=False) bpy.types.World.lnx_play_camera = EnumProperty( items=[('Scene', 'Scene', 'Scene'), diff --git a/leenkx/blender/lnx/props_renderpath.py b/leenkx/blender/lnx/props_renderpath.py index 29066a8..1e19a5d 100644 --- a/leenkx/blender/lnx/props_renderpath.py +++ b/leenkx/blender/lnx/props_renderpath.py @@ -65,8 +65,8 @@ def update_preset(self, context): rpdat.rp_background = 'World' rpdat.rp_stereo = False rpdat.rp_voxelgi_resolution = '32' - rpdat.lnx_voxelgi_size = 0.25 - rpdat.rp_voxels = 'Voxel AO' + rpdat.lnx_voxelgi_size = 0.125 + rpdat.rp_voxels = 'Voxel GI' rpdat.rp_render_to_texture = True rpdat.rp_supersampling = '1' rpdat.rp_antialiasing = 'SMAA' @@ -142,8 +142,8 @@ def update_preset(self, context): rpdat.rp_stereo = False rpdat.rp_voxels = 'Voxel GI' rpdat.rp_voxelgi_resolution = '64' - rpdat.lnx_voxelgi_size = 0.25 - rpdat.lnx_voxelgi_step = 0.25 + rpdat.lnx_voxelgi_size = 0.125 + rpdat.lnx_voxelgi_step = 0.01 rpdat.lnx_voxelgi_revoxelize = False rpdat.lnx_voxelgi_camera = False rpdat.rp_voxelgi_emission = False @@ -152,7 +152,7 @@ def update_preset(self, context): rpdat.rp_antialiasing = 'TAA' rpdat.rp_compositornodes = True rpdat.rp_volumetriclight = False - rpdat.rp_ssgi = 'RTAO' + rpdat.rp_ssgi = 'SSGI' rpdat.lnx_ssrs = False rpdat.lnx_micro_shadowing = True rpdat.rp_ssr = True @@ -330,6 +330,7 @@ class LnxRPListItem(bpy.types.PropertyGroup): rp_shadowmap_atlas: BoolProperty(name="Shadow Map Atlasing", description="Group shadow maps of lights of the same type in the same texture", default=False, update=update_renderpath) rp_shadowmap_atlas_single_map: BoolProperty(name="Shadow Map Atlas single map", description="Use a single texture for all different light types.", default=False, update=update_renderpath) rp_shadowmap_atlas_lod: BoolProperty(name="Shadow Map Atlas LOD (Experimental)", description="When enabled, the size of the shadow map will be determined on runtime based on the distance of the light to the camera", default=False, update=update_renderpath) + rp_shadowmap_transparent: BoolProperty(name="Transparency", description="Enable shadows for transparent objects", default=False, update=update_renderpath) rp_shadowmap_atlas_lod_subdivisions: EnumProperty( items=[('2', '2', '2'), ('3', '3', '3'), @@ -391,7 +392,8 @@ class LnxRPListItem(bpy.types.PropertyGroup): rp_ssgi: EnumProperty( items=[('Off', 'No AO', 'Off'), ('SSAO', 'SSAO', 'Screen space ambient occlusion'), - ('RTAO', 'RTAO', 'Ray-traced ambient occlusion') + ('SSGI', 'SSGI', 'Screen space global illumination') + #('RTAO', 'RTAO', 'Ray-traced ambient occlusion') # ('RTGI', 'RTGI', 'Ray-traced global illumination') ], name="SSGI", description="Screen space global illumination", default='SSAO', update=update_renderpath) @@ -508,7 +510,7 @@ class LnxRPListItem(bpy.types.PropertyGroup): ('1', '1', '1'), ('2', '2', '2')], name="Bounces", description="Trace multiple light bounces", default='1', update=update_renderpath) - lnx_voxelgi_clipmap_count: IntProperty(name="Clipmap count", description="Number of clipmaps", default=3, update=assets.invalidate_compiled_data) + lnx_voxelgi_clipmap_count: IntProperty(name="Clipmap count", description="Number of clipmaps", default=5, update=assets.invalidate_compiled_data) lnx_voxelgi_temporal: BoolProperty(name="Temporal Filter", description="Use temporal filtering to stabilize voxels", default=False, update=assets.invalidate_shader_cache) lnx_voxelgi_shadows: BoolProperty(name="Shadows", description="Use voxels to render shadows", default=False, update=update_renderpath) lnx_samples_per_pixel: EnumProperty( @@ -530,9 +532,10 @@ class LnxRPListItem(bpy.types.PropertyGroup): lnx_voxelgi_spec: FloatProperty(name="Reflection", description="", default=1.0, update=assets.invalidate_shader_cache) lnx_voxelgi_refr: FloatProperty(name="Refraction", description="", default=1.0, update=assets.invalidate_shader_cache) lnx_voxelgi_shad: FloatProperty(name="Shadows", description="Contrast for voxels shadows", default=1.0, update=assets.invalidate_shader_cache) + lnx_voxelgi_env: FloatProperty(name="Environment", description="", default=1.0, update=assets.invalidate_shader_cache) lnx_voxelgi_occ: FloatProperty(name="Occlusion", description="", default=1.0, update=assets.invalidate_shader_cache) lnx_voxelgi_size: FloatProperty(name="Size", description="Voxel size", default=0.25, update=assets.invalidate_shader_cache) - lnx_voxelgi_step: FloatProperty(name="Step", description="Step size", default=0.25, update=assets.invalidate_shader_cache) + lnx_voxelgi_step: FloatProperty(name="Step", description="Step size", default=1.0, update=assets.invalidate_shader_cache) lnx_voxelgi_range: FloatProperty(name="Range", description="Maximum range", default=100.0, update=assets.invalidate_shader_cache) lnx_voxelgi_offset: FloatProperty(name="Offset", description="Multiplicative Offset for dealing with self occlusion", default=1.0, update=assets.invalidate_shader_cache) lnx_voxelgi_aperture: FloatProperty(name="Aperture", description="Cone aperture for shadow trace", default=0.0, update=assets.invalidate_shader_cache) @@ -545,15 +548,17 @@ class LnxRPListItem(bpy.types.PropertyGroup): lnx_water_density: FloatProperty(name="Density", default=1.0, update=assets.invalidate_shader_cache) lnx_water_refract: FloatProperty(name="Refract", default=1.0, update=assets.invalidate_shader_cache) lnx_water_reflect: FloatProperty(name="Reflect", default=1.0, update=assets.invalidate_shader_cache) - lnx_ssgi_strength: FloatProperty(name="Strength", default=1.0, update=assets.invalidate_shader_cache) - lnx_ssgi_radius: FloatProperty(name="Radius", default=1.0, update=assets.invalidate_shader_cache) + lnx_ssgi_strength: FloatProperty(name="Strength", default=1.250, update=assets.invalidate_shader_cache) + lnx_ssgi_radius: FloatProperty(name="Radius", default=0.750, update=assets.invalidate_shader_cache) lnx_ssgi_step: FloatProperty(name="Step", default=2.0, update=assets.invalidate_shader_cache) - lnx_ssgi_max_steps: IntProperty(name="Max Steps", default=8, update=assets.invalidate_shader_cache) + lnx_ssgi_samples: IntProperty(name="Samples", default=32, update=assets.invalidate_shader_cache) + """ lnx_ssgi_rays: EnumProperty( items=[('9', '9', '9'), ('5', '5', '5'), ], name="Rays", description="Number of rays to trace for RTAO", default='5', update=assets.invalidate_shader_cache) + """ lnx_ssgi_half_res: BoolProperty(name="Half Res", description="Trace in half resolution", default=False, update=assets.invalidate_shader_cache) lnx_bloom_threshold: FloatProperty(name="Threshold", description="Brightness above which a pixel is contributing to the bloom effect", min=0, default=0.8, update=assets.invalidate_shader_cache) lnx_bloom_knee: FloatProperty(name="Knee", description="Smoothen transition around the threshold (higher values = smoother transition)", min=0, max=1, default=0.5, update=assets.invalidate_shader_cache) diff --git a/leenkx/blender/lnx/props_ui.py b/leenkx/blender/lnx/props_ui.py index 50af3e3..1c0c555 100644 --- a/leenkx/blender/lnx/props_ui.py +++ b/leenkx/blender/lnx/props_ui.py @@ -1736,6 +1736,7 @@ class LNX_PT_RenderPathShadowsPanel(bpy.types.Panel): col.prop(rpdat, 'rp_shadowmap_cube') layout.prop(rpdat, 'rp_shadowmap_cascade') layout.prop(rpdat, 'rp_shadowmap_cascades') + layout.prop(rpdat, 'rp_shadowmap_transparent') col = layout.column() col2 = col.column() col2.enabled = rpdat.rp_shadowmap_cascades != '1' @@ -1867,7 +1868,7 @@ class LNX_PT_RenderPathVoxelsPanel(bpy.types.Panel): col3.enabled = rpdat.rp_voxels == 'Voxel AO' col.prop(rpdat, 'lnx_voxelgi_shadows', text='Shadows') col2.prop(rpdat, 'lnx_voxelgi_refract', text='Refraction') - col.prop(rpdat, 'lnx_voxelgi_clipmap_count') + #col.prop(rpdat, 'lnx_voxelgi_clipmap_count') #col.prop(rpdat, 'lnx_voxelgi_cones') col.prop(rpdat, 'rp_voxelgi_resolution') col.prop(rpdat, 'lnx_voxelgi_size') @@ -1881,9 +1882,10 @@ class LNX_PT_RenderPathVoxelsPanel(bpy.types.Panel): col2.prop(rpdat, 'lnx_voxelgi_spec') col2.prop(rpdat, 'lnx_voxelgi_refr') col.prop(rpdat, 'lnx_voxelgi_shad') + col.prop(rpdat, 'lnx_voxelgi_env') col.prop(rpdat, 'lnx_voxelgi_occ') col.label(text="Ray") - col.prop(rpdat, 'lnx_voxelgi_offset') + #col.prop(rpdat, 'lnx_voxelgi_offset') col.prop(rpdat, 'lnx_voxelgi_step') col.prop(rpdat, 'lnx_voxelgi_range') #col.prop(rpdat, 'lnx_voxelgi_aperture') @@ -1974,10 +1976,10 @@ class LNX_PT_RenderPathPostProcessPanel(bpy.types.Panel): sub = col.column() sub.enabled = rpdat.rp_ssgi != 'Off' sub.prop(rpdat, 'lnx_ssgi_half_res') - sub.prop(rpdat, 'lnx_ssgi_rays') + #sub.prop(rpdat, 'lnx_ssgi_rays') sub.prop(rpdat, 'lnx_ssgi_radius') sub.prop(rpdat, 'lnx_ssgi_strength') - sub.prop(rpdat, 'lnx_ssgi_max_steps') + sub.prop(rpdat, 'lnx_ssgi_samples') layout.separator() row = layout.row() diff --git a/leenkx/blender/lnx/write_data.py b/leenkx/blender/lnx/write_data.py index e3bd2ec..438fd22 100644 --- a/leenkx/blender/lnx/write_data.py +++ b/leenkx/blender/lnx/write_data.py @@ -207,6 +207,8 @@ project.addSources('Sources'); # get instantiated khafile.write("""project.addParameter("--macro include('leenkx.logicnode')");\n""") + if wrd.lnx_render_viewport: + assets.add_khafile_def('lnx_render_viewport') import_traits = list(set(import_traits)) for i in range(0, len(import_traits)): khafile.write("project.addParameter('" + import_traits[i] + "');\n") @@ -625,32 +627,18 @@ def write_compiledglsl(defs, make_variants): idx_emission = 2 idx_refraction = 2 + if '_gbuffer2' in wrd.world_defs: f.write('#define GBUF_IDX_2 2\n') idx_emission += 1 idx_refraction += 1 - - # Special case for WebGL with both TAA and SSRefraction - webgl_with_taa_refr = ('_kha_webgl' in wrd.world_defs and - ('_SSRefraction' in wrd.world_defs or '_VoxelRefract' in wrd.world_defs) and - ('_TAA' in wrd.world_defs or '_SMAA' in wrd.world_defs)) - - if webgl_with_taa_refr: - # WebGL needs refraction to come before emission for correct rendering - if '_SSRefraction' in wrd.world_defs or '_VoxelRefract' in wrd.world_defs: - f.write(f'#define GBUF_IDX_REFRACTION {idx_emission}\n') - idx_emission += 1 - - if '_EmissionShaded' in wrd.world_defs: - f.write(f'#define GBUF_IDX_EMISSION {idx_emission}\n') - else: - # Standard order for all other platforms - if '_EmissionShaded' in wrd.world_defs: - f.write(f'#define GBUF_IDX_EMISSION {idx_emission}\n') - idx_refraction += 1 - if '_SSRefraction' in wrd.world_defs or '_VoxelRefract' in wrd.world_defs: - f.write(f'#define GBUF_IDX_REFRACTION {idx_refraction}\n') + if '_EmissionShaded' in wrd.world_defs: + f.write(f'#define GBUF_IDX_EMISSION {idx_emission}\n') + idx_refraction += 1 + + if '_SSRefraction' in wrd.world_defs or '_VoxelRefract' in wrd.world_defs: + f.write(f'#define GBUF_IDX_REFRACTION {idx_refraction}\n') f.write("""#if defined(HLSL) || defined(METAL) #define _InvY @@ -684,16 +672,16 @@ const float waterReflect = """ + str(round(rpdat.lnx_water_reflect * 100) / 100) f'const float ditherStrengthValue = {rpdat.lnx_dithering_strength};\n' ) - if rpdat.rp_ssgi == 'SSAO' or rpdat.rp_ssgi == 'RTAO' or rpdat.rp_volumetriclight: + if rpdat.rp_ssgi == 'SSAO' or rpdat.rp_ssgi == 'SSGI' or rpdat.rp_ssgi == 'RTAO' or rpdat.rp_volumetriclight: f.write( """const float ssaoRadius = """ + str(round(rpdat.lnx_ssgi_radius * 100) / 100) + """; const float ssaoStrength = """ + str(round(rpdat.lnx_ssgi_strength * 100) / 100) + """; const float ssaoScale = """ + ("2.0" if rpdat.lnx_ssgi_half_res else "20.0") + """; """) - if rpdat.rp_ssgi == 'RTGI' or rpdat.rp_ssgi == 'RTAO': + if rpdat.rp_ssgi == 'RTGI' or rpdat.rp_ssgi == 'RTAO' or rpdat.rp_ssgi == 'SSGI' : f.write( -"""const int ssgiMaxSteps = """ + str(rpdat.lnx_ssgi_max_steps) + """; +"""const int ssgiSamples = """ + str(rpdat.lnx_ssgi_samples) + """; const float ssgiRayStep = 0.005 * """ + str(round(rpdat.lnx_ssgi_step * 100) / 100) + """; const float ssgiStrength = """ + str(round(rpdat.lnx_ssgi_strength * 100) / 100) + """; """) @@ -840,6 +828,7 @@ const float voxelgiRange = """ + str(round(rpdat.lnx_voxelgi_range * 100) / 100) const float voxelgiOffset = """ + str(round(rpdat.lnx_voxelgi_offset * 1000) / 1000) + """; const float voxelgiAperture = """ + str(round(rpdat.lnx_voxelgi_aperture * 100) / 100) + """; const float voxelgiShad = """ + str(round(rpdat.lnx_voxelgi_shad * 100) / 100) + """; +const float voxelgiEnv = """ + str(round(rpdat.lnx_voxelgi_env * 100) / 100) + """; """) if rpdat.rp_voxels == 'Voxel GI': f.write("""