Code archives/3D Graphics - Effects/Simple shadows

This code has been declared by its author to be Public Domain code.

Download source code

Simple shadows by nawi
(Posted 19 years ago)
This is a simple shadow system I made for fun. It's not that fast, and alpha shadows don't work properly.. but you might learn something from this.

Pic:
Graphics3D 800,600,0,2
SetBuffer BackBuffer()


Global Cam = CreateCamera()
MoveEntity Cam,0,5,-2



NewObject = GetObject()



;Position our entity
MoveEntity NewObject,0,2.5,0

;White plane
Plane = CreatePlane()
EntityColor Plane,255,255,255
MoveEntity Plane,0,-0.01,0

;Create light
Light = CreateSphere(5)
Spot = CreateLight(2,Light)
ScaleEntity Light,0.1,0.1,0.1
EntityColor Light,255,255,0



Repeat
	;Camera movement
	If KeyDown(200) Then MoveEntity Cam,0,0,1
	If KeyDown(208) Then MoveEntity Cam,0,0,-1
	If KeyDown(203) Then MoveEntity Cam,-1,0,0
	If KeyDown(205) Then MoveEntity Cam,1,0,0


	;Shadow object must be created and destroyed every frame
	Shadow = CreateMesh()
	
	EntityAlpha Shadow,1 
	;There is sadly a bug with alpha shadows.. Didn't figure out a proper solution to this one
	;You could use a camera, but would be a major slowdown
	
;	EntityColor Shadow,0,0,0
	

	;Light movement
	GY# = 7+Sin(MilliSecs()/10)*0.5
	GX# = Cos(MilliSecs()/10)*3
	
	;Draw shadow
	DrawShadow(NewObject,GX#,GY#,GZ#,Shadow)
	PositionEntity Light,GX#,GY#,GZ#
	
	
	;FPS
	FPSC=FPSC+1
	If MilliSecs()>FPSTimer+999 Then
		FPSTimer = MilliSecs()
		FPS=FPSC
		FPSC=0
	EndIf
	
	


	RenderWorld

	Text 0,0,"FPS: " + FPS
	;Text 0,20,"Trisrendered: " + TrisRendered()
	Flip 0

	;Destroy shadow
	FreeEntity Shadow

Until KeyHit(1)

Function DrawShadow(Entity,SX#,SY#,SZ#,Shadow)
	;This works by looping through all triangles, then calculating a line for each vertex to ground (y=0)

	EX#=EntityX#(Entity,1)
	EY#=EntityY#(Entity,1)
	EZ#=EntityZ#(Entity,1)
	ShadowSurface = CreateSurface(Shadow)
	Surfaces=CountSurfaces(Entity)
	For s=1 To Surfaces
		Surface = GetSurface(Entity,s)
		

		Triangles=CountTriangles(Surface)-1
		For t=0 To Triangles
			v1 = TriangleVertex(Surface,t,0)
			v2 = TriangleVertex(Surface,t,1)
			v3 = TriangleVertex(Surface,t,2)
			
			v1X# = VertexX#(Surface,v1)+EX#
			v1Y# = VertexY#(Surface,v1)+EY#
			v1Z# = VertexZ#(Surface,v1)+EZ#
			K#=-SY#/(SY#-v1Y#)
			v1XR# = SX# + (SX#-v1X#)*K#
			v1ZR# = SZ# + (SZ#-v1Z#)*K#

			v2X# = VertexX#(Surface,v2)+EX#
			v2Y# = VertexY#(Surface,v2)+EY#
			v2Z# = VertexZ#(Surface,v2)+EZ#
			K#=-SY#/(SY#-v2Y#)
			v2XR# = SX# + (SX#-v2X#)*K#
			v2ZR# = SZ# + (SZ#-v2Z#)*K#
			
			v3X# = VertexX#(Surface,v3)+EX#
			v3Y# = VertexY#(Surface,v3)+EY#
			v3Z# = VertexZ#(Surface,v3)+EZ#
			K#=-SY#/(SY#-v3Y#)
			v3XR# = SX# + (SX#-v3X#)*K#
			v3ZR# = SZ# + (SZ#-v3Z#)*K#
			
			;Backface culling works by calculating a camera vector and a surface normal
			;If the dot product is > 0 then draw
			
			;Camera vector
			CX#=SX#-(v1X#+v2X#+v3X#)*0.33333
			CY#=SY#-(v1Y#+v2Y#+v3Y#)*0.33333
			CZ#=SZ#-(v1Z#+v2Z#+v3Z#)*0.33333
			
			;Surface normal, create 2 vectors and then create vector W from their cross product
			UX# = V2X#-V1X#
			UY# = V2Y#-V1Y#
			UZ# = V2Z#-V1Z#
			VX# = V3X#-V1X#
			VY# = V3Y#-V1Y#
			VZ# = V3Z#-V1Z#
			WX# = UY#*VZ#-UZ#*VY#
			WY# = -(UX#*VZ#-UZ#*VX#)
			WZ# = UX#*VY#-UY#*VX#
			
			;Add triangle
			If (SY#>v1Y#) And (SY#>v2Y#) And (SY#>v3Y#) And (CX#*WX#+CY#*WY#+CZ#*WZ#)>0.0 Then
				AddTriangle(ShadowSurface,AddVertex(ShadowSurface,v1XR#,0,v1ZR#),AddVertex(ShadowSurface,v2XR#,0,v2ZR#),AddVertex(ShadowSurface,v3XR#,0,v3ZR#))
			EndIf

		Next
	Next
End Function

;Create a test object
Function GetObject()
	NewObject = CreateMesh()
	Cube = CreateCube()
	ScaleMesh Cube,0.6,2.5,0.6
	
	PositionMesh Cube,-3,0,3
	AddMesh Cube,NewObject
	
	PositionMesh Cube,6,0,0
	AddMesh Cube,NewObject
	
	PositionMesh Cube,-6,0,-6
	AddMesh Cube,NewObject
	
	PositionMesh Cube,6,0,0
	AddMesh Cube,NewObject
	
	Sphere = CreateSphere(16)

	
	PositionMesh Sphere,-3,2.5,3
	AddMesh Sphere,NewObject

	PositionMesh Sphere,6,0,0
	AddMesh Sphere,NewObject
	
	PositionMesh Sphere,-6,0,-6
	AddMesh Sphere,NewObject
	
	PositionMesh Sphere,6,0,0
	AddMesh Sphere,NewObject
	
	FreeEntity Cube
	FreeEntity Sphere
	
	EntityColor NewObject,0,200,0
	Return NewObject
End Function