Я делаю программный растеризатор для школы и использую необычный метод рендеринга вместо традиционных матричных вычислений. Он основан на камере-обскуре . У меня есть несколько точек в 3D-пространстве, и я преобразую их в 2D-координаты экрана, беря расстояние между ним и камерой и нормализуя его
Vec3 ray_to_camera = (a_Point - plane_pos).Normalize();
Это дает мне вектор направления к камере. Затем я превращаю это направление в луч, помещая источник луча на камеру и выполняя пересечение плоскости луча с плоскостью, немного расположенной за камерой.
Vec3 plane_pos = m_Position + (m_Direction * m_ScreenDistance);
float dot = ray_to_camera.GetDotProduct(m_Direction);
if (dot < 0)
{
float time = (-m_ScreenDistance - plane_pos.GetDotProduct(m_Direction)) / dot;
// if time is smaller than 0 the ray is either parallel to the plane or misses it
if (time >= 0)
{
// retrieving the actual intersection point
a_Point -= (m_Direction * ((a_Point - plane_pos).GetDotProduct(m_Direction)));
// subtracting the plane origin from the intersection point
// puts the point at world origin (0, 0, 0)
Vec3 sub = a_Point - plane_pos;
// the axes are calculated by saying the directional vector of the camera
// is the new z axis
projected.x = sub.GetDotProduct(m_Axis[0]);
projected.y = sub.GetDotProduct(m_Axis[1]);
}
}
Это прекрасно работает, но мне интересно: можно ли сделать алгоритм быстрее? Прямо сейчас, для каждого треугольника в сцене, я должен вычислить три нормали.
float length = 1 / sqrtf(GetSquaredLength());
x *= length;
y *= length;
z *= length;
Даже с быстрым приближением квадратного корня (1 / sqrt(x)
) это будет очень требовательным.
Мои вопросы таковы:
Есть ли хороший способ приблизить три нормали?
Как называется эта техника рендеринга?
Можно ли аппроксимировать три точки вершины, используя нормаль центроида? ((v0 + v1 + v2) / 3)
Заранее спасибо.
P.S. «В течение следующих семи недель вы создадите полнофункциональный программный растеризатор с помощью эксперта в этой области. Начните». Я обожаю свое образование. :)
EDIT:
Vec2 projected;
// the plane is behind the camera
Vec3 plane_pos = m_Position + (m_Direction * m_ScreenDistance);
float scale = m_ScreenDistance / (m_Position - plane_pos).GetSquaredLength();
// times -100 because of the squared length instead of the length
// (which would involve a squared root)
projected.x = a_Point.GetDotProduct(m_Axis[0]).x * scale * -100;
projected.y = a_Point.GetDotProduct(m_Axis[1]).y * scale * -100;
return projected;
Возвращает правильные результаты, однако модель теперь не зависит от положения камеры. (
Хотя это намного короче и быстрее!