【问题标题】:GLES: FrameBuffer object showing weird imagesGLES:FrameBuffer 对象显示奇怪的图像
【发布时间】:2017-11-13 20:35:19
【问题描述】:

我目前正在尝试使用 Android Studio 让 FBO 在我的游戏中工作。

我已经成功地设置了一个 FBO 并为其绘制了一个填充的白色矩形 (64x64px)。

但是当我尝试将 FBO 的颜色缓冲区渲染到屏幕上时, 出现随机噪声和奇怪的图像。

FBO 正在制作的奇怪图像的快照



我既不知道为什么我的纯色矩形没有出现也不知道为什么 有一张 Whatsapp 聊天的个人资料图片,但并非如此。

这就是我初始化我的 FrameBuffer 对象的方式:

private void initFrameBuffer() {

    int[] temp = new int[1];

    //Create a texture object and bind it. This will be the color buffer.
    glGenTextures(1, temp, 0);
    colorTexture = temp[0];

    glBindTexture(GL_TEXTURE_2D, colorTexture);

    //Set parameters. We're probably using non-power-of-two (NPOT) dimensions,
    //so some values may not be available for use!
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    //Create a texture storage:
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, null);

    //Create framebuffer object and bind it.
    glGenBuffers(1, temp, 0);
    frameBufferID = temp[0];
    glBindFramebuffer(GL_FRAMEBUFFER, frameBufferID);

    //Create a depth buffer and bind it.
    glGenRenderbuffers(1, temp, 0);
    depthBuffer = temp[0];

    glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);

    //Allocate storage for the depth buffer.
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);

    //Attach the depth buffer and the texture (color buffer) to the framebuffer object.
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
            GL_TEXTURE_2D, colorTexture, 0);

    //Check if GL ES is happy with all this ... :)
    int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if (status != GL_FRAMEBUFFER_COMPLETE) {
        throw new RuntimeException("Framebuffer not complete! StatusID: " + status);
    }

    //Switch back to the default framebuffer.
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

我是如何画整个风景的:

@Override
public void draw() {
    GLES20.glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObject.getID());
        Graphics.setColor(new Color(255, 255, 255));
        Graphics.fillRect(0, 0, 64, 64);
    GLES20.glBindFramebuffer(GL_FRAMEBUFFER, 0);

    Graphics.drawFrameBuffer(frameBufferObject, 0, 0, frameBufferObject.getWidth(), frameBufferObject.getHeight());
}

最后但同样重要的是,这是我使用简单着色器程序将 FBO 的颜色缓冲区绘制到屏幕的方式:

public static void drawFrameBuffer(FrameBufferObject frameBufferObject, int x, int y, int w, int h) {

    ImageMesh mesh = new ImageMesh(generateMesh(x, y, w, h));

    imageShader.start();

    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, frameBufferObject.getColorTexture());
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);

    //Enable generic vertex attribute array
    GLES20.glEnableVertexAttribArray(imageShader.positionHandle);

    //Prepare triangle coordinate data
    GLES20.glVertexAttribPointer(imageShader.positionHandle, 3, GLES20.GL_FLOAT, false, 0, mesh.baseMesh.vertexBuffer);

    //Enable generic vertex attribute array
    GLES20.glEnableVertexAttribArray(imageShader.texCoordLocation);

    //Prepare the textureCoordinates
    GLES20.glVertexAttribPointer(imageShader.texCoordLocation, 2, GLES20.GL_FLOAT, false, 0, mesh.uvBuffer);

    //Apply the projection and view transformation
    GLES20.glUniformMatrix4fv(imageShader.mtrxHandle, 1, false, Renderer.getUMVPMatrix(), 0);

    //Set the sampler texture unit to 0
    GLES20.glUniform1i(imageShader.samplerLoc, 0);

    //Draw the triangles
    GLES20.glDrawElements(GLES20.GL_TRIANGLES, mesh.baseMesh.indices.length, GLES20.GL_UNSIGNED_SHORT, mesh.baseMesh.drawListBuffer);

    //Disable vertex arrays
    GLES20.glDisableVertexAttribArray(imageShader.positionHandle);
    GLES20.glDisableVertexAttribArray(imageShader.texCoordLocation);

    //Unbind the texture
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);

    imageShader.stop();
}

我使用的 Android API 级别是 22。 此外,我创建的 FBO 完全适合屏幕尺寸, 即 720x1280 像素。

这个问题浪费了我一整天的时间, 而且我不知道是什么导致了这个问题!

我非常感谢任何形式的帮助!

【问题讨论】:

    标签: java android opengl-es fbo


    【解决方案1】:

    几个小时后,我终于设法让它工作了!

    错误的主要原因是我没有正确设置我的 FBO, 这导致了这个故障图像。

    所以我在 Youtube 上观看了 ThinMatrix 的 OpenGL 教程,他帮助我摆脱了这种糟糕的情况。 :)

    这是我更新的 FrameBuffer 对象代码:

    public class FrameBufferObject {
    
    private int width;
    private int height;
    
    private int frameBufferID;
    private int texture;
    private int depthTexture;
    private int depthBuffer;
    
    private Matrices.MatrixKit previousMatrixKit;
    
    public FrameBufferObject(int width, int height) {
        this.width = width;
        this.height = height;
    
        initFrameBuffer();
    }
    
    private void initFrameBuffer() {
    
        frameBufferID = createFrameBuffer();
        texture = createTextureAttachment();
        depthTexture = createDepthTextureAttachment(width, height);
        depthBuffer = createDepthBufferAttachment();
    
        int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
        if (status != GL_FRAMEBUFFER_COMPLETE) {
            Logger.error("Framebuffer not Complete! STATUS: " + status + "\nWidth: " + width + "\nHeight: " + height);
        }
    
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
    }
    
    private int createFrameBuffer() {
        int[] ids = new int[1];
        glGenFramebuffers(1, ids, 0);
        int frameBufferID = ids[0];
        glBindFramebuffer(GL_FRAMEBUFFER, frameBufferID);
    
        int[] buffers = new int[] {GL_COLOR_ATTACHMENT0};
    
        GLES30.glDrawBuffers(1, buffers, 0);
        return frameBufferID;
    }
    
    private int createTextureAttachment() {
        int[] ids = new int[1];
        glGenTextures(1, ids, 0);
        int colorTexture = ids[0];
    
        glBindTexture(GL_TEXTURE_2D, colorTexture);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, null);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
        return colorTexture;
    }
    
    private int createDepthTextureAttachment(int width, int height) {
        int[] ids = new int[1];
        glGenTextures(1, ids, 0);
        int depthTextureID = ids[0];
    
        glBindTexture(GL_TEXTURE_2D, depthTextureID);
        //glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, null);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, null);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTextureID, 0);
        return depthTextureID;
    }
    
    private int createDepthBufferAttachment() {
        int[] ids = new int[1];
        glGenBuffers(1, ids, 0);
        int depthBuffer = ids[0];
    
        glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
        return depthBuffer;
    }
    
    public int getColorTexture() {
        return this.texture;
    }
    
    public void bindFrameBuffer() {
        glBindTexture(GL_TEXTURE_2D, 0); //just make sure the texture isn't bound
        glBindFramebuffer(GL_FRAMEBUFFER, frameBufferID);
        glViewport(0, 0, width, height);
    
        previousMatrixKit = Renderer.getMatrices();
        Renderer.setMatrixKit(Matrices.createMatrixKit(width, height));
    }
    
    public void unbindFrameBuffer() {
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        glViewport(0, 0, previousMatrixKit.width, previousMatrixKit.height);
    
        Renderer.setMatrixKit(previousMatrixKit);
    }
    
    public int getWidth() {
        return this.width;
    }
    
    public int getHeight() {
        return this.height;
    }
    
    public int getID() {
        return this.frameBufferID;
    }
    }
    

    【讨论】:

      猜你喜欢
      • 2019-03-22
      • 2021-08-27
      • 1970-01-01
      • 2015-05-21
      • 1970-01-01
      • 2019-02-09
      • 2012-12-24
      • 1970-01-01
      • 2023-03-04
      相关资源
      最近更新 更多