Если у меня есть структура, затем возможно генерировать карту нормалей для этой структуры, таким образом, это может использоваться для наложения рельефа?
Или как карты нормалей обычно делаются?
Да. Ну вроде как. Карты нормалей можно точно составить из карт высот.Как правило, вы также можете использовать обычную текстуру и получить приличные результаты. Имейте в виду, что есть и другие методы создания карты нормалей, такие как создание модели с высоким разрешением, уменьшение ее разрешения, а затем выполнение преобразования лучей, чтобы увидеть, какой должна быть нормаль для модели с низким разрешением, чтобы имитировать модель с более высоким разрешением.
Для карты высот в карту нормалей вы можете использовать Оператор Собеля . Этот оператор может быть запущен в направлении x, сообщая вам x-компонент нормали, а затем в направлении y, сообщая вам y-компонент. Вы можете рассчитать z с помощью 1.0 / сила
, где сила - это акцент или «глубина» карты нормалей. Затем возьмите эти x, y и z, поместите их в вектор, нормализуйте его, и в этот момент у вас будет нормальный. Закодируйте его в пиксель, и все готово.
Вот старый неполный код, демонстрирующий это:
// pretend types, something like this
struct pixel
{
uint8_t red;
uint8_t green;
uint8_t blue;
};
struct vector3d; // a 3-vector with doubles
struct texture; // a 2d array of pixels
// determine intensity of pixel, from 0 - 1
const double intensity(const pixel& pPixel)
{
const double r = static_cast<double>(pPixel.red);
const double g = static_cast<double>(pPixel.green);
const double b = static_cast<double>(pPixel.blue);
const double average = (r + g + b) / 3.0;
return average / 255.0;
}
const int clamp(int pX, int pMax)
{
if (pX > pMax)
{
return pMax;
}
else if (pX < 0)
{
return 0;
}
else
{
return pX;
}
}
// transform -1 - 1 to 0 - 255
const uint8_t map_component(double pX)
{
return (pX + 1.0) * (255.0 / 2.0);
}
texture normal_from_height(const texture& pTexture, double pStrength = 2.0)
{
// assume square texture, not necessarily true in real code
texture result(pTexture.size(), pTexture.size());
const int textureSize = static_cast<int>(pTexture.size());
for (size_t row = 0; row < textureSize; ++row)
{
for (size_t column = 0; column < textureSize; ++column)
{
// surrounding pixels
const pixel topLeft = pTexture(clamp(row - 1, textureSize), clamp(column - 1, textureSize));
const pixel top = pTexture(clamp(row - 1, textureSize), clamp(column, textureSize));
const pixel topRight = pTexture(clamp(row - 1, textureSize), clamp(column + 1, textureSize));
const pixel right = pTexture(clamp(row, textureSize), clamp(column + 1, textureSize));
const pixel bottomRight = pTexture(clamp(row + 1, textureSize), clamp(column + 1, textureSize));
const pixel bottom = pTexture(clamp(row + 1, textureSize), clamp(column, textureSize));
const pixel bottomLeft = pTexture(clamp(row + 1, textureSize), clamp(column - 1, textureSize));
const pixel left = pTexture(clamp(row, textureSize), clamp(column - 1, textureSize));
// their intensities
const double tl = intensity(topLeft);
const double t = intensity(top);
const double tr = intensity(topRight);
const double r = intensity(right);
const double br = intensity(bottomRight);
const double b = intensity(bottom);
const double bl = intensity(bottomLeft);
const double l = intensity(left);
// sobel filter
const double dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl);
const double dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr);
const double dZ = 1.0 / pStrength;
math::vector3d v(dX, dY, dZ);
v.normalize();
// convert to rgb
result(row, column) = pixel(map_component(v.x), map_component(v.y), map_component(v.z));
}
}
return result;
}
Вероятно, существует много способов создания карты нормалей, но, как говорили другие, вы можете сделать это из карты высот, а 3d пакеты, такие как XSI/3dsmax/Blender/любой из них, могут вывести ее для вас в виде изображения.
Затем вы можете вывести RGB-изображение с помощью плагина Nvidia для фотошопа, алгоритма для его преобразования или вы можете вывести его непосредственно из этих 3d-пакетов с помощью сторонних плагинов.
Имейте в виду, что в некоторых случаях вам может понадобиться инвертировать каналы (R, G или B) сгенерированной карты нормалей.
Вот некоторые ресурсы с примерами и более полным объяснением:
Я не думаю, что карты нормалей генерируются из текстуры. они генерируются из модели.
Так же, как текстурирование позволяет вам определять сложные цветовые детали с минимальным количеством поликов (в отличие от использования миллионов слоев и просто вершинных цветов для определения цвета на вашей сетке)
Карта нормалей позволяет вам определять сложные детали нормалей с минимальным количеством поликов.
Я полагаю, что карты нормалей обычно создаются на основе сетки высокого разрешения, а затем используются с сеткой низкого разрешения.
Я уверен, что 3D инструменты, такие как 3ds max или maya, а также более специфические инструменты сделают это для вас. В отличие от текстур, я не думаю, что они обычно делаются вручную.
но они генерируются из сетки, а не из текстуры.