пятница, 19 июня 2009 г.

Calculation deep normal map

Calculation normal map for “Bump mapping” & “Parallax Mapping” II

Вот еще один, более сложный пример расчета.

Что тут добавлено:
I. При расчете переворачивается ось Y, для приведения соответствующего tangent space к нормальному виду.
Это связанно с тем, что в мировой системе координат ось Y смотрит в верх, а в текстуре в низ.
II. Сглаживание normal map
III. Масштабирование для получения более глубокого эффекта.

(код примера)
///
/// Расчет normal map к текстуре
///

/// Текстура для расчета (цветная, черно-белая - по барабану)
/// Во сколько целых раз нужно уменьшить (2^n)
/// Рассчитанная normal map текстура
private Texture2D GenNormalMamp(Texture2D inTex, int K)
{
int inX = inTex.Width;
int inY = inTex.Height;
int outX = inTex.Width / K;
int outY = inTex.Height / K;
float z = 1;
int l = inX * inY;
Texture2D outTex = new Texture2D(graphics.GraphicsDevice, outX, outY);
Color[] inColor = new Color[l];
Color[] outColor = new Color[l / (K * K)];
float[,] heightMap = new float[outX, outY];
Vector3[,] normalMap = new Vector3[outX, outY];
inTex.GetData(inColor);
// height map
for (int iy = 0; iy < outY; iy++)
{
for (int ix = 0; ix < outX; ix++)
{
Vector3 v3 = inColor[iy * inX * K + ix * K].ToVector3();
heightMap[ix, iy] = (v3.X + v3.Y + v3.Z) / 3;
}
}
// normal map
float[] delHeight = new float[8];
Vector3[] v38 = new Vector3[8];
Vector3 vAddPack = new Vector3(0.5f, 0.5f, 0.5f);
Vector3 vScale = new Vector3(2f, 2f, 1f);
for (int iy = 0; iy < outY; iy++)
{
for (int ix = 0; ix < outX; ix++)
{
if (iy == 0 || iy == outY - 1 || ix == 0 || ix == outX - 1)
{
normalMap[ix, iy] = Vector3.Backward;
continue;
}
delHeight[0] = heightMap[ix, iy] - heightMap[ix - 1, iy - 1];
delHeight[1] = heightMap[ix, iy] - heightMap[ix, iy - 1];
delHeight[2] = heightMap[ix, iy] - heightMap[ix + 1, iy - 1];
delHeight[3] = heightMap[ix, iy] - heightMap[ix - 1, iy];
delHeight[4] = heightMap[ix, iy] - heightMap[ix + 1, iy];
delHeight[5] = heightMap[ix, iy] - heightMap[ix - 1, iy + 1];
delHeight[6] = heightMap[ix, iy] - heightMap[ix, iy + 1];
delHeight[7] = heightMap[ix, iy] - heightMap[ix + 1, iy + 1];
v38[0] = new Vector3(-delHeight[0], delHeight[0], z - delHeight[0]);
v38[1] = new Vector3(0f, delHeight[1], z - delHeight[1]);
v38[2] = new Vector3(delHeight[2], delHeight[2], z - delHeight[2]);
v38[3] = new Vector3(-delHeight[3], 0f, z - delHeight[3]);
v38[4] = new Vector3(delHeight[4], 0f, z - delHeight[4]);
v38[5] = new Vector3(-delHeight[5], -delHeight[5], z - delHeight[5]);
v38[6] = new Vector3(0f, -delHeight[6], z - delHeight[6]);
v38[7] = new Vector3(delHeight[7], -delHeight[7], z - delHeight[7]);
normalMap[ix, iy] = Vector3.Zero;
for (int ii = 0; ii < 8; ii++) normalMap[ix, iy] += v38[ii] * vScale;
normalMap[ix, iy].Normalize();
}
}
// smooth
Vector3[] s = new Vector3[8];
int pas = 4;
for (int iS = 0; iS < pas; iS++)
{
for (int iy = 1; iy < outY - 2; iy++)
{
for (int ix = 1; ix < outY - 2; ix++)
{
if (normalMap[ix, iy] == Vector3.Backward) continue;
s[0] = normalMap[ix - 1, iy - 1];
s[1] = normalMap[ix, iy];
s[2] = normalMap[ix + 1, iy - 1];
s[3] = normalMap[ix - 1, iy];
s[4] = normalMap[ix + 1, iy];
s[5] = normalMap[ix - 1, iy + 1];
s[6] = normalMap[ix, iy + 1];
s[7] = normalMap[ix + 1, iy + 1];
normalMap[ix, iy] = Vector3.Zero;
for (int ii = 0; ii < s.Length; ii++)
normalMap[ix, iy] += s[ii];
normalMap[ix, iy].Normalize();
}
}
}
// color
int i = 0;
for (int iy = 0; iy < outY; iy++)
{
for (int ix = 0; ix < outX; ix++)
{
normalMap[ix, iy] *= new Vector3(16f, 16f, 1f);
normalMap[ix, iy].Normalize();
outColor[i] = new Color(new Color(normalMap[ix, iy] * 0.5f + vAddPack), heightMap[ix, iy]);
i++;
}
}
// texture
outTex.SetData(outColor);
outTex.Save(@"normalMap.tga", ImageFileFormat.Tga);
return outTex;
}

картинка normal map

результат Bump mapping'а

4 комментария:

  1. Спасибо! Будем пробовать интегрировать и эту функцию в ContentProcessor, потом могу другим способом на xnadev.ru залить

    ОтветитьУдалить
  2. Только я подумал и наверное исключу возможность уменьшения текстуры, кому надо сами уменьшат размер исходной карты высот....

    ОтветитьУдалить
  3. Сделал, работает, старую функцию заменил новой, теперь надо на сайт выложить... я тебе по аське послал файл с исходником.

    ОтветитьУдалить
  4. творчество - процесс бесконечный :)

    ОтветитьУдалить