直接体渲染纹理重叠伪影

问题描述 投票:0回答:1

我尝试在 Chai3D 中使用直接体积渲染,但有一个伪影使托管边界网格的边缘始终可见,即使在其前面有另一个对象也是如此。有任何可能导致问题的线索吗?

完整代码可以在这里看到,无论是否连接了触觉设备,应用程序都会运行:

Chai3D 直接体渲染示例

这是着色器代码:

uniform vec3 uMinCorner;
uniform vec3 uMaxCorner;
uniform vec3 uTextureScale;
uniform vec3 uGradientDelta;
uniform sampler3D uVolume;
uniform sampler1D uColorLUT;
uniform float uIsosurface;
uniform float uOpacityThreshold;
uniform float uOpticalDensityFactor;
uniform float uResolution;

varying vec4 vPosition;

vec3 dx = vec3(uGradientDelta.x, 0.0, 0.0);
vec3 dy = vec3(0.0, uGradientDelta.y, 0.0);
vec3 dz = vec3(0.0, 0.0, uGradientDelta.z);

float entry(vec3 e1, vec3 d)
{
    float t = distance(uMinCorner, uMaxCorner);
    vec3 a = (uMinCorner - e1) / d;
    vec3 b = (uMaxCorner - e1) / d;
    vec3 u = min(a, b);
    return max(max(-t, u.x), max(u.y, u.z));
}

vec3 gradient(vec3 tc)
{
    vec3 nabla = vec3(
        texture3D(uVolume, tc + dx).r - texture3D(uVolume, tc - dx).r,
        texture3D(uVolume, tc + dy).r - texture3D(uVolume, tc - dy).r,
        texture3D(uVolume, tc + dz).r - texture3D(uVolume, tc - dz).r
    );
    return (nabla / uGradientDelta) * uTextureScale;
}

vec3 shade(vec3 p, vec3 v, vec3 n)
{
    vec4 lp = gl_ModelViewMatrixInverse * gl_LightSource[0].position;
    vec3 l = normalize(lp.xyz - p * lp.w);
    vec3 h = normalize(l + v);
    float cos_i = max(dot(n, l), 0.0);
    float cos_h = max(dot(n, h), 0.0);
    vec3 Ia = gl_FrontLightProduct[0].ambient.rgb;
    vec3 Id = gl_FrontLightProduct[0].diffuse.rgb * cos_i;
    vec3 Is = gl_FrontLightProduct[0].specular.rgb * pow(cos_h, gl_FrontMaterial.shininess);
    return (Ia + Id + Is);
}

void main(void)
{
    vec4 camera = gl_ModelViewMatrixInverse * vec4(0.0, 0.0, 0.0, 1.0);
    vec3 raydir = normalize(vPosition.xyz - camera.xyz);
    float t_entry = entry(vPosition.xyz, raydir);
    t_entry = max(t_entry, -distance(camera.xyz, vPosition.xyz);
    float t_step = distance(uMinCorner, uMaxCorner) / uResolution;
    vec3 tc_step = uTextureScale * (t_step * raydir);
    vec4 sum = vec4(0.0);
    vec3 tc = gl_TexCoord[0].stp + t_entry * tc_step / t_step;
    
    for (float t = t_entry; t < 0.0; t += t_step, tc += tc_step)
    {
        float intensity = texture3D(uVolume, tc).r;
        vec4 colour = texture1D(uColorLUT, intensity);
        if (colour.a < 0.001) continue;
        vec3 nabla = gradient(tc);
        vec3 position = vPosition.xyz + t * raydir;
        vec3 normal = -normalize(nabla);
        vec3 view = -raydir;
        vec3 shaded = shade(position, view, normal);
        colour.rgb *= shaded;
        float Tr = exp(-colour.a * uOpticalDensityFactor);
        colour.rgb *= 1.0 - Tr;
        colour.a = 1.0 - Tr;
        sum += (1.0 - sum.a) * colour;
        if (sum.a > uOpacityThreshold)
        {
            vec4 clip = gl_ModelViewProjectionMatrix * vec4(position, 1.0);
            gl_FragDepth = (gl_DepthRange.diff * clip.z / clip.w + gl_DepthRange.near + gl_DepthRange.far) * 0.5;
            break;
        }
    }
    
    gl_FragColor = sum;
}

这是我的主要图形循环:

    while (!glfwWindowShouldClose(window))
    {
        // get width and height of window
        glfwGetWindowSize(window, &width, &height);
    
        // render graphics
        updateGraphics();
    
        // swap buffers
        glfwSwapBuffers(window);
    
        // process events
        glfwPollEvents();
    
        // signal frequency counter
        freqCounterGraphics.signal(1);
    }

UpdateGraphics() 使用 Chai3D 函数:

// update shadow maps (if any)
world->updateShadowMaps(false, mirroredDisplay);

// render world
camera->renderView(width, height);

// wait until all GL commands are completed
glFinish();
c++ opengl glsl glfw haptic-feedback
1个回答
0
投票

这些伪影可能是由于体渲染针对其他对象的深度排序不正确造成的。确保首先渲染不透明对象,然后渲染体渲染以与背景正确混合。使用适当的深度测试和混合设置以避免与深度相关的伪影。

glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

另一个原因可能是体数据的采样和插值。确保您正确地对体积数据进行采样,并且使用三线性或各向异性过滤来最大限度地减少伪影。

glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

在着色器中,您应该考虑启用背面剔除以减少与渲染体积背面相关的伪影。

glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
© www.soinside.com 2019 - 2024. All rights reserved.