В качестве учебного пособия я использую книгу «Ray Tracer From the Up», но у меня нет одинаковых результатов в одном и том же коде, я думаю, что это то же самое (я проверял это пару раз).
Моя проблема — сферическое отображение текстуры в сфере.
код (d_type :: Bfloat является двойным):
void getTexelCoord(const Vector3Bf localHitPoint, const d_type::Bint m_width, const d_type::Bint m_height, d_type::Bint& row, d_type::Bint& column) const
{
d_type::Bfloat theta=acosf(localHitPoint.y);
d_type::Bfloat phi= atan2f(localHitPoint.x,localHitPoint.z);
if(phi<0.0)
{
phi+=TWO_PI;
}
d_type::Bfloat u =phi*INV_TWO_PI;
d_type::Bfloat v=1-theta*INV_PI;
column = (d_type::Bint)((m_width-1)*u);
row = (d_type::Bint)((m_height-1)*v);
}virtual Colour getColour(const Info&info )const
{
d_type::Bint row,column;
if(m_mapping)
{
m_mapping->getTexelCoord(info.m_localHitPoint,hres, vres, row, column);
}
else
{
row=(int)(info.uv.x*(hres-1));
column=(int)(info.uv.y*(vres-1));
}
return m_image->getColour(row,column);
}Colour getColour(const int row, const int column) const {
int index = column + hres * (vres - row - 1);
int pixels_size = hres*vres;
if (index < pixels_size)
return (m_pixels[index]);
else
return (Colour::Red);
}
Местный хит в Сфере рассчитывается так:
info.m_localHitPoint=(ray.getOrigin()+(ray.getDirection()*t));
где T является точкой пересечения
В зависимости от вашего пространства координат, у меня есть следующее почти эквивалентный код в моем собственном трассировщике лучей:
double u = 0.5 - atan2(n.z, n.x) * math::one_over_2pi;
double v = 0.5 - asin(n.y) * math::one_over_pi;
Обратите внимание на использование 0.5, в моем случае все координаты находятся в диапазоне 0..1.
Это все странно … но сияние сферы должно быть 1 .. и все работает;)
Проблема была в локальном HitPoint. это было не локально, это было глобально, так что в этот Вопрос все объяснил. Код работающего SphereMapping:
void getTexelCoord(const Vector3Bf &localHitPoint, const d_type::Bint m_width, const d_type::Bint m_height, d_type::Bint& row, d_type::Bint& column) const
{
Vector3Bf normal=localHitPoint - m_sphere->getCenter();
Vector3Bf::normalize(normal);
d_type::Bfloat u=0.5+atan2(normal.z,normal.x)*INV_TWO_PI;
d_type::Bfloat v = 0.5-asin(normal.y)*INV_PI;
column =(int)(m_width*u);
row =(int)(m_height)*v;
}
Где m_sphere — сфера, которая имеет материал (текстуру) этого отображения.