From 7074d96c040081d523fed9cbe41a65117de1342a Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 12 Sep 2014 14:11:56 -0700 Subject: [PATCH] Working on support for specular components in deferred lights. --- .../resources/shaders/directional_light.frag | 42 ++++++++- ...directional_light_cascaded_shadow_map.frag | 21 ++++- .../shaders/directional_light_shadow_map.frag | 21 ++++- .../src/renderer/DeferredLightingEffect.cpp | 85 ++++++++++--------- 4 files changed, 121 insertions(+), 48 deletions(-) diff --git a/interface/resources/shaders/directional_light.frag b/interface/resources/shaders/directional_light.frag index 7fb5d83719..5c76fd3ff4 100644 --- a/interface/resources/shaders/directional_light.frag +++ b/interface/resources/shaders/directional_light.frag @@ -17,10 +17,44 @@ uniform sampler2D diffuseMap; // the normal texture uniform sampler2D normalMap; +// the specular texture +uniform sampler2D specularMap; + +// the depth texture +uniform sampler2D depthMap; + +// the distance to the near clip plane +uniform float near; + +// scale factor for depth: (far - near) / far +uniform float depthScale; + +// offset for depth texture coordinates +uniform vec2 depthTexCoordOffset; + +// scale for depth texture coordinates +uniform vec2 depthTexCoordScale; + void main(void) { - // compute the base color based on OpenGL lighting model + // compute the view space position using the depth + float z = near / (texture2D(depthMap, gl_TexCoord[0].st).r * depthScale - 1.0); + vec4 position = vec4((depthTexCoordOffset + gl_TexCoord[0].st * depthTexCoordScale) * z, z, 0.0); + + // get the normal from the map vec4 normal = texture2D(normalMap, gl_TexCoord[0].st); - gl_FragColor = vec4((texture2D(diffuseMap, gl_TexCoord[0].st) * (gl_FrontLightModelProduct.sceneColor + - gl_FrontLightProduct[0].ambient + gl_FrontLightProduct[0].diffuse * max(0.0, dot(normal * 2.0 - - vec4(1.0, 1.0, 1.0, 2.0), gl_LightSource[0].position)))).rgb, normal.a); + vec4 normalizedNormal = normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0); + + // compute the base color based on OpenGL lighting model + float diffuse = dot(normalizedNormal, gl_LightSource[0].position); + float facingLight = step(0.0, diffuse); + vec4 baseColor = texture2D(diffuseMap, gl_TexCoord[0].st) * (gl_FrontLightModelProduct.sceneColor + + gl_FrontLightProduct[0].ambient + gl_FrontLightProduct[0].diffuse * (diffuse * facingLight)); + + // compute the specular multiplier (sans exponent) + float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(position)), + normalizedNormal)); + + // add specular contribution + vec4 specularColor = texture2D(specularMap, gl_TexCoord[0].st); + gl_FragColor = vec4(baseColor.rgb + pow(specular, specularColor.a * 255.0) * specularColor.rgb, normal.a); } diff --git a/interface/resources/shaders/directional_light_cascaded_shadow_map.frag b/interface/resources/shaders/directional_light_cascaded_shadow_map.frag index d16467520e..054b505f8e 100644 --- a/interface/resources/shaders/directional_light_cascaded_shadow_map.frag +++ b/interface/resources/shaders/directional_light_cascaded_shadow_map.frag @@ -17,6 +17,9 @@ uniform sampler2D diffuseMap; // the normal texture uniform sampler2D normalMap; +// the specular texture +uniform sampler2D specularMap; + // the depth texture uniform sampler2D depthMap; @@ -51,15 +54,27 @@ void main(void) { vec3 shadowTexCoord = vec3(dot(gl_EyePlaneS[shadowIndex], position), dot(gl_EyePlaneT[shadowIndex], position), dot(gl_EyePlaneR[shadowIndex], position)); - // compute the color based on OpenGL lighting model, use the alpha from the normal map + // get the normal from the map vec4 normal = texture2D(normalMap, gl_TexCoord[0].st); - float diffuse = dot(normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0), gl_LightSource[0].position); + vec4 normalizedNormal = normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0); + + // average values from the shadow map + float diffuse = dot(normalizedNormal, gl_LightSource[0].position); float facingLight = step(0.0, diffuse) * 0.25 * (shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, -shadowScale, 0.0)).r + shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, shadowScale, 0.0)).r + shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, -shadowScale, 0.0)).r + shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, shadowScale, 0.0)).r); + + // compute the base color based on OpenGL lighting model vec4 baseColor = texture2D(diffuseMap, gl_TexCoord[0].st) * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient + gl_FrontLightProduct[0].diffuse * (diffuse * facingLight)); - gl_FragColor = vec4(baseColor.rgb, normal.a); + + // compute the specular multiplier (sans exponent) + float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(vec4(position.xyz, 0.0))), + normalizedNormal)); + + // add specular contribution + vec4 specularColor = texture2D(specularMap, gl_TexCoord[0].st); + gl_FragColor = vec4(baseColor.rgb + pow(specular, specularColor.a * 255.0) * specularColor.rgb, normal.a); } diff --git a/interface/resources/shaders/directional_light_shadow_map.frag b/interface/resources/shaders/directional_light_shadow_map.frag index d4ac254fc5..b167d58b2a 100644 --- a/interface/resources/shaders/directional_light_shadow_map.frag +++ b/interface/resources/shaders/directional_light_shadow_map.frag @@ -17,6 +17,9 @@ uniform sampler2D diffuseMap; // the normal texture uniform sampler2D normalMap; +// the specular texture +uniform sampler2D specularMap; + // the depth texture uniform sampler2D depthMap; @@ -46,15 +49,27 @@ void main(void) { // compute the corresponding texture coordinates vec3 shadowTexCoord = vec3(dot(gl_EyePlaneS[0], position), dot(gl_EyePlaneT[0], position), dot(gl_EyePlaneR[0], position)); - // compute the color based on OpenGL lighting model, use the alpha from the normal map + // get the normal from the map vec4 normal = texture2D(normalMap, gl_TexCoord[0].st); - float diffuse = dot(normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0), gl_LightSource[0].position); + vec4 normalizedNormal = normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0); + + // average values from the shadow map + float diffuse = dot(normalizedNormal, gl_LightSource[0].position); float facingLight = step(0.0, diffuse) * 0.25 * (shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, -shadowScale, 0.0)).r + shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, shadowScale, 0.0)).r + shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, -shadowScale, 0.0)).r + shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, shadowScale, 0.0)).r); + + // compute the base color based on OpenGL lighting model vec4 baseColor = texture2D(diffuseMap, gl_TexCoord[0].st) * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient + gl_FrontLightProduct[0].diffuse * (diffuse * facingLight)); - gl_FragColor = vec4(baseColor.rgb, normal.a); + + // compute the specular multiplier (sans exponent) + float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(vec4(position.xyz, 0.0))), + normalizedNormal)); + + // add specular contribution + vec4 specularColor = texture2D(specularMap, gl_TexCoord[0].st); + gl_FragColor = vec4(baseColor.rgb + pow(specular, specularColor.a * 255.0) * specularColor.rgb, normal.a); } diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index 38a92fb153..7fd53af70a 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -60,6 +60,12 @@ void DeferredLightingEffect::render() { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryNormalTextureID()); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimarySpecularTextureID()); + + glActiveTexture(GL_TEXTURE3); + glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryDepthTextureID()); + // get the viewport side (left, right, both) int viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); @@ -68,15 +74,15 @@ void DeferredLightingEffect::render() { float sMin = viewport[VIEWPORT_X_INDEX] / (float)primaryFBO->width(); float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)primaryFBO->width(); - if (Menu::getInstance()->getShadowsEnabled()) { - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryDepthTextureID()); - - glActiveTexture(GL_TEXTURE3); + ProgramObject* program = &_directionalLight; + const LightLocations* locations = &_directionalLightLocations; + bool shadowsEnabled = Menu::getInstance()->getShadowsEnabled(); + if (shadowsEnabled) { + glActiveTexture(GL_TEXTURE4); glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getShadowDepthTextureID()); - ProgramObject* program = &_directionalLightShadowMap; - const LightLocations* locations = &_directionalLightShadowMapLocations; + program = &_directionalLightShadowMap; + locations = &_directionalLightShadowMapLocations; if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) { program = &_directionalLightCascadedShadowMap; locations = &_directionalLightCascadedShadowMapLocations; @@ -90,38 +96,42 @@ void DeferredLightingEffect::render() { program->setUniformValue(locations->shadowScale, 1.0f / Application::getInstance()->getTextureCache()->getShadowFramebufferObject()->width()); - float left, right, bottom, top, nearVal, farVal; - glm::vec4 nearClipPlane, farClipPlane; - Application::getInstance()->computeOffAxisFrustum( - left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); - program->setUniformValue(locations->nearLocation, nearVal); - program->setUniformValue(locations->depthScale, (farVal - nearVal) / farVal); - float nearScale = -1.0f / nearVal; - float sScale = 1.0f / sWidth; - float depthTexCoordScaleS = (right - left) * nearScale * sScale; - program->setUniformValue(locations->depthTexCoordOffset, left * nearScale - sMin * depthTexCoordScaleS, - bottom * nearScale); - program->setUniformValue(locations->depthTexCoordScale, depthTexCoordScaleS, (top - bottom) * nearScale); - - renderFullscreenQuad(sMin, sMin + sWidth); - - program->release(); - - glBindTexture(GL_TEXTURE_2D, 0); - - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, 0); - - glActiveTexture(GL_TEXTURE1); - } else { - _directionalLight.bind(); - renderFullscreenQuad(sMin, sMin + sWidth); - _directionalLight.release(); + program->bind(); + } + + float left, right, bottom, top, nearVal, farVal; + glm::vec4 nearClipPlane, farClipPlane; + Application::getInstance()->computeOffAxisFrustum( + left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); + program->setUniformValue(locations->nearLocation, nearVal); + program->setUniformValue(locations->depthScale, (farVal - nearVal) / farVal); + float nearScale = -1.0f / nearVal; + float sScale = 1.0f / sWidth; + float depthTexCoordScaleS = (right - left) * nearScale * sScale; + program->setUniformValue(locations->depthTexCoordOffset, left * nearScale - sMin * depthTexCoordScaleS, + bottom * nearScale); + program->setUniformValue(locations->depthTexCoordScale, depthTexCoordScaleS, (top - bottom) * nearScale); + + renderFullscreenQuad(sMin, sMin + sWidth); + + program->release(); + + if (shadowsEnabled) { + glBindTexture(GL_TEXTURE_2D, 0); + glActiveTexture(GL_TEXTURE3); } glBindTexture(GL_TEXTURE_2D, 0); + + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, 0); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, 0); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, 0); freeFBO->release(); @@ -145,8 +155,6 @@ void DeferredLightingEffect::render() { glEnable(GL_DEPTH_TEST); glDepthMask(true); - glDisable(GL_ALPHA_TEST); - glPopMatrix(); glMatrixMode(GL_MODELVIEW); @@ -160,8 +168,9 @@ void DeferredLightingEffect::loadLightProgram(const char* name, ProgramObject& p program.bind(); program.setUniformValue("diffuseMap", 0); program.setUniformValue("normalMap", 1); - program.setUniformValue("depthMap", 2); - program.setUniformValue("shadowMap", 3); + program.setUniformValue("specularMap", 2); + program.setUniformValue("depthMap", 3); + program.setUniformValue("shadowMap", 4); locations.shadowDistances = program.uniformLocation("shadowDistances"); locations.shadowScale = program.uniformLocation("shadowScale"); locations.nearLocation = program.uniformLocation("near");