我有一个射线箱相交算法,该算法应该将距离返回到相交平面,但是不能满足我的期望。
我将相交点的位置的绝对值输出为颜色。我的期望是,无论相机在哪里,颜色都应该相同,因为交点没有移动。
不过,根据从哪里看,我的多维数据集有不同的颜色:
前视图:
微微左右视图(同一张脸):
您会看到颜色根据位置而改变。
我正在如下片段着色器上对整个结构进行光线追踪:
#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世界坐标系中的位置。
答案 0 :(得分:3)
原因是boxIntersection()
中的这一行:
dir = normalize(dir);
您正在计算的t
是x = 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)