diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh index a7f4055bba..0538b01fac 100755 --- a/libraries/render-utils/src/DeferredBufferWrite.slh +++ b/libraries/render-utils/src/DeferredBufferWrite.slh @@ -17,6 +17,23 @@ uniform float glowIntensity; // the alpha threshold uniform float alphaThreshold; +uniform sampler2D normalFittingScaleMap; + +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 = texture2D(normalFittingScaleMap, texcoord).a; + cN *= fittingScale; + return (cN * 0.5 + 0.5); +} + float evalOpaqueFinalAlpha(float alpha, float mapAlpha) { return mix(alpha * glowIntensity, 1.0 - alpha * glowIntensity, step(mapAlpha, alphaThreshold)); } @@ -26,7 +43,7 @@ void packDeferredFragment(vec3 normal, float alpha, vec3 diffuse, vec3 specular, discard; } gl_FragData[0] = vec4(diffuse.rgb, alpha); - gl_FragData[1] = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); + gl_FragData[1] = vec4(bestFitNormal(normal), 1.0); gl_FragData[2] = vec4(specular, shininess / 128.0); } @@ -36,8 +53,7 @@ void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 diffuse, vec3 s } gl_FragData[0] = vec4(diffuse.rgb, alpha); - //gl_FragData[1] = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); - gl_FragData[1] = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 0.5); + gl_FragData[1] = vec4(bestFitNormal(normal), 0.5); gl_FragData[2] = vec4(emissive, shininess / 128.0); } diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 2f312e42d8..debad16e9b 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -111,12 +111,15 @@ vec3 evalSkyboxGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec4 fragEyeVector = invViewMat * vec4(-position, 0.0); vec3 fragEyeDir = normalize(fragEyeVector.xyz); - vec3 color = diffuse.rgb * evalSphericalLight(ambientSphere, fragNormal).xyz * getLightAmbientIntensity(light); - + vec3 ambient = diffuse.rgb * evalSphericalLight(ambientSphere, fragNormal).xyz * getLightAmbientIntensity(light); + vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss); - color += vec3(diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light); + vec3 reflectedDir = reflect(-fragEyeDir, fragNormal); + vec3 skyTexel = evalSkyboxLight(reflectedDir, 1 - gloss).xyz; + vec3 color = ambient + vec3(diffuse + shading.rgb) * shading.w * shadowAttenuation * skyTexel * getLightColor(light) * getLightIntensity(light); + return color; } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 080b63370a..84be730977 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -111,6 +111,8 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key, slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), 2)); slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), 3)); + slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingScaleMap"), 4)); + gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vertexShader, pixelShader)); gpu::Shader::makeProgram(*program, slotBindings); @@ -186,6 +188,7 @@ void Model::RenderPipelineLib::initLocations(gpu::ShaderPointer& program, Model: locations.texcoordMatrices = program->getUniforms().findLocation("texcoordMatrices"); locations.emissiveParams = program->getUniforms().findLocation("emissiveParams"); locations.glowIntensity = program->getUniforms().findLocation("glowIntensity"); + locations.normalFittingScaleMapUnit = program->getTextures().findLocation("normalFittingScaleMap"); locations.specularTextureUnit = program->getTextures().findLocation("specularMap"); locations.emissiveTextureUnit = program->getTextures().findLocation("emissiveMap"); @@ -2149,6 +2152,10 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f if ((locations->glowIntensity > -1) && (mode != RenderArgs::SHADOW_RENDER_MODE)) { GLBATCH(glUniform1f)(locations->glowIntensity, DependencyManager::get()->getIntensity()); } + + if ((locations->normalFittingScaleMapUnit > -1)) { + batch.setUniformTexture(locations->normalFittingScaleMapUnit, DependencyManager::get()->getNormalFittingScaleTexture()); + } } int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 126e8ad4d1..aa065039e0 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -336,6 +336,7 @@ private: int emissiveTextureUnit; int emissiveParams; int glowIntensity; + int normalFittingScaleMapUnit; int materialBufferUnit; int clusterMatrices; int clusterIndices; diff --git a/libraries/render-utils/src/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp index c1817169c9..def6a78a8a 100644 --- a/libraries/render-utils/src/TextureCache.cpp +++ b/libraries/render-utils/src/TextureCache.cpp @@ -148,6 +148,13 @@ const gpu::TexturePointer& TextureCache::getBlueTexture() { return _blueTexture; } +const gpu::TexturePointer& TextureCache::getNormalFittingScaleTexture() { + if (!_NFSTexture) { + _NFSTexture = getTexture(QUrl("http://advances.realtimerendering.com/s2010/Kaplanyan-CryEngine3(SIGGRAPH%202010%20Advanced%20RealTime%20Rendering%20Course)-NormalsFittingTexture.dds")); + } + return _NFSTexture->getGPUTexture(); +} + /// Extra data for creating textures. class TextureExtra { public: diff --git a/libraries/render-utils/src/TextureCache.h b/libraries/render-utils/src/TextureCache.h index 381359ef80..cb14baa9b0 100644 --- a/libraries/render-utils/src/TextureCache.h +++ b/libraries/render-utils/src/TextureCache.h @@ -52,6 +52,9 @@ public: /// Returns the a pale blue texture (useful for a normal map). const gpu::TexturePointer& getBlueTexture(); + // Returns a map used to compress the normals through a fitting scale algorithm + const gpu::TexturePointer& getNormalFittingScaleTexture(); + /// Returns a texture version of an image file gpu::TexturePointer getImageTexture(const QString & path); @@ -109,6 +112,7 @@ private: gpu::TexturePointer _permutationNormalTexture; gpu::TexturePointer _whiteTexture; gpu::TexturePointer _blueTexture; + NetworkTexturePointer _NFSTexture; QHash > _dilatableNetworkTextures;