4

如何让 box2dlights 忽略环境光照中的纹理和精灵?例如,我有一个环境照明设置为暗的舞台。我希望我的灯照亮灯正下方的平台,但灯后面的背景图像应该保持黑暗而不是亮起。目前,灯光是顶部渲染层,灯光下方的所有内容都被点亮。

4

1 回答 1

3

实现这一目标的正确方法如下:

  1. 更新你的物理和相机。
  2. 渲染光照贴图,以便您以后可以从RayHandler's中获取纹理FrameBuffer
  3. 按所需顺序将顶层渲染到透明FrameBuffer对象,但不要在其中渲染光照贴图。不要在此处渲染您的 HUD 或您不想受到光照影响的任何最顶层。
  4. 完成向您的渲染FBO并开始向您的屏幕渲染。
  5. 渲染不受灯光影响的背景。
  6. Texture Units将光照贴图和顶层'绑定到0 和 1 FBO Texture
  7. 开始一个Shader你将用来混合你的光照贴图和你的FBO Texture. 混合非常简单(发生在 中Fragment Shader) :,glFragColor = tex0.rgb * tex1.rgb并且保持tex1.a不变(tex0= 光照贴图纹理,tex1= fbo 纹理)。使用这种RayHandler渲染方法会丢失 的环境光,因此您可以将环境光颜色传递给着色器并将其添加到光照贴图通道中。
  8. 将纹理单元绑定到着色器并执行渲染。此渲染必须在启用 Alpha 混合(SRC_ALPHA、ONE_MINUS_SRC_ALPHA)的情况下完成。
  9. 再次绑定默认值Texture Unit,以便正确完成剩余的渲染 ( TEXTURE_0):渲染任何剩余的最顶层和 HUD(如果有)。

一些示例代码:

@Override
public void render(float delta) {

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

	tweenManager.update(delta);
        worldUpdate(delta);

        /* We have three cameras (foreground + double parallax background) */
        moveForegroundCamera(player.getPosition().x, player.getPosition().y);
        moveBackground0Camera(player.getPosition().x, player.getPosition().y);
        moveBackground1Camera(player.getPosition().x, player.getPosition().y);

        cameraMatrixCopy.set(foregroundCamera.combined);
        rayHandler.setCombinedMatrix(cameraMatrixCopy.scale(Globals.BOX_TO_WORLD, Globals.BOX_TO_WORLD, 1.0f), foregroundCamera.position.x,
                foregroundCamera.position.y, foregroundCamera.viewportWidth * camera.zoom * Globals.BOX_TO_WORLD,
                foregroundCamera.viewportHeight * foregroundCamera.zoom * Globals.BOX_TO_WORLD);
        rayHandler.update();
        rayHandler.render();
        lightMap = rayHandler.getLightMapTexture();

        fbo.begin();
        {
            Gdx.gl.glClearColor(0, 0, 0, 0);
            Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

            /* Draw the second background (affected by lights),  the player, the enemies and all the objects */
            batch.enableBlending();
            batch.setProjectionMatrix(background1Camera.combined);
            batch.begin();
            background1.draw(batch);
            batch.end();
            batch.setProjectionMatrix(foregroundCamera.combined);
            batch.begin();

            // Draw stuff...

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

        /* Now let's pile things up: draw the bottom-most layer */
        batch.setProjectionMatrix(background0Camera.combined);
        batch.disableBlending();
        batch.begin();
        background0.draw(batch);
        batch.end();

        /* Blend the frame buffer's texture with the light map in a fancy way */
        Gdx.gl20.glActiveTexture(GL20.GL_TEXTURE0);
        fboRegion.getTexture().bind(); // fboRegion = new TextureRegion(fbo.getColorBufferTexture());

        Gdx.gl20.glActiveTexture(GL20.GL_TEXTURE1);
        lightMap.bind();

        Gdx.gl20.glEnable(Gdx.gl20.GL_BLEND);
        Gdx.gl20.glBlendFunc(Gdx.gl20.GL_SRC_ALPHA, Gdx.gl20.GL_ONE_MINUS_SRC_ALPHA);
        lightShader.begin();
        lightShader.setUniformf("ambient_color", level.getAmbientLightColor());
        lightShader.setUniformi("u_texture0", 0);
        lightShader.setUniformi("u_texture1", 1);
        fullScreenQuad.render(lightShader, GL20.GL_TRIANGLE_FAN, 0, 4);
        lightShader.end();
        Gdx.gl20.glDisable(Gdx.gl20.GL_BLEND);

        Gdx.gl20.glActiveTexture(GL20.GL_TEXTURE0); // Bind again the default texture unit

        /* Draw any top-most layers you might have */
        hud.draw();

    }

于 2015-06-06T11:02:07.937 回答