【问题标题】:Creating and blending a dynamic texture in OpenGL在 OpenGL 中创建和混合动态纹理
【发布时间】:2012-09-20 13:03:17
【问题描述】:

我需要将球体渲染到纹理(使用帧缓冲区对象 (FBO) 完成),然后将该纹理与后台缓冲区进行 alpha 混合。到目前为止,我没有对纹理进行任何处理,除了在每一帧开始时清除它。

我应该说我的场景只包含一个空旷空间中的行星,球体应该出现在行星旁边或周围(现在有点像月亮)。当我将球体直接渲染到后台缓冲区时,它会正确显示;但是当我执行将其渲染为纹理然后将该纹理与后台缓冲区混合的中间步骤时,球体仅在它位于行星前面时才会出现,不在前面的部分只是“切断” ":

我使用glutSolidSphere 将球体渲染为绑定到 FBO 的 RGBA8 全屏纹理,确保每个球体像素接收 1.0 的 alpha 值。然后,我将纹理传递给片段着色器程序,并使用此代码在 alpha 混合时将全屏四边形(纹理映射到其上)渲染到后缓冲区:

glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);

glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glBegin(GL_QUADS);
glTexCoord2i(0, 1);
glVertex3i(-1,  1, -1);   // TOP LEFT
glTexCoord2i(0, 0);
glVertex3i(-1, -1, -1);   // BOTTOM LEFT
glTexCoord2i(1, 0);   
glVertex3i( 1, -1, -1);   // BOTTOM RIGHT
glTexCoord2i(1, 1);   
glVertex3i( 1,  1, -1);   // TOP RIGHT
glEnd();
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glEnable(GL_DEPTH_TEST);

glDisable(GL_BLEND);

这是着色器代码(取自用 Cg 编写的 FX 文件):

sampler2D BlitSamp = sampler_state
{
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    MipFilter = LINEAR;
    AddressU = Clamp;
    AddressV = Clamp;
};

float4 blendPS(float2 texcoords : TEXCOORD0) : COLOR
{
    float4 outColor = tex2D(BlitSamp, texcoords);
    return outColor;
}

我什至不知道这是深度缓冲区的问题还是 alpha 混合的问题,我尝试了很多启用和禁用深度测试(将深度缓冲区附加到 FBO)和 alpha 混合的组合.

编辑:我尝试将一个空白的全屏四边形直接渲染到后台缓冲区,甚至在地球边缘裁剪。出于某种原因,启用渲染四边形的深度测试(即删除线 glDisable(GL_DEPTH_TEST)glEnable(GL_DEPTH_TEST) in the code above)解决了这个问题,但是现在除了行星和球体之外的所有东西都显示为白色:

我确定(并且可以确认)纹理的 Alpha 通道在每个像素上都是 0,但球体除外,​​所以我不明白可以在哪里引入白度。 (也仍然有兴趣解释为什么启用深度测试会产生这种效果。)

【问题讨论】:

  • 您是否启用了 alpha 测试 (GL_ALPHA_TEST)?
  • 你能生成一个显示问题的最小编译示例吗?
  • 您的着色器代码在我看来不像 GLSL。你用的是 Cg 还是类似的东西?
  • 是CG,不好意思,忘记说了。我应该禁用 GL_ALPHA_TEST,对吗?我会尽快检查。
  • 是的,它应该被禁用。其他要检查的事项: 1. 将shader的body改成return float4(1, 1, 1, texcoords.x);有什么效果? (语法可能关闭,有一段时间没有接触 Cg) 2. 当您将四边形偏离中心放置时会发生什么,例如向左移动一个单位?

标签: c++ opengl shader alphablending render-to-texture


【解决方案1】:

我在这里看到两个可能的错误来源:

1。渲染到 FBO

如果丢失的像素在渲染后甚至不存在于 FBO 中,则必须有某种机制丢弃相应的片段。 OpenGL 管道包括四种不同类型的片段测试,这些测试可能导致片段被丢弃:

  1. 剪刀测试:不太可能是原因,因为剪刀测试只影响屏幕的矩形部分。
  2. Alpha 测试:同样不可能,因为您的片段都应该具有相同的 Alpha 值。
  3. 模板测试:也不太可能,除非您在绘制背景行星时使用模板操作并将模板缓冲区从后台缓冲区复制到 FBO。
  4. 深度测试:与模板测试相同。

因此,渲染到 FBO 很可能不是这里的问题。但是为了绝对确定,您应该读回您的颜色附件纹理并将其转储到文件中以供检查。为此,您可以使用以下函数:

void TextureToFile(GLuint texture, const char* filename) {
  glBindTexture(GL_TEXTURE_2D, texture);
  GLint width, height;
  glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
  glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);

  std::vector<GLubyte> pixels(3 * width * height);
  glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, &pixels[0]);

  std::ofstream out(filename, std::ios::out | std::ios::binary);
  out << "P6\n"
      << width << '\n'
      << height << '\n'
      << 255 << '\n';
  out.write(reinterpret_cast<const char*>(&pixels[0]), pixels.size());  
}

生成的文件是portable pixmap (.ppm)。在读回纹理之前,请务必取消绑定 FBO。

2。纹理映射

假设渲染到 FBO 中按预期工作,唯一的其他错误来源是在先前渲染的场景上混合纹理。有两种情况:

a) 片段被丢弃

fragment被丢弃的可能原因同1.:

  1. 剪刀测试:不,仅影响矩形区域。
  2. Alpha 测试:可能不会,覆盖的球体的纹素应该都具有相同的 alpha 值。
  3. 模板测试:如果您在绘制背景行星时使用模板操作/模板测试并且旧的模板状态仍处于活动状态,则可能是原因。
  4. 深度测试:可能是原因,但由于您已经禁用它,它确实不应该有任何影响。

因此,您应该确保禁用所有这些测试,尤其是模板测试。

b) 混合的错误结果

假设所有片段都到达后台缓冲区,混合是唯一仍然可能导致错误结果的事情。使用混合函数(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) 后缓冲区中的值与混合无关,我们假设纹理中的 alpha 值是正确的。所以我看不出为什么混合应该是这里的根本原因。

结论

总之,观察结果的唯一合理原因似乎是模板测试。如果不是,我别无选择:)

【讨论】:

  • 非常感谢您的想法,我现在确定场景已正确渲染到 FBO,并且还禁用了模板测试,但这似乎不是原因。我现在认为这个问题与深度有关,我用新的发现编辑了我的问题。
  • 说我很困惑是轻描淡写的。我相信除非您显示一些更相关的代码或提供一个显示问题的最小、完整的程序,否则我无法为您提供任何进一步的帮助。
【解决方案2】:

我解决了它,或者至少想出了一个解决方法。

首先,白度源于glClearColor 已设置为glClearColor(1.0f, 1.0f, 1.0f, 1000.0f),因此除了地球之外的所有内容最终都没有被写入。我现在在渲染球体之前将后台缓冲区的内容(即行星、大气及其周围的空间)复制到纹理中,然后在该副本之前渲染大气和空间before/ blit 操作,因此它们包含在其中。以前,除了行星本身之外的所有东西都是在我的四边形之后渲染的,当使用深度测试时 - 显然将一切都放在了四边形后面,使其不可见。

我想要实现的效果的参考实现在其代码中一直使用这种blit操作,但我认为效果没有必要。现在我觉得可能没有别的办法了……

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多