If you want to load your textures and manipulate them in code, you could try this. You will be prompted for an image file which should contain your texture, and a new image file for the normal map. These can be any combination of .bmp, .tga, .jpg.
There are two adjustable parameters which are not properly tested yet.
You can obviously edit out the text output to the screen.
` Green Gandalf's normal map creator and viewer - Version 3
` Created: 16 Dec 2005
` Modified: 17 Dec 2005
set display mode 800,600,32
sync on: sync rate 60: sync
set cursor 20,20: input "Enter image file to process: ",imageFile$
set cursor 20,40: input "Enter output normal map name:",mapFile$
if right$(imageFile$,3)="bmp"
text 20,60," Loading bitmap - please wait"
sync
load bitmap imageFile$,1
get image 1,0,0,bitmap width(),bitmap height()
else
load image imageFile$,1,1
make memblock from image 1,1
text 20,60," Creating bitmap from image - please wait"
sync
make bitmap from memblock 1,1
endif
set current bitmap 0
text 20,80,"Starting to process bitmap - please wait"
sync
prepareNormalMap(1,2,3,4,mapFile$)
text 20,160," All done! Press any key to view."
sync
wait key
autocam off
position camera 0.0,0.0,-180.0
point camera 0.0,0.0,0.0
color backdrop 0
position light 0,-150.0,0.0,-200.0
point light 0,0.0,0.0,0.0
make object sphere 1,100,25,25
position object 1,0.0,0.0,0.0
texture object 1,1 ` your original image texture
set bump mapping on 1,2 ` use modified image as normal map
counter1#=0: counter2#=0
do
xrotate object 1,counter1#
yrotate object 1,counter2#
inc counter1#,0.2: inc counter2#,0.15
sync
loop
end
function prepareNormalMap(bmp,normalBmp,smooth,steep,mapFile$)
colour as dword
set current bitmap bmp
width=bitmap width(): height=bitmap height()
dim heightMap(width,height)
bottom=height-1: right=width-1
timer1=timer()
` calculate raw heightmap first
lock pixels
for x=0 to right
for y=0 to bottom
colour=point(x,y)
heightMap(x+1,y+1)=rgbr(colour)+rgbg(colour)+rgbb(colour)
next y
next x
unlock pixels
timer1=timer()-timer1
` create normal map
create bitmap normalBmp,width,height
timer2=timer()
lock pixels
for x=1 to width
for y=1 to height
tempx=0: tempy=0
for i=1 to smooth
xpi=x+i: xmi=x-i: ypi=y+i: ymi=y-i
if xpi >width then dec xpi,width
if xmi < 1 then inc xmi,width
if ypi >height then dec ypi,height
if ymi < 1 then inc ymi,height
inc tempx,heightMap(xpi,y)-heightMap(xmi,y)
inc tempy,heightMap(x,ypi)-heightMap(x,ymi)
next i
` calculate crude normals
nx#=-tempx: ny#=-tempy: nz#=(1024.0*(smooth+1))/steep
` calculate normalising factor
factor#=127.0/sqrt(nx#*nx#+ny#*ny#+nz#*nz#)
` calculate colours for normal map
red=128+factor#*nx#: green=128+factor#*ny#: blue=128+factor#*nz#
dot x-1,y-1,rgb(red,green,blue)
next y
next x
unlock pixels
timer2=timer()-timer2
set current bitmap 0
text 20,100,...
"Finished creating height map in "+str$(timer1)+" msecs"
text 20,120,...
"Finished creating normal bitmap in "+str$(timer2)+" msecs"
sync
set current bitmap normalbmp
get image 2,0,0,width,height,1
save image mapFile$,2
set current bitmap 0
endfunction
[Edit: code revised to run faster - and the adjustable parameters "smooth" and "steep" work.]