diff --git a/libraries/render-utils/src/ssao.slh b/libraries/render-utils/src/ssao.slh index d34d92276b..17ac229805 100644 --- a/libraries/render-utils/src/ssao.slh +++ b/libraries/render-utils/src/ssao.slh @@ -243,6 +243,32 @@ vec4 fetchTap(ivec4 side, vec2 tapSidePixelPos, float tapRadius, vec2 sideImageS return P; } +vec3 buildPosition(ivec4 side, vec2 fragUVPos, ivec2 depthTexFragPixelPos, ivec2 deltaDepthTexPixel, vec2 uvScale) { + depthTexFragPixelPos += deltaDepthTexPixel; + fragUVPos += deltaDepthTexPixel * uvScale; + float Zeye = getZEyeAtPixel(depthTexFragPixelPos, 0); + return evalEyePositionFromZeye(side.x, Zeye, fragUVPos); +} + +vec3 getMinDiff(vec3 centralPoint, vec3 offsetPoint0, vec3 offsetPoint1) { + vec3 delta0 = offsetPoint0 - centralPoint; + vec3 delta1 = centralPoint - offsetPoint1; + return dot(delta0, delta0) < dot(delta1, delta1) ? delta0 : delta1; +} + +vec3 buildNormal(ivec4 side, vec2 fragUVPos, ivec2 depthTexFragPixelPos, vec3 fragPositionES, ivec2 depthTextureScale, vec2 sideImageSize) { + vec2 uvScale = vec2(1.0) / (sideImageSize * depthTextureScale); + vec3 fragPositionDxPos = buildPosition(side, fragUVPos, depthTexFragPixelPos, ivec2(1,0), uvScale); + vec3 fragPositionDxNeg = buildPosition(side, fragUVPos, depthTexFragPixelPos, ivec2(-1,0), uvScale); + vec3 fragPositionDyPos = buildPosition(side, fragUVPos, depthTexFragPixelPos, ivec2(0,1), uvScale); + vec3 fragPositionDyNeg = buildPosition(side, fragUVPos, depthTexFragPixelPos, ivec2(0,-1), uvScale); + + vec3 fragPositionDx = getMinDiff(fragPositionES, fragPositionDxPos, fragPositionDxNeg); + vec3 fragPositionDy = getMinDiff(fragPositionES, fragPositionDyPos, fragPositionDyNeg); + + return normalize( cross(fragPositionDx, fragPositionDy) ); +} + <@endfunc@> diff --git a/libraries/render-utils/src/ssao_buildNormals.slf b/libraries/render-utils/src/ssao_buildNormals.slf index 8e06d4ffc9..f21a529807 100644 --- a/libraries/render-utils/src/ssao_buildNormals.slf +++ b/libraries/render-utils/src/ssao_buildNormals.slf @@ -26,7 +26,8 @@ void main(void) { ivec2 fragPixelPos = ivec2(fragCoord.xy); // Fetch the z under the pixel (stereo or not) - ivec2 depthTexFragPixelPos = fragPixelPos * getDepthTextureSize(0) / renderSize ; + ivec2 depthTextureScale = getDepthTextureSize(0) / renderSize; + ivec2 depthTexFragPixelPos = fragPixelPos * depthTextureScale; float Zeye = getZEyeAtPixel(depthTexFragPixelPos, 0); // Stereo side info @@ -38,7 +39,7 @@ void main(void) { // The position and normal of the pixel fragment in Eye space vec3 fragPositionES = evalEyePositionFromZeye(side.x, Zeye, fragUVPos); - vec3 fragNormalES = evalEyeNormal(fragPositionES); + vec3 fragNormalES = buildNormal(side, fragUVPos, depthTexFragPixelPos, fragPositionES, depthTextureScale, sideImageSize); vec3 absFragNormalES = abs(fragNormalES); outFragColor = vec4(vec3(fragNormalES)*0.5 + vec3(0.5), 1.0); diff --git a/libraries/render-utils/src/ssao_makeOcclusion.slf b/libraries/render-utils/src/ssao_makeOcclusion.slf index 3db497fdc7..cee5ef6fe3 100644 --- a/libraries/render-utils/src/ssao_makeOcclusion.slf +++ b/libraries/render-utils/src/ssao_makeOcclusion.slf @@ -36,7 +36,8 @@ void main(void) { #endif // Fetch the z under the pixel (stereo or not) - ivec2 depthTexFragPixelPos = fragPixelPos * getDepthTextureSize(0) / renderSize ; + ivec2 depthTextureScale = getDepthTextureSize(0) / renderSize; + ivec2 depthTexFragPixelPos = fragPixelPos * depthTextureScale; float Zeye = getZEyeAtPixel(depthTexFragPixelPos, 0); #if SSAO_USE_QUAD_SPLIT vec3 fragNormalES = getNormalEyeAtPixel(fragPixelPos, 0); @@ -52,7 +53,7 @@ void main(void) { // The position and normal of the pixel fragment in Eye space vec3 fragPositionES = evalEyePositionFromZeye(side.x, Zeye, fragUVPos); #if !SSAO_USE_QUAD_SPLIT - vec3 fragNormalES = evalEyeNormal(fragPositionES); + vec3 fragNormalES = buildNormal(side, fragUVPos, depthTexFragPixelPos, fragPositionES, depthTextureScale, sideImageSize); #endif // Choose the screen-space sample radius