我的FrameBuffer只渲染了一个纹理

时间:2014-10-22 19:07:46

标签: opengl lwjgl framebuffer

我尝试使用SpriteBatch和FrameBuffer渲染三张图片。

这些是我正在做的步骤。

  1. 清除屏幕,深度和模板缓冲区。
  2. 绑定FrameBuffer。见FrameBuffer.bind()。
  3. 使用我的SpriteBatch渲染三个具有不同大小和不同位置的实心四边形。
  4. 取消绑定我的FrameBuffer。见FrameBuffer.unbind()。
  5. 绑定我的FrameBuffers colorTexture。
  6. 使用我的SpriteBatch渲染我的FrameBuffer。
  7. 以下是我对此问题了解的一些事实

    • 纹理显示正确的颜色。他们不是白人。
    • 显示我呈现的第一个纹理,而另外两个不是。如果我改变顺序,第一个纹理仍然会被渲染。
    • 使用三个纹理,我的意思是三个单独的纹理ID。
    • 我启用了深度测试。
    • 没有抛出OpenGL错误或FrameBuffer错误。
    • 当使用我的SpriteBatch直接渲染到屏幕时,会显示所有三个四边形。
    • 我的FrameBuffer的大小是我的屏幕大小。

    这是它应该是什么样子的样子 Here's how it's supposed to look like

    以下是我用帧缓冲区查看的内容。 Here's how it's looking with my framebuffer.

    以下是我使用我的帧缓冲区和第一次纹理绘制两次的方式。仍然缺少其他两个纹理。定位不是问题。 Here's how it's looking with my framebuffer and drawing the first texture two times. Still missing the other two textures. Position in not the problem.

    这是我的FrameBuffer的代码:

    // Stencil is broken currently broken, in my example. I'm not using any stencil buffers.
    public FrameBuffer(int width, int height, boolean hasDepth, boolean hasStencil) {
        this.width = width;
        this.height = height;
        frameBufferID = GL30.glGenFramebuffers();
        GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBufferID);
    
        if (hasDepth && hasStencil) {
            int depthAndStencilBufferID = GL30.glGenRenderbuffers();
    
            GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, depthAndStencilBufferID);
            GL30.glRenderbufferStorage(GL30.GL_RENDERBUFFER, GL30.GL_DEPTH24_STENCIL8, width, height);
            GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_STENCIL_ATTACHMENT, GL30.GL_RENDERBUFFER, depthAndStencilBufferID);
        }
    
        else if (hasDepth) {
            int depthBufferID = GL30.glGenRenderbuffers();
    
            GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, depthBufferID);
            GL30.glRenderbufferStorage(GL30.GL_RENDERBUFFER, GL30.GL_DEPTH_COMPONENT32F, width, height);
            GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, GL30.GL_RENDERBUFFER, depthBufferID);
        }
    
        else if (hasStencil) {
            int stencilBufferID = GL30.glGenRenderbuffers();
            GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, stencilBufferID);
            GL30.glRenderbufferStorage(GL30.GL_RENDERBUFFER, GL30.GL_STENCIL_INDEX16, width, height);
            GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_STENCIL_ATTACHMENT, GL30.GL_RENDERBUFFER, stencilBufferID);
        }
    
        colorTexture = new Texture(width, height);
        colorTexture.bind();
    
        GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, GL11.GL_TEXTURE_2D, colorTexture.getTextureID(), 0);
        int result = GL30.glCheckFramebufferStatus(GL30.GL_FRAMEBUFFER);
        //error handling
        RenderUtil.unbindFrameBuffer();
    }
    
    private Texture colorTexture;
    
    private int width, height;
    
    private int frameBufferID, depthBufferID, stencilBufferID;
    
    public void begin () {
        GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBufferID);
        GL11.glViewport(0, 0, width, height);
    }
    
    public void end () {
        GL11.glViewport(0, 0, RenderingEngine.getWidth(), RenderingEngine.getHeight());
        RenderUtil.unbindFrameBuffer();
        RenderUtil.unbindTextures();
    }
    
    public Texture getColorTexture () {
        return colorTexture;
    }
    
    public int getWidth () {
        return width;
    }
    
    public int getHeight () {
        return height;
    }
    

    如果有任何用途,我可以创建一个纹理:

    private void loadTexture (ByteBuffer buffer, int textureID, int width, int height) {
        GL13.glActiveTexture(GL13.GL_TEXTURE0);
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);
    
        GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
    
        GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, width, width, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer);
    
        GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D);
    
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
    
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR_MIPMAP_LINEAR);
    }
    

    切换纹理时,我的SpriteBatch似乎有问题。以下是切换的工作原理。 我提醒你,使用我的SpriteBatch渲染到屏幕上给出了我想要的结果。但渲染到FrameBuffer并不起作用。

    `

    public void flush () {
    
        flushes++;
        buffer.flip();
        MESH.setVertices(buffer);
    
        if (lastTexture != null) {
            lastTexture.bind();
        }
    
        MESH.draw();
    
        buffer.clear();
    }
    
    /** Begins the SpriteBatch. */
    public void begin () {
        if (rendering) {
            new IllegalStateException("You have to SpriteBatch.end() before calling begin again!").printStackTrace();
        }
        flushes = 0;
        rendering = true;
        shader.bind();
        shader.setUniformMat4f("projection", camera.getCombined());
        shader.setUniformVec4("color", color);
    }
    
    /** Ends the SpriteBatch, also flushes it. */
    public void end () {
        if (!rendering) {
            new IllegalStateException("You've to SpriteBatch.begin before ending the spritebatch").printStackTrace();
        }
        rendering = false;
        flush();
        RenderUtil.unbindShaders();
        RenderUtil.unbindTextures();
    }
    
    /** Switches the textures and flushes the old one.
     * @param t */
    private void switchTextures (Texture t) {
        if (lastTexture != null) {
            flush();
        }
        lastTexture = t;
    }
    

    ` 打算创建一个小例子。应该很快。

    编辑: 问题不在于我的FrameBuffer。是我的SpriteBatch。

1 个答案:

答案 0 :(得分:3)

您需要在FBO绑定时清除缓冲区,否则您只清除与窗口关联的颜色/模板/深度缓冲区。这不是您想要的行为,因为此场景中的深度测试使用您的FBO深度而不是窗口(默认帧缓冲区)。

public void begin ()是最合理的地方:

public void begin () {
    GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBufferID);
    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT);
    GL11.glViewport(0, 0, width, height);
}