LibGDX - custom shadow display
I need to create shadows in my scene. I dont want to use Environment
with DirectionalShadowLight
because it is deprecated and DefaultShader
is redundant. So, I need to implement my own shader with shadow support. Based on this article , I created 2 shaders. One of them is ShadowGen
shader:
Vertex:
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;
}
Fragment:
#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);
}
And one more is the main shader that uses this shadow map:
Vertex:
#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;
}
Fragment:
#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);
}
I am using these shaders in a class Shadow
like below:
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 code:
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);
}
So the actual result:
If I use DefaultShader
with Environment
, the result is as expected:
What's wrong with that? Any help would be appreciated!
source to share
No one has answered this question yet
Check out similar questions: