OpenGL 帧缓冲区渲染到纹理不起作用

发布于 2024-11-11 13:34:04 字数 4624 浏览 2 评论 0原文

我正在尝试使用帧缓冲区来使用 Java 和 JOGL 创建发光效果,但我遇到了问题。目前,我的目标是将带有照明纹理的宇宙飞船模型渲染到帧缓冲区纹理,然后将帧缓冲区纹理绘制到三角形扇形四边形。我正在使用 OpenGL 2.1 和/或 2.0 运行 这是我用于生成帧缓冲区及其纹理的代码:

private int createFrameBuffer(GL2GL3 gl) {
    _frameBufferTextureId = GLHelper.makeTextureBuffer(gl, GL2GL3.GL_RGBA, _width / 2, _height / 2, 0, GL2GL3.GL_RGBA,
            GL2GL3.GL_UNSIGNED_BYTE, GL2GL3.GL_TEXTURE_MIN_FILTER, GL2GL3.GL_TEXTURE_MIN_FILTER, GL2GL3.GL_REPEAT, null);
    int frameBufferId = GLHelper.makeFrameBuffer(gl, _frameBufferTextureId, _width / 2, _height / 2);
    return frameBufferId;
}

public static int makeTextureBuffer(GL2GL3 gl, int glEnumInternalFormat, int width, int height, int border,
        int glEnumPixelFormat, int glEnumPixelType, int glEnumMinFilter, int glEnumMagFilter, int glEnumWrapMode,
        File textureFile) {
    ByteBuffer textureDataBuffer = null;
    if (textureFile != null) {
        String filePath = textureFile.getPath();
        String extension = filePath.substring(filePath.lastIndexOf('.') + 1, filePath.length());
        TextureData textureData = null;
        try {
            textureData = TextureIO.newTextureData(gl.getGLProfile(), textureFile, false, extension);
        } catch (IOException e) {
            throw new RuntimeException("Error reading texture");
        }
        textureDataBuffer = getProperlyFormattedBuffer(textureData);
    }
    IntBuffer texture = IntBuffer.allocate(1);
    gl.glGenTextures(1, texture);
    gl.glBindTexture(GL2GL3.GL_TEXTURE_2D, texture.get(0));
    gl.glTexParameteri(GL2GL3.GL_TEXTURE_2D, GL2GL3.GL_TEXTURE_MIN_FILTER, glEnumMinFilter);
    gl.glTexParameteri(GL2GL3.GL_TEXTURE_2D, GL2GL3.GL_TEXTURE_MAG_FILTER, glEnumMagFilter);
    gl.glTexParameteri(GL2GL3.GL_TEXTURE_2D, GL2GL3.GL_TEXTURE_WRAP_S, glEnumWrapMode);
    gl.glTexParameteri(GL2GL3.GL_TEXTURE_2D, GL2GL3.GL_TEXTURE_WRAP_T, glEnumWrapMode);
    gl.glTexImage2D(GL2GL3.GL_TEXTURE_2D, 0, glEnumInternalFormat, width, height, border, glEnumPixelFormat, glEnumPixelType,
            textureDataBuffer);
    gl.glBindTexture(GL2GL3.GL_TEXTURE_2D, 0);
    return texture.get(0);
}

public static int makeFrameBuffer(GL2GL3 gl, int textureBufferId, int width, int height) {
    IntBuffer frameBuffer = IntBuffer.allocate(1);
    gl.glGenFramebuffers(1, frameBuffer);
    gl.glBindFramebuffer(GL2GL3.GL_FRAMEBUFFER, frameBuffer.get(0));
    gl.glFramebufferTexture2D(GL2GL3.GL_FRAMEBUFFER, GL2GL3.GL_COLOR_ATTACHMENT0, GL2GL3.GL_TEXTURE_2D, textureBufferId, 0);
    verifyFrameBuffer(gl);
    gl.glBindFramebuffer(GL2GL3.GL_FRAMEBUFFER, 0);
    return frameBuffer.get(0);
}

private void drawTextureQuad(GL2GL3 gl) {
    _glowShader.bind(gl);
    int textureLocation = _glowShader.getUniformFields().getIlluminationTextureLocation();
    gl.glUniform1i(textureLocation, 0);
    gl.glActiveTexture(GL2GL3.GL_TEXTURE0);
    gl.glBindTexture(GL2GL3.GL_TEXTURE_2D, _frameBufferTextureId);

    int vertexLocation = _glowShader.getAttributeFields().getVertexLocation();
    gl.glBindBuffer(GL2GL3.GL_ARRAY_BUFFER, _textureQuadId);
    gl.glVertexAttribPointer(vertexLocation, 3, GL2GL3.GL_FLOAT, false, 0, 0);
    gl.glEnableVertexAttribArray(vertexLocation);

    int textureCoordLocation = _glowShader.getAttributeFields().getVertexTextureCoordinateLocation();
    gl.glBindBuffer(GL2GL3.GL_ARRAY_BUFFER, _textureQuadCoordsId);
    gl.glVertexAttribPointer(textureCoordLocation, 2, GL2GL3.GL_FLOAT, false, 0, 0);
    gl.glEnableVertexAttribArray(textureCoordLocation);

    gl.glDrawArrays(GL2GL3.GL_TRIANGLE_FAN, 0, 4);
    _glowShader.unbind(gl);
}

在我的渲染循环中,我正在执行以下操作:

_glowShader.bind(gl);// bind my Shader object.
gl.glUniformMatrix4fv(_glowShader.getUniformFields().getProjectionMatrixLocation(), 1, true, _projectionMatrix.getBuffer());
gl.glUniformMatrix4fv(_glowShader.getUniformFields().getModelViewMatrixLocation(), 1, true, _modelViewMat.getBuffer());
gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, _framebufferId);
gl.glDrawBuffers(1, _frameBufferAttachmentss); //contains GL_COLOR_ATTACHMENT0
gl.glViewport(0, 0, _width / 2, _height / 2); // same size as texture
_spaceship.draw(gl, _glowShader);// draw method in my ModelObject class
gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0);
_glowShader.unbind(gl);

drawTextureQuad(gl);

当我运行此命令时,我的四边形按应有的方式绘制,但是纹理是全黑的。当我注释掉渲染循环中的任何帧缓冲区绑定时,模型会按应有的方式渲染,因此我知道我的着色器代码没有任何问题。当我用从文件加载的另一个纹理替换 _frameBufferTextureId 时,该纹理已正确绘制,因此我知道我的纹理坐标正在工作,而且我的着色器代码也是正确的。不过,每当我绑定帧缓冲区时,我都不会得到任何我期望的东西。我还在验证我的帧缓冲区,它是 GL_FRAMEBUFFER_COMPLETE。

我在 stackoverflow 上阅读了无数的教程和帖子,但我一生都无法弄清楚我做错了什么。任何帮助都会很棒!谢谢。

I'm experimenting with framebuffers to create a glow effect using Java and JOGL, but I am having problems. At the moment, my goal is to render my spaceship model, textured with an illumination texture, to a framebuffer texture and then draw the framebuffer texture to a triangle fan quad. I'm running with OpenGL 2.1 and/or 2.0 Here is my code for generating the framebuffer and its texture:

private int createFrameBuffer(GL2GL3 gl) {
    _frameBufferTextureId = GLHelper.makeTextureBuffer(gl, GL2GL3.GL_RGBA, _width / 2, _height / 2, 0, GL2GL3.GL_RGBA,
            GL2GL3.GL_UNSIGNED_BYTE, GL2GL3.GL_TEXTURE_MIN_FILTER, GL2GL3.GL_TEXTURE_MIN_FILTER, GL2GL3.GL_REPEAT, null);
    int frameBufferId = GLHelper.makeFrameBuffer(gl, _frameBufferTextureId, _width / 2, _height / 2);
    return frameBufferId;
}

public static int makeTextureBuffer(GL2GL3 gl, int glEnumInternalFormat, int width, int height, int border,
        int glEnumPixelFormat, int glEnumPixelType, int glEnumMinFilter, int glEnumMagFilter, int glEnumWrapMode,
        File textureFile) {
    ByteBuffer textureDataBuffer = null;
    if (textureFile != null) {
        String filePath = textureFile.getPath();
        String extension = filePath.substring(filePath.lastIndexOf('.') + 1, filePath.length());
        TextureData textureData = null;
        try {
            textureData = TextureIO.newTextureData(gl.getGLProfile(), textureFile, false, extension);
        } catch (IOException e) {
            throw new RuntimeException("Error reading texture");
        }
        textureDataBuffer = getProperlyFormattedBuffer(textureData);
    }
    IntBuffer texture = IntBuffer.allocate(1);
    gl.glGenTextures(1, texture);
    gl.glBindTexture(GL2GL3.GL_TEXTURE_2D, texture.get(0));
    gl.glTexParameteri(GL2GL3.GL_TEXTURE_2D, GL2GL3.GL_TEXTURE_MIN_FILTER, glEnumMinFilter);
    gl.glTexParameteri(GL2GL3.GL_TEXTURE_2D, GL2GL3.GL_TEXTURE_MAG_FILTER, glEnumMagFilter);
    gl.glTexParameteri(GL2GL3.GL_TEXTURE_2D, GL2GL3.GL_TEXTURE_WRAP_S, glEnumWrapMode);
    gl.glTexParameteri(GL2GL3.GL_TEXTURE_2D, GL2GL3.GL_TEXTURE_WRAP_T, glEnumWrapMode);
    gl.glTexImage2D(GL2GL3.GL_TEXTURE_2D, 0, glEnumInternalFormat, width, height, border, glEnumPixelFormat, glEnumPixelType,
            textureDataBuffer);
    gl.glBindTexture(GL2GL3.GL_TEXTURE_2D, 0);
    return texture.get(0);
}

public static int makeFrameBuffer(GL2GL3 gl, int textureBufferId, int width, int height) {
    IntBuffer frameBuffer = IntBuffer.allocate(1);
    gl.glGenFramebuffers(1, frameBuffer);
    gl.glBindFramebuffer(GL2GL3.GL_FRAMEBUFFER, frameBuffer.get(0));
    gl.glFramebufferTexture2D(GL2GL3.GL_FRAMEBUFFER, GL2GL3.GL_COLOR_ATTACHMENT0, GL2GL3.GL_TEXTURE_2D, textureBufferId, 0);
    verifyFrameBuffer(gl);
    gl.glBindFramebuffer(GL2GL3.GL_FRAMEBUFFER, 0);
    return frameBuffer.get(0);
}

private void drawTextureQuad(GL2GL3 gl) {
    _glowShader.bind(gl);
    int textureLocation = _glowShader.getUniformFields().getIlluminationTextureLocation();
    gl.glUniform1i(textureLocation, 0);
    gl.glActiveTexture(GL2GL3.GL_TEXTURE0);
    gl.glBindTexture(GL2GL3.GL_TEXTURE_2D, _frameBufferTextureId);

    int vertexLocation = _glowShader.getAttributeFields().getVertexLocation();
    gl.glBindBuffer(GL2GL3.GL_ARRAY_BUFFER, _textureQuadId);
    gl.glVertexAttribPointer(vertexLocation, 3, GL2GL3.GL_FLOAT, false, 0, 0);
    gl.glEnableVertexAttribArray(vertexLocation);

    int textureCoordLocation = _glowShader.getAttributeFields().getVertexTextureCoordinateLocation();
    gl.glBindBuffer(GL2GL3.GL_ARRAY_BUFFER, _textureQuadCoordsId);
    gl.glVertexAttribPointer(textureCoordLocation, 2, GL2GL3.GL_FLOAT, false, 0, 0);
    gl.glEnableVertexAttribArray(textureCoordLocation);

    gl.glDrawArrays(GL2GL3.GL_TRIANGLE_FAN, 0, 4);
    _glowShader.unbind(gl);
}

In my render loop, I am doing the following:

_glowShader.bind(gl);// bind my Shader object.
gl.glUniformMatrix4fv(_glowShader.getUniformFields().getProjectionMatrixLocation(), 1, true, _projectionMatrix.getBuffer());
gl.glUniformMatrix4fv(_glowShader.getUniformFields().getModelViewMatrixLocation(), 1, true, _modelViewMat.getBuffer());
gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, _framebufferId);
gl.glDrawBuffers(1, _frameBufferAttachmentss); //contains GL_COLOR_ATTACHMENT0
gl.glViewport(0, 0, _width / 2, _height / 2); // same size as texture
_spaceship.draw(gl, _glowShader);// draw method in my ModelObject class
gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0);
_glowShader.unbind(gl);

drawTextureQuad(gl);

When I run this, my quad is drawn as it should, but the texture is all black. When I comment out any framebuffer bindings in my render loop, the model is rendered as it should, so I know that there is nothing wrong with my shader code. When I replace _frameBufferTextureId with another texture loaded from a file, that texture is properly drawn, so I know my texture coordinates are working and, again, my shader code is correct. Whenever I bind my frame buffer though, I don't get anything I expect. I'm also verifying my framebuffer and it is GL_FRAMEBUFFER_COMPLETE.

I've read countless tutorials and posts here on stackoverflow, but I can't for the life of me figure out what I'm doing wrong. Any help would be great! Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

无力看清 2024-11-18 13:34:04

正如 Bethor 指出的,我将 GL_TEXTURE_MIN_FILTER 两次传递给我的 makeTextureBuffer 方法。这是对 glTexParameteri() 调用的解析:

gl.glTexParameteri(GL2GL3.GL_TEXTURE_2D, GL2GL3.GL_TEXTURE_MIN_FILTER, GL2GL2.GL_TEXTURE_MIN_FILTER);
gl.glTexParameteri(GL2GL3.GL_TEXTURE_2D, GL2GL3.GL_TEXTURE_MAG_FILTER, GL2GL2.GL_TEXTURE_MIN_FILTER);

这当然是没有意义的。更改我的调用以传入 GL_LINEAR 修复了所有问题。

As Bethor pointed out, I was passing in GL_TEXTURE_MIN_FILTER twice to my makeTextureBuffer method. This was resolving to the glTexParameteri() calls of:

gl.glTexParameteri(GL2GL3.GL_TEXTURE_2D, GL2GL3.GL_TEXTURE_MIN_FILTER, GL2GL2.GL_TEXTURE_MIN_FILTER);
gl.glTexParameteri(GL2GL3.GL_TEXTURE_2D, GL2GL3.GL_TEXTURE_MAG_FILTER, GL2GL2.GL_TEXTURE_MIN_FILTER);

which of course, makes no sense. Changing my calls to pass in GL_LINEAR fixed everything.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文