Несколько вопросов о трассировке лучей с помощью opengl - PullRequest
7 голосов
/ 27 июля 2011

Мне нужно сделать ограниченную форму трассировки лучей.Мне не нужны размышления.Мне нужно только изменить цвет пикселя, в зависимости от того, как он проходит мимо объекта и преломления.Мне также нужно только проверить наличие пересечений между лучом, сферами и дисками, и ничего больше.

Это основная функция моего шейдера:

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);
        }
}

Проблема в том, что если тела [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 ]

3 голосов
/ 27 июля 2011

Что касается вашего второго вопроса: не используйте расстояние, используйте квадратное расстояние. Это более быстрая обработка, и я подозреваю, что это может решить вашу проблему.

1 голос
/ 06 июля 2017

Точка пересечения луча и плоскости рассчитывается следующим образом:

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);
    }
}
1 голос
/ 27 апреля 2012
  1. Начало луча действительно зависит от вас, однако я рекомендую вам указать исходную точку так, чтобы положения пикселей были приблизительно равноудалены от начала координат и объектов.

  2. Будьте осторожны с направлением луча, это означает, что объекты, которые вы пытаетесь увидеть, должны находиться перед камерой. (Отправляемые лучи должны попадать на объекты.)

...