在LibGDX游戏中使用着色器叠加灯光

时间:2015-01-30 19:57:24

标签: opengl libgdx shader light

我正在与Libgdx进行回合制游戏。

我试图通过在地图上添加一个面具并在战斗区域中的每个单元格上设置一个地图灯来为战斗创造战争迷雾。

要做到这一点,我必须叠加灯光,但我不能。

游戏中的结果:

enter image description here

java渲染代码:

//draw the light to the FBO
fbo.begin();
batch.setProjectionMatrix(cam.combined);
batch.setShader(defaultShader);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

batch.begin();
float lightSize = lightOscillate? (4.75f + 0.25f * (float)Math.sin(zAngle) + .2f*MathUtils.random()):5.0f;
//Draw light 1
batch.draw(light, 0, 0, lightSize, lightSize);

//Draw light 2
batch.draw(light, 2, 2, lightSize, lightSize);

batch.end();
fbo.end();

//draw the actual scene
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(cam.combined);
batch.setShader(finalShader);
batch.begin();
fbo.getColorBufferTexture().bind(1); //this is important! bind the FBO to the 2nd texture unit
light.bind(0); //we force the binding of a texture on first texture unit to avoid artefacts
            //this is because our default and ambiant shader dont use multi texturing...
            //youc can basically bind anything, it doesnt matter
tilemap.render(batch, dt);
batch.end();

片段着色器代码:

varying LOWP vec4 vColor;
varying vec2 vTexCoord;

//texture samplers
uniform sampler2D u_texture; //diffuse map
uniform sampler2D u_lightmap;   //light map

//additional parameters for the shader
uniform vec2 resolution; //resolution of screen
uniform LOWP vec4 ambientColor; //ambient RGB, alpha channel is intensity 

void main() {
   vec4 diffuseColor = texture2D(u_texture, vTexCoord);
   vec2 lighCoord = gl_FragCoord.xy / resolution.xy;
   vec4 light = texture2D(u_lightmap, lighCoord);

   vec3 ambient = ambientColor.rgb * ambientColor.a;
   vec3 intensity = ambient + light.rgb;
    vec3 finalColor = diffuseColor.rgb * intensity;

   gl_FragColor = vColor * light; //vec4(finalColor, diffuseColor.a);
}

1 个答案:

答案 0 :(得分:0)

我找到了解决方案。必须启用Alpha混合。

这里有正确的渲染代码:

public void render() {
    final float dt = Gdx.graphics.getRawDeltaTime();

    Gdx.gl.glClearColor(0f,0f,0f,1f);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);   

    batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE);

    //draw the light to the FBO
    fbo.begin();
    Gdx.gl.glClearColor(0f,0f,0f,0f);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        batch.setProjectionMatrix(cam.combined);
        batch.setShader(defaultShader);

        batch.begin();
        float lightSize = lightOscillate? (4.75f + 0.25f * (float)Math.sin(zAngle) + .2f*MathUtils.random()):5.0f;
        //Draw light 1
        batch.draw(light, 0, 0, lightSize, lightSize);

        //Draw light 2
        batch.draw(light, 2, 2, lightSize, lightSize);

        batch.end();
    fbo.end();

    batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);

    //draw the actual scene
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    batch.setProjectionMatrix(cam.combined);
    batch.setShader(finalShader);
    batch.begin();
    fbo.getColorBufferTexture().bind(1); //this is important! bind the FBO to the 2nd texture unit
    light.bind(0); //we force the binding of a texture on first texture unit to avoid artefacts
                   //this is because our default and ambiant shader dont use multi texturing...
                   //youc can basically bind anything, it doesnt matter
    tilemap.render(batch, dt);
    batch.end();
}