overte-HifiExperiments/libraries/render-utils/src/Shadow.slh
2016-05-18 18:58:28 -07:00

99 lines
2.6 KiB
Text
Executable file

<!
// 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;
struct ShadowTransform {
mat4 projection;
mat4 viewInverse;
float bias;
float scale;
};
uniform shadowTransformBuffer {
ShadowTransform _shadowTransform;
};
mat4 getShadowViewInverse() {
return _shadowTransform.viewInverse;
}
mat4 getShadowProjection() {
return _shadowTransform.projection;
}
float getShadowScale() {
return _shadowTransform.scale;
}
float getShadowBias() {
return _shadowTransform.bias;
}
// Compute the texture coordinates from world coordinates
vec4 evalShadowTexcoord(vec4 position) {
mat4 biasMatrix = mat4(
0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
0.5, 0.5, 0.5, 1.0);
float bias = -getShadowBias();
vec4 shadowCoord = biasMatrix * getShadowProjection() * getShadowViewInverse() * position;
return vec4(shadowCoord.xy, shadowCoord.z + bias, 1.0);
}
// Sample the shadowMap with PCF (built-in)
float fetchShadow(vec3 shadowTexcoord) {
return texture(shadowMap, shadowTexcoord);
}
vec2 PCFkernel[4] = vec2[4](
vec2(-1.5, 0.5),
vec2(0.5, 0.5),
vec2(-1.5, -1.5),
vec2(0.5, -1.5)
);
float evalShadowAttenuationPCF(vec4 position, vec4 shadowTexcoord) {
float pcfRadius = 3.0;
float shadowScale = getShadowScale();
// Offset for efficient PCF, see http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
vec2 offset = pcfRadius * step(fract(position.xy), vec2(0.5, 0.5));
float shadowAttenuation = (0.25 * (
fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(offset + PCFkernel[0], 0.0)) +
fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(offset + PCFkernel[1], 0.0)) +
fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(offset + PCFkernel[2], 0.0)) +
fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(offset + PCFkernel[3], 0.0))
));
return shadowAttenuation;
}
float evalShadowAttenuation(vec4 position) {
vec4 shadowTexcoord = evalShadowTexcoord(position);
if (shadowTexcoord.x < 0.0 || shadowTexcoord.x > 1.0 ||
shadowTexcoord.y < 0.0 || shadowTexcoord.y > 1.0 ||
shadowTexcoord.z < 0.0 || shadowTexcoord.z > 1.0) {
// If a point is not in the map, do not attenuate
return 1.0;
}
return evalShadowAttenuationPCF(position, shadowTexcoord);
}
<@endif@>