From 6fcd63ed64dffa6169be2db56fafbefe8b426993 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 2 Oct 2018 15:08:39 +0200 Subject: [PATCH] Improved acnee issues --- .../src/gpu/gl/GLTexelFormat.cpp | 9 +++- .../src/AmbientOcclusionEffect.cpp | 8 ++-- libraries/render-utils/src/ssao.slh | 45 +++++++++++++++---- .../render-utils/src/ssao_buildNormals.slf | 4 +- .../render-utils/src/ssao_makeOcclusion.slf | 12 ++--- 5 files changed, 52 insertions(+), 26 deletions(-) diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLTexelFormat.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLTexelFormat.cpp index 4d94f8d8e7..fef823718f 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLTexelFormat.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLTexelFormat.cpp @@ -329,6 +329,8 @@ GLenum GLTexelFormat::evalGLTexelFormatInternal(const gpu::Element& dstFormat) { result = GL_RGBA8_SNORM; break; case gpu::NINT2_10_10_10: + result = GL_RGB10_A2; + break; case gpu::NUINT32: case gpu::NINT32: case gpu::COMPRESSED: @@ -729,9 +731,9 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E texel.internalFormat = GL_DEPTH_COMPONENT24; break; } + case gpu::NINT2_10_10_10: case gpu::COMPRESSED: case gpu::NUINT2: - case gpu::NINT2_10_10_10: case gpu::NUM_TYPES: { // quiet compiler Q_UNREACHABLE(); } @@ -893,9 +895,12 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E texel.format = GL_RGBA; texel.internalFormat = GL_RGBA2; break; + case gpu::NINT2_10_10_10: + texel.format = GL_RGBA; + texel.internalFormat = GL_RGB10_A2; + break; case gpu::NUINT32: case gpu::NINT32: - case gpu::NINT2_10_10_10: case gpu::COMPRESSED: case gpu::NUM_TYPES: // quiet compiler Q_UNREACHABLE(); diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 8c56d17b71..9110285fc9 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -115,7 +115,7 @@ void AmbientOcclusionFramebuffer::allocate() { } auto width = sideSize.x; auto height = sideSize.y; - auto format = gpu::Element::COLOR_RGBA_32; + auto format = gpu::Element{ gpu::VEC4, gpu::NINT2_10_10_10, gpu::RGBA }; _normalTexture = gpu::Texture::createRenderBuffer(format, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT, gpu::Sampler::WRAP_CLAMP)); _normalFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("ssaoNormals")); @@ -206,10 +206,10 @@ gpu::TexturePointer AmbientOcclusionFramebuffer::getNormalTexture() { AmbientOcclusionEffectConfig::AmbientOcclusionEffectConfig() : render::GPUJobConfig::Persistent(QStringList() << "Render" << "Engine" << "Ambient Occlusion", false), - radius{ 0.5f }, + radius{ 0.7f }, perspectiveScale{ 1.0f }, - obscuranceLevel{ 0.25f }, - falloffAngle{ 0.4f }, + obscuranceLevel{ 0.15f }, + falloffAngle{ 0.1f }, edgeSharpness{ 1.0f }, blurDeviation{ 2.5f }, numSpiralTurns{ 7.0f }, diff --git a/libraries/render-utils/src/ssao.slh b/libraries/render-utils/src/ssao.slh index 9ae32695c5..09c3cd3a66 100644 --- a/libraries/render-utils/src/ssao.slh +++ b/libraries/render-utils/src/ssao.slh @@ -287,8 +287,17 @@ float getZEyeAtUV(ivec4 side, vec2 texCoord, int level, ivec2 texelOffset) { return getZEyeAtUV(texCoord, level, texelOffset); } +vec3 packNormal(vec3 normal) { + vec3 absNormal = abs(normal); + return 0.5 + normal * 0.5 / max(absNormal.x, max(absNormal.y, absNormal.z)); +} + +vec3 unpackNormal(vec3 packedNormal) { + return normalize(packedNormal*2.0 - 1.0); +} + vec3 getNormalEyeAtUV(vec2 texCoord, int level) { - return normalize(textureLod(normalTex, texCoord, level).xyz*2.0 - vec3(1.0)); + return unpackNormal(textureLod(normalTex, texCoord, level).xyz); } vec3 getNormalEyeAtUV(ivec4 side, vec2 texCoord, int level) { @@ -297,7 +306,11 @@ vec3 getNormalEyeAtUV(ivec4 side, vec2 texCoord, int level) { } vec3 getNormalEyeAtPixel(ivec2 pixel, int level) { - return normalize(texelFetch(normalTex, pixel, level).xyz*2.0 - vec3(1.0)); + return unpackNormal(texelFetch(normalTex, pixel, level).xyz); +} + +vec2 snapToTexel(vec2 uv, vec2 pixelSize) { + return (floor(uv * pixelSize - 0.5) + 0.5) / pixelSize; } int evalMipFromRadius(float radius) { @@ -418,12 +431,12 @@ float computeWeightedHorizon(float horizonLimit, float distanceSquared) { } <@func computeHorizon()@> - if (fragUVPos.x<0 || fragUVPos.y<0 || fragUVPos.x>=1.0 || fragUVPos.y>=1.0) { + if (tapUVPos.x<0 || tapUVPos.y<0 || tapUVPos.x>=1.0 || tapUVPos.y>=1.0) { // Early exit because we've hit the borders of the frame break; } - vec2 tapMipZ = fetchTap(side, fragUVPos, radius); - vec3 tapPositionES = evalEyePositionFromZeye(side.x, tapMipZ.y, fragUVPos); + vec2 tapMipZ = fetchTap(side, tapUVPos, radius); + vec3 tapPositionES = evalEyePositionFromZeye(side.x, tapMipZ.y, tapUVPos); vec3 deltaVec = tapPositionES - fragPositionES; float distanceSquared = dot(deltaVec, deltaVec); float deltaDotNormal = dot(deltaVec, fragFrameES.normal); @@ -460,16 +473,18 @@ float computeWeightedHorizon(float horizonLimit, float distanceSquared) { #define HBAO_HORIZON_SEARCH_CONSTANT_STEP 0 float computeOcclusion(ivec4 side, vec2 fragUVPos, vec3 fragPositionES, TBNFrame fragFrameES, vec2 searchDir, float searchRadius, int stepCount) { + float occlusion = 0.0; #if HBAO_USE_COS_ANGLE float horizonLimit = getFalloffCosAngle(); - float occlusion = 0.0; #else float horizonLimit = getFalloffSinAngle(); #endif if (stepCount>0) { vec2 deltaTapUV = searchDir / float(stepCount); + vec2 tapUVPos; float deltaRadius = searchRadius / float(stepCount); + vec2 sideDepthSize = getDepthTextureSideSize(0); #if HBAO_HORIZON_SEARCH_CONSTANT_STEP float radius = 0.0; @@ -478,6 +493,7 @@ float computeOcclusion(ivec4 side, vec2 fragUVPos, vec3 fragPositionES, TBNFrame for (stepIndex=0 ; stepIndex } @@ -488,6 +504,7 @@ float computeOcclusion(ivec4 side, vec2 fragUVPos, vec3 fragPositionES, TBNFrame while (radius<=searchRadius) { fragUVPos += deltaTapUV; + tapUVPos = snapToTexel(fragUVPos, sideDepthSize); <$computeHorizon()$> @@ -495,6 +512,7 @@ float computeOcclusion(ivec4 side, vec2 fragUVPos, vec3 fragPositionES, TBNFrame mipLevel = tapMipZ.x; deltaRadius *= 2; deltaTapUV *= 2; + sideDepthSize = getDepthTextureSideSize(int(mipLevel)); } radius += deltaRadius; } @@ -511,16 +529,27 @@ float computeOcclusion(ivec4 side, vec2 fragUVPos, vec3 fragPositionES, TBNFrame } float evalVisibilityHBAO(ivec4 side, vec2 fragUVPos, vec2 invSideImageSize, vec2 deltaTap, float diskPixelRadius, - vec3 fragPositionES, TBNFrame fragFrameES) { + vec3 fragPositionES, vec3 fragNormalES) { vec2 pixelSearchVec = deltaTap * diskPixelRadius; vec2 searchDir = pixelSearchVec * invSideImageSize; + vec2 deltaTapUV = deltaTap * invSideImageSize; float obscuranceH1 = 0.0; float obscuranceH2 = 0.0; pixelSearchVec = abs(pixelSearchVec); int stepCount = int(ceil(max(pixelSearchVec.x, pixelSearchVec.y))); + TBNFrame fragFrameES; + + fragFrameES.tangent = vec3(0.0); + fragFrameES.binormal = vec3(0.0); + fragFrameES.normal = fragNormalES; #if HBAO_USE_OVERHANG_HACK || !HBAO_USE_COS_ANGLE - fragFrameES.tangent = normalize(fragFrameES.tangent * deltaTap.x + fragFrameES.binormal * deltaTap.y); + vec3 positionPos = buildPosition(side, fragUVPos + deltaTapUV); + vec3 positionNeg = buildPosition(side, fragUVPos - deltaTapUV); + + fragFrameES.tangent = getMinDelta(fragPositionES, positionPos, positionNeg); + fragFrameES.tangent -= dot(fragNormalES, fragFrameES.tangent) * fragNormalES; + fragFrameES.tangent = normalize(fragFrameES.tangent); #endif // Forward search for h1 obscuranceH1 = computeOcclusion(side, fragUVPos, fragPositionES, fragFrameES, searchDir, diskPixelRadius, stepCount); diff --git a/libraries/render-utils/src/ssao_buildNormals.slf b/libraries/render-utils/src/ssao_buildNormals.slf index 9c183f640c..0dea63ae14 100644 --- a/libraries/render-utils/src/ssao_buildNormals.slf +++ b/libraries/render-utils/src/ssao_buildNormals.slf @@ -37,8 +37,6 @@ void main(void) { // The position and normal of the pixel fragment in Eye space vec3 fragPositionES = buildPosition(side, fragUVPos); vec3 fragNormalES = buildNormal(side, fragUVPos, fragPositionES, deltaDepthUV); - vec3 absFragNormalES = abs(fragNormalES); - fragNormalES /= max(absFragNormalES.z, max(absFragNormalES.x, absFragNormalES.y)); - outFragColor = vec4(vec3(fragNormalES)*0.5 + vec3(0.5), 1.0); + outFragColor = vec4(packNormal(fragNormalES), 1.0); } diff --git a/libraries/render-utils/src/ssao_makeOcclusion.slf b/libraries/render-utils/src/ssao_makeOcclusion.slf index d456b7bb9a..aabc28a326 100644 --- a/libraries/render-utils/src/ssao_makeOcclusion.slf +++ b/libraries/render-utils/src/ssao_makeOcclusion.slf @@ -42,6 +42,8 @@ void main(void) { // From now on, fragUVPos is the UV pos in the side fragUVPos.x = mix(fragUVPos.x, fragUVPos.x * 2.0 - getStereoSide(side), isStereo()); + fragUVPos = snapToTexel(fragUVPos, sideDepthSize); + // The position and normal of the pixel fragment in Eye space vec2 deltaDepthUV = vec2(2.0) / sideDepthSize; vec3 fragPositionES = buildPosition(side, fragUVPos); @@ -55,14 +57,6 @@ void main(void) { diskPixelRadius = min(diskPixelRadius, SSAO_HBAO_MAX_RADIUS); } - TBNFrame fragFrameES; - - fragFrameES.tangent = vec3(0.0); - fragFrameES.binormal = vec3(0.0); - fragFrameES.normal = fragNormalES; -#if HBAO_USE_OVERHANG_HACK || !HBAO_USE_COS_ANGLE - buildTangentBinormal(side, fragUVPos, fragPositionES, fragNormalES, deltaDepthUV, fragFrameES.tangent, fragFrameES.binormal); -#endif // Let's make noise float randomPatternRotationAngle = getAngleDithering(fragPixelPos); @@ -74,7 +68,7 @@ void main(void) { if (isHorizonBased()) { for (int i = 0; i < numSamples; ++i) { vec3 deltaTap = getUnitTapLocation(i, 1.0, randomPatternRotationAngle, PI); - obscuranceSum += evalVisibilityHBAO(side, fragUVPos, deltaDepthUV, deltaTap.xy, diskPixelRadius, fragPositionES, fragFrameES); + obscuranceSum += evalVisibilityHBAO(side, fragUVPos, deltaDepthUV, deltaTap.xy, diskPixelRadius, fragPositionES, fragNormalES); } obscuranceSum *= invNumSamples; #if HBAO_USE_COS_ANGLE