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

Opengl 在LibGDX游戏中使用着色器叠加灯光,opengl,libgdx,shader,light,Opengl,Libgdx,Shader,Light,我正在用Libgdx做一个基于回合的游戏 我试图通过在地图上添加一个遮罩和在战斗区的每个单元上添加一个地图灯来为战斗创造一个战争迷雾 要做到这一点,我必须叠加灯光,但我不能 比赛结果: java渲染代码: //draw the light to the FBO fbo.begin(); batch.setProjectionMatrix(cam.combined); batch.setShader(defaultShader); Gdx.gl.glClear(GL20.GL_COLOR_BUFF

我正在用Libgdx做一个基于回合的游戏

我试图通过在地图上添加一个遮罩和在战斗区的每个单元上添加一个地图灯来为战斗创造一个战争迷雾

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

比赛结果:

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);
}
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();
}
片段着色器代码:

//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);
}
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();
}

我找到了解决办法。必须启用alpha混合

下面是正确的渲染代码:

//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);
}
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();
}

看起来您需要启用alpha混合;Gdx.gl20.glBlendFuncGL20.GL_SRC_ALPHA,gl20.GL_ONE_减去SRC_ALPHA;在batch.begin和create方法之后,但它不执行任何操作。