From 3fe9b67e45e43963a91d547a08dbdcb6c4c50261 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 27 May 2016 19:24:56 -0700 Subject: [PATCH 1/2] FIxing the reflection jittering by moving the normal into world space --- libraries/gpu/src/gpu/Transform.slh | 9 +++++++++ libraries/render-utils/src/DeferredGlobalLight.slh | 3 ++- libraries/render-utils/src/model.slv | 2 +- libraries/render-utils/src/model_lightmap.slv | 2 +- libraries/render-utils/src/model_lightmap_normal_map.slv | 4 ++-- libraries/render-utils/src/model_normal_map.slv | 4 ++-- libraries/render-utils/src/overlay3D.slv | 2 +- libraries/render-utils/src/point_light.slf | 2 +- libraries/render-utils/src/sdf_text3D.slv | 2 +- libraries/render-utils/src/simple.slv | 2 +- libraries/render-utils/src/skin_model.slv | 3 +-- libraries/render-utils/src/skin_model_normal_map.slv | 4 ++-- libraries/render-utils/src/spot_light.slf | 2 +- libraries/render-utils/src/standardTransformPNTC.slv | 2 +- 14 files changed, 26 insertions(+), 17 deletions(-) diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 078b19d494..246167e186 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -119,6 +119,15 @@ TransformObject getTransformObject() { } <@endfunc@> +<@func transformModelToWorldDir(cameraTransform, objectTransform, modelDir, worldDir)@> + { // transformModelToEyeDir + vec3 mr0 = <$objectTransform$>._modelInverse[0].xyz; + vec3 mr1 = <$objectTransform$>._modelInverse[1].xyz; + vec3 mr2 = <$objectTransform$>._modelInverse[2].xyz; + + <$worldDir$> = vec3(dot(mr0, <$modelDir$>), dot(mr1, <$modelDir$>), dot(mr2, <$modelDir$>)); + } +<@endfunc@> <@func transformModelToEyeDir(cameraTransform, objectTransform, modelDir, eyeDir)@> { // transformModelToEyeDir diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 7608c8ae08..d29c8bea87 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -66,7 +66,8 @@ vec3 evalGlobalSpecularIrradiance(Light light, vec3 fragEyeDir, vec3 fragNormal, // prepareGlobalLight // Transform directions to worldspace - vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); + // vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); + vec3 fragNormal = vec3((normal)); vec3 fragEyeVector = vec3(invViewMat * vec4(-position, 0.0)); vec3 fragEyeDir = normalize(fragEyeVector); diff --git a/libraries/render-utils/src/model.slv b/libraries/render-utils/src/model.slv index f1989dcf76..825cb66a48 100755 --- a/libraries/render-utils/src/model.slv +++ b/libraries/render-utils/src/model.slv @@ -36,5 +36,5 @@ void main(void) { TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> - <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> + <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$> } diff --git a/libraries/render-utils/src/model_lightmap.slv b/libraries/render-utils/src/model_lightmap.slv index f73b6a02a7..161ceed14c 100755 --- a/libraries/render-utils/src/model_lightmap.slv +++ b/libraries/render-utils/src/model_lightmap.slv @@ -39,6 +39,6 @@ void main(void) { TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> - <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> + <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$> } diff --git a/libraries/render-utils/src/model_lightmap_normal_map.slv b/libraries/render-utils/src/model_lightmap_normal_map.slv index cb333f50e3..5fb60d9227 100755 --- a/libraries/render-utils/src/model_lightmap_normal_map.slv +++ b/libraries/render-utils/src/model_lightmap_normal_map.slv @@ -39,6 +39,6 @@ void main(void) { TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> - <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> - <$transformModelToEyeDir(cam, obj, inTangent.xyz, _tangent)$> + <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$> + <$transformModelToWorldDir(cam, obj, inTangent.xyz, _tangent)$> } diff --git a/libraries/render-utils/src/model_normal_map.slv b/libraries/render-utils/src/model_normal_map.slv index ded37923c2..425dc204d9 100755 --- a/libraries/render-utils/src/model_normal_map.slv +++ b/libraries/render-utils/src/model_normal_map.slv @@ -39,6 +39,6 @@ void main(void) { TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> - <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> - <$transformModelToEyeDir(cam, obj, inTangent.xyz, _tangent)$> + <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$> + <$transformModelToWorldDir(cam, obj, inTangent.xyz, _tangent)$> } diff --git a/libraries/render-utils/src/overlay3D.slv b/libraries/render-utils/src/overlay3D.slv index d39e5a2f01..ee28367413 100644 --- a/libraries/render-utils/src/overlay3D.slv +++ b/libraries/render-utils/src/overlay3D.slv @@ -32,5 +32,5 @@ void main(void) { TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> - <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> + <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$> } diff --git a/libraries/render-utils/src/point_light.slf b/libraries/render-utils/src/point_light.slf index 8c9ff2c8ad..96cf7152d9 100644 --- a/libraries/render-utils/src/point_light.slf +++ b/libraries/render-utils/src/point_light.slf @@ -61,7 +61,7 @@ void main(void) { vec3 fragLightDir = fragLightVec / fragLightDistance; // Eval shading - vec3 fragNormal = vec3(invViewMat * vec4(frag.normal, 0.0)); + vec3 fragNormal = vec3(frag.normal); vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0); vec3 fragEyeDir = normalize(fragEyeVector.xyz); vec4 shading = evalFragShading(fragNormal, fragLightDir, fragEyeDir, frag.metallic, frag.specular, frag.roughness); diff --git a/libraries/render-utils/src/sdf_text3D.slv b/libraries/render-utils/src/sdf_text3D.slv index d8b7587789..29bc1a9e85 100644 --- a/libraries/render-utils/src/sdf_text3D.slv +++ b/libraries/render-utils/src/sdf_text3D.slv @@ -27,5 +27,5 @@ void main() { TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> - <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal.xyz)$> + <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal.xyz)$> } \ No newline at end of file diff --git a/libraries/render-utils/src/simple.slv b/libraries/render-utils/src/simple.slv index d56d1cc8e2..64d3e24192 100644 --- a/libraries/render-utils/src/simple.slv +++ b/libraries/render-utils/src/simple.slv @@ -34,5 +34,5 @@ void main(void) { TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> - <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> + <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$> } \ No newline at end of file diff --git a/libraries/render-utils/src/skin_model.slv b/libraries/render-utils/src/skin_model.slv index c8501b8ddf..c538c8321e 100755 --- a/libraries/render-utils/src/skin_model.slv +++ b/libraries/render-utils/src/skin_model.slv @@ -45,6 +45,5 @@ void main(void) { TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToEyeAndClipPos(cam, obj, position, _position, gl_Position)$> - <$transformModelToEyeDir(cam, obj, interpolatedNormal.xyz, interpolatedNormal.xyz)$> - _normal = interpolatedNormal.xyz; + <$transformModelToWorldDir(cam, obj, interpolatedNormal.xyz, _normal.xyz)$> } diff --git a/libraries/render-utils/src/skin_model_normal_map.slv b/libraries/render-utils/src/skin_model_normal_map.slv index db4b206405..b57a52f2e6 100755 --- a/libraries/render-utils/src/skin_model_normal_map.slv +++ b/libraries/render-utils/src/skin_model_normal_map.slv @@ -50,8 +50,8 @@ void main(void) { TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToEyeAndClipPos(cam, obj, position, _position, gl_Position)$> - <$transformModelToEyeDir(cam, obj, interpolatedNormal.xyz, interpolatedNormal.xyz)$> - <$transformModelToEyeDir(cam, obj, interpolatedTangent.xyz, interpolatedTangent.xyz)$> + <$transformModelToWorldDir(cam, obj, interpolatedNormal.xyz, interpolatedNormal.xyz)$> + <$transformModelToWorldDir(cam, obj, interpolatedTangent.xyz, interpolatedTangent.xyz)$> _normal = interpolatedNormal.xyz; _tangent = interpolatedTangent.xyz; diff --git a/libraries/render-utils/src/spot_light.slf b/libraries/render-utils/src/spot_light.slf index 4191ba3f63..e5bdac1325 100644 --- a/libraries/render-utils/src/spot_light.slf +++ b/libraries/render-utils/src/spot_light.slf @@ -68,7 +68,7 @@ void main(void) { } // Eval shading - vec3 fragNormal = vec3(invViewMat * vec4(frag.normal, 0.0)); + vec3 fragNormal = vec3(frag.normal); vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0); vec3 fragEyeDir = normalize(fragEyeVector.xyz); vec4 shading = evalFragShading(fragNormal, fragLightDir, fragEyeDir, frag.metallic, frag.specular, frag.roughness); diff --git a/libraries/render-utils/src/standardTransformPNTC.slv b/libraries/render-utils/src/standardTransformPNTC.slv index f7e72b6997..0ced5ba6e2 100644 --- a/libraries/render-utils/src/standardTransformPNTC.slv +++ b/libraries/render-utils/src/standardTransformPNTC.slv @@ -30,6 +30,6 @@ void main(void) { TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> - <$transformModelToEyeDir(cam, obj, inNormal.xyz, varNormal)$> + <$transformModelToWorldDir(cam, obj, inNormal.xyz, varNormal)$> varPosition = inPosition.xyz; } \ No newline at end of file From 1dca62f752067786afe90c5ea779c6bc32005f6d Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 1 Jun 2016 17:51:53 -0700 Subject: [PATCH 2/2] Introducing a new technique for normal packing and fixing a bug on the normal buffer format --- .../src/RenderableProceduralItemShader.h | 49 +++++++++----- libraries/render-utils/src/DeferredBuffer.slh | 66 +++++++++++++++++++ .../render-utils/src/DeferredBufferRead.slh | 2 +- .../render-utils/src/DeferredBufferWrite.slh | 24 +------ .../render-utils/src/FramebufferCache.cpp | 5 +- 5 files changed, 107 insertions(+), 39 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableProceduralItemShader.h b/libraries/entities-renderer/src/RenderableProceduralItemShader.h index 1afd3bc608..4762f619bf 100644 --- a/libraries/entities-renderer/src/RenderableProceduralItemShader.h +++ b/libraries/entities-renderer/src/RenderableProceduralItemShader.h @@ -25,24 +25,43 @@ layout(location = 2) out vec4 _fragColor2; // the alpha threshold uniform float alphaThreshold; -uniform sampler2D normalFittingMap; -vec3 bestFitNormal(vec3 normal) { - vec3 absNorm = abs(normal); - float maxNAbs = max(absNorm.z, max(absNorm.x, absNorm.y)); +vec2 signNotZero(vec2 v) { + return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0); +} - vec2 texcoord = (absNorm.z < maxNAbs ? - (absNorm.y < maxNAbs ? absNorm.yz : absNorm.xz) : - absNorm.xy); - texcoord = (texcoord.x < texcoord.y ? texcoord.yx : texcoord.xy); - texcoord.y /= texcoord.x; - vec3 cN = normal / maxNAbs; - float fittingScale = texture(normalFittingMap, texcoord).a; - cN *= fittingScale; - return (cN * 0.5 + 0.5); +vec2 float32x3_to_oct(in vec3 v) { + vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z))); + return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p); } +vec3 oct_to_float32x3(in vec2 e) { + vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y)); + if (v.z < 0) { + v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy); + } + return normalize(v); +} + +vec3 snorm12x2_to_unorm8x3(vec2 f) { + vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0)); + float t = floor(u.y / 256.0); + + return floor(vec3( + u.x / 16.0, + fract(u.x / 16.0) * 256.0 + t, + u.y - t * 256.0 + )) / 255.0; +} + +vec2 unorm8x3_to_snorm12x2(vec3 u) { + u *= 255.0; + u.y *= (1.0 / 16.0); + vec2 s = vec2( u.x * 16.0 + floor(u.y), + fract(u.y) * (16.0 * 256.0) + u.z); + return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0)); +} float mod289(float x) { return x - floor(x * (1.0 / 289.0)) * 289.0; @@ -322,7 +341,7 @@ void main(void) { } vec4 diffuse = vec4(_color.rgb, alpha); - vec4 normal = vec4(normalize(bestFitNormal(_normal)), 0.5); + vec4 normal = vec4(packNormal(normalize(_normal)), 0.5); _fragColor0 = diffuse; _fragColor1 = normal; @@ -355,7 +374,7 @@ void main(void) { float emissiveAmount = getProceduralColors(diffuse, specular, shininess); _fragColor0 = vec4(diffuse.rgb, 1.0); - _fragColor1 = vec4(bestFitNormal(normalize(_normal.xyz)), 1.0 - (emissiveAmount / 2.0)); + _fragColor1 = vec4(packNormal(normalize(_normal.xyz)), 1.0 - (emissiveAmount / 2.0)); _fragColor2 = vec4(specular, shininess / 128.0); } )SCRIBE"; diff --git a/libraries/render-utils/src/DeferredBuffer.slh b/libraries/render-utils/src/DeferredBuffer.slh index aed89b30d0..b9c65a3bff 100755 --- a/libraries/render-utils/src/DeferredBuffer.slh +++ b/libraries/render-utils/src/DeferredBuffer.slh @@ -51,4 +51,70 @@ float packUnlit() { return FRAG_PACK_UNLIT; } + +vec2 signNotZero(vec2 v) { + return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0); +} + +vec2 float32x3_to_oct(in vec3 v) { + vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z))); + return ((v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p); +} + + +vec3 oct_to_float32x3(in vec2 e) { + vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y)); + if (v.z < 0) { + v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy); + } + return normalize(v); +} + +vec3 snorm12x2_to_unorm8x3(vec2 f) { + vec2 u = vec2(round(clamp(f, -1.0, 1.0) * 2047.0 + 2047.0)); + float t = floor(u.y / 256.0); + + return floor(vec3( + u.x / 16.0, + fract(u.x / 16.0) * 256.0 + t, + u.y - t * 256.0 + )) / 255.0; +} + +vec2 unorm8x3_to_snorm12x2(vec3 u) { + u *= 255.0; + u.y *= (1.0 / 16.0); + vec2 s = vec2( u.x * 16.0 + floor(u.y), + fract(u.y) * (16.0 * 256.0) + u.z); + return clamp(s * (1.0 / 2047.0) - 1.0, vec2(-1.0), vec2(1.0)); +} + +uniform sampler2D normalFittingMap; + +vec3 bestFitNormal(vec3 normal) { + vec3 absNorm = abs(normal); + float maxNAbs = max(absNorm.z, max(absNorm.x, absNorm.y)); + + vec2 texcoord = (absNorm.z < maxNAbs ? + (absNorm.y < maxNAbs ? absNorm.yz : absNorm.xz) : + absNorm.xy); + texcoord = (texcoord.x < texcoord.y ? texcoord.yx : texcoord.xy); + texcoord.y /= texcoord.x; + vec3 cN = normal / maxNAbs; + + float fittingScale = texture(normalFittingMap, texcoord).a; + cN *= fittingScale; + + return (cN * 0.5 + 0.5); +} + +vec3 packNormal(in vec3 n) { + return snorm12x2_to_unorm8x3(float32x3_to_oct(n)); +} + +vec3 unpackNormal(in vec3 p) { + return oct_to_float32x3(unorm8x3_to_snorm12x2(p)); +} + + <@endif@> diff --git a/libraries/render-utils/src/DeferredBufferRead.slh b/libraries/render-utils/src/DeferredBufferRead.slh index 569063955d..7714859f5a 100644 --- a/libraries/render-utils/src/DeferredBufferRead.slh +++ b/libraries/render-utils/src/DeferredBufferRead.slh @@ -100,7 +100,7 @@ DeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) { frag.obscurance = texture(obscuranceMap, texcoord).x; // Unpack the normal from the map - frag.normal = normalize(frag.normalVal.xyz * 2.0 - vec3(1.0)); + frag.normal = unpackNormal(frag.normalVal.xyz); frag.roughness = frag.normalVal.a; // Diffuse color and unpack the mode and the metallicness diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh index 2be38fbea3..e869f32dc6 100755 --- a/libraries/render-utils/src/DeferredBufferWrite.slh +++ b/libraries/render-utils/src/DeferredBufferWrite.slh @@ -17,24 +17,6 @@ layout(location = 0) out vec4 _fragColor0; layout(location = 1) out vec4 _fragColor1; layout(location = 2) out vec4 _fragColor2; -uniform sampler2D normalFittingMap; - -vec3 bestFitNormal(vec3 normal) { - vec3 absNorm = abs(normal); - float maxNAbs = max(absNorm.z, max(absNorm.x, absNorm.y)); - - vec2 texcoord = (absNorm.z < maxNAbs ? - (absNorm.y < maxNAbs ? absNorm.yz : absNorm.xz) : - absNorm.xy); - texcoord = (texcoord.x < texcoord.y ? texcoord.yx : texcoord.xy); - texcoord.y /= texcoord.x; - vec3 cN = normal / maxNAbs; - - float fittingScale = texture(normalFittingMap, texcoord).a; - cN *= fittingScale; - return (cN * 0.5 + 0.5); -} - // the alpha threshold const float alphaThreshold = 0.5; @@ -55,7 +37,7 @@ void packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness discard; } _fragColor0 = vec4(albedo, packShadedMetallic(metallic)); - _fragColor1 = vec4(bestFitNormal(normal), clamp(roughness, 0.0, 1.0)); + _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0)); _fragColor2 = vec4(emissive, occlusion); } @@ -65,7 +47,7 @@ void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float r discard; } _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic)); - _fragColor1 = vec4(bestFitNormal(normal), clamp(roughness, 0.0, 1.0)); + _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0)); _fragColor2 = vec4(emissive, 1.0); } @@ -74,7 +56,7 @@ void packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) { discard; } _fragColor0 = vec4(color, packUnlit()); - _fragColor1 = vec4(bestFitNormal(normal), 1.0); + _fragColor1 = vec4(packNormal(normal), 1.0); //_fragColor2 = vec4(vec3(0.0), 1.0); // If unlit, do not worry about the emissive color target } diff --git a/libraries/render-utils/src/FramebufferCache.cpp b/libraries/render-utils/src/FramebufferCache.cpp index 3223ee5535..2d322b1726 100644 --- a/libraries/render-utils/src/FramebufferCache.cpp +++ b/libraries/render-utils/src/FramebufferCache.cpp @@ -59,8 +59,8 @@ void FramebufferCache::createPrimaryFramebuffer() { _deferredFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); _deferredFramebufferDepthColor = gpu::FramebufferPointer(gpu::Framebuffer::create()); - // auto colorFormat = gpu::Element::COLOR_RGBA_32; auto colorFormat = gpu::Element::COLOR_SRGBA_32; + auto linearFormat = gpu::Element::COLOR_RGBA_32; auto width = _frameBufferSize.width(); auto height = _frameBufferSize.height(); @@ -70,7 +70,8 @@ void FramebufferCache::createPrimaryFramebuffer() { _primaryFramebuffer->setRenderBuffer(0, _primaryColorTexture); _deferredColorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); - _deferredNormalTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); + + _deferredNormalTexture = gpu::TexturePointer(gpu::Texture::create2D(linearFormat, width, height, defaultSampler)); _deferredSpecularTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); _deferredFramebuffer->setRenderBuffer(0, _deferredColorTexture);