【问题标题】:Ray box intersection computing wrong distances光线盒相交计算错误距离
【发布时间】:2018-11-29 01:29:56
【问题描述】:

我有一个光线盒相交算法,据说它可以返回相交平面的距离,但它没有达到我的预期。

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

但是我的立方体有不同的颜色,这取决于它从哪里看:

前视图:

略 uo 和右视图(同一张脸):

如您所见,颜色已根据位置发生变化。

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

#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 世界坐标系中的位置。

【问题讨论】:

  • 什么是f_coord,它在什么坐标系中?你除以纵横比看起来有点奇怪。 camera_pos 生活在什么坐标系中?
  • 如果我看对了,那么你正在投射你的光线,因为透视相机正在看,所以光线不平行......这意味着即使你的平面与 znear 投影平面平行,每条光线都击中不同的距离...您应该从屏幕中心看到一个类似圆圈的图案...
  • f_coord是像素在-1到1的opengl规范化坐标系中的位置,camera_pos活在世界坐标系中
  • @Makogan 看看这个How to best write a voxel engine in C with performance in mind 看看顶点着色器,它的唯一目的是投射这样的光线......如果没有偏差,请与你的东西比较......
  • @Spektre 我不确定我是否理解您的评论。光线确实不平行,因为这不是正交投影光线追踪。然而问题不在于一帧立方体有不同的颜色而不是相同的颜色,而是当我移动相机时,立方体的颜色会发生变化。然而,我的期望是,立方体没有移动,只有相机移动了,因此交点应该相同,因此无论相机在哪里,立方体的颜色都应该是相同的(在我展示的图片)

标签: opengl math graphics geometry glsl


【解决方案1】:

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

dir = normalize(dir);

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

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

r += dir*(t);

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-11
    • 1970-01-01
    • 2012-12-31
    相关资源
    最近更新 更多