射线盒相交计算错误的距离

时间:2018-06-20 02:26:46

标签: opengl math graphics geometry glsl

我有一个射线箱相交算法,该算法应该将距离返回到相交平面,但是不能满足我的期望。

我将相交点的位置的绝对值输出为颜色。我的期望是,无论相机在哪里,颜色都应该相同,因为交点没有移动。

不过,根据从哪里看,我的多维数据集有不同的颜色:

前视图:

enter image description here

微微左右视图(同一张脸):

enter image description here

您会看到颜色根据位置而改变。

我正在如下片段着色器上对整个结构进行光线追踪:

#version 430

in vec2 f_coord;

out vec4 fragment_color;

uniform vec3 camera_pos;
uniform float aspect_ratio;
uniform float cube_dim;

#define EPSILON 0.0001
// 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
    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()
{
    vec3 r = vec3(f_coord.x, f_coord.y, 1.f/tan(radians(40)));
    vec3 dir = r;
    dir.y /= aspect_ratio;
    r = camera_pos;
    float t = boxIntersection(r, dir, vec3(-cube_dim), cube_dim*2);
    if(isinf(t))
        discard;
    r += dir*(t);

    fragment_color = vec4(abs(r)/100,0);
}

编辑:

f_coord是从-1到1(opengl窗口中的归一化屏幕坐标)的归一化坐标系

camera_pos是相机在3D世界坐标系中的位置。

1 个答案:

答案 0 :(得分:3)

原因是boxIntersection()中的这一行:

dir = normalize(dir);

您正在计算的tx = origin + t * dir中的ray参数。如果对dir进行归一化,则t等于欧几里得距离。

但是在main()中,您使用了不同的dir

r += dir*(t);

在这里,dir未标准化,因此您得到了不同的交点。

解决方案很简单:根本不进行标准化。或者,如果您需要实际距离,请在main()中而不是boxIntersection()进行归一化。另外,您可以将dir参数设置为inout参数。这样,从函数内部对dir所做的任何更改都会反映回调用者:

float boxIntersection(vec3 origin, inout vec3 dir, vec3 corner0, float size)