How to make Normal mapping?

Advanced game related topics
Anonymous

How to make Normal mapping?

Post by Anonymous »

With this texture :
Image

with obtain this result :
Image

it's for simulate relief on 3D environement :

Image


Try this code for make your Normal map! :)

Code: Select all

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))
Violet
Enthusiast
Enthusiast
Posts: 106
Joined: Sun Dec 23, 2007 6:30 pm

Post by Violet »

I just get tons of Linker Errors concerning the Image Plugins (PureBasic 4.30 on Ubuntu 32 Bit). But if I use "UseJPEGImageDecoder" (a.s.o.) in an other Source Code, there are no problems.

By the way: Wouldn't be Parallax Mapping enough for that? It just makes a relief in one direction (normal map is grayscale), not like bump mapping using red, green and blue colorchannel.
best regards,

Violet
DarkDragon
Addict
Addict
Posts: 2347
Joined: Mon Jun 02, 2003 9:16 am
Location: Germany
Contact:

Post by DarkDragon »

Violet wrote:I just get tons of Linker Errors concerning the Image Plugins (PureBasic 4.30 on Ubuntu 32 Bit). But if I use "UseJPEGImageDecoder" (a.s.o.) in an other Source Code, there are no problems.

By the way: Wouldn't be Parallax Mapping enough for that? It just makes a relief in one direction (normal map is grayscale), not like bump mapping using red, green and blue colorchannel.
No, Parallax is not enough for that. Maybe steep parallax (This is steep afaik), but not normal parallax.
bye,
Daniel
Anonymous

Post by Anonymous »

I just get tons of Linker Errors concerning the Image Plugins (PureBasic 4.30 on Ubuntu 32 Bit). But if I use "UseJPEGImageDecoder" (a.s.o.) in an other Source Code, there are no problems.
Strange , code work fine for me. just the progress bar don't work correctly on linux.
mpz
Enthusiast
Enthusiast
Posts: 497
Joined: Sat Oct 11, 2008 9:07 pm
Location: Germany, Berlin > member German forum

Post by mpz »

Hi Cpl.Bator,

Amazing, cool and exactly what i need. Here is a little Example made with my MP 3D Engine and a created normal map from your program.

MP_normal_test.exe:
http://uploaded.to/?id=cemkz2

Code:

Code: Select all

;////////////////////////////////////////////////////////////////
;//
;// Project Title: MP 3D Engine
;// File Title: EarthBumpmap.pb
;// Created On: 2.12.2008
;// Updated On: 
;// Author: Michael Paulwitz
;// OS:Windows
;// 
;// Demofile Earth Bumpmap
;// 
;////////////////////////////////////////////////////////////////

;-
;- ProgrammStart


MP_Graphics3D (640,480,0,3) ; Create Windows #Window = 0
SetWindowTitle(0, "3D Bumpmap Demo, left world / right with created normals") ; Name

camera=MP_CreateCamera() ; Create Camera

x.f=0 : y.f=0 : z.f = -4 
MP_PositionCamera(camera,x.f,y.f,z.f) ; Camera position 

light=MP_CreateLight(1,90,0,0) ; Light on 

earth1=MP_Createsphere(20) ; Sphere 1
earth2=MP_Createsphere(20) ; Sphere 2

Textur=MP_CreateTextureFromFileInMemory (?Earth_map,?Earth_map-?Earth_map_normals)
Textur2=MP_CreateTextureFromFileInMemory (?Earth_map_normals,?Earth_map_normals-?Earth_map_end)

MP_EntityTexture (earth1,textur)
MP_EntityBumpmapTexture (earth1,textur2)

MP_EntityTexture (earth2,textur)

MP_PositionEntity (Earth1,1,0,0) ; Position Earth1 
MP_PositionEntity (Earth2,-1,0,0) ; Position Earth2 

While Not MP_KeyDown(#PB_Key_Escape) And Not MP_WindowEvent() = #PB_Event_CloseWindow; Esc or close

    MP_TurnEntity (earth1,-0.05,0,0) ; Move Earth1
    MP_TurnEntity (earth2,-0.05,0,0) ; Move Earth2
    MP_RenderWorld () ; Hier gehts los
    MP_Flip () ; 

Wend

DataSection
  Earth_map:
  IncludeBinary "c:\earth_map.jpg" ; Mein MP Bild included
  Earth_map_normals:
  IncludeBinary "c:\earth_map_normals.jpg" ; Mein MP Bild included
  Earth_map_end:
EndDataSection

best regards,
Michael
Last edited by mpz on Tue Dec 23, 2008 11:57 pm, edited 1 time in total.
Anonymous

Post by Anonymous »

i can't test your exe , i'm on linux :/ your engine work on linux ?
mpz
Enthusiast
Enthusiast
Posts: 497
Joined: Sat Oct 11, 2008 9:07 pm
Location: Germany, Berlin > member German forum

Post by mpz »

Hi Cpl.Bator,

i am sorry, it is DX9 with Windows...

[img]
http://picfront.de/d/4XXNDZGLH/3dEarthDemo.png
[/img]


Michael
Anonymous

Post by Anonymous »

it's 100% pb your engine ? why do you not use Opengl ? :D
mpz
Enthusiast
Enthusiast
Posts: 497
Joined: Sat Oct 11, 2008 9:07 pm
Location: Germany, Berlin > member German forum

Post by mpz »

Yes all commands are Purebasic codes and you can use a Purebasic lib file, you don't need a Dll (only DX9).

xperience2003 is working on a Opengl 3D System and this works great. I hope he will do sometimes a linux version. Long years ago i use BlitzBasic on amiga and then BlitzBasic 3D on PC. I want to have the same easy commands for 3D on Purebasic and find some good codes for DX9.

OpenGl Tlib (windows)
http://www.purebasic.fr/german/viewtopi ... light=tlib

You have seen the picture 3DEarthDemo.png? :P
Anonymous

Post by Anonymous »

yes , great work , tomorow i will test your exe on my other pc with xp!:D
Thx for th link ;)
mpz
Enthusiast
Enthusiast
Posts: 497
Joined: Sat Oct 11, 2008 9:07 pm
Location: Germany, Berlin > member German forum

Post by mpz »

Hi Cpl.Bator,

in this case i send you a file to test your own Normal maps with 4 mesh types. you can load the texture and normal map and test it with sphere, cube, teapot (you know for all games the importants meshs like in the film "The bloody killer teapot coming on earth") and plane:

MP_normal_test2.exe
http://uploaded.to/?id=ifygew

This code with the mp_engine looks like:

Code: Select all


;////////////////////////////////////////////////////////////////
;//
;// Project Title: MP 3D Engine
;// File Title: EarthBumpmap.pb
;// Created On: 2.12.2008
;// Updated On: 
;// Author: Michael Paulwitz
;// OS:Windows
;// 
;// Demofile Earth Bumpmap
;// 
;////////////////////////////////////////////////////////////////

;-
;- ProgrammStart

MP_Graphics3D (640,480,0,3) ; Create Windows #Window = 0
SetWindowTitle(0, "3D Bumpmap Demo, left world / right with created normals") ; Name

  If CreateMenu(0, WindowID(0)) ; Menü erstellen/Create Menu 
    MenuTitle("&File")
      MenuItem( 1, "&Load Texture") 
      MenuItem( 2, "&Load Bumpmap Texture") 
      MenuBar() 
      MenuItem( 3, "&End") 
    MenuTitle("&Mesh") 
      MenuItem(4, "Sphere")
      SetMenuItemState(0,4,1)
      MenuItem(5, "Cube")
      MenuItem(6, "Teapot")
      MenuItem(7, "Plane")
  EndIf 

camera=MP_CreateCamera() ; Create Camera

x.f=0 : y.f=0 : z.f = -4 
MP_PositionCamera(camera,x.f,y.f,z.f) ; Camera position 
light=MP_CreateLight(1,90,0,0) ; Light on 
earth1=MP_Createsphere(20) ; Sphere 1
earth2=MP_Createsphere(20) ; Sphere 2

Textur=MP_CreateTextureFromFileInMemory (?Earth_map,?Earth_map-?Earth_map_normals)
Textur2=MP_CreateTextureFromFileInMemory (?Earth_map_normals,?Earth_map_normals-?Earth_map_end)

MP_EntityTexture (earth1,textur)
MP_EntityBumpmapTexture (earth1,textur2)

MP_EntityTexture (earth2,textur)

MP_PositionEntity (Earth1,1,0,0) ; Position Earth1 
MP_PositionEntity (Earth2,-1,0,0) ; Position Earth2 

While Not MP_KeyDown(#PB_Key_Escape) ; ESC 
 Select MP_WindowEvent()  ; WindowsEvent abfrage 
      Case #PB_Event_Menu 
        Select EventMenu()  ; Welches Menü? / Menuquestion 
          Case 1 ; Load Texture
              Pattern$ = "Image Files (bmp,jpg,tga,png,dds,ppm,dib,hdr,pfm|*.bmp;*.jpg;*.tga;*.png;*.dds;*.ppm;*.dib;*.hdr;*.pfm" 
              ;directory$ = "C:\Programme\PureBasic\media\" 
              File.s = OpenFileRequester("Load Texture!", directory$, Pattern$,  0) 
              If File
                 MP_FreeTexture (Textur)
                 Texture =  MP_LoadTexture(File.s)
                 MP_EntityTexture (earth1,Textur)
                 MP_EntityTexture (earth2,Textur)
               EndIf
          Case 2 ; Load Bumpmap Texture
              Pattern$ = "Image Files (bmp,jpg,tga,png,dds,ppm,dib,hdr,pfm|*.bmp;*.jpg;*.tga;*.png;*.dds;*.ppm;*.dib;*.hdr;*.pfm" 
              ;directory$ = "C:\Programme\PureBasic\media\" 
              File.s = OpenFileRequester("Load Bump Texture!", directory$, Pattern$,  0) 
              If File
                 MP_FreeTexture (Textur2)
                 Texture2 =  MP_LoadTexture(File.s)
                 MP_EntityBumpmapTexture (earth1,textur2)
               EndIf
          Case 3 ; end
                  End
          Case 4 ; Sphere
               SetMenuItemState(0,4,1)
               SetMenuItemState(0,5,0)
               SetMenuItemState(0,6,0)
               SetMenuItemState(0,7,0)
               MP_FreeEntity (earth1)
               MP_FreeEntity (earth2)
               earth1=MP_Createsphere(20) ; Sphere 1
               earth2=MP_Createsphere(20) ; Sphere 2
               MP_PositionEntity (Earth1,1,0,0) ; Position Earth1 
               MP_PositionEntity (Earth2,-1,0,0) ; Position Earth2
               MP_EntityTexture (earth1,textur)
               MP_EntityBumpmapTexture (earth1,textur2)
               MP_EntityTexture (earth2,textur)
          Case 5 ; Cube
               SetMenuItemState(0,4,0)
               SetMenuItemState(0,5,1)
               SetMenuItemState(0,6,0)
               SetMenuItemState(0,7,0)
               MP_FreeEntity (earth1)
               MP_FreeEntity (earth2)
               earth1=MP_Createcube() ; Cube 1
               earth2=MP_Createcube() ; Cube 2
               MP_PositionEntity (Earth1,1,0,0) ; Position Earth1 
               MP_PositionEntity (Earth2,-1,0,0) ; Position Earth2
               MP_EntityTexture (earth1,textur)
               MP_EntityBumpmapTexture (earth1,textur2)
               MP_EntityTexture (earth2,textur)
          Case 6 ; Teapot
               SetMenuItemState(0,4,0)
               SetMenuItemState(0,5,0)
               SetMenuItemState(0,6,1)
               SetMenuItemState(0,7,0)
               MP_FreeEntity (earth1)
               MP_FreeEntity (earth2)
               earth1=MP_CreateTeapot () ; Teapot 1
               earth2=MP_CreateTeapot () ; Teapot 1
               MP_PositionEntity (Earth1,1,0,0) ; Position Earth1 
               MP_PositionEntity (Earth2,-1,0,0) ; Position Earth2
               MP_EntityTexture (earth1,textur)
               MP_EntityBumpmapTexture (earth1,textur2)
               MP_EntityTexture (earth2,textur)
          Case 7 ; Plane
               SetMenuItemState(0,4,0)
               SetMenuItemState(0,5,0)
               SetMenuItemState(0,6,0)
               SetMenuItemState(0,7,1)
               MP_FreeEntity (earth1)
               MP_FreeEntity (earth2)
               earth1=MP_CreatePolygon (1,4) ; Plane 1
               earth2=MP_CreatePolygon (1,4) ; Plane 2
               MP_PositionEntity (Earth1,1,0,0) ; Position Earth1 
               MP_PositionEntity (Earth2,-1,0,0) ; Position Earth2
               MP_EntityTexture (earth1,textur)
               MP_EntityBumpmapTexture (earth1,textur2)
               MP_EntityTexture (earth2,textur)               
        EndSelect 
      Case #PB_Event_CloseWindow 
         End 
EndSelect

    MP_TurnEntity (earth1,-0.06,0,0) ; Move Earth1
    MP_TurnEntity (earth2,-0.06,0,0) ; Move Earth2
    
    MP_RenderWorld () ; Hier gehts los
    MP_Flip () ; 

Wend

DataSection
  Earth_map:
  IncludeBinary "c:\earth_map.jpg" ; Mein MP Bild included
  Earth_map_normals:
  IncludeBinary "c:\earth_map_normals.jpg" ; Mein MP Bild included
  Earth_map_end:
EndDataSection

Anonymous

Post by Anonymous »

hi , For more effect , you can add light and move this for play with the bump :)

And for TLib , it's doesn't work with pb 4.3 , "pb_string missing" , and Avast found virus in the archive :?
mpz
Enthusiast
Enthusiast
Posts: 497
Joined: Sat Oct 11, 2008 9:07 pm
Location: Germany, Berlin > member German forum

Post by mpz »

Hi Cpl.Bator,

the author works on a new version for 4.30, but he has only one example for now. Please use the SmalTLib instead the Tlib library.

http://www.digitalarts-egypt.com/tlx/tlibpublic.rar

I think the new version will come soon...

P.S. The TLib-terrain.pb, DemoFX-Bitmapfonts.pb, 3-TLib-Drawing3d.pb and 2-TLib-Drawing2d.pb example of the old Tlib works fine too

Michael
vanbeck
Enthusiast
Enthusiast
Posts: 104
Joined: Mon Jun 11, 2007 1:31 pm
Location: The Swan

Post by vanbeck »

''By the way: Wouldn't be Parallax Mapping enough for that? It just makes a relief in one direction (normal map is grayscale), not like bump mapping using red, green and blue colorchannel.''

Not sure what you mean.

Bump mapping uses greyscale images.
Normal mapping uses RGB images.
Parallax mapping uses RGB normal map plus separate height map.

Parallax mapping can produce some incredible results, but these normal maps look good, a lot of bump to normal generators are a real pain to use.
Violet
Enthusiast
Enthusiast
Posts: 106
Joined: Sun Dec 23, 2007 6:30 pm

Parallax Mapping

Post by Violet »

Oh, alright. I just read in Wikipedia (once upon a time :wink: ) that Parallax Mapping just uses a grayscale Map.
best regards,

Violet
Post Reply