2014-02-02 1 views
17

EDIT: Я решил проблему; вы можете увидеть мое решение в ответах.Что вызывает артефакты в моем raytracer?

Я в процессе написания raytracer в реальном времени с использованием OpenGL (в GLSL Compute Shader), и у меня возникла небольшая проблема с некоторыми из моих пересечений линий треугольника (или, по крайней мере, я считаю, что они являются виновником). Вот картина того, что происходит:

Spheres in a room with some artifacts

Как вы можете видеть, что некоторые пиксели будут окрашены в черный цвет, на пересечении двух треугольников в верхней части изображения. Вероятно, это связано с тем, как я обрабатываю поплавки или что-то в этом роде, и я попытался найти решение в Интернете, но не могу найти похожие ситуации. Возможно, есть ключевое ключевое слово, которое я пропускаю?

В любом случае, важная часть кода это одна:

#define EPSILON 0.001f 
#define FAR_CLIP 10000.0f 
float FindRayTriangleIntersection(Ray r, Triangle p) 
{ 
    // Based on Moller-Trumbone paper 
    vec3 E1 = p.v1 - p.v0; 
    vec3 E2 = p.v2 - p.v0; 
    vec3 T = r.origin - p.v0; 
    vec3 D = r.dir; 
    vec3 P = cross(D, E2); 
    vec3 Q = cross(T, E1); 

    float f = 1.0f/dot(P, E1); 
    float t = f * dot(Q, E2); 
    float u = f * dot(P, T); 
    float v = f * dot(Q, D); 

    if (u > -EPSILON && v > -EPSILON && u+v < 1.0f+EPSILON) return t; 
    else return FAR_CLIP; 
} 

Я пробовал различные значения для EPSILON, попытался вариации с +/- для EPSILON значений, но безрезультатно. Кроме того, изменение 1.0f+EPSILON на 1.0-EPSILON дает устойчивую черную линию на всем пути.

Также, чтобы уточнить, определенно нет промежутка между двумя треугольниками. Они плотно упакованы (и я также попытался расширить их, чтобы они пересекались, но я все равно получаю одни и те же черные точки).

Любопытно, что на нижнем перекрестке нет признаков этого явления.

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

ОБНОВЛЕНИЕ: Было указано, что «черные артефакты» на самом деле коричневые. Так что я выкопал немного глубже и выключил все отражения, и получил этот результат:

Spheres without reflections

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

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

Итак, я думаю, теперь вопрос сводится к следующему: как я могу иметь какую-то последовательность в определении того, какой треугольник следует ударять в таких случаях?

+0

Пикселы не черные, они темно-коричневые. Проблема заключается в маловероятности вашего кода пересечения лучей треугольника. – Soonts

+0

Спасибо, это было очень полезно для решения, я не понял. Я обновил свой пост с дополнительной информацией. –

+0

Попробуйте изменить EPSILON на 0.0f - что произойдет? – Soonts

ответ

8

Так получилось, что это был не код, который я опубликовал, что вызвало проблему. Благодаря некоторой помощи в комментариях, я был в состоянии найти именно этот код, когда я определить ближайший объект к камере:

float nearest_t = FAR_CLIP; 
int nearest_index = 0; 
for (int j=0; j<NumObjects; j++) 
{ 
    float t = FAR_CLIP; 
    t = FindRayObjectIntersection(r, objects[j]); 

    if (t < nearest_t && t > EPSILON && t < FAR_CLIP) 
    { 
     nearest_t = t; 
     nearest_index = j; 
    } 
} 

При определении т, иногда треугольники были так близко друг к другу, что t < nearest_t имел почти вероятностный результат, поскольку пересечения были примерно на таком же расстоянии от камеры.

Мое первоначальное решение было изменить внутреннее, если-заявление:

if (t < nearest_t-EPSILON && t > EPSILON && t < FAR_CLIP) 

Это гарантирует, что если два пересечения очень близко друг к другу, он всегда будет выбирать первый объект для отображения (если второй объект не является ближе по крайней мере к EPSILON). Вот результирующее изображение (с отражениями отключена):

Spheres

Теперь еще некоторые мелкие артефакты, так что было ясно, что по-прежнему существует небольшая проблема. Поэтому, когда некоторые обсуждения в комментариях, @Soonts придумали идею смешения цветов треугольников. Это привело меня, чтобы изменить код выше дополнительно для того, чтобы отслеживать расстояние до обоих треугольников:

if (t > EPSILON && t < FAR_CLIP && abs(nearest_t - t) < EPSILON) 
{ 
    nearest_index2 = nearest_index; 
    nearest_t2 = nearest_t; 
} 
if (t < nearest_t+EPSILON && t > EPSILON && t < FAR_CLIP) 
{ 
    nearest_t = t; 
    nearest_index = j; 
} 

Я также добавил этот цвет смешивания код:

OverallColor = mix(c1, c2, 0.5f * abs(T1 - T2)/EPSILON); 

После этих двух шагов, и честно говоря, я думаю, этот эффект был больше от изменения логики, чем смешивающие изменения, я получил этот результат:

Spheres

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

Happy raytracing

Happy трассировке лучей!

 Смежные вопросы

  • Нет связанных вопросов^_^