Generally we have 2 ways to get the normal map: for the 3D model, use the high poly 3D model to get it; for the plane objects, wall, ground etc. use the PS or GIMP or CrazyBump to get it from texture directly. Now, I want to get normal map from the texture with code, without height map.
below is the function:
-- ????????????(???)??
-- ??????????????: (1, pMax)
function clamp(pX, pMax)
if (pX > pMax) then
return pMax;
elseif (pX < 1) then
return 1;
else
return pX;
end
end
-- ??????: ??
function intensity(col)
-- ?????????
--local average = (col.r + col.g + col.b)/3;
local average = 0.3*col.r + 0.59*col.g + 0.11*col.b
return average
end
-- ?????? [-1.0, 1.0] ????? [0,255]
function normal2Color(p)
return (p + vec3(1,1,1)) * (255 / 2)
end
-- ???????
function genGreyMap(img, s)
local t = image(img.width, img.height)
for y =1,img.height do
for x = 1,img.width do
local r,g,b,a = img:get(x,y)
local g = (0.3*r+0.59*g+0.11*b)*s
t:set(x,y,color(g,g,g,255))
end
end
return t
end
function greyNormal(img,s)
local w,h = img.width,img.height
local temp = image(w,h)
for y =1,img.height do
for x = 1,img.width do
-- ????????? rgba?(???)
topLeft = color(img:get(clamp( x - 1, w), clamp(y + 1, h)))
top = color(img:get(clamp( x , w), clamp(y + 1, h)))
topRight = color(img:get(clamp( x + 1, w), clamp(y + 1, h)))
right = color(img:get(clamp( x - 1, w), clamp(y , h)))
bottomRight = color(img:get(clamp( x + 1, w), clamp(y - 1 , h)))
bottom = color(img:get(clamp( x , w), clamp(y - 1 , h)))
bottomLeft = color(img:get(clamp( x - 1, w), clamp(y - 1 , h)))
left = color(img:get(clamp( x - 1, w), clamp(y , h)))
--?? sobel filter
dX = (topRight.r + 2.0 * right.r + bottomRight.r) - (topLeft.r + 2.0 * left.r + bottomLeft.r);
dY = (bottomLeft.r + 2.0 * bottom.r + bottomRight.r) - (bottomLeft.r + 2.0 * top.r + topRight.r);
dZ = 255 / s;
newCol = normal2Color(vec3(dX,dY,dZ):normalize())
--print(newCol)
temp:set(x,y,color(newCol.x, newCol.y, newCol.z, 255))
end
end
return temp
end
Usage:
1 Generate grey map from texture:
2 Generate normal map from grey map: greyNormal(greyImg, 1)
The texture:
Generated with the function:
Generated with the software(PS, GIMP or others)
If you can not see the image, please see here: http://www.oschina.net/question/219279_2170736
The function can get the normal map, but it looks not so good, it is more similar as a bump map, so I need your help to improve it, please give me some idea, thanks!
Reference articles:
https://github.com/mattdesl/lwjgl-basics/wiki/ShaderLesson6
http://stackoverflow.com/questions/2368728/can-normal-maps-be-generated-from-a-texture