Назад | Содержание | Вперед
Данная техника позволяет без геометрического изменения поверхности и, как следствие, не сильно замедляя трассировку, получить эффект шероховатости. У материала появляется еще одна карта – карта высоты (bump map). В зависимости от яркости точки, условно "поднимаются" точки на поверхности. Особенность заключается в том, что сама поверхность не изменяется, а меняется только нормаль в точке. К нормали прибавляются небольшие вектора: чем больше разность высот между точками, тем больше нужен прибавляемый вектор. Из-за этого, с помощью такой техники невозможно получить тени от возвышенностей, но для имитации мелких деталей она подходит идеально.
Рассмотрим задачи, которые нужно решить для получения эффекта.
Во-первых, необходимо найти единичные вектора, которые мы будем прибавлять к нормали. Напомню, что основным примитивом в демонстрационной программе является треугольник. Следовательно, у нас есть пространственные (x, y, z) и текстурные (u, v, w) координаты вершин треугольника. Из текстурных координат здесь используются только u и v (да и сам бамп-меппинг в программе пока реализован только для растровых карт). Из несложных построений и последовательности преобразований можно получить следующий алгоритм для этого:
void Triangle::Prepare() { ... // ptw0, ptw1, ptw2 - пространсвенные координаты вершин // texture0, texture1, texture2 - текстурные координаты // bump_du, bump_dv - векторы смещения для нормали VectorSubtraction(&vw1, ptw1, ptw0); VectorSubtraction(&vw2, ptw2, ptw0); REAL du1 = texture1.x - texture0.x; REAL du2 = texture2.x - texture0.x; REAL dv1 = texture1.y - texture0.y; REAL dv2 = texture2.y - texture0.y; REAL d = du2*dv1 - du1*dv2; bump_dv.x = du2*vw1.x - du1*vw2.x; bump_dv.y = du2*vw1.y - du1*vw2.y; bump_dv.z = du2*vw1.z - du1*vw2.z; bump_du.x = dv2*vw1.x - dv1*vw2.x; bump_du.y = dv2*vw1.y - dv1*vw2.y; bump_du.z = dv2*vw1.z - dv1*vw2.z; if (d > EPS) { bump_dv.Normalize(); bump_du.Normalize(); bump_dv.Invert(); } else if (d < - EPS) { bump_dv.Normalize(); bump_du.Normalize(); bump_du.Invert(); } else { bump_dv = Vector(0.0f, 0.0f, 0.0f); bump_du = Vector(0.0f, 0.0f, 0.0f); } }
Во-вторых, необходимо найти яркости точек, вычислить разности, произвести сглаживание полученных величин. Если с поиском яркости точек и нахождением разности проблем возникнуть не должно, то со сглаживанием придется повозится.
Простейший способ найти величину смещения вектора – взять разность яркости точки над и под искомой точкой. Но у такого решения будет большой минус – будут видны переходы между пикселями в растре. Чтобы от этого избавиться можно добавить билинейное сглаживание (билинейная фильтрация, bilinear filtering).
Билинейная фильтрация – просто напросто линейная интерполяция четырех пикселей в растровом изображении. Пара вещественных координат (x, y) определяет четыре точки на растре, а два вещественных остатка определяют весовые коэффициенты для них.
Дальше только дело техники. Если в треугольнике, с которым найдено пересечение, используется бамп-карта, в растре высчитывается разность яркости пар точек с текстурными координатами (u + 1, v), (u - 1, v) и (u, v - 1), (u, b + 1) (вместо единицы можно попробовать использовать другие числа, например 0,5 или 0,25). Затем, к найденной нормали в точке прибавляются соответственные вектора bump_du, bump_dv, умноженные на найденные разности. Все.
Назад | Содержание | Вперед