在 OpenGL 中渲染到纹理(辅助帧缓冲区)时,任何透明的东西都会覆盖下面的透明度,而不是像应该添加的那样增加透明度。这意味着,如果我在现有的不透明对象上渲染透明对象,则结果将是透明的纹理,即使它应该是不透明的。
在此图片中,通常将空间渲染为背景,然后更改framebuffer
,然后渲染不透明的蓝色,然后渲染绿色/红色。 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
中吗?不一致吗?我觉得也许我的framebuffer
缺少附件,但是我不确定。我看到一个解决方案,据说使用glColorMask(true,true,true,false)
,这是最后一个错误,表示没有alpha写入,乍看起来似乎可以正常工作,但是为什么要使用透明性,为什么我应该禁用透明性呢?如果继续使用,它也会引起很多问题。谁能提供一些见识?预先感谢!
编辑:经过进一步分析,glColorMask不是解决方案。
答案 0 :(得分:1)
您必须使用可分离的混合函数,该函数分别处理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);
答案 1 :(得分:0)
对于任何想知道的人,对我的问题的最佳解决方案是使用glBlendFuncSeparate(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA,GL_ONE_MINUS_DST_ALPHA,GL_ONE)代替glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_>