参考:
添加链接描述
添加链接描述
一.硬阴影
CalcLightMVP(translate, scale) {
let lightMVP = mat4.create();
let modelMatrix = mat4.create();
let viewMatrix = mat4.create();
let projectionMatrix = mat4.create();
mat4.translate(modelMatrix, modelMatrix, translate);
mat4.scale(modelMatrix, modelMatrix, scale);
mat4.lookAt(viewMatrix, this.lightPos, this.focalPoint, this.lightUp);
mat4.ortho(projectionMatrix, -150, 150, -150, 150, 0.01, 500);
mat4.multiply(lightMVP, projectionMatrix, viewMatrix);
mat4.multiply(lightMVP, lightMVP, modelMatrix);
return lightMVP;
}
float useShadowMap(sampler2D shadowMap, vec4 shadowCoord){
float shadowz = unpack(texture2D(shadowMap, shadowCoord.xy));
if(shadowz + EPS > shadowCoord.z)
return 1.0;
else
return 0.0;
}
void main(void) {
vec3 shadowCoord = vPositionFromLight.xyz / vPositionFromLight.w;
shadowCoord = (shadowCoord + 1.0) / 2.0;
float visibility;
visibility = useShadowMap(uShadowMap, vec4(shadowCoord, 1.0));
vec3 phongColor = blinnPhong();
gl_FragColor = vec4(phongColor * visibility, 1.0);
}
二.PCF
float PCF(sampler2D shadowMap, vec4 coords, float filterSize) {
poissonDiskSamples(coords.xy);
float res = 0.0;
float filterRange = filterSize / 2048.0;
for(int i = 0; i < NUM_SAMPLES; i++){
vec2 sampleuv = coords.xy + poissonDisk[i] * filterRange;
float shadowz = unpack(texture2D(shadowMap, sampleuv));
if(shadowz + 5.0 * EPS > coords.z)
res += 1.0;
}
return res / float(NUM_SAMPLES);
}
void main(void) {
float visibility;
float filterSize = 7.0;
vec3 shadowCoord = vPositionFromLight.xyz / vPositionFromLight.w;
shadowCoord = (shadowCoord + 1.0) / 2.0;
visibility = PCF(uShadowMap, vec4(shadowCoord, 1.0), filterSize);
vec3 phongColor = blinnPhong();
gl_FragColor = vec4(phongColor * visibility, 1.0);
}
三.PCSS
float findBlocker( sampler2D shadowMap, vec2 uv, float zReceiver ) {
poissonDiskSamples(uv);
float res = 0.0;
float searchSize = 20.0;
float filterRange = searchSize / 2048.0;
float blockerDepthSum = 0.0;
float blockerCount = 0.0;
for (int i = 0; i < BLOCKER_SEARCH_NUM_SAMPLES; i++) {
vec2 sampleuv = uv + poissonDisk[i] * filterRange;
float shadowz = unpack(texture2D(shadowMap, sampleuv));
if(shadowz + EPS <= zReceiver) {
blockerDepthSum += shadowz;
blockerCount++;
}
}
if(blockerCount == 0.0) {
return zReceiver;
}
return blockerDepthSum / blockerCount;
}
#define LIGHTWIDTH 10.0
float PCSS(sampler2D shadowMap, vec4 coords) {
float avgblockerDepth = clamp(findBlocker(shadowMap, coords.xy, coords.z), 1e-7, coords.z);
float penumbraWidth = LIGHTWIDTH * (coords.z - avgblockerDepth) / avgblockerDepth;
float filterSize = 2.0 * penumbraWidth;
return PCF(shadowMap, coords, filterSize);
}
void main(void) {
float visibility;
vec3 shadowCoord = vPositionFromLight.xyz / vPositionFromLight.w;
shadowCoord = (shadowCoord + 1.0) / 2.0;
visibility = PCSS(uShadowMap, vec4(shadowCoord, 1.0));
vec3 phongColor = blinnPhong();
gl_FragColor = vec4(phongColor * visibility, 1.0);
}