显示2个半透明物体的共同部分?

时间:2017-12-06 19:54:01

标签: opengl testing transparency intersection depth

我正在创建一个使用OpenGL显示几个几何3D形状的数学应用程序。在某些情况下,这些形状相交,当发生这种情况时,我想在另一个内部显示每个形状的交叉部分。由于这两种形状都是半透明的,我所需要的或多或少是这样的:

Perfect intersection

然而,对于2个半透明的球体,我得到的结果是:

With depth testing

我知道,要获得正确的透明效果,应在绘制透明形状之前关闭深度测试。然而,当透明形状超出另一个非透明形状时,这会产生另一个副作用:

Without depth testing

那么,有没有办法正确显示2个体积形状的交叉部分,每个体积形状都在另一个体积内,而不会破坏深度测试?

1 个答案:

答案 0 :(得分:1)

  

那么,有没有办法显示(...)体积形状

OpenGL(本身)并不了解"卷"。它知道平面三角形,线条和点,这些通过纯粹的偶然事件也可能导致渲染副作用,如通过深度缓冲测试进行深度排序。

从技术上讲,可以链接一系列绘图和模板缓冲区操作来执行CSG(建设性实体几何);有关详细信息,请参阅ftp://ftp.sgi.com/opengl/contrib/blythe/advanced99/notes/node22.html

但是,您希望通过片段着色器中执行的简单光线跟踪更容易实现。现在光线追踪本身就是一个广泛的主题,你可以在上面填写书籍(实际上已经写了很多关于这个主题的书籍)。最好参考一个例子。在这种情况下,我引用了下面的ShaderToy https://www.shadertoy.com/view/ldS3DW - 该着色器的略微剥离版本绘制了您感兴趣的交叉几何体:

float sphere(vec3 ray, vec3 dir, vec3 center, float radius)
{
    vec3 rc = ray-center;
    float c = dot(rc, rc) - (radius*radius);
    float b = dot(dir, rc);
    float d = b*b - c;
    float t = -b - sqrt(abs(d));
    float st = step(0.0, min(t,d));
    return mix(-1.0, t, st);
}


void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = (-1.0 + 2.0*fragCoord.xy / iResolution.xy) * 
        vec2(iResolution.x/iResolution.y, 1.0);

    vec3 ro = vec3(0.0, 0.0, -3.0);
    vec3 rd = normalize(vec3(uv, 1.0));

    vec3 p0 = vec3(0.5, 0.0, 0.0);
    float t0 = sphere(ro, rd, p0, 1.0);

    vec3 p1 = vec3(-0.05, 0.0, 0.0);
    float t1 = sphere(ro, rd, p1, 1.0);

    fragColor = vec4( step(0.0,t0)*step(0.0,t1)*rd, 1.0 );
}