Le normal mapping est une technique qui permet de simuler du relief sur un modèle 3d, l'avantage de cette technique c'est l'économie du maillage , car le relief est simulé par la texture.
Avec cette texture en niveau de gris :

on obtient ceci :

Cette image coloré est en fait une représentation de vecteur 3d.
c'est elle qui permet de simulé le relief :

Voici le code qui permet de créer une normal map via une image en niveau de gris :
Code : Tout sélectionner
Global Threshold = 5
Global Progress.i = 0
Procedure.d Min(a.d,b.d)
If a<b
ProcedureReturn a
Else
ProcedureReturn b
EndIf
EndProcedure
Procedure.d Max(a.d,b.d)
If a>b
ProcedureReturn a
Else
ProcedureReturn b
EndIf
EndProcedure
Structure VECTOR3
x.f : y.f : z.f
EndStructure
Macro SetVector3(V,_x,_y,_z)
V\x=_x
V\y=_y
V\z=_z
EndMacro
Macro VectorLength(V)
(V\x*V\x + V\y*V\y + V\z*V\z)
EndMacro
Macro Normalize(V)
l.f = VectorLength(V)
If (l <> 0)
l = Sqr(l)
V\x / l
V\y / l
V\z / l
EndIf
EndMacro
Procedure.f DotProduct(*A.VECTOR3,*B.VECTOR3)
ProcedureReturn *A\X * *B\X + *A\Y * *B\Y + *A\Z * *B\Z
EndProcedure
Macro CharToByte(Char)
Char/255.0
EndMacro
Macro ByteToChar(Byte)
Byte*255
EndMacro
Procedure GetGrayLevel(x,y)
Color = Point(x,y)
Red = Red(Color)
Green = Green(Color)
Blue = Blue(Color)
Gray = (Red+Green+Blue)/3
ProcedureReturn Gray
EndProcedure
Procedure Map0_to_255(*V.VECTOR3)
*V\x = max(-256,*V\x)
*V\y = max(-256,*V\y)
*V\z = max(-256,*V\z)
*V\x = min(256,*V\x)
*V\y = min(256,*V\y)
*V\z = min(256,*V\z)
*V\x =*V\x/2 + 127
*V\y =*V\y/2 + 127
*V\z =*V\z/2 + 127
EndProcedure
Procedure Conv3x3(ImageID, Array Gradient.f(2) , Array Sobel(2))
StartDrawing(ImageOutput(ImageID))
For y = 1 To ImageHeight(ImageID)-1
For x = 1 To ImageWidth(ImageID)-1
Gradient(x,y) = (CharToByte(GetGrayLevel(x-1,y-1))*Sobel(0,0))+(CharToByte(GetGrayLevel(x,y-1))*Sobel(1,0))+(CharToByte(GetGrayLevel(x+1,y-1))*Sobel(2,0))+(CharToByte(GetGrayLevel(x-1,y))*Sobel(0,1))+(CharToByte(GetGrayLevel(x,y-1))*Sobel(1,1))+(CharToByte(GetGrayLevel(x+1,y))*Sobel(2,1))+(CharToByte(GetGrayLevel(x-1,y+1))*Sobel(0,2))+(CharToByte(GetGrayLevel(x,y+1))*Sobel(1,2))+(CharToByte(GetGrayLevel(x+1,y+1))*Sobel(2,2))
Gradient(x,y) * Threshold
SetGadgetState(0,Progress) : SmartWindowRefresh(0,1)
Progress + 1
Next
Next
StopDrawing()
EndProcedure
Global Dim SobelX(2,2) :
SobelX(0,0)=-1 : SobelX(1,0)=-2 : SobelX(2,0)=-1
SobelX(0,1)=0 : SobelX(1,1)=0 : SobelX(2,1)=0
SobelX(0,2)=1 : SobelX(1,2)=2 : SobelX(2,2)=1
Global Dim SobelY(2,2) :
SobelY(0,0)=-1 : SobelY(1,0)=0 : SobelY(2,0)=1
SobelY(0,1)=-2 : SobelY(1,1)=0 : SobelY(2,1)=2
SobelY(0,2)=-1 : SobelY(1,2)=0 : SobelY(2,2)=1
UsePNGImageDecoder()
UseJPEG2000ImageDecoder()
UseJPEGImageDecoder()
UsePNGImageDecoder()
UseTGAImageDecoder()
UseTIFFImageDecoder()
UsePNGImageEncoder()
UseJPEG2000ImageEncoder()
UseJPEGImageEncoder()
UsePNGImageEncoder()
Filtre$ = "Images|*.bmp;*.jpg,*.png,*.tga,*.tif"
Input$ = OpenFileRequester("Ouvrir une image","",Filtre$,0)
UseJPEGImageDecoder()
LoadImage(0,Input$)
CreateImage(1,ImageWidth(0),ImageHeight(0))
OpenWindow(0,0,0,640,32,"",#PB_Window_BorderLess | #PB_Window_ScreenCentered)
ProgressBarGadget(0,0,0,640,32,0,ImageWidth(0)*ImageHeight(0)*3,#PB_ProgressBar_Smooth)
StickyWindow(0,1)
Global Dim GradientX.f(ImageWidth(0),ImageHeight(0))
Global Dim GradientY.f(ImageWidth(0),ImageHeight(0))
Conv3x3(0, gradientX(), sobelX() );
Conv3x3(0, gradientY(), sobelY() );
StartDrawing(ImageOutput(1))
For y = 0 To ImageHeight(1)
For x = 0 To ImageWidth(1)
V.VECTOR3
SetVector3(V,GradientX(x,y),GradientY(x,y),1)
Normalize(V)
Color.VECTOR3
SetVector3(Color,ByteToChar(V\x),ByteToChar(V\y),ByteToChar(V\z))
Map0_to_255(Color)
Plot(x,y,RGB(Color\x,Color\y,Color\z))
SetGadgetState(0,Progress) : SmartWindowRefresh(0,1)
Progress+1
Next
Next
StopDrawing()
SaveImage(1,SaveFileRequester("Sauvegarder","",Filtre$,0))