此别名的来源可能是什么?

时间:2018-06-21 23:09:36

标签: c++ opengl graphics glsl aliasing

我正在手动跟踪3D图像。我注意到,离3D图像越远,混叠就越大。

此3D图像基本上是斯坦福巨龙的体素化表示。我将音量置于原点中心(对角线交叉于(0,0,0)),这意味着其中一个角位于(-cube_dim,-cube_dim,-cube_dim),另一个位于(cube_dim,cube_dim, cube_dim)。

在近距离下图像很好:

enter image description here

(您在此处看到的次要“别名”是由于我执行了光线行进算法,这不是我担心的别名,这是预期的并可以接受)

但是,如果我们走得足够远,就会出现一些混叠现象:enter image description here (这是完全不同的别名)

用于生成图像的片段着色器是这样的:

#version 430

in vec2 f_coord;

out vec4 fragment_color;

uniform layout(binding=0, rgba8) image3D volume_data;

uniform vec3 camera_pos;
uniform float aspect_ratio;
uniform float cube_dim;
uniform int voxel_resolution;

#define EPSILON 0.01
// Check whether the position is inside of the specified box
bool inBoxBounds(vec3 corner, float size, vec3 position)
{
    bool inside = true;
    //Put the position in the coordinate frame of the box
    position-=corner;
    //The point is inside only if all of it's components are inside
    for(int i=0; i<3; i++)
    {
        inside = inside && (position[i] > -EPSILON);
        inside = inside && (position[i] < size+EPSILON);
    }

    return inside;
}
//Calculate the distance to the intersection to a box, or inifnity if the bos cannot be hit
float boxIntersection(vec3 origin, vec3 dir, vec3 corner0, float size)
{
    //dir = normalize(dir);
    //calculate opposite corner
    vec3 corner1 = corner0 + vec3(size,size,size);

    //Set the ray plane intersections
    float coeffs[6];
    coeffs[0] = (corner0.x - origin.x)/(dir.x);
    coeffs[1] = (corner0.y - origin.y)/(dir.y);
    coeffs[2] = (corner0.z - origin.z)/(dir.z);
    coeffs[3] = (corner1.x - origin.x)/(dir.x);
    coeffs[4] = (corner1.y - origin.y)/(dir.y);
    coeffs[5] = (corner1.z - origin.z)/(dir.z);

    float t = 1.f/0.f;
    //Check for the smallest valid intersection distance
    //We allow negative values up to -size to create correct sorting if the origin is
    //inside the box
    for(uint i=0; i<6; i++)
        t = (coeffs[i]>=0) && inBoxBounds(corner0,size,origin+dir*coeffs[i])?
            min(coeffs[i],t) : t;

    return t;
}

void main()
{
    float v_size = cube_dim/voxel_resolution;
    vec3 r = (vec3(f_coord.xy,1.f/tan(radians(40))));
    r.y /= aspect_ratio;
    vec3 dir = normalize(r);//;*v_size*0.5;
    r+= camera_pos;

    float t = boxIntersection(r, dir, -vec3(cube_dim), cube_dim*2);

    if(isinf(t))
        discard;

    if(!((r.x>=-cube_dim) && (r.x<=cube_dim) && (r.y>=-cube_dim) &&
        (r.y<=cube_dim) && (r.z>=-cube_dim) && (r.z<=cube_dim)))
    r += dir*t;

    vec4 color = vec4(0);
    int c=0;
    while((r.x>=-cube_dim) && (r.x<=cube_dim) && (r.y>=-cube_dim) &&
        (r.y<=cube_dim) && (r.z>=-cube_dim) && (r.z<=cube_dim))
    {
        r += dir*v_size*0.5;
        vec4 val = imageLoad(volume_data, ivec3(((r)*0.5/cube_dim+vec3(0.5))*(voxel_resolution-1)));

        if(val.w > 0)
        {
            color = val;
            break;
        }
        c++;
    }
    fragment_color = color;
}

了解算法

首先,我们基于屏幕坐标创建射线(我们使用标准射线跟踪技术,焦距为1 / tan(角度))。

然后我们在相机的当前位置开始光线

我们检查射线与包含对象的盒子的交集(我们基本上假设3D纹理在场景中是一个大立方体,然后检查是否击中了它)。

如果我们不击中它,我们将丢弃该碎片。如果我们确实击中它,而我们在外面,则沿着射线移动,直到到达盒子的表面。如果我们击中它并进入里面,我们将留在原处。

在这一点上,我们保证射线的位置在盒子内部。

现在,我们沿着射线沿小段移动,直到找到一个非零值或到达方框的末端为止。

0 个答案:

没有答案