簡體   English   中英

Open GL Translucid Sprites

[英]Open GL Translucid Sprites

所以,我的目標是用透明像素繪制精靈。

首先,我使用僅渲染不透明像素的着色器渲染精靈。 然后,我禁用深度緩沖區寫入並使用僅渲染透明(或透明精靈)的着色器渲染相同的精靈,如下所述:

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

這是我用作測試的動畫精靈表:

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 <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. _programIDglClear(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)將不執行任何操作,因此保留深度緩沖區。

正如你在下面看到的那樣,在第二張照片上,它會描繪出所有鳥類畫面的輪廓。 這是因為深度緩沖區永遠不會被清除,這只鳥是最前面的鳥。 如果在調用glClear(GL_DEPTH_BUFFER_BIT)啟用寫入深度緩沖區,則它會正確生成第一個圖片。

正確錯誤

左:在glClear上啟用深度寫入。 右:在glClear上禁用深度寫入。

請注意,這種關系適用於glClear(...)和任何gl*Mask(GL_FALSE)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM