# c ++ – Calculation of the normal map from the height map using the Sobel operator

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?