Direct Volume Rendering Texture overlapping artifacts

146 views Asked by At

I'm trying to use the direct volume rendering in Chai3D, but there is an artifact that makes the edges of the hosting boundary mesh always visible, even when there is another object in front of it. Any cues of what could be causing the issue?

Edge Artifact

The whole code can be seen here, the application runs regardless of having a haptic device connected to it:

Chai3D Direct Volume Rendering example

Here is the shader code:

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;
}

This is the rendering function, which can be seen inside renderSceneGraph here, I have attempted to use single and multipass:

    //-----------------------------------------------------------------------
// Init
//-----------------------------------------------------------------------

glEnable(GL_LIGHTING);
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);

//-----------------------------------------------------------------------
// Render bounding box, frame, collision detector. (opaque components)
//-----------------------------------------------------------------------
if (SECTION_RENDER_OPAQUE_PARTS_ONLY(a_options) && (!a_options.m_rendering_shadow))
{
    // disable lighting
    glDisable(GL_LIGHTING);

    // render boundary box
    if (m_showBoundaryBox)
    {
        // set size on lines
        glLineWidth(1.0);

        // set color of boundary box
        glColor4fv(s_boundaryBoxColor.getData());

        // draw box line
        cDrawWireBox(m_boundaryBoxMin(0) , m_boundaryBoxMax(0) ,
                     m_boundaryBoxMin(1) , m_boundaryBoxMax(1) ,
                     m_boundaryBoxMin(2) , m_boundaryBoxMax(2) );
    }

    // render collision tree
    if (m_showCollisionDetector && (m_collisionDetector != NULL))
    {
        m_collisionDetector->render(a_options);
    }

    // enable lighting
    glEnable(GL_LIGHTING);
}

// render frame
if (m_showFrame && (a_options.m_single_pass_only || a_options.m_render_opaque_objects_only))
{
    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_INDEX_ARRAY);
    glDisableClientState(GL_EDGE_FLAG_ARRAY);
    glDisable(GL_COLOR_MATERIAL);

    glEnable(GL_COLOR_MATERIAL);
    glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
    glColor4f(1.0,1.0,1.0,1.0);

    // set rendering properties
    glPolygonMode(GL_FRONT, GL_FILL);
        
    // draw frame
    cDrawFrame(m_frameSize, m_frameThicknessScale);
}

//-----------------------------------------------------------------------
// Render graphical representation of object
//-----------------------------------------------------------------------
if (m_showEnabled)
{
    // set polygon and face mode
    glPolygonMode(GL_FRONT_AND_BACK, m_triangleMode);

    // initialize line width
    glLineWidth(1.0f);

    /////////////////////////////////////////////////////////////////////
    // CREATING SHADOW DEPTH MAP
    /////////////////////////////////////////////////////////////////////
    if (a_options.m_creating_shadow_map)
    {
        glEnable(GL_CULL_FACE);
        glCullFace(GL_FRONT);

        // render object
        render(a_options);
        glDisable(GL_CULL_FACE);
    }

    /////////////////////////////////////////////////////////////////////
    // SINGLE PASS RENDERING
    /////////////////////////////////////////////////////////////////////
    else if (a_options.m_single_pass_only)
    {
        if (m_cullingEnabled)
        {
            glEnable(GL_CULL_FACE);
            glCullFace(GL_BACK);
        }
        else
        {
            glDisable(GL_CULL_FACE);
        }

        if (m_useTransparency)
        {
            glEnable(GL_BLEND);
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
            glDepthMask(GL_FALSE);
        }
        else
        {
            glDisable(GL_BLEND);
            glDepthMask(GL_TRUE);
        }

        // render object
        render(a_options);

        // disable blending
        glDisable(GL_BLEND);
        glDepthMask(GL_TRUE);
    }


    /////////////////////////////////////////////////////////////////////
    // MULTI PASS RENDERING
    /////////////////////////////////////////////////////////////////////
    else
    {
        // opaque objects
        if (a_options.m_render_opaque_objects_only)
        {
            if (m_cullingEnabled)
            {
                glEnable(GL_CULL_FACE);
                glCullFace(GL_BACK);
            }
            else
            {
                glDisable(GL_CULL_FACE);
            }

            render(a_options);
        }

        // render transparent back triangles
        if (a_options.m_render_transparent_back_faces_only)
        {
            if (m_useTransparency)
            {
                glEnable(GL_BLEND);
                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                glDepthMask(GL_FALSE);
            }
            else
            {
                glDisable(GL_BLEND);
                glDepthMask(GL_TRUE);
            }

            glEnable(GL_CULL_FACE);
            glCullFace(GL_FRONT);
            
            render(a_options);

            // disable blending
            glDisable(GL_BLEND);
            glDepthMask(GL_TRUE);
        }

        // render transparent front triangles
        if (a_options.m_render_transparent_front_faces_only)
        {
            if (m_useTransparency)
            {
                glEnable(GL_BLEND);
                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                glDepthMask(GL_FALSE);
            }
            else
            {
                glDisable(GL_BLEND);
                glDepthMask(GL_TRUE);
            }

            glEnable(GL_CULL_FACE);
            glCullFace(GL_BACK);

            render(a_options);
    
            // disable blending
            glDisable(GL_BLEND);
            glDepthMask(GL_TRUE);
        }
    }
}
0

There are 0 answers