接上一篇文章,把平面移到物体中间,低于平面的部分仍然会投影到平面上,如下图:
出现这种原因,是因为shader中
shadowPos.y = u_Plane_Height + 0.0001;
固定了阴影的高度,所以低于平面的阴影也投影到了平面上,解决的方法是:低于平面的点在片元着色器中舍弃掉。下面只给出修改后的顶点着色器和片元着色器。
var vs = `
#if defined(GL_FRAGMENT_PRECISION_HIGH)
precision highp float;
#else
precision mediump float;
#endif
#include "Lighting.glsl";
attribute vec4 a_Position;
uniform mat4 u_WorldMat;
uniform mat4 u_ViewProjection;
uniform float u_Plane_Height;
uniform DirectionLight u_SunLight;
varying float v_offset;
#ifdef BONE
const int c_MaxBoneCount = 24;
attribute vec4 a_BoneIndices;
attribute vec4 a_BoneWeights;
uniform mat4 u_Bones[c_MaxBoneCount];
#endif
void main() {
vec4 position;
#ifdef BONE
mat4 skinTransform;
#ifdef SIMPLEBONE
float currentPixelPos;
#ifdef GPU_INSTANCE
currentPixelPos = a_SimpleTextureParams.x+a_SimpleTextureParams.y;
#else
currentPixelPos = u_SimpleAnimatorParams.x+u_SimpleAnimatorParams.y;
#endif
float offset = 1.0/u_SimpleAnimatorTextureSize;
skinTransform = loadMatFromTexture(currentPixelPos,int(a_BoneIndices.x),offset) * a_BoneWeights.x;
skinTransform += loadMatFromTexture(currentPixelPos,int(a_BoneIndices.y),offset) * a_BoneWeights.y;
skinTransform += loadMatFromTexture(currentPixelPos,int(a_BoneIndices.z),offset) * a_BoneWeights.z;
skinTransform += loadMatFromTexture(currentPixelPos,int(a_BoneIndices.w),offset) * a_BoneWeights.w;
#else
skinTransform = u_Bones[int(a_BoneIndices.x)] * a_BoneWeights.x;
skinTransform += u_Bones[int(a_BoneIndices.y)] * a_BoneWeights.y;
skinTransform += u_Bones[int(a_BoneIndices.z)] * a_BoneWeights.z;
skinTransform += u_Bones[int(a_BoneIndices.w)] * a_BoneWeights.w;
#endif
position=skinTransform*a_Position;
#else
position=a_Position;
#endif
vec3 lightDir = normalize(u_SunLight.direction);
//计算顶点的世界坐标
vec4 worldPos = u_WorldMat * position;
vec4 shadowPos = worldPos;
//跟据之前的公式计算Sx和Sz
shadowPos.xz = worldPos.xz + lightDir.xz * (u_Plane_Height - worldPos.y) / lightDir.y;
//给Sy赋值并加上一个偏移量,保证阴影在平面上方
shadowPos.y = u_Plane_Height + 0.0001;
//世界坐标转换为裁剪空间坐标
gl_Position = u_ViewProjection * shadowPos;
gl_Position=remapGLPositionZ(gl_Position);
//计算该顶点是否低于投影平面
v_offset = worldPos.y - u_Plane_Height;
}
`;
var fs = `
#if defined(GL_FRAGMENT_PRECISION_HIGH)
precision highp float;
#else
precision mediump float;
#endif
varying float v_offset;
void main()
{
if(v_offset < 0.0)
{
discard;
}
gl_FragColor = vec4(0, 0, 0, 0.3);
}
`;
修改后的效果:
下一章节解决硬阴影的问题。