关于使用opengl进行光线跟踪的几个问题

时间:2011-07-26 20:43:51

标签: opengl glsl raytracing

我需要进行有限形式的光线追踪。我不需要反思。我只需要改变一个像素的颜色,这取决于它如何通过一个物体和折射。我也只需要测试光线和球体和磁盘之间的交叉点,没有别的。

这是我的着色器中的主要功能:

void main(void)
{
    Ray ray;
    ray.origin=vec3(0.5,0.5,.75);

    ray.direction=vec3(gl_FragCoord.x/width,gl_FragCoord.y/height,-gl_FragCoord.z)-ray.origin;
    ray.direction=normalize(ray.direction);

    gl_FragColor=trace(ray);
}

我的第一个问题是关于射线的起源。我如何获得它的位置?现在,我只是在它看起来正确,但如果我改变屏幕的宽度或高度,我必须四处玩,直到它看起来正确。

我的第二个问题是光线与光盘的交叉点。我这样做是首先检查光线是否与平面相交,然后检查交叉点是否在光盘的半径范围内。 我的代码看起来像这样

float intersectPlane(Ray ray,vec3 point,vec3 normal)
{
    return dot(point-ray.origin,normal)/dot(ray.direction,normal);
}
...

det=intersectPlane(ray,bodies[count].position,vec3(0,0,1));
if(det>0)
{
        if(distance(det*ray.direction,bodies[count].position)<=bodies[count].radius) 
        {
            return vec4(1.0,0.0,0.0,1.0);
        }
}

问题在于,如果body [count] .radius小于或等于光线原点的z位置,则不显示任何内容。所以

if(det>0)
{
        if(distance(det*ray.direction,bodies[count].position)<=.76) 
        {
            return vec4(1.0,0.0,0.0,1.0);
        }
}

导致可见磁盘,而使用实际半径则无效。

3 个答案:

答案 0 :(得分:3)

至于你的第二个问题:不要使用距离,使用平方距离。这是更快的处理,我怀疑它可以解决你的问题。

答案 1 :(得分:1)

  1. 光线的来源实际上取决于你,但我建议你指定原点,使像素位置与原点和物体大致等距。

  2. 请注意光线的方向,这意味着您要查看的对象必须位于相机前方。 (发送的光线必须击中物体。)

答案 2 :(得分:1)

光线和平面的交点计算如下:

dist = dot( plane_origin - ray.origin, plane_NV ) / dot( ray.direction, plane_NV );
plane_isect = ray.origin + ray.direction * dist;

您的函数intersectPlane计算从光源原点到平面交点的距离,但在将其与光盘中心进行比较之前,不要计算交点。

要测试交叉点是否在半径范围内,您必须执行以下操作:

vec3 plane_isect = ray.origin + det * ray.direction;
if ( distance( plane_isect, bodies[count].position ) <= bodies[count].radius ) 

像这样调整你的代码:

det = intersectPlane( ray, bodies[count].position, vec3(0,0,1) );
if ( det>0 )
{
    vec3 plane_isect = ray.origin + det * ray.direction;
    if ( distance( plane_isect, bodies[count].position ) <= bodies[count].radius ) 
    {
        return vec4(1.0,0.0,0.0,1.0);
    }
}