LibGDX - 自定义阴影贴图

时间:2014-09-11 12:06:35

标签: android libgdx opengl-es-2.0 shader glsles

我需要在场景中创建阴影。我不想将EnvironmentDirectionalShadowLight一起使用,因为它已被弃用且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);
}    

所以,实际结果是: Actual result
如果我将DefaultShaderEnvironment一起使用,则结果符合预期: Expected result 这有什么问题?任何帮助将不胜感激!

0 个答案:

没有答案