lighting shading using custom vertexcolors on walls and shapes

Started by RemiD, November 12, 2022, 17:40:03

Previous topic - Next topic

RemiD


;lighting shading with custom vertex colors (pipe walls and cubes)
;more realistic and customizable than lightmesh
;by RemiD 2022/11/23

Graphics3D(854,480,32,2)
HidePointer()

SeedRnd(MilliSecs())

;Origine
Global Origine = CreateCube()
ScaleMesh(Origine,0.01,0.01,0.01)
EntityColor(Origine,255,000,255)
EntityFX(Origine,1)

;Camera
Global Camera = CreateCamera()
CameraViewport(Camera,0,0,GraphicsWidth(),GraphicsHeight())
CameraRange(Camera,0.15,150)
CameraClsColor(Camera,000,000,000)

Global Pivot = CreatePivot()

;Input
Global MX%
Global MY%
Global MXDiff%
Global MYDiff%

;Ghost
Global GhostRoot
Global GhostRootYaw#
Global GhostEyes
Global GhostEyesPitch#
AddGhost()

;create some walls (pipe)
;texture the walls
;set fx to fullbright, allow vertices colors (Fx 1+2)
PipeSeg = CreatePipeSeg(32,5.0,1.0)
HideEntity(PipeSeg)
;Global Pipe_Mesh = CreateCylinder(32) : ScaleMesh(Pipe_Mesh,5,50.0/2,5) : PositionMesh(Pipe_Mesh,0,50.0/2,0) : RotateMesh(Pipe_Mesh,90,0,0) : FlipMesh(Pipe_Mesh)
Global Pipe_Mesh = CreateMesh()
For S% = 1 To 50 Step 1
Part = CopyMesh(PipeSeg)
PositionMesh(Part,0,0,S-1)
AddMesh(Part,Pipe_Mesh) : FreeEntity(Part)
Next
UpdateNormals(Pipe_Mesh)
FreeEntity(PipeSeg)
ColorTex = CreateTexture(8,8)
SetBuffer(TextureBuffer(ColorTex))
Color(240,240,240) : Rect(0,0,8,8,True)
EntityTexture(Pipe_Mesh,ColorTex)
EntityFX(Pipe_Mesh,1+2)

;create some shapes (cubes)
;texture the shapes
;set fx to fullbright, allow vertices colors (Fx 1+2)
Global ShapesCount%
Dim Shape_Mesh(30)

For n% = 1 To 30 Step 1
ShapesCount = ShapesCount + 1 : I% = ShapesCount
Shape_Mesh(I) = CreateCube()
ScaleMesh(Shape_Mesh(I),1.0/2,1.0/2,1.0/2)
ColorTex = CreateTexture(8,8)
SetBuffer(TextureBuffer(ColorTex))
  Color(Rand(180,240),Rand(180,240),Rand(180,240)) : Rect(0,0,8,8,True)
EntityTexture(Shape_Mesh(I),ColorTex)
EntityFX(Shape_Mesh(I),1+2)
PositionEntity(Shape_Mesh(I),0,0,Rnd(0+1,50-1),True)
RotateEntity(Shape_Mesh(I),90,0,0,True)
TurnEntity(Shape_Mesh(I),0,Rand(-180,180),0) : MoveEntity(Shape_Mesh(I),Rand(2,4),0,0)
Next

;create some lights (only the properties)
Global LightsCount%
Dim Light_Rang#(16) ;range in units
Dim Light_R%(16)
Dim Light_G%(16)
Dim Light_B%(16)
Dim Light_Source(16)

For n% = 1 To 16
LightsCount = LightsCount + 1 : I% = LightsCount
Light_Rang(I) = 7.5
;RandomColor()
;Light_R(I) = ColorR : Light_G(I) = ColorG : Light_B(I) = ColorB
Light_R(I) = Rand(060,240) : Light_G(I) = Rand(060,240) : Light_B(I) = Rand(060,240)
Light_Source(I) = CreateSphere(2)
ScaleMesh(Light_Source(I),0.05/2,0.05/2,0.05/2) : EntityColor(Light_Source(I),Light_R(I),Light_G(I),Light_B(I)) : EntityFX(Light_Source(I),1)
Z# = Rnd(0+3,50-3)
PositionEntity(Pivot,0,0,Z,True) : RotateEntity(Pivot,0,0,Rand(-180,+180),True)
TFormPoint(0,+5-Rnd(1.5,2.5),0,Pivot,0)
PositionEntity(Light_Source(I),TFormedX(),TFormedY(),TFormedZ(),True)
Next

;define the ambient light
AmbientR% = 030
AmbientG% = 030
AmbientB% = 030

;light the scene using vertexcolor lighting
;reset vertices color (pipe)
;ResetVertColor(GetSurface(Pipe_Mesh,1)) ;not needed
;color with ambientlight (pipe)
AmbientVertColor(GetSurface(Pipe_Mesh,1),AmbientR,AmbientG,AmbientB)
;light with vertexcolor (pipe)
For LI% = 1 To LightsCount
LightVertColor(Pipe_Mesh,GetSurface(Pipe_Mesh,1),EntityX(Light_Source(LI),True),EntityY(Light_Source(LI),True),EntityZ(Light_Source(LI),True),Light_R(LI),Light_G(LI),Light_B(LI),Light_Rang(LI))
Next

;reset vertices color (shapes)
;For I% = 1 To ShapesCount
; ResetVertColor(GetSurface(Shape_Mesh(I),1)) ;not needed
;Next
;color with ambientlight (shapes)
For I% = 1 To ShapesCount
AmbientVertColor(GetSurface(Shape_Mesh(I),1),AmbientR,AmbientG,AmbientB)
Next
;light with vertexcolor (shapes)
For I% = 1 To ShapesCount
For LI% = 1 To LightsCount
  LightVertColor(Shape_Mesh(I),GetSurface(Shape_Mesh(I),1),EntityX(Light_Source(LI),True),EntityY(Light_Source(LI),True),EntityZ(Light_Source(LI),True),Light_R(LI),Light_G(LI),Light_B(LI),Light_Rang(LI))
Next
Next

PositionEntity(GhostRoot,0,1.0,-5)

Repeat

MX = MouseX() : MY = MouseY()

MXDiff = MouseXSpeed() : MYDiff = MouseYSpeed()

UpdateGhost()     

PositionEntity(Camera,EntityX(GhostEyes,True),EntityY(GhostEyes,True),EntityZ(GhostEyes,True),True)
RotateEntity(Camera,EntityPitch(GhostEyes,True),EntityYaw(GhostEyes,True),EntityRoll(GhostEyes,True),True)

WireFrame(False)
If( KeyDown(2)=1 )
  WireFrame(True)
EndIf

SetBuffer(BackBuffer())
RenderWorld()

Flip(1)

Until( KeyDown(1)=1 )

End

Function Distance2D#(PAX#,PAZ#,PBX#,PBZ#)

Distance2D# = Sqr( ( ( PBX - PAX ) * ( PBX - PAX ) ) + ( ( PBZ - PAZ ) * ( PBZ - PAZ ) ) )
Return Distance2D

End Function

Function Distance3D#(PAX#,PAY#,PAZ#,PBX#,PBY#,PBZ#)

Distance3D# = Sqr( ( ( PBX - PAX ) * ( PBX - PAX ) ) + ( ( PBY - PAY ) * ( PBY - PAY ) ) + ( ( PBZ - PAZ ) * ( PBZ - PAZ ) ) )
Return Distance3D

End Function

Function Angle3D#(V1X#,V1Y#,V1Z#,V2X#,V2Y#,V2Z#)

D# = (V1X*V2X) + (V1Y*V2Y) + (V1Z*V2Z)
M# = Sqr( V1X*V1X + V1Y*V1Y + V1Z*V1Z ) * Sqr( V2X*V2X + V2Y*V2Y + V2Z*V2Z )
A# = ACos(D#/M#)
Return A#

End Function

Function AddGhost()

GhostRoot = CreatePivot()

GhostEyes = CreatePivot()
EntityParent(GhostEyes,GhostRoot,True)

End Function

Function UpdateGhost()

MoveMouse(GraphicsWidth()/2,GraphicsHeight()/2)
GhostEyesPitch = GhostEyesPitch + Float(MYDiff)/10
If( GhostEyesPitch < -89 )
  GhostEyesPitch = -89
Else If( GhostEyesPitch > 89 )
  GhostEyesPitch = 89
EndIf
RotateEntity(GhostEyes,GhostEyesPitch,0,0,False)
GhostRootYaw = GhostRootYaw - Float(MXDiff)/10
RotateEntity(GhostRoot,0,GhostRootYaw,0,False)

If( KeyDown(42) = 0 And KeyDown(29) = 0 )
  Speed# = 0.1
Else If( KeyDown(42) = 1 And KeyDown(29) = 0 )
  Speed# = 1
Else If( KeyDown(42) = 0 And KeyDown(29) = 1 )
  Speed# = 0.01
EndIf

If( KeyDown(17)=1 )
  MoveEntity(GhostRoot,0,0,Speed)
Else If( KeyDown(31)=1 )
  MoveEntity(GhostRoot,0,0,-Speed)
EndIf
If( KeyDown(30)=1 )
  MoveEntity(GhostRoot,-Speed,0,0)
Else If( KeyDown(32)=1 )
  MoveEntity(GhostRoot,Speed,0,0)
EndIf
If( KeyDown(16)=1 )
  MoveEntity(GhostRoot,0,-Speed,0)
Else If( KeyDown(18)=1 )
  MoveEntity(GhostRoot,0,Speed,0)
EndIf

End Function

Function CreatePipeSeg(Sides%=32,Radius#=5.0,Length#=1.0)

Rotor = CreatePivot()

Mesh = CreateMesh()

;surface
Surface = CreateSurface(Mesh)

;vertices
S% = 0 
SRoll# = 360.0/Sides
PositionEntity(Rotor,0,0,0,True) : RotateEntity(Rotor,0,0,0,True)
For Z# = 0 To Length Step 1
  S% = 0
  Repeat
   S = S + 1
   TFormPoint(0,+Radius,Z,Rotor,0)
   ;Marker = CreateCube() : ScaleMesh(Marker,0.03/2+Float(S)/1000,0.03/2+Float(S)/1000,0.03/2+Float(S)/1000)
   ;PositionEntity(Marker,TFormedX(),TFormedY(),TFormedZ())
   AddVertex(Surface,TFormedX(),TFormedY(),TFormedZ())
   TurnEntity(Rotor,0,0,SRoll)
  Until( S = Sides )
Next

;triangles
For S% = 1 To Sides Step 1
  V0I% = S  : If( S = Sides ) : V0I% = 0 : EndIf
  V1I% = S-1
  V2I% = Sides+S : If( S = Sides ) : V2I% = Sides+0 : EndIf
  V3I% = Sides+S-1
  AddTriangle(Surface,V0I,V1I,V2I)
  AddTriangle(Surface,V2I,V1I,V3I)
Next

FreeEntity(Rotor)

UpdateNormals(Mesh)

;DebugLog(CountVertices(Surface))
;DebugLog(CountTriangles(Surface))

Return Mesh

End Function

Function ResetVertColor(Surface)

For VI% = 0 To CountVertices(Surface)-1

  VertexColor(Surface,VI,-255,-255,-255)

Next

End Function

Function AmbientVertColor(Surface,AmbientR%,AmbientG%,AmbientB%)

For VI% = 0 To CountVertices(Surface)-1

  VertexColor(Surface,VI,AmbientR,AmbientG,AmbientB)

Next

End Function

Function LightVertColor(Mesh,Surface,LightX#,LightY#,LightZ#,LightR%,LightG%,LightB%,LightRang#)

For VI% = 0 To CountVertices(Surface)-1
  ;get the vertex current color
  VertR% = VertexRed(Surface,VI) : VertG% = VertexGreen(Surface,VI) : VertB% = VertexBlue(Surface,VI)
  ;get the vertex position
  TFormPoint(VertexX(Surface,VI),VertexY(Surface,VI),VertexZ(Surface,VI),Mesh,0)
  VertX# = TFormedX() : VertY# = TFormedY() : VertZ# = TFormedZ()
  ;calculate the distance3d from light to vertex
  Dist# = Distance3D(LightX,LightY,LightZ,VertX,VertY,VertZ)
  ;if in range
  If( Dist < LightRang )
   ;calculate the distance attenuation coeff
   DistC# = 1.0 - ( Dist / LightRang )
   ;calculate the vector normal light->vertex
   LVX# = VertX-LightX : LVY# = VertY-LightY : LVZ# = VertZ-LightZ
   ;normalise the vector
   LNX# = LVX/Dist : LNY# = LVY/Dist : LNZ# = LVZ/Dist
   ;get the vertex normal
   TFormNormal(VertexNX(Surface,VI),VertexNY(Surface,VI),VertexNZ(Surface,VI),Mesh,0)
   VertNX# = TFormedX() : VertNY# = TFormedY() : VertNZ# = TFormedZ()
   
   ;TNormal = createcube() : ScaleMesh(TNormal,0.02/2,0.02/2,1.0/2) : PositionMesh(TNormal,0,0,1.0/2) : EntityFX(TNormal,1)
   ;PositionEntity(TNormal,VertX,VertY,VertZ,True) : AlignToVector(TNormal,VertNX,VertNY,VertNZ,3,1.0)

   ;calculate the angle3d between light normal and vertex normal
   Angl# = Abs(Angle3D#(LNX,LNY,LNZ,VertNX,VertNY,VertNZ))
   ;DebugLog(Angl) : WaitKey()
   ;if facing
   If( Angl >= 90.0 And Angl <= 180.0 )
    ;calculate the angle attenuation coeff
    AnglC# = ( (Angl-90.0) / 90.0 )
    ;calculate the final lighting color
    FinaR% = VertR+LightR*DistC*AnglC : If( FinaR > 255 ) : FinaR = 255 : EndIf
    FinaG% = VertG+LightG*DistC*AnglC : If( FinaG > 255 ) : FinaG = 255 : EndIf
    FinaB% = VertB+LightR*DistC*AnglC : If( FinaB > 255 ) : FinaB = 255 : EndIf
    ;set the vertex color
    VertexColor(Surface,VI,FinaR,FinaG,FinaB)
   EndIf
  EndIf
Next

End Function

RemiD

just noticed a bug and fixed it...

another scene to test the lighting shading with vertexcolor :

;lighting shading with custom vertex colors (room walls and cubes)
;more realistic and customizable than lightmesh
;by RemiD 2022/11/23

Graphics3D(854,480,32,2)
HidePointer()

SeedRnd(MilliSecs())

;Origine
Global Origine = CreateCube()
ScaleMesh(Origine,0.01,0.01,0.01)
EntityColor(Origine,255,000,255)
EntityFX(Origine,1)

;Camera
Global Camera = CreateCamera()
CameraViewport(Camera,0,0,GraphicsWidth(),GraphicsHeight())
CameraRange(Camera,0.15,150)
CameraClsColor(Camera,000,000,000)

Global Pivot = CreatePivot()

;Input
Global MX%
Global MY%
Global MXDiff%
Global MYDiff%

;Ghost
Global GhostRoot
Global GhostRootYaw#
Global GhostEyes
Global GhostEyesPitch#
AddGhost()

;create some walls (room)
;texture the walls
;set fx to fullbright, allow vertices colors (Fx 1+2)
Room_Mesh = CreateRoom(30,3,30)
PositionEntity(Room_Mesh,0,0,0,True)
ColorTex = CreateTexture(8,8)
SetBuffer(TextureBuffer(ColorTex))
Color(240,240,240) : Rect(0,0,8,8,True)
EntityTexture(Room_Mesh,ColorTex)
EntityFX(Room_Mesh,1+2)

;create some shapes (cubes)
;texture the shapes
;set fx to fullbright, allow vertices colors (Fx 1+2)
Global ShapesCount%
Dim Shape_Mesh(30)

For n% = 1 To 30 Step 1
.linechooseshapeposition
x# = Rand(0,30-1)+0.5 : z# = Rand(0,30-1)+0.5
;check if the shape will be far enough from others shapes
For oi% = 1 To ShapesCount
  If( Distance2D( x,z,EntityX(Shape_Mesh(oi),True),EntityZ(Shape_Mesh(oi),True) ) < 0.5+1.5+0.5 )
   Goto linechooseshapeposition
  EndIf
Next
;create new shape at this position
ShapesCount = ShapesCount + 1 : i% = ShapesCount
Shape_Mesh(i) = CreateCube()
ScaleMesh(Shape_Mesh(i),1.0/2,1.0/2,1.0/2)
ColorTex = CreateTexture(8,8)
SetBuffer(TextureBuffer(ColorTex))
  Color(240,240,240) : Rect(0,0,8,8,True)
EntityTexture(Shape_Mesh(i),ColorTex)
EntityFX(Shape_Mesh(i),1+2)
PositionEntity(Shape_Mesh(i),x,0.5,z,True)
RotateEntity(Shape_Mesh(i),0,Rand(-180,+180),0,True)
Next

;create some lights (only the properties)
Global LightsCount%
Dim Light_Rang#(16) ;range in units
Dim Light_R%(16)
Dim Light_G%(16)
Dim Light_B%(16)
Dim Light_Source(16)

For n% = 1 To 16
LightsCount = LightsCount + 1 : I% = LightsCount
Light_Rang(I) = 6.0
;RandomColor()
;Light_R(I) = ColorR : Light_G(I) = ColorG : Light_B(I) = ColorB
Light_R(I) = Rand(060,240) : Light_G(I) = Rand(060,240) : Light_B(I) = Rand(060,240)
Light_Source(I) = CreateSphere(2)
ScaleMesh(Light_Source(I),0.05/2,0.05/2,0.05/2) : EntityColor(Light_Source(I),Light_R(I),Light_G(I),Light_B(I)) : EntityFX(Light_Source(I),1)
x# = Rnd(1.5,30-1.5) : z# = Rnd(1.5,30-1.5)
PositionEntity(Light_Source(i),x,1.5,z,True)
Next

;define the ambient light
AmbientR% = 030
AmbientG% = 030
AmbientB% = 030

;light the scene using vertexcolor lighting
;reset vertices color (room)
;ResetVertColor(GetSurface(Room_Mesh,1)) ;not needed
;color with ambientlight (room)
AmbientVertColor(GetSurface(Room_Mesh,1),AmbientR,AmbientG,AmbientB)
;light with vertexcolor (room)
For li% = 1 To LightsCount
LightVertColor(Room_Mesh,GetSurface(Room_Mesh,1),EntityX(Light_Source(li),True),EntityY(Light_Source(li),True),EntityZ(Light_Source(li),True),Light_R(li),Light_G(li),Light_B(li),Light_Rang(li))
Next

;reset vertices color (shapes)
;For i% = 1 To ShapesCount
; ResetVertColor(GetSurface(Shape_Mesh(i),1)) ;not needed
;Next
;color with ambientlight (shapes)
For i% = 1 To ShapesCount
AmbientVertColor(GetSurface(Shape_Mesh(i),1),AmbientR,AmbientG,AmbientB)
Next
;light with vertexcolor (shapes)
For i% = 1 To ShapesCount
For li% = 1 To LightsCount
  LightVertColor(Shape_Mesh(i),GetSurface(Shape_Mesh(i),1),EntityX(Light_Source(li),True),EntityY(Light_Source(li),True),EntityZ(Light_Source(li),True),Light_R(li),Light_G(li),Light_B(li),Light_Rang(li))
Next
Next

PositionEntity(GhostRoot,15,1.75,0.5)

Repeat

MX = MouseX() : MY = MouseY()

MXDiff = MouseXSpeed() : MYDiff = MouseYSpeed()

UpdateGhost()     

PositionEntity(Camera,EntityX(GhostEyes,True),EntityY(GhostEyes,True),EntityZ(GhostEyes,True),True)
RotateEntity(Camera,EntityPitch(GhostEyes,True),EntityYaw(GhostEyes,True),EntityRoll(GhostEyes,True),True)

WireFrame(False)
If( KeyDown(2)=1 )
  WireFrame(True)
EndIf

SetBuffer(BackBuffer())
RenderWorld()

Flip(1)

Until( KeyDown(1)=1 )

End

Function Distance2D#(PAX#,PAZ#,PBX#,PBZ#)

Distance2D# = Sqr( ( ( PBX - PAX ) * ( PBX - PAX ) ) + ( ( PBZ - PAZ ) * ( PBZ - PAZ ) ) )
Return Distance2D

End Function

Function Distance3D#(PAX#,PAY#,PAZ#,PBX#,PBY#,PBZ#)

Distance3D# = Sqr( ( ( PBX - PAX ) * ( PBX - PAX ) ) + ( ( PBY - PAY ) * ( PBY - PAY ) ) + ( ( PBZ - PAZ ) * ( PBZ - PAZ ) ) )
Return Distance3D

End Function

Function Angle3D#(V1X#,V1Y#,V1Z#,V2X#,V2Y#,V2Z#)

D# = (V1X*V2X) + (V1Y*V2Y) + (V1Z*V2Z)
M# = Sqr( V1X*V1X + V1Y*V1Y + V1Z*V1Z ) * Sqr( V2X*V2X + V2Y*V2Y + V2Z*V2Z )
A# = ACos(D#/M#)
Return A#

End Function

Function AddGhost()

GhostRoot = CreatePivot()

GhostEyes = CreatePivot()
EntityParent(GhostEyes,GhostRoot,True)

End Function

Function UpdateGhost()

MoveMouse(GraphicsWidth()/2,GraphicsHeight()/2)
GhostEyesPitch = GhostEyesPitch + Float(MYDiff)/10
If( GhostEyesPitch < -89 )
  GhostEyesPitch = -89
Else If( GhostEyesPitch > 89 )
  GhostEyesPitch = 89
EndIf
RotateEntity(GhostEyes,GhostEyesPitch,0,0,False)
GhostRootYaw = GhostRootYaw - Float(MXDiff)/10
RotateEntity(GhostRoot,0,GhostRootYaw,0,False)

If( KeyDown(42) = 0 And KeyDown(29) = 0 )
  Speed# = 0.1
Else If( KeyDown(42) = 1 And KeyDown(29) = 0 )
  Speed# = 1
Else If( KeyDown(42) = 0 And KeyDown(29) = 1 )
  Speed# = 0.01
EndIf

If( KeyDown(17)=1 )
  MoveEntity(GhostRoot,0,0,Speed)
Else If( KeyDown(31)=1 )
  MoveEntity(GhostRoot,0,0,-Speed)
EndIf
If( KeyDown(30)=1 )
  MoveEntity(GhostRoot,-Speed,0,0)
Else If( KeyDown(32)=1 )
  MoveEntity(GhostRoot,Speed,0,0)
EndIf
If( KeyDown(16)=1 )
  MoveEntity(GhostRoot,0,-Speed,0)
Else If( KeyDown(18)=1 )
  MoveEntity(GhostRoot,0,Speed,0)
EndIf

End Function

Function CreateRoom(Width%,Height%,Depth%)

Mesh = CreateMesh()

;floor
TFloorPart = CreateMesh()
TSurface = CreateSurface(TFloorPart)
AddVertex(TSurface,0,0,1)
AddVertex(TSurface,1,0,1)
AddVertex(TSurface,0,0,0)
AddVertex(TSurface,1,0,0)
AddTriangle(TSurface,0,1,2)
AddTriangle(TSurface,2,1,3)
UpdateNormals(TFloorPart)

For gx% = 0 To Width-1 Step 1
  For gz% = 0 To Depth-1 Step 1
   TPart = CopyMesh(TFloorPart)
   PositionMesh(TPart,gx,0,gz)
   AddMesh(TPart,Mesh) : FreeEntity(TPart)
  Next
Next

FreeEntity(TFloorPart)

;ceiling
TCeilingPart = CreateMesh()
TSurface = CreateSurface(TCeilingPart)
AddVertex(TSurface,0,0,0)
AddVertex(TSurface,1,0,0)
AddVertex(TSurface,0,0,1)
AddVertex(TSurface,1,0,1)
AddTriangle(TSurface,0,1,2)
AddTriangle(TSurface,2,1,3)
UpdateNormals(TCeilingPart)

For gx% = 0 To Width-1 Step 1
  For gz% = 0 To Depth-1 Step 1
   TPart = CopyMesh(TCeilingPart)
   PositionMesh(TPart,gx,Height,gz)
   AddMesh(TPart,Mesh) : FreeEntity(TPart)
  Next
Next

FreeEntity(TCeilingPart)

;wallfront
TWallFrontPart = CreateMesh()
TSurface = CreateSurface(TWallFrontPart)
AddVertex(TSurface,0,1,0)
AddVertex(TSurface,1,1,0)
AddVertex(TSurface,0,0,0)
AddVertex(TSurface,1,0,0)
AddTriangle(TSurface,0,1,2)
AddTriangle(TSurface,2,1,3)
UpdateNormals(TWallFrontPart)

For gx% = 0 To Width-1 Step 1
  For gy% = 0 To Height-1 Step 1
   TPart = CopyMesh(TWallFrontPart)
   PositionMesh(TPart,gx,gy,Depth)
   AddMesh(TPart,Mesh) : FreeEntity(TPart)
  Next
Next

FreeEntity(TWallFrontPart)

;wallback
TWallBackPart = CreateMesh()
TSurface = CreateSurface(TWallBackPart )
AddVertex(TSurface,1,1,0)
AddVertex(TSurface,0,1,0)
AddVertex(TSurface,1,0,0)
AddVertex(TSurface,0,0,0)
AddTriangle(TSurface,0,1,2)
AddTriangle(TSurface,2,1,3)
UpdateNormals(TWallBackPart )

For gx% = 0 To Width-1 Step 1
  For gy% = 0 To Height-1 Step 1
   TPart = CopyMesh(TWallBackPart )
   PositionMesh(TPart,gx,gy,0)
   AddMesh(TPart,Mesh) : FreeEntity(TPart)
  Next
Next

FreeEntity(TWallBackPart )

;wallleft
TWallLeftPart = CreateMesh()
TSurface = CreateSurface(TWallLeftPart)
AddVertex(TSurface,0,1,0)
AddVertex(TSurface,0,1,1)
AddVertex(TSurface,0,0,0)
AddVertex(TSurface,0,0,1)
AddTriangle(TSurface,0,1,2)
AddTriangle(TSurface,2,1,3)
UpdateNormals(TWallLeftPart)

For gy% = 0 To Height-1 Step 1
  For gz% = 0 To Depth-1 Step 1
   TPart = CopyMesh(TWallLeftPart)
   PositionMesh(TPart,0,gy,gz)
   AddMesh(TPart,Mesh) : FreeEntity(TPart)
  Next
Next

FreeEntity(TWallLeftPart)

;wallright
TWallRightPart = CreateMesh()
TSurface = CreateSurface(TWallRightPart)
AddVertex(TSurface,0,1,1)
AddVertex(TSurface,0,1,0)
AddVertex(TSurface,0,0,1)
AddVertex(TSurface,0,0,0)
AddTriangle(TSurface,0,1,2)
AddTriangle(TSurface,2,1,3)
UpdateNormals(TWallRightPart)

For gy% = 0 To Height-1 Step 1
  For gz% = 0 To Depth-1 Step 1
   TPart = CopyMesh(TWallRightPart)
   PositionMesh(TPart,Width,gy,gz)
   AddMesh(TPart,Mesh) : FreeEntity(TPart)
  Next
Next

FreeEntity(TWallRightPart)

Return Mesh

End Function

Function ResetVertColor(Surface)

For VI% = 0 To CountVertices(Surface)-1

  VertexColor(Surface,VI,-255,-255,-255)

Next

End Function

Function AmbientVertColor(Surface,AmbientR%,AmbientG%,AmbientB%)

For VI% = 0 To CountVertices(Surface)-1

  VertexColor(Surface,VI,AmbientR,AmbientG,AmbientB)

Next

End Function

Function LightVertColor(Mesh,Surface,LightX#,LightY#,LightZ#,LightR%,LightG%,LightB%,LightRang#)

For VI% = 0 To CountVertices(Surface)-1
  ;get the vertex current color
  VertR% = VertexRed(Surface,VI) : VertG% = VertexGreen(Surface,VI) : VertB% = VertexBlue(Surface,VI)
  ;get the vertex position
  TFormPoint(VertexX(Surface,VI),VertexY(Surface,VI),VertexZ(Surface,VI),Mesh,0)
  VertX# = TFormedX() : VertY# = TFormedY() : VertZ# = TFormedZ()
  ;calculate the distance3d from light to vertex
  Dist# = Distance3D(LightX,LightY,LightZ,VertX,VertY,VertZ)
  ;if in range
  If( Dist < LightRang )
   ;calculate the distance attenuation coeff
   DistC# = 1.0 - ( Dist / LightRang )
   ;calculate the vector normal light->vertex
   LVX# = VertX-LightX : LVY# = VertY-LightY : LVZ# = VertZ-LightZ
   ;normalise the vector
   LNX# = LVX/Dist : LNY# = LVY/Dist : LNZ# = LVZ/Dist
   ;get the vertex normal
   TFormNormal(VertexNX(Surface,VI),VertexNY(Surface,VI),VertexNZ(Surface,VI),Mesh,0)
   VertNX# = TFormedX() : VertNY# = TFormedY() : VertNZ# = TFormedZ()

   ;TNormal = createcube() : ScaleMesh(TNormal,0.02/2,0.02/2,1.0/2) : PositionMesh(TNormal,0,0,1.0/2) : EntityFX(TNormal,1)
   ;PositionEntity(TNormal,VertX,VertY,VertZ,True) : AlignToVector(TNormal,VertNX,VertNY,VertNZ,3,1.0)

   ;calculate the angle3d between light normal and vertex normal
   Angl# = Abs(Angle3D#(LNX,LNY,LNZ,VertNX,VertNY,VertNZ))
   ;DebugLog(Angl) : WaitKey()
   ;if facing
   If( Angl >= 90.0 And Angl <= 180.0 )
    ;calculate the angle attenuation coeff
    AnglC# = ( (Angl-90.0) / 90.0 )
    ;calculate the final lighting color
    FinaR% = VertR+LightR*DistC*AnglC : If( FinaR > 255 ) : FinaR = 255 : EndIf
    FinaG% = VertG+LightG*DistC*AnglC : If( FinaG > 255 ) : FinaG = 255 : EndIf
    FinaB% = VertB+LightR*DistC*AnglC : If( FinaB > 255 ) : FinaB = 255 : EndIf
    ;set the vertex color
    VertexColor(Surface,VI,FinaR,FinaG,FinaB)
   EndIf
  EndIf
Next

End Function