Было время, когда разбирался с реализацией Bump и Parallax Mapping.
В статьях которые я находил, помнится очень раздражали высказывания типа:
"... Для расчета карт нормалей существуют специальные программы. На сайте nVidia для разработчиков есть плагин к PhotoShop'у. Все они действуют по одному и тому же принципу. В них задается карта высот, которая представляет собой черно-белое изображение, на котором более светлые пятна соответствует более высоким местам ..."(из оригинала).
Это не хорошо и не плохо. Просто нужна была конкретика.
Что нам может дать собственный расчет? Он избавит нас от необходимости включения в проект предварительно рассчитанных normal map текстур. И тем самым сократить размер дистрибутива. Так же во время расчета, проигравшись с коэффициентами, можно добиться различных результатов.
Потому, дабы сэкономить Вам время, привожу свой пример для XNA GS.
private Texture2D GenNormalMamp(Texture2D inTex)
{
int x = inTex.Width;
int y = inTex.Height;
int l = x * y;
Texture2D outTex = new Texture2D(graphics.GraphicsDevice, x, y);
Color[] color = new Color[l];
float[] height = new float[l];
inTex.GetData
for (int i = 0; i < l; i++)
{
Vector3 v3 = color[i].ToVector3();
height[i] = (v3.X + v3.Y + v3.Z) / 3;
}
float[] delHeight = new float[8];
Vector3[] v38 = new Vector3[8];
for (int iy = 0; iy < y; iy++)
{
for (int ix = 0; ix < x; ix++)
{
if (iy == 0 || iy == y - 1 || ix == 0 || ix == x - 1)
{
color[iy * x + ix] = new Color(0.5f, 0.5f, 1f, 1f);
continue;
}
delHeight[0] = height[iy * x + ix] - height[(iy - 1) * x + ix - 1];
delHeight[1] = height[iy * x + ix] - height[(iy - 1) * x + ix ];
delHeight[2] = height[iy * x + ix] - height[(iy - 1) * x + ix + 1];
delHeight[3] = height[iy * x + ix] - height[iy * x + ix - 1];
delHeight[4] = height[iy * x + ix] - height[iy * x + ix + 1];
delHeight[5] = height[iy * x + ix] - height[(iy + 1) * x + ix - 1];
delHeight[6] = height[iy * x + ix] - height[(iy + 1) * x + ix ];
delHeight[7] = height[iy * x + ix] - height[(iy + 1) * x + ix + 1];
v38[0] = new Vector3(-delHeight[0], -delHeight[0], 1f);
v38[1] = new Vector3(0f, -delHeight[1], 1f);
v38[2] = new Vector3(delHeight[2], -delHeight[2], 1f);
v38[3] = new Vector3(-delHeight[3], 0f, 1f);
v38[4] = new Vector3(delHeight[4], 0f, 1f);
v38[5] = new Vector3(-delHeight[5], delHeight[5], 1f);
v38[6] = new Vector3(0f, delHeight[6], 1f);
v38[7] = new Vector3(delHeight[7], delHeight[7], 1f);
Vector3 vS = new Vector3();
for (int s = 0; s < 8; s++) vS += v38[s];
Vector3 v = vS;
v.X = v.X * 0.5f + 0.5f;
v.Y = v.Y * 0.5f + 0.5f;
color[iy * x + ix] = new Color(v);
}
}
outTex.SetData
return outTex;
}
И получаем:
Если не поленюсь, чуть позже, приведу примеры реализации “Bump mapping” & “Parallax Mapping” в XNA.
Спасибо за статейку, буду ждать продолжения о поводу “Bump mapping” & “Parallax Mapping” в XNA :)
ОтветитьУдалитьспасибо за отзыв!
ОтветитьУдалитьесть вариант более глубокого результата со сглаживанием и (в отличие от этого примера) для нормально ориентированного tangent space
выкладывать? :)
Выкладывать :)
ОтветитьУдалитьА есть пример как можно преобразовать карту высот в карту нормалей в ContentProcessor'е? или другого примера работы с текстурами на этапе компиляции?
на выходных постараюсь написать про глубокий normal map (сглаженный, c alpha каналом) и Bump mapping (пример готов, описание нет).
ОтветитьУдалитьс ContentProcessor'ом еще не разбирался.
не горит пока.
Написал на основе данной статьи расширенный текстурный процессор. Выложить на xnadev.ru?
ОтветитьУдалитьВыложил
ОтветитьУдалитьсупер. только данный расчет поправить нужно.
ОтветитьУдалитьдля корректного расчета tangent space
для простоты примера я не инвертировал ось Y.
ОтветитьУдалитьт.к. в текстуре эта ось смотрит в низ, а в мировой системе координат в верх, tangent space получается извращенный, нужно переводить.
ща закину пост с более сложным расчетом.