用GLSL过滤曲面法线,用texture3d过滤体积数据

时间:2014-05-13 14:47:51

标签: opengl textures glsl normalize

我想使用GLSL着色器为texture3D模拟参数曲面。 texture3D到处都是白色(这是一种简化)。从TEXTURE3D开始,我选择那些位于带抛物线底座的圆柱体上的体素:

顶点着色器:

 varying vec3 texture_coordinate;
 uniform float thickness;
 uniform float curvature;
 varying vec4 pvertex;
 void main()
 {
    vec4 v=gl_Vertex;
    texture_coordinate= v.xyz;
    gl_Position = gl_ModelViewProjectionMatrix*v;
    pvertex = v;
 }

Fragment Shader:

varying vec3 texture_coordinate;
uniform sampler3D my_color_texture;
varying vec4 pvertex;
uniform float thickness;
uniform float curvature;
void main()
{
    // Filter out the vertices outside a given surface normal
    float parametricSurfaceEquation = (pvertex.x*pvertex.x)/curvature;
    if ( distance(pvertex.xz,vec2(pvertex.x,parametricSurfaceEquation)) <= thickness )
    {
        gl_FragColor = vec4(1.0);
    }
    else
    {
        // color the vertices outside that small volume around the surface to black
        gl_FragColor = vec4(0.0,0.0,0.0,1.0);
    }
    if ( ((pvertex.x*pvertex.x) + (pvertex.z*pvertex.z)) <= curvature*0.5f )
        gl_FragColor = vec4(0.0);
}

但结果是,虽然这适用于曲率较低的区域,但在高度弯曲的区域,表面比低弯曲区域更厚,如下图所示。这对我来说是理想的情况:

Thin surface

但如果我增加thickness参数,则中心比周边厚得多。

thick surface

是否有可能以某种方式避免此问题?我基本上将表面周围小半径内的体素着色为白色但是我想指定每个区域的厚度相同,指向该点的法线。

将着色器更改为:

varying vec3 texture_coordinate;
uniform sampler3D my_color_texture;
varying vec4 pvertex;
uniform float thickness;
uniform float curvature;
void main()
{
    // Filter out the vertices outside a given surface normal
    float parametricSurfaceEquation = (pvertex.x*pvertex.x)/curvature;
    float normalLength = sqrt(1.0+(2.0*pvertex.x/curvature)*(2.0*pvertex.x/curvature));
    if ( abs((pvertex.z - parametricSurfaceEquation)/normalLength) <= thickness)
    {
        gl_FragColor = vec4(1.0);
    }
    else
    {
        // color the vertices outside that small volume around the surface to black
        gl_FragColor = vec4(0.0,0.0,0.0,1.0);
    }
    if ( ((pvertex.x*pvertex.x) + (pvertex.z*pvertex.z)) <= curvature*0.5f )
        gl_FragColor = vec4(0.0);
}

,结果如下:

Constant width shape

1 个答案:

答案 0 :(得分:1)

我认为您简化了着色器代码以进行说明?在您发布的表单中,它根本没有使用3D纹理。

在任何情况下,我理解你的代码的方式,你得到的是基于你做的数学。想象一下抛物线的常见y = x * x形式和厚度t。同样使用曲率参数c,我相信您要渲染以下两条曲线之间的区域:

y1 = x * x / c - t
y2 = x * x / c + t

虽然y2 - y1始终为2 * t,但曲线的粗细将不均匀。要测量曲线的感知厚度,您可以测量通过将线正交与您的区域相交的曲线形成的线段的长度。为了使它看起来一致,你会希望所有这些线段的长度相同。使用上面的等式,y方向上的线段都是相同的长度,但不是与曲线正交的线段。

要做我认为你想要的事情,你必须计算你的片段到曲线的距离。当我试图快速解决时,数学比我希望的要复杂一点。你应该能够找到一些搜索词的方向,例如&#34;点抛物线距离&#34;。例如。这是此网站上的一个搜索结果:How to find the distance between a point and a parabola in code