所以,我的目标是用透明像素绘制精灵。
首先,我使用仅渲染不透明像素的着色器渲染精灵。然后,我禁用深度缓冲区写入并使用仅渲染透明(或透明精灵)的着色器渲染相同的精灵,如下所述:
这是我用作测试的动画精灵表:
https://i.stack.imgur.com/MMs2W.png
这是我的渲染器更新功能:
updateRenderData();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthMask(GL_TRUE);
glUseProgram(_programID);
render();
glDepthMask(GL_FALSE);
glUseProgram(_translucencyPogramID);
render();
_window->SwapBuffers();
这是我的渲染函数(以防你想知道我如何渲染精灵):
GLint baseInstance = 0;
GLsizei spriteCount;
for (int i = 0; i < _spriteManager->GetSpriteBatchVector()->size(); i++)
{
_SpriteBatch* spriteBatch = _spriteManager->GetSpriteBatchVector()->at(i);
setTexture(spriteBatch->GetTexture());
spriteCount = (GLsizei)spriteBatch->GetSpriteVector()->size();
glDrawElementsInstancedBaseInstance(_quad.renderMode, _quad.indexCount, _quad.indexDataType, 0, spriteCount, baseInstance);
baseInstance += spriteCount;
}
但是当我执行此代码时,它只渲染透明像素: https://i.stack.imgur.com/f4AY6.png
实际上,如果我删除第二个 render()调用(仅限调用,我仍然更改着色器并将深度掩码设置为false),则不会渲染(黑屏),如下所示:
updateRenderData();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthMask(GL_TRUE);
glUseProgram(_programID);
render();
glDepthMask(GL_FALSE);
glUseProgram(_translucencyPogramID);
_window->SwapBuffers();
但是如果我没有更改着色器,也没有在第一次渲染后将glDepthMask设置为false,它会正确渲染我精灵的不透明像素。
编辑: 这是我用于第二遍的片段着色器:
out layout(location = 0) vec4 outColor;
in vec2 texCoord;
uniform sampler2D tex;
void main()
{
vec4 texel = texture(tex, texCoord);
if(texel.a == 1)
{
discard;
}
outColor = texel;
}
第一遍是相同的,但是如果alpha&lt; 1。 顶点着色器是标准的。
所以,我的问题是:造成这种情况的原因是什么?
编辑2:
为了澄清,这正确呈现(没有半透明像素):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthMask(GL_TRUE);
glUseProgram(_programID);
render();
这根本不会呈现:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthMask(GL_TRUE);
glUseProgram(_programID);
render();
glDepthMask(GL_FALSE);//Just added this line
这根本不会呈现:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthMask(GL_TRUE);
glUseProgram(_programID);
render();
glUseProgram(_translucencyPogramID);//Just added this line
答案 0 :(得分:0)
假设_programID
用于绘制鸟的不透明部分,_translucencyPogramID
用于绘制半透明部分。
您提供的代码中没有任何内容显示原因可能是什么。然而,它可能是:
的结果render()
时,您实际上并没有致电_programID
。_programID
你之后glClear(GL_COLOR_BUFFER_BIT)
GL_ONE_MINUS_SRC_ALPHA
作为glBlendFunc()
&#39; s sfactor
因此,您的_programID
片段着色器包含:
if (texel.a < 1.0)
discard;
并且您的_translucencyPogramID
片段着色器包含:
if (texel.a == 1.0)
discard;
然后授予你的绘制循环就像这样(伪代码):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthMask(GL_TRUE)
glUseProgram(_programID)
for each sprite
glDrawArrays(....)
glDepthMask(GL_FALSE)
glUseProgram(_translucencyPogramID)
for each sprite
glDrawArrays(....)
glDepthMask(GL_TRUE)
然后在使用glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
时,那应该会得到所需的结果。
修改强>
然后当您添加glDepthMask(GL_FALSE)
时,它会因为您之后再次启用它而导致其中断。您可以通过执行以下操作来检查:
GLboolean enabled;
glGetBooleanv(GL_DEPTH_WRITEMASK, &enabled);
assert(enabled == GL_TRUE);
在glClear(GL_DEPTH_BUFFER_BIT)
之前。
这个原因中断是因为如果禁用写入深度缓冲区,则glClear(GL_DEPTH_BUFFER_BIT)
不会做任何事情,因此保留深度缓冲区。
正如你在下面看到的那样,在第二张照片上,它会描绘出所有鸟类画面的轮廓。这是因为深度缓冲区永远不会被清除,这只鸟是最前面的鸟。如果在调用glClear(GL_DEPTH_BUFFER_BIT)
时启用写入深度缓冲区,则它会正确生成第一张图片。
左:在glClear上启用深度写入。右:在glClear上禁用深度写入。
请注意,这种关系适用于glClear(...)
和任何gl*Mask(GL_FALSE)
。