Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/390.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 渲染使用透明度时渲染到纹理时覆盖透明度_Java_Opengl - Fatal编程技术网

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

Java 渲染使用透明度时渲染到纹理时覆盖透明度,java,opengl,Java,Opengl,在OpenGL中渲染到纹理(次帧缓冲区)时,任何透明的内容都会覆盖下面内容的透明度,而不是像透明度应该的那样添加透明度。这意味着,如果在现有不透明对象的顶部渲染透明对象,结果将是透明的纹理,即使它应该是不透明的 在这张图片中,通常将空间渲染为背景,然后更改帧缓冲区,然后渲染不透明的蓝色,然后渲染绿色/红色。帧缓冲区渲染到的纹理用于渲染到原始帧缓冲区(窗口)上,结果如图所示 一些代码: 帧缓冲区/纹理创建: int texture = glGenTextures();

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

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

一些代码:

帧缓冲区/纹理创建:

        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
中会发生这种情况呢?这不应该是一致的吗?我觉得我的
framebuffer
可能缺少了一些附件,但我不能确定是什么。我看到一个解决方案,它说使用
glColorMask(真、真、真、假)
,最后一个假意思是没有alpha写入,乍一看就可以工作,但是为什么我要禁用透明性,而透明性正是我想要的呢?如果不打开,它似乎也会导致许多问题。有人能提供一些见解吗?提前谢谢

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

您必须使用可分离的混合函数,该函数分别处理RGB和Alpha值:。对于您一直使用的RGB值,请使用
GL\u SRC\u ALPHA、GL\u SRC\u ONE\u减去\u ALPHA
。对于Alpha值,使用类似于
GL_ONE,GL_ONE
的东西,以便简单地相加

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);

对于任何想知道我的问题的人来说,最好的解决方案是使用glBlendFuncSeparate(GL_SRC_ALPHA,GL_ONE _减_SRC_ALPHA,GL_ONE _减_DST_ALPHA,GL_ONE _减_SRC_ALPHA),而不是glBlendFunc(GL_SRC_ALPHA,GL_ONE _减_SRC_ALPHA)

哇,这似乎奏效了!我最大的问题是为什么?让我感到困惑的是,使用glBlendFunc(GL_SRC_ALPHA,GL_ONE_减去_SRC_ALPHA)的透明度在正常帧缓冲区(fbo#0)中工作,那么为什么它在链接到纹理的帧缓冲区中不工作呢?我是否需要在帧缓冲区上编辑一些东西以使更简单的函数工作,或者我是否误解了一些基本的东西?我刚才检查过,可以确认这两个函数在fbo 0中看起来相同,但在任何其他fbo中都不相同。请原谅我的提问,但我需要理解。@ToxinedPorkChop:原因是,除非指定了一个
GL_DST \…
blend func,否则在混合过程中不会考虑目标alpha值,因此如果目标alpha变得“疯狂”,则不会看到效果。但是,如果生成的目标alpha值作为源alpha值输入到以后的渲染过程中,则情况会发生变化。这就是在你的例子中发生的情况:你正在渲染一个纹理,你拥有的混合函数,只会将透明的alpha传递到目标像素,覆盖不透明的,如果你不使用分离。那么,像这样的事情?glBlendFuncSeparate(GL_SRC_ALPHA,GL_ONE_减去glu SRC_ALPHA,GL_SRC_ALPHA,GL_DST_ALPHA);上面的代码修复了覆盖现有alpha值的问题,但它似乎没有堆叠alpha值(也就是说,两个半透明度对象相互叠加会生成半透明度对象,而不透明对象和半透明度对象会生成不透明对象)。@ToxinedPorkChop:使用您建议的值,源alpha与自身相乘,目标alpha也与自身相乘,然后相加。即,您得到
s²+d²