Improving the quality of the normals with a better packing algorithm in th edeferred

This commit is contained in:
Sam Cake 2015-05-17 16:57:32 -07:00
parent ba571314b4
commit ad99a0f053
6 changed files with 44 additions and 6 deletions

View file

@ -17,6 +17,23 @@ uniform float glowIntensity;
// the alpha threshold // the alpha threshold
uniform float alphaThreshold; 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) { float evalOpaqueFinalAlpha(float alpha, float mapAlpha) {
return mix(alpha * glowIntensity, 1.0 - alpha * glowIntensity, step(mapAlpha, alphaThreshold)); 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; discard;
} }
gl_FragData[0] = vec4(diffuse.rgb, alpha); 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); 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[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), 0.5);
gl_FragData[1] = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 0.5);
gl_FragData[2] = vec4(emissive, shininess / 128.0); gl_FragData[2] = vec4(emissive, shininess / 128.0);
} }

View file

@ -111,12 +111,15 @@ vec3 evalSkyboxGlobalColor(float shadowAttenuation, vec3 position, vec3 normal,
vec4 fragEyeVector = invViewMat * vec4(-position, 0.0); vec4 fragEyeVector = invViewMat * vec4(-position, 0.0);
vec3 fragEyeDir = normalize(fragEyeVector.xyz); 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); 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; return color;
} }

View file

@ -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("specularMap"), 2));
slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), 3)); 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::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vertexShader, pixelShader));
gpu::Shader::makeProgram(*program, slotBindings); gpu::Shader::makeProgram(*program, slotBindings);
@ -186,6 +188,7 @@ void Model::RenderPipelineLib::initLocations(gpu::ShaderPointer& program, Model:
locations.texcoordMatrices = program->getUniforms().findLocation("texcoordMatrices"); locations.texcoordMatrices = program->getUniforms().findLocation("texcoordMatrices");
locations.emissiveParams = program->getUniforms().findLocation("emissiveParams"); locations.emissiveParams = program->getUniforms().findLocation("emissiveParams");
locations.glowIntensity = program->getUniforms().findLocation("glowIntensity"); locations.glowIntensity = program->getUniforms().findLocation("glowIntensity");
locations.normalFittingScaleMapUnit = program->getTextures().findLocation("normalFittingScaleMap");
locations.specularTextureUnit = program->getTextures().findLocation("specularMap"); locations.specularTextureUnit = program->getTextures().findLocation("specularMap");
locations.emissiveTextureUnit = program->getTextures().findLocation("emissiveMap"); 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)) { if ((locations->glowIntensity > -1) && (mode != RenderArgs::SHADOW_RENDER_MODE)) {
GLBATCH(glUniform1f)(locations->glowIntensity, DependencyManager::get<GlowEffect>()->getIntensity()); GLBATCH(glUniform1f)(locations->glowIntensity, DependencyManager::get<GlowEffect>()->getIntensity());
} }
if ((locations->normalFittingScaleMapUnit > -1)) {
batch.setUniformTexture(locations->normalFittingScaleMapUnit, DependencyManager::get<TextureCache>()->getNormalFittingScaleTexture());
}
} }
int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,

View file

@ -336,6 +336,7 @@ private:
int emissiveTextureUnit; int emissiveTextureUnit;
int emissiveParams; int emissiveParams;
int glowIntensity; int glowIntensity;
int normalFittingScaleMapUnit;
int materialBufferUnit; int materialBufferUnit;
int clusterMatrices; int clusterMatrices;
int clusterIndices; int clusterIndices;

View file

@ -148,6 +148,13 @@ const gpu::TexturePointer& TextureCache::getBlueTexture() {
return _blueTexture; 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. /// Extra data for creating textures.
class TextureExtra { class TextureExtra {
public: public:

View file

@ -52,6 +52,9 @@ public:
/// Returns the a pale blue texture (useful for a normal map). /// Returns the a pale blue texture (useful for a normal map).
const gpu::TexturePointer& getBlueTexture(); 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 /// Returns a texture version of an image file
gpu::TexturePointer getImageTexture(const QString & path); gpu::TexturePointer getImageTexture(const QString & path);
@ -109,6 +112,7 @@ private:
gpu::TexturePointer _permutationNormalTexture; gpu::TexturePointer _permutationNormalTexture;
gpu::TexturePointer _whiteTexture; gpu::TexturePointer _whiteTexture;
gpu::TexturePointer _blueTexture; gpu::TexturePointer _blueTexture;
NetworkTexturePointer _NFSTexture;
QHash<QUrl, QWeakPointer<NetworkTexture> > _dilatableNetworkTextures; QHash<QUrl, QWeakPointer<NetworkTexture> > _dilatableNetworkTextures;