Я работаю над алгоритмом raytracing для класса и столкнулся с какой-то странной проблемой.Артефакты отражения отражения и прозрачность
Это основная сцена, которую я сейчас работаю. Ничего серьезного, все в порядке. Теперь мой код организован таким образом:
Image* Tracer::render()
{
int w = _scr.width();
int h = _scr.height();
Image* im = new Image(w, h);
int i, j;
for(i = 0; i < h; i++)
{
for(j = 0; j < w; j++)
{
im->setColour(i, j, render(i, j));
}
}
return im;
}
Я вызываю эту функцию для генерации изображения. Для того, чтобы цвет каждого пикселя:
Vec Tracer::render(int i, int j)
{
Vec pxlcol(0,0,0);
Vec p(0,0,0);
int obj;
Vec dir = _scr.point(i,j);
dir = dir - _obs;
obj = intercept(_obs, dir, p);
if(obj != -1)
{
pxlcol = objCol(_obs, p, obj, _ref);
}
return pxlcol;
}
Где INT Tracer :: перехватывает (Vec о, Vec д, Vec & р) является следующей функцией
int Tracer::intercept(Vec o, Vec d, Vec& p)
{
int obj, k;
Vec temp = o;
Vec ptry = o;
obj = -1;
for(k = 0; k < _nobj; k++)
{
temp = _obj[k]->intercept(o, d);
if(!(temp == o) && (((temp - o).mod() < (ptry - o).mod()) || (ptry == o)))
{
ptry = temp;
obj = k;
}
}
p = ptry;
return obj;
}
, который находит индекс к объекту который перехватывает луч г начиная с ö, а также возвращает точку р, где такое происходит перехват и Vec Tracer :: objCol (Vec о, Ve ф, Int OBJ, Int г) функция
Vec Tracer::objCol(Vec o, Vec p, int obj, int r)
{
Vec colour(0,0,0);
Vec point(0,0,0), reflected(0,0,0);
unit ref = _obj[obj]->ref(p);
if((1 - ref) > 0)
point = pointCol(o, p, obj);
if(ref > 0 && r > 0)
reflected = refCol(o, p, _obj[obj]->normal(o, p), r - 1);
colour = (point*(1 - ref)) + (reflected*ref);
return colour;
}
, который находит цвет, который указывал р посылает в направлении о зная, что он принадлежит к объекту OBJ и что максимальное число разрешенные отражения r.
Когда я делаю назад (белый) стена отражает свет, это результат:
Выглядит довольно хорошо, никаких проблем там. Теперь, если я право (синий) стена отражающий результат заключается в следующем:
(я не могу отправить более чем 2 ссылки еще, удалите круглые скобки, чтобы увидеть изображение). И это становится еще хуже, если я решу сделать сферу отражающих:
Он становится прозрачным! И я не знаю, почему это произойдет, так как я искал перехват лучей, прежде чем добираться до цветов.
Вот мои коды для нахождения цвета точки и отраженный цвет:
Vec Tracer::pointCol(Vec o, Vec p, int obj)
{
Vec pcol(0,0,0);
Vec inten(0,0,0);
unit cos = 0;
Vec c(0,0,0);
Vec normal = _obj[obj]->normal(o, p);
Vec inter = o;
Vec objcol = _obj[obj]->colour(p);
bool block = false;
if(_amb == 1)
return objcol;
int l = 0;
int k = 0;
for(l = 0; l < _nlight; l++)
{
c = _li[l]->getPos() - p;
block = false;
if(c*normal > 0)
{
for(k = 0; k < _nobj; k++)
{
if(k != obj)
{
inter = _obj[k]->intercept(p, c);
inter = inter - p;
if(!(inter.null()) && (inter.mod() < c.mod()))
{
block = true;
k = _nobj;
}
}
}
if(!block)
{
cos = (c*normal)/(c.mod()*normal.mod());
inten = inten + _li[l]->getInt()*cos;
}
}
}
inten = inten.div(_totalinten);
pcol = objcol*_amb + objcol.multi(inten)*(1 - _amb);
return pcol;
}
Константа _amb определяет, сколько из света окружающего света и сколько рассеивается.
Функция Vec Vec :: DIV (Vec v) возвращает точечную деление векторов (например, (а, б, в) .div ((х, у, г)) = (а/х, b/y, c/z)). Функция Vec Vec :: multi (Vec v) делает то же самое для умножения.
Vec Tracer::refCol(Vec o, Vec p, Vec n, int r)
{
Vec rcol(0,0,0);
Vec i = p - o;
Vec refl(0,0,0);
int obj = 0;
Vec point(0,0,0);
i.normalise();
refl = reflected(i, n);
obj = intercept(p, refl, point);
if(obj != -1)
{
rcol = objCol(p, point, obj, r);
}
return rcol;
}
С objCol вызовы refCol с параметром R-1, число отражений ограничена сверху _ref.
Любая идея, что может вызвать эти странные эффекты отражения?
Кровавый ад это сработало: O Я пробовал первое, перемещая точку пересечения немного по нормали, я попробую другую вещь. –
Рад это слышать - я изменил комментарий на ответ и написал немного больше, чтобы объяснить, что происходит. – schnaader