So I'm trying to generate a normal map from a grayscale height map. Unfortunately the result I am getting does not seem very correct.
Here is the height map that I am using to generate the normal map:
<img src = "https://i.stack.imgur.com/Xv4Zu.png" alt = "height map
“/>
Here is my normal generated map:
For reference, here is the normal map that is generated from http://cpetry.github.io/NormalMap-Online/:
One thing I noticed on my normal map is that there seems to be edges. I'm not really sure why I'm getting these limits, does anyone know why?
Here is the code I am using to generate the normal map:
// Source:
// https://stackoverflow.com/questions/2368728/can-normal-maps-be-generated-from-a-texture
// Y
// http://www.catalinzima.com/2008/01/converting-displacement-maps-into-normal-maps/
Height of float32 (const std :: vector& data, const int width, const int height, uint32 x, uint32 z)
{
if (x> = width) x% = width;
while (x < 0) x += width;
if (z >= height) z% = height;
while (z <0) z + = height;
return static_cast(data[z*width*4 + x*4 + 3]) / 255.0f;
}
uint8 textureCoordinateToRgb (const float32 value)
{
return (value + 1.0) * (255.0 / 2.0);
}
glm :: vec3 calculaNormal (const std :: vector& data, const int width, const int height, uint32 x, uint32 z)
{
force float32 const = 8.0f;
// surrounding pixels
float32 tl = height (data, width, height, x-1, z-1); // up to the left
float32 l = height (data, width, height, x-1, z); // left
float32 bl = height (data, width, height, x-1, z + 1); // down left
float32 t = height (data, width, height, x, z-1); // upper part
float32 b = height (data, width, height, x, z + 1); // background
float32 tr = height (data, width, height, x + 1, z-1); // top right
float32 r = height (data, width, height, x + 1, z); // straight
float32 br = height (data, width, height, x + 1, z + 1); // Bottom right
// filter sobel
const float32 dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl);
const float32 dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr);
const float32 dZ = 1.0 / force;
glm :: vec3 n (dX, dY, dZ);
n = glm :: normalize (n);
returns n;
}
void calculaNormal (std :: vectorand data, constant width int, constant height int)
{
for (int i = 0; i <width; ++ i)
{
for (int j = 0; j <height; ++ j)
{
const glm :: vec3 n = normalFigure (data, width, height, i, j);
// convert to rgb
data[j*width*4 + i*4 + 0] = textureCoordinateToRgb (n.x);
data[j*width*4 + i*4 + 1] = textureCoordinateToRgb (n.y);
data[j*width*4 + i*4 + 2] = textureCoordinateToRgb (n.z);
}
}
}
std :: unique_ptr generateFormattedHeightmap (const Image & image)
{
std :: vector data;
int width = image.width ();
int height = image.height ();
data.resize (width * height * 4);
if (image.format () == Image :: Format :: FORMAT_RGB)
{
int j = 0;
for (int i = 0; i <data.size (); i + = 4)
{
data[i] = image.data ()[j];
data[i+1] = image.data ()[j+1];
data[i+2] = image.data ()[j+2];
data[i+3] = (image.data ()[j] + image.data ()[j+1] + image.data ()[j+2]) / 3;
j + = 3;
}
}
else if (image.format () == Image :: Format :: FORMAT_RGBA)
{
for (int i = 0; i <image.data (). size (); i + = 4)
{
data[i] = image.data ()[i];
data[i+1] = image.data ()[i+1];
data[i+2] = image.data ()[i+2];
data[i+3] = (image.data ()[i] + image.data ()[i+1] + image.data ()[i+2]) / 3;
}
}
Normal calculations (data, width, height);
return std :: make_unique(data, width, height, Image :: Format :: FORMAT_RGBA);
}
Does anyone have any ideas?