java - 使用透明度渲染到纹理时渲染覆盖透明度

标签 java opengl

OpenGL 中渲染到纹理(辅助帧缓冲区)时,任何透明内容都会覆盖下面内容的透明度,而不是像透明度那样添加透明度。这意味着如果我在现有的不透明对象之上渲染一个透明对象,结果是透明的纹理,即使它应该是不透明的。

/image/Y0YiT.png

在这张图中,空间通常被渲染为背景,然后更改帧缓冲区并渲染不透明的蓝色,然后渲染绿色/红色。 framebuffer 渲染到的纹理用于渲染到原始 framebuffer(窗口)上,结果如图所示。

一些代码:

帧缓冲区/纹理创建:

        int texture = glGenTextures();
        framebufferID = glGenFramebuffers();
        glBindFramebuffer(GL_FRAMEBUFFER,framebufferID);
        glBindTexture(GL_TEXTURE_2D, texture);
        int width,height;
        width = (int)(getMaster().getWindow().getWidth()*(xscale/(16f*getMaster().getGuiCamera().getWidth()))*1.2f);
        height = (int)(getMaster().getWindow().getHeight()*(yscale/9f)*1.15f);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture,0);
        int depth = glGenTextures();
        glBindTexture(GL_TEXTURE_2D, depth);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth, 0);
        this.texture = new Texture(texture,width,height,true);
        glDrawBuffer(GL_FRONT_AND_BACK);

这里的深度缓冲区是我试图让它工作的东西,但它对输出纹理没有影响。

渲染代码:

        getMaster().returnToViewportAfterFunction(new Vector2i(texture.getWidth(),texture.getHeight()),
            () -> getMaster().returnToFramebufferAfterFunction(framebufferID, () -> {

                shapeShader.bind();
                glEnable(GL_BLEND);
                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                model.bind();
                shapeShader.setUniform("color", 0f, 0f, 1f, 1f); //Blue
                shapeShader.setUniform("projection", this.camera.getProjectionForGuiWindow(vec2zero, xscale, yscale));
                glDrawElements(GL_TRIANGLES, model.getVerticeCount(), GL_UNSIGNED_INT, 0);

                shapeShader.setUniform("color", 0f, 1f, 0f, 0.5f); //Green
                shapeShader.setUniform("projection", this.camera.getProjectionForGuiWindow(vec2zero, xscale/2f, yscale/2f));
                glDrawElements(GL_TRIANGLES, model.getVerticeCount(), GL_UNSIGNED_INT, 0);

                shapeShader.setUniform("color", 1f, 0f, 0f, .2f); //Red
                shapeShader.setUniform("projection", this.camera.getProjectionForGuiWindow(vec2zero, xscale/4f, yscale/2f));
                glDrawElements(GL_TRIANGLES, model.getVerticeCount(), GL_UNSIGNED_INT, 0);

                glDisable(GL_BLEND);

                model.unbind();
            })
        );
        //Renders the texture we just made
        shader.bind();
        model.bind();
        textureCoords.bind(texture);

        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        shader.setUniform("color", 1f, 1f, 1f, 1f);
        shader.setUniform("projection", camera.getProjectionForGuiWindow(getPosition(), xscale, yscale));
        glDrawElements(GL_TRIANGLES, model.getVerticeCount(), GL_UNSIGNED_INT, 0);
        glDisable(GL_BLEND);

        model.unbind();

使用透明对象渲染 framebuffer 0 中的不透明对象不会导致生成的像素透明,否则它们将显示为 glClearColor 和不透明的对象,那么为什么会在我用来渲染纹理的帧缓冲区中发生这种情况呢?难道不应该一致吗?我觉得我的 framebuffer 可能缺少一些附件,但我不确定是什么。我看到一个解决方案说使用 glColorMask(true,true,true,false) ,最后一个 false 意味着没有 alpha 写入,乍一看似乎可以工作,但是为什么我应该在透明时禁用透明度我要做什么?如果继续存在,它似乎还会导致许多问题。任何人都可以提供一些见解吗?提前致谢!

编辑:经过进一步分析,glColorMask 不是解决方案。

最佳答案

您必须使用可分离的混合函数来分别处理 RGB 和 Alpha 值:glBlendFuncSeparate 。对于 RGB 值,您继续使用GL_SRC_ALPHA、GL_SRC_ONE_MINUS_ALPHA。对于 Alpha 值,请使用诸如 GL_ONE, GL_ONE 之类的值,以便简单地累加。

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);

关于java - 使用透明度渲染到纹理时渲染覆盖透明度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55465954/

相关文章:

java - 如何用ajax解析json数组?

java - Hazelcast - 如何获取 EntryProcessor 中当前的 hazelcast 实例?

java - 使用并行线程进行不同的网络操作

c# - OpenGL - 性能差且标度值高

opengl - 为什么这个 glsl 着色器在尝试使用该程序时会导致 "Invalid Operation"?

optimization - 分析时,大部分时间都花在 nvoglv64.dll 中。我应该推断出什么?

javascript - AJAX响应失败

java - catch-Exception 库未按预期工作。下面这段代码有什么问题?

c++ - NURBS 和 opengl 4.2 内核怎么样?

winapi - Win32 opengl 窗口创建