我需要在场景中创建阴影。我不想将Environment
与DirectionalShadowLight
一起使用,因为它已被弃用且DefaultShader
是冗余的。所以,我需要实现我自己的阴影支持着色器。基于this article,我创建了2个着色器。其中一个是ShadowGen
着色器:
顶点:
attribute vec4 a_position;
uniform mat4 u_m4LightMVP;
uniform mat4 u_worldTrans;
varying vec4 v_v4TexCoord;
void main()
{
v_v4TexCoord = u_m4LightMVP * u_worldTrans * a_position;
gl_Position = v_v4TexCoord;
}
片段:
#ifdef GL_ES
precision mediump float;
#endif
varying vec4 v_v4TexCoord;
void main(void)
{
/* Generate shadow map - write fragment depth. */
float value = 10.0 - v_v4TexCoord.z;
float v = floor(value);
float f = value - v;
float vn = v * 0.1;
gl_FragColor = vec4(vn, f, 0.0, 1.0);
}
另一个是使用此阴影贴图的基本着色器:
顶点:
#ifdef GL_ES
precision highp float;
#endif
attribute vec4 a_position;
uniform mat4 u_worldTrans;
uniform mat4 u_projTrans;
uniform mat4 u_m4Light;
varying vec4 v_v4TexCoord;
void main()
{
const mat4 biasMat = mat4(0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.5, 0.5, 0.0, 1.0);
v_v4TexCoord = u_m4Light * u_worldTrans * a_position;
v_v4TexCoord = biasMat * v_v4TexCoord;
gl_Position = u_projTrans * u_worldTrans * a_position;
}
片段:
#ifdef GL_ES
precision highp float;
#endif
uniform sampler2D u_s2dShadowMap;
varying vec4 v_v4TexCoord;
void main()
{
vec2 vfDepth = texture2DProj(u_s2dShadowMap, v_v4TexCoord).xy;
float fDepth = (vfDepth.x * 10.0 + vfDepth.y);
/* Unpack the light distance. See how it is packed in the shadow.frag file. */
float fLDepth = (10.0 - v_v4TexCoord.z) + 0.1 - fDepth ;
float fLight = 1.0;
if(fDepth > 0.0 && fLDepth < 0.0)
{
fLight = 0.2;
}
vec4 FinalColor = vec4(1.0,1.0,1.0,1.0);
gl_FragColor = vec4(FinalColor.rgb * fLight, FinalColor.a);
}
我在Shadow
类中使用这些着色器,如下所示:
public Shadow(){
depthBatch = new ModelBatch();
shadowMap = new FrameBuffer(Format.RGBA8888, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true);
lightCam = new PerspectiveCamera(67, shadowMap.getWidth(), shadowMap.getHeight());
lightCam.position.set(40, -35, -35);
lightCam.lookAt(10, 0, 0);
lightCam.update();
shadowGenShader = new ShadowGenMaliShader();
shadowGenShader.init();
shadowMapShader = new ShadowMapMaliShader();
shadowMapShader.init();
}
public void render(Mesh quad, Camera camera, Array<ModelInstance> instances) {
shadowMap.begin();
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glEnable(GL20.GL_CULL_FACE);
Gdx.gl.glCullFace(GL20.GL_FRONT);
depthBatch.begin(lightCam);
depthBatch.render(instances, shadowGenShader);
depthBatch.end();
shadowMap.end();
Gdx.gl.glDisable(GL20.GL_CULL_FACE);
shadowMapShader.shadowMapTexture = shadowMap.getColorBufferTexture();
shadowMapShader.u_m4Light = lightCam.combined;
depthBatch.begin(camera);
depthBatch.render(instances, shadowMapShader);
depthBatch.end();
}
shadowMapShader的代码是:
ShaderProgram program;
int u_projTrans;
int u_worldTrans;
int s_shadowMap;
public Texture shadowTexture;
public Matrix4 u_m4Light;
@Override
public void init() {
String vert = Gdx.files.internal("shaders/shadowmap_mali_vs.glsl").readString();
String frag = Gdx.files.internal("shaders/shadowmap_mali_ps.glsl").readString();
program = new ShaderProgram(vert, frag);
if (!program.isCompiled())
throw new GdxRuntimeException(program.getLog());
else Gdx.app.log("ShadowMapMaliShader", "shader compiled successfully!");
u_projTrans = program.getUniformLocation("u_projTrans");
u_worldTrans = program.getUniformLocation("u_worldTrans");
s_shadowMap = program.getUniformLocation("u_s2dShadowMap");
}
@Override
public void begin(Camera camera, RenderContext context) {
program.begin();
program.setUniformMatrix(u_projTrans, camera.combined);
program.setUniformMatrix("u_m4Light", u_m4Light);
}
@Override
public void render(Renderable renderable) {
program.setUniformMatrix(u_worldTrans, renderable.worldTransform);
shadowTexture.bind(0);
program.setUniformi(s_shadowMap, 0);
renderable.mesh.render(program, renderable.primitiveType, renderable.meshPartOffset, renderable.meshPartSize);
}
所以,实际结果是:
如果我将DefaultShader
与Environment
一起使用,则结果符合预期:
这有什么问题?任何帮助将不胜感激!