Adding the shadow.slh file containing the shader functions used for shadowing, itis used by both normal and cascaded shadow deferred lighting passes

This commit is contained in:
Sam Gateau 2015-01-05 11:27:29 -08:00
parent 384899e977
commit 458ea6759e
5 changed files with 130 additions and 31 deletions

View file

@ -2795,13 +2795,14 @@ void Application::updateShadowMap() {
QOpenGLFramebufferObject* fbo = DependencyManager::get<TextureCache>()->getShadowFramebufferObject(); QOpenGLFramebufferObject* fbo = DependencyManager::get<TextureCache>()->getShadowFramebufferObject();
fbo->bind(); fbo->bind();
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(/*GL_COLOR_BUFFER_BIT | */GL_DEPTH_BUFFER_BIT);
glm::vec3 lightDirection = -getSunDirection(); glm::vec3 lightDirection = -getSunDirection();
glm::quat rotation = rotationBetween(IDENTITY_FRONT, lightDirection); glm::quat rotation = rotationBetween(IDENTITY_FRONT, lightDirection);
glm::quat inverseRotation = glm::inverse(rotation); glm::quat inverseRotation = glm::inverse(rotation);
const float SHADOW_MATRIX_DISTANCES[] = { 0.0f, 2.0f, 6.0f, 14.0f, 30.0f }; //const float SHADOW_MATRIX_DISTANCES[] = { 0.0f, 2.0f, 6.0f, 14.0f, 30.0f };
const float SHADOW_MATRIX_DISTANCES[] = { 1.0f, 2.5f, 5.0f, 10.0f, 20.0f };
const glm::vec2 MAP_COORDS[] = { glm::vec2(0.0f, 0.0f), glm::vec2(0.5f, 0.0f), const glm::vec2 MAP_COORDS[] = { glm::vec2(0.0f, 0.0f), glm::vec2(0.5f, 0.0f),
glm::vec2(0.0f, 0.5f), glm::vec2(0.5f, 0.5f) }; glm::vec2(0.0f, 0.5f), glm::vec2(0.5f, 0.5f) };
@ -2855,8 +2856,8 @@ void Application::updateShadowMap() {
glm::vec3 maxima(center.x + radius, center.y + radius, center.z + radius); glm::vec3 maxima(center.x + radius, center.y + radius, center.z + radius);
// stretch out our extents in z so that we get all of the avatars // stretch out our extents in z so that we get all of the avatars
minima.z -= _viewFrustum.getFarClip() * 0.5f; // minima.z -= _viewFrustum.getFarClip() * 0.5f;
maxima.z += _viewFrustum.getFarClip() * 0.5f; // maxima.z += _viewFrustum.getFarClip() * 0.5f;
// save the combined matrix for rendering // save the combined matrix for rendering
_shadowMatrices[i] = glm::transpose(glm::translate(glm::vec3(coord, 0.0f)) * _shadowMatrices[i] = glm::transpose(glm::translate(glm::vec3(coord, 0.0f)) *
@ -2897,8 +2898,9 @@ void Application::updateShadowMap() {
viewTransform.setRotation(rotation); viewTransform.setRotation(rotation);
setViewTransform(viewTransform); setViewTransform(viewTransform);
glEnable(GL_POLYGON_OFFSET_FILL); glDisable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.1f, 4.0f); // magic numbers courtesy http://www.eecs.berkeley.edu/~ravir/6160/papers/shadowmaps.ppt //glEnable(GL_POLYGON_OFFSET_FILL);
//glPolygonOffset(1.1f, 4.0f); // magic numbers courtesy http://www.eecs.berkeley.edu/~ravir/6160/papers/shadowmaps.ppt
{ {
PerformanceTimer perfTimer("avatarManager"); PerformanceTimer perfTimer("avatarManager");
@ -2907,7 +2909,7 @@ void Application::updateShadowMap() {
{ {
PerformanceTimer perfTimer("entities"); PerformanceTimer perfTimer("entities");
// _entities.render(RenderArgs::SHADOW_RENDER_MODE); _entities.render(RenderArgs::SHADOW_RENDER_MODE);
} }
// render JS/scriptable overlays // render JS/scriptable overlays
@ -2921,7 +2923,7 @@ void Application::updateShadowMap() {
_overlays.renderWorld(true, RenderArgs::SHADOW_RENDER_MODE); _overlays.renderWorld(true, RenderArgs::SHADOW_RENDER_MODE);
} }
glDisable(GL_POLYGON_OFFSET_FILL); //glDisable(GL_POLYGON_OFFSET_FILL);
glPopMatrix(); glPopMatrix();

View file

@ -166,7 +166,14 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
// TODO: this is the majority of model render time. And rendering of a cube model vs the basic Box render // TODO: this is the majority of model render time. And rendering of a cube model vs the basic Box render
// is significantly more expensive. Is there a way to call this that doesn't cost us as much? // is significantly more expensive. Is there a way to call this that doesn't cost us as much?
PerformanceTimer perfTimer("model->render"); PerformanceTimer perfTimer("model->render");
_model->renderInScene(alpha, args); // filter out if not needed to render
if (args && (args->_renderMode == RenderArgs::SHADOW_RENDER_MODE)) {
if (isMoving() || isAnimatingSomething()) {
_model->renderInScene(alpha, args);
}
} else {
_model->renderInScene(alpha, args);
}
} else { } else {
// if we couldn't get a model, then just draw a cube // if we couldn't get a model, then just draw a cube
glColor3ub(getColor()[RED_INDEX],getColor()[GREEN_INDEX],getColor()[BLUE_INDEX]); glColor3ub(getColor()[RED_INDEX],getColor()[GREEN_INDEX],getColor()[BLUE_INDEX]);

View file

@ -0,0 +1,98 @@
<!
// Shadow.slh
// libraries/render-utils/src
//
// Created by Sam Gateau on 1/4/15.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
!>
<@if not SHADOW_SLH@>
<@def SHADOW_SLH@>
// the shadow texture
uniform sampler2DShadow shadowMap;
// the distances to the cascade sections
uniform vec3 shadowDistances;
// the inverse of the size of the shadow map
uniform float shadowScale;
vec2 samples[8] = vec2[8](
vec2(-2.0, -2.0),
vec2(2.0, -2.0),
vec2(2.0, 2.0),
vec2(-2.0, 2.0),
vec2(1.0, 0.0),
vec2(0.0, 1.0),
vec2(-1.0, 0.0),
vec2(0.0, -1.0)
);
vec4 evalShadowTexcoord(vec4 position) {
// compute the index of the cascade to use and the corresponding texture coordinates
int shadowIndex = int(dot(step(vec3(position.z), shadowDistances), vec3(1.0, 1.0, 1.0)));
vec3 shadowTexcoord = vec3(dot(gl_EyePlaneS[shadowIndex], position), dot(gl_EyePlaneT[shadowIndex], position),
dot(gl_EyePlaneR[shadowIndex], position));
return vec4(shadowTexcoord, shadowIndex);
}
float evalShadowAttenuationPCF(vec4 shadowTexcoord) {
float radiusScale = (shadowTexcoord.w + 1.0);
float shadowAttenuation = (0.25 * (
texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[0], 0.0)) +
texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[1], 0.0)) +
texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[2], 0.0)) +
texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[3], 0.0))
));
if ((shadowAttenuation > 0) && (shadowAttenuation < 1.0)) {
radiusScale *= 0.5;
shadowAttenuation = 0.5 * shadowAttenuation + (0.125 * (
texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[4], 0.0)) +
texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[5], 0.0)) +
texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[6], 0.0)) +
texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[7], 0.0))
));
}
return shadowAttenuation;
}
float evalShadowAttenuationBasic(vec4 shadowTexcoord) {
float radiusScale = 0.5;
float shadowAttenuation = (0.25 * (
texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[0], 0.0)) +
texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[1], 0.0)) +
texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[2], 0.0)) +
texture(shadowMap, shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[3], 0.0))
));
return shadowAttenuation;
}
float evalShadowAttenuation(vec4 shadowTexcoord) {
return evalShadowAttenuationBasic(shadowTexcoord);
}
vec3 debugShadowMap(float shadowAttenuation, vec4 shadowTexcoord) {
vec3 colorArray[4];
colorArray[0].xyz = vec3(1.0, 1.0, 1.0);
colorArray[1].xyz = vec3(1.0, 0.0, 0.0);
colorArray[2].xyz = vec3(0.0, 1.0, 0.0);
colorArray[3].xyz = vec3(0.0, 0.0, 1.0);
vec2 offsetArray[4];
offsetArray[0] = vec2(0.0, 0.0);
offsetArray[1] = vec2(0.5, 0.0);
offsetArray[2] = vec2(0.0, 0.5);
offsetArray[3] = vec2(0.5, 0.5);
return shadowAttenuation * colorArray[int(shadowTexcoord.w)];
// return shadowAttenuation * vec3(2.0*(shadowTexcoord.xy - offsetArray[int(shadowTexcoord.w)]), 0);
}
<@endif@>

View file

@ -299,8 +299,9 @@ QOpenGLFramebufferObject* TextureCache::getShadowFramebufferObject() {
glGenTextures(1, &_shadowDepthTextureID); glGenTextures(1, &_shadowDepthTextureID);
glBindTexture(GL_TEXTURE_2D, _shadowDepthTextureID); glBindTexture(GL_TEXTURE_2D, _shadowDepthTextureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE,
0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0); 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
//0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
@ -308,6 +309,8 @@ QOpenGLFramebufferObject* TextureCache::getShadowFramebufferObject() {
const float DISTANT_BORDER[] = { 1.0f, 1.0f, 1.0f, 1.0f }; const float DISTANT_BORDER[] = { 1.0f, 1.0f, 1.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, DISTANT_BORDER); glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, DISTANT_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
_shadowFramebufferObject->bind(); _shadowFramebufferObject->bind();

View file

@ -24,14 +24,7 @@ uniform sampler2D specularMap;
// the depth texture // the depth texture
uniform sampler2D depthMap; uniform sampler2D depthMap;
// the shadow texture <@include Shadow.slh@>
uniform sampler2DShadow shadowMap;
// the distances to the cascade sections
uniform vec3 shadowDistances;
// the inverse of the size of the shadow map
uniform float shadowScale;
// the distance to the near clip plane // the distance to the near clip plane
uniform float near; uniform float near;
@ -55,17 +48,9 @@ void main(void) {
float z = near / (depthVal * depthScale - 1.0); float z = near / (depthVal * depthScale - 1.0);
vec4 position = vec4((depthTexCoordOffset + gl_TexCoord[0].st * depthTexCoordScale) * z, z, 1.0); vec4 position = vec4((depthTexCoordOffset + gl_TexCoord[0].st * depthTexCoordScale) * z, z, 1.0);
// compute the index of the cascade to use and the corresponding texture coordinates // Eval shadow Texcoord and then Attenuation
int shadowIndex = int(dot(step(vec3(position.z), shadowDistances), vec3(1.0, 1.0, 1.0))); vec4 shadowTexcoord = evalShadowTexcoord(position);
vec3 shadowTexCoord = vec3(dot(gl_EyePlaneS[shadowIndex], position), dot(gl_EyePlaneT[shadowIndex], position), float shadowAttenuation = evalShadowAttenuation(shadowTexcoord);
dot(gl_EyePlaneR[shadowIndex], position));
// evaluate the shadow test but only relevant for light facing fragments
float shadowAttenuation = (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));
// get the normal from the map // get the normal from the map
vec3 normalizedNormal = normalize(normalVal.xyz * 2.0 - vec3(1.0)); vec3 normalizedNormal = normalize(normalVal.xyz * 2.0 - vec3(1.0));
@ -75,7 +60,7 @@ void main(void) {
// Light mapped or not ? // Light mapped or not ?
if ((normalVal.a >= 0.45) && (normalVal.a <= 0.55)) { if ((normalVal.a >= 0.45) && (normalVal.a <= 0.55)) {
normalVal.a = 0.0; normalVal.a = 1.0;
// need to catch normals perpendicular to the projection plane hence the magic number for the threshold // need to catch normals perpendicular to the projection plane hence the magic number for the threshold
// it should be just 0, but we have innacurracy so we need to overshoot // it should be just 0, but we have innacurracy so we need to overshoot
@ -108,4 +93,8 @@ void main(void) {
vec4 specularColor = specularVal; vec4 specularColor = specularVal;
gl_FragColor = vec4(baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb, normalVal.a); gl_FragColor = vec4(baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb, normalVal.a);
} }
if (gl_FragCoord.x > 1024) {
gl_FragColor = vec4(debugShadowMap(shadowAttenuation, shadowTexcoord) * diffuse, normalVal.a);
}
} }