完全透明的OpenGL模型

时间:2013-09-19 13:04:55

标签: c++ opengl

解释我做错了什么。我已经将3d模型加载到自编码的opengl渲染(v 3.3)并尝试使用顶点着色器使其像xray效果一样透明:

#version 330

attribute vec3 coord3d;
attribute vec2 texcoord;
varying vec2 f_texcoord;

uniform mat4 projectionMatrix; 
uniform mat4 modelViewMatrix; 

layout (location = 0) in vec3 inPosition;
layout (location = 1) in vec4 inColor;

smooth out vec4 theColor;

void main()
{
    gl_Position = projectionMatrix*modelViewMatrix*vec4(inPosition, 1.0);
    theColor = vec4(0.0,0.2,0.4,0.4);
    f_texcoord = texcoord;

}

模型在编辑器中进行了三角测量并绘制:

glDrawArrays(GL_TRIANGLE_FAN, 0, (vertices.at(i)->size()/3));

如果我使用

glEnable(GL_ALPHA_TEST);
glEnable( GL_BLEND );
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glEnable(GL_DEPTH_TEST);
glClearDepth(1.0); 

我看到一些不需要的三角形或线条:

如果我没有深度测试,我会看到多个三角形的内部面孔(我不想要):  

如何摆脱不必要的效果并实施像Google Sketchup那样的X射线效果

如果我希望所有模型都透明,我应该实施深度排序吗?

我该如何实现:

GS

2 个答案:

答案 0 :(得分:10)

问题1:

首先,不要禁用深度测试。在混合之前执行深度测试,以确保正确删除片段,即使启用了混合也是如此。有关每个片段操作及其执行顺序的更多信息,请参阅核心OpenGL 4.4规范的第17.3节

当您禁用深度测试时,您将获得意外的结果,除非绘制调用的顺序是绝对正确的,因此无视深度缓冲的目的。即使您获得正确的订单,您也不能指望所有副作用都消失,并且尝试按照您需要的方式订购每个命令并不适用于除最简单程序之外的其他任何操作。

考虑以下非常简单的例子:

enter image description here

你可以看到3个四边形,最远可视化通常的tex坐标空间(s,t E [0,1]),一个与后者混合的蓝色四边形,以及一个不透明的红色四边形应该是在前面。显然,红色四边形不在前面,尽管深度值表示不是这样。同样显而易见的是,意图是将蓝色四边形与红色四边形混合。在蓝色四边形之后渲染红色四边形似乎可以解决问题,但是如果你绘制另一个应该在后面蓝色红色四边形的四边形,那么它就会简单出现在禁用深度测试的顶部。这都错了。

enter image description here

黄色四边形掩盖了一切,虽然它应该落在红色和蓝色四边形的后面。正确的图像如下,纯粹通过启用深度测试获得:

enter image description here

我的一般建议是:除非您有充分的理由禁用深度测试,例如在渲染叠加层时不想使用深度缓冲区,否则请启用深度测试。

注意:深度缓冲无法解决您通常需要从前到后排列非透明几何体以获得正确结果的问题!如果您想在尝试模拟透明度时完全独立于排序,请在订单独立透明度的许多论文中查找常见的嫌疑人。

问题2:

从它的外观来看,我假设您使用以下混合函数:

gl::BlendFunc (gl::ONE, gl::ONE);

或任何导致稳定,连续积累价值的东西,如

gl::BlendFunc (gl::SRC_ALPHA, gl::ONE);

和RGB和alpha组件的默认混合方程:

gl::BlendEquation (gl::FUNC_ADD);

如果不是这种情况,请添加说明实际值的注释,以便我可以重新检查并可能编辑我的建议。以下仍然适用,因为颜色不会说谎。 ;)

你的第二个问题是由于投射下的z-fighting。有些片段被正确丢弃,有些片段则没有。由于您显然在某些地方具有完全重合的重复面,因此对于一个片段,可能会为第一个面生成稍高的深度值。渲染第二个面时,会产生一个略低的深度值,片段会通过,导致透支,实际上没有。

第一个片段已经完成了所有魔法,并且混合值被写入帧缓冲区并且深度值被写入深度缓冲区,即你有一个面部片段通过了所有测试并且已经混合了背景。现在出现了第二个片段 not ,因为深度值略低,并再次与帧缓冲区中已经混合的颜色混合。由于添加剂混合,您可以获得观察到的结果。我在下面的示例中使用您使用的相同颜色和alpha值重现了这种情况:

enter image description here

问题3:您的模型似乎有很多重复的面孔,一般来说,三角测量看起来很糟糕。你应该重做它。理解和使用混合很难实现。不要将其与次优数据复杂化。

答案 1 :(得分:0)

渲染透明对象的典型过程如下:

  1. 绘制不透明的物体
  2. 将深度掩码设置为false:glDepthMask(GL_FALSE);
  3. 将透明三角形排在前面。
  4. 按此顺序渲染透明。
  5. 将深度掩码设置为true:glDepthMask(GL_TRUE);
  6. 这是确保您获得准确结果的唯一方法。不幸的是,深度排序既复杂又耗时。有时,你可以跳过它并获得“足够好”的结果。还有一些订单独立透明的技术,可以提供相当好的结果。

    在你的情况下,看起来深度排序将是不可避免的。

    编辑:绘制透明对象时,无法完全启用深度测试,因为您绘制的任何内容后面的像素都会被覆盖。你也不能完全禁用它,因为那时你就能看到透明物体,即使它们在不透明物体后面。解决方案是仍然检查您绘制的透明片段是否被更近(不透明)的片段遮挡,但不是为了保存透明片段的深度,因此以后不会对它们进行检查。用于告诉OpenGL停止/开始保存深度值的方法是glDepthMask()