使用 OpenGL / LibGDX 的后处理问题 - 黑屏(FBO、着色器、四边形)

Posted

技术标签:

【中文标题】使用 OpenGL / LibGDX 的后处理问题 - 黑屏(FBO、着色器、四边形)【英文标题】:Postprocessing problems using OpenGL / LibGDX - black screen (FBO, shaders, quad) 【发布时间】:2014-10-13 21:44:43 【问题描述】:

我在将后处理阶段渲染到屏幕上时遇到了一些问题。我写了一些可以在屏幕上渲染好的代码,然后决定我需要一些后处理(棕褐色的绽放效果,但之后会出现)所以我决定将所有内容渲染到 FrameBuffer 对象,然后使用它的颜色纹理来渲染纹理,全屏四边形。问题是,即使使用一些简单的着色器,我要么得到一个黑屏(或者我用来清除颜色缓冲区的任何颜色),要么禁用深度测试,或者一些垃圾像素占据屏幕的左下四分之一,启用时深度测试(那只是盲测,我不确定是否需要在 2D 游戏中进行深度测试,但我的 OpenGL 理解很差)。

那么,我做错了什么?代码如下:

简单的顶点着色器:

attribute vec4 a_position;
attribute vec4 a_color;
attribute vec2 a_texCoord0;

varying vec4 vColor;
varying vec2 vTexCoord;

void main() 
    vColor = a_color;
    vTexCoord = a_texCoord0;
    gl_Position = a_position;

简单的片段着色器:

#ifdef GL_ES
precision mediump float;
#endif

varying vec4 vColor;
varying vec2 vTexCoord;

uniform sampler2D u_texture;

void main() 
    vec4 texColor = texture2D(u_texture, vTexCoord);
    gl_FragColor = vColor.rgba * vec4(texColor.rgb, 1.0);

初始化:

FrambeBuffer fbo;
ShaderProgram focusShader;
Mesh focusQuad;

@Override
public void show() 

    camera1 = new OrthographicCamera();
    camera1.setToOrtho(false);
    camera1.zoom = 0.8f;
    viewport = new ExtendViewport(Globals.VIEWPORT_WIDTH, Globals.VIEWPORT_HEIGHT, camera1);
    batch = new SpriteBatch();
    moveCamera(camera1, player.getX(), player.getY());
    fbo = new FrameBuffer(Format.RGBA8888, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true);
    ShaderProgram.pedantic = false;
    focusShader = new ShaderProgram(Gdx.files.internal("shaders/trivial_vshader"), Gdx.files.internal("shaders/trivial_fshader"));
    focusQuad = createFullScreenQuad(); //TAKEN FROM https://github.com/manuelbua/libgdx-contribs/blob/master/postprocessing/src/main/java/com/bitfire/postprocessing/utils/FullscreenQuad.java
    // Other game initialization...

渲染循环:

@Override
public void render(float delta) 
    // (UPDATE PHYSICS)...
    fbo.begin();
    
    /* DRAW THE PLAYER */
        batch.setProjectionMatrix(camera1.combined);
        batch.begin();
        player.drawTrail(batch, delta);
        player.draw(batch, delta);
        batch.end();

        Gdx.gl.glEnable(GL20.GL_BLEND);
        Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
        shapeRenderer.setProjectionMatrix(camera1.combined);
        shapeRenderer.begin(ShapeType.Filled);
        map.drawEffects(camera1, shapeRenderer);
        //(OTHER GAME STUFF AND EFFECTS...)
        shapeRenderer.end();
        Gdx.gl.glDisable(GL20.GL_BLEND);
    
    fbo.end();

    //NOW THE PROBLEM
    Gdx.gl.glClearColor(0, 0.4f, 0.3f, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    //Gdx.gl.glEnable(GL20.GL_DEPTH_TEST);
    Gdx.gl.glEnable(GL20.GL_BLEND);
    Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
    fbo.getColorBufferTexture().bind();
    focusShader.begin();
    focusShader.setUniformi("u_texture", 0);
    focusQuad.render(focusShader, GL20.GL_TRIANGLE_FAN, 0, 4);
    focusShader.end();

【问题讨论】:

检查过你的帧缓冲中的内容了吗?尝试在 fbo.end() 之前获取 fbo 颜色纹理。这可能会有所帮助。如果其他一切正常。 感谢您的回复。我认为 FBO 具有正确的内容,因为在我绘制到 FBO 之前,我正在绘制到屏幕(并且它工作),并且,更重要的是,我可以使用SpriteBatch(没有着色器),我可以看到它还不错(我没有尝试这么多,但缩放或视口仍然存在问题 - 一切都太大了 - 但我可以看到游戏正常运行)。 我查找了“createFullScreenQuad”代码,它创建了一个没有颜色属性的网格,但您使用的是顶点颜色。您是否修改了createFullScreenQuad 以使用颜色属性?深度测试不应该用于纯 2D 场景,除非您有不透明的精灵想要为您排序。另外,这个问题只在桌面还是安卓上?并非所有 android 设备都支持 RGBA8888。 谢谢,Tenfour04。这就是重点。我没有修改它。我现在可以看到现场了;它有一些意想不到的问题,因为在渲染循环内没有接触任何东西(原来的循环,现在在fbo.begin()fbo.end() 之间)现在我看不到正在渲染的灯光(我使用的是 Box2D 灯光;现在一切都是就像我没有灯时一样 - 一切都很明亮,原始颜色 - ),并且颜色缓冲区没有被正确清除。我在家时会详细说明答案,请随时将其发布为答案,以便我投票。 【参考方案1】:

您是否尝试过在 fbo.end 之前获取颜色纹理的参考。我不确定 fbo end 是否会自动处理它。

【讨论】:

鉴于我的最后一个答案,这不可能。结束 FBO 只不过是从渲染目标 AFAIK 中解除绑定,因此它不会处理它。另外,启用深度测试时我可以看到的“垃圾”与应该看到的内容有关(当我的播放器应该移动时它会改变或闪烁)。它一定是别的东西。

以上是关于使用 OpenGL / LibGDX 的后处理问题 - 黑屏(FBO、着色器、四边形)的主要内容,如果未能解决你的问题,请参考以下文章

libgdx中的OpenGL问题

需要带有 FBO 扩展的 OpenGL 2.0 或更高版本 - LibGDX 错误

OpenGL 帧缓冲区 + LibGDX

渲染大量四边形的有效方法(LibGDX/OpenGL ES)

libgdx 通过鼠标单击绘制矩形

显卡不支持OpenGL