【问题标题】:render transparent textures渲染透明纹理
【发布时间】:2010-11-21 16:08:45
【问题描述】:

我有一个纹理,它的某些部分是透明的,我想将其应用在一个对象上,该对象的面是一些不透明的材料(或者颜色,如果更简单的话),但最终的对象变得透明。我希望最终的对象完全不透明。

这是我的代码:

首先我设置材质:

   glDisable(GL_COLOR_MATERIAL);
   glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
   glColor4f(0.00, 0.00, 0.00, 1.00);
   glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
   glColor4f(0.80, 0.80, 0.80, 1.00);
   glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
   glColor4f(0.01, 0.01, 0.01, 1.00);
   glEnable(GL_COLOR_MATERIAL);

然后我设置 VBO

   glBindTexture(GL_TEXTURE_2D, object->texture);
   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

   glBindBuffer(GL_ARRAY_BUFFER, object->object);
   glVertexPointer(3, GL_FLOAT, sizeof(Vertex), ver_offset);
   glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), tex_offset);
   glNormalPointer(GL_FLOAT, sizeof(Vertex), nor_offset);

最后我画了对象

   glEnable(GL_BLEND);
   glDisable(GL_DEPTH_TEST);

   glDisable(GL_TEXTURE_2D);
   glBlendFunc(GL_ONE, GL_ZERO);
   glDrawArrays(GL_TRIANGLES, 0, object->num_faces);

   glEnable(GL_TEXTURE_2D);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   glDrawArrays(GL_TRIANGLES, 0, object->num_faces);

   glDisableClientState(GL_VERTEX_ARRAY);
   glDisableClientState(GL_TEXTURE_COORD_ARRAY);

   glDisable(GL_BLEND); 
   glEnable(GL_DEPTH_TEST);

我尝试将不同的参数传递给 glBlendFunc() 没有占上风。我在这里上传了源代码:http://dpaste.com/83559/

更新 我得到 this,但我想要 this(或没有纹理this)。

第二张和第三张图片是用glm制作的。我研究了来源,但由于我对 OpenGL 的了解有限,所以我不太了解。

【问题讨论】:

  • 你想达到什么目的?一个带有一些实心像素的透明物体?还是一个带有一些透明纹理的实体对象,下面是纯色?
  • 后者:一个带有一些透明纹理的实体对象,下面显示出纯色?
  • 感谢您的更新...并按照我的建议明确整理您的 Z-Buffering。
  • 更新了我的答案以包含 Z 缓冲修复。

标签: opengl textures alphablending


【解决方案1】:

如果您尝试将两个纹理应用到您的对象,您确实需要设置两个纹理并使用多重纹理来实现这种外观。您的方法是两次绘制几何图形,这是对性能的巨大浪费。

多重纹理将仅从两个纹理单元中采样,而仅绘制一次几何图形。您可以使用着色器(真正应该做的事情)来做到这一点,或者您仍然可以使用固定功能管道(参见:http://bluevoid.com/opengl/sig00/advanced00/notes/node62.html)

【讨论】:

  • 我不同意一切都应该使用着色器来完成。但是你比我快了 19 秒 ;-)
  • OpenGL 3.X 已经完全淘汰了部分 FFP,着色器是未来。
  • 我不想贴图。我想要一种材料和一种纹理(如灰色金属(材料)上的绘画(纹理))。我同意两次绘制几何图形是浪费时间,并且可能是问题,所以我正在寻找替代方案。
  • 您可能仍想在此处使用两个纹理 - 将您的第一个纹理设置为一个非常小的纹理,为您的灰色材质适当着色,并将您的第二个纹理设置为您的细节纹理。这可能看起来很尴尬,但在现代硬件上读取两个纹理非常快,而渲染几何图形和切换渲染状态要慢得多。如果您需要动态着色,用颜色填充 2x2 纹理非常快,并且会给您相同的净效果。
【解决方案2】:

AFAIK 混合功能采用片段颜色(与纹理颜色相反)。因此,如果您通过混合再次绘制对象,则三角形将变为透明。

您想要完成的事情可以使用 multitexturing 来完成。

【讨论】:

    【解决方案3】:

    这只是一个疯狂的猜测,因为您没有提供任何实际问题的屏幕截图,但为什么要禁用深度测试?您确定要使用标准 GL_LESS 在第一次通过时启用深度测试,然后使用 GL_EQUAL 进行第二次通过吗?

    编辑:

    即

    glEnable(GL_BLEND);
    glEnable(GL_DEPTH_TEST);  // ie do not disable
    glDepthFunc( GL_LESS );   // only pass polys have a z value less than ones already in the z-buffer (ie are in front of any previous pixels)
    
    glDisable(GL_TEXTURE_2D);
    glBlendFunc(GL_ONE, GL_ZERO);
    glDrawArrays(GL_TRIANGLES, 0, object->num_faces);
    
    // for the second pass we only want to blend pixels where they occupy the same position 
    // as in the previous pass.  Therefore set to equal and only pixels that match the
    // previous pass will be blended together.
    glDepthFunc( GL_EQUAL );
    
    glEnable(GL_TEXTURE_2D);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glDrawArrays(GL_TRIANGLES, 0, object->num_faces);
    
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    
    glDisable(GL_BLEND); 
    

    【讨论】:

      【解决方案4】:

      尝试禁用混合并在纹理函数设置为GL_DECAL 而不是GL_MODULATE 的情况下绘制单通道。这将根据纹理的 Alpha 通道混合顶点颜色和纹理颜色,但将 Alpha 通道设置为顶点颜色。

      请注意,这将忽略在纹理不透明的任何位置应用到顶点颜色的任何光照,但根据您的描述,这听起来像是预期的效果。

      【讨论】:

        【解决方案5】:

        使用像素着色器会简单得多。否则我认为您需要多次渲染或多个纹理。 你可以在这里找到全面的细节:http://www.opengl.org/resources/faq/technical/transparency.htm

        【讨论】:

        • 像素着色器比多重纹理更简单?
        • 当然!这取决于您的目标平台和引擎,但是如果您想实现像玻璃一样的下降透明效果或切出效果,使用简单的像素着色器比使用固定功能管道要容易得多
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-08-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-10
        • 1970-01-01
        • 2016-02-29
        相关资源
        最近更新 更多