gpt4 book ai didi

c++ - Opengl 半透明 Sprite

转载 作者:太空宇宙 更新时间:2023-11-04 13:04:36 27 4
gpt4 key购买 nike

所以,我的目标是绘制具有半透明像素的 Sprite 。

首先,我使用仅渲染不透明像素的着色器渲染 Sprite 。然后,我禁用深度缓冲区写入并使用仅渲染半透明(或透明 Sprite )的着色器渲染相同的 Sprite ,如下所述:

https://gamedev.stackexchange.com/questions/51202/how-do-you-display-non-cutout-transparent-2d-textures-with-a-depth-buffer-open

这是我用作测试的动画 Sprite 表:

/image/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();

这是我的渲染函数(以防万一你想知道我是如何渲染 Sprite 的):

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;
}

但是当我执行这段代码时,它只渲染半透明像素: /image/f4AY6.png

事实上,如果我删除第二个 render() 调用(仅调用,我仍然更改着色器并将深度 mask 设置为 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,它会正确渲染我的 Sprite 的不透明像素。

编辑:这是我在第二遍中使用的片段着色器:

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 < 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

最佳答案

假设 _programID 用于绘制鸟的不透明部分,_translucencyPogramID 用于绘制半透明部分。

您提供的代码中没有任何内容显示可能的原因。然而,它可能是以下结果:

  1. 在使用 _programID 时,您实际上并没有调用 render()
  2. _programID之后你glClear(GL_COLOR_BUFFER_BIT)
  3. 您正在使用 GL_ONE_MINUS_SRC_ALPHA 作为 glBlendFunc()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) 时启用写入深度缓冲区,那么它会正确生成第一张图片。

correct wrong

左图:在 glClear 上启用了深度写入。右图:在 glClear 上禁用了深度写入。

请注意,此关系适用于 glClear(...) 和任何 gl*Mask(GL_FALSE)

关于c++ - Opengl 半透明 Sprite ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43005866/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com