Real time 3draytracer.

Miscellaneous Forums/Blitz Showcase/Real time 3draytracer.

Inspired by the thread on it, here is a simple yet nice looking 3d tracer engine.



It uses b3d meshes so you can load and trace any entity, easily. Just call newPrim(entity) to add to the scene.
newLight() to add a colored light(Casts shadows by default)

It renders from the point of view of a blitz camera. Although the entire scene is drawn using writepixelfast, so don't expect massive speeds.)

Has shadows and true diffuse lighting.

Neither demo requires outside media.


You can set Res to any pixel size to improve the res/quality.

Low Quality Version. this one is not only real time but you can move above, wasd controls.
Still has lights/shadows.(3)
;Infini.
;
Global res=45

Graphics3D res+5,res+5,32,3
SetBuffer BackBuffer()


test=CreateCube()

;test=LoadMesh("tmedia\jeep1.3ds")
If Not test End
;FitMesh test,-3,-1,-3,6,1,6
other=CreateCube()
FitMesh other,-20,-1,-20,40,20,40
FlipMesh other
newPrim(other,2)
newPrim(test,2)
;EntityPickMode

vcam=CreateCamera()
PositionEntity vcam,3,10,-5
PointEntity vcam,test
UpdateNormals other
UpdateNormals test
TurnEntity test,0,0,-45


newLight(10,8,4,0,0,512)
newLight(-10,8,4,255,255,100)

newLight(0,3.5,-6,412,412,412)






Repeat


Cls
	;RenderWorld
  PositionEntity test,0,10+Cos(aa)*4,0
	aa=aa+20
	
	TurnEntity vcam,MouseYSpeed(),-MouseXSpeed(),0,True
	RotateEntity vcam,EntityPitch(vcam),EntityYaw(vcam),0
	MoveMouse 20,20
	FlushMouse
	
;	PointEntity vcam,test
		;FlushMouse
		
	If KeyDown(17)
		MoveEntity vcam,0,0,2
	EndIf
	
	If KeyDown(31)
		MoveEntity vcam,0,0,-2
	EndIf
	
	If KeyDown(30)
		MoveEntity vcam,1,0,0
	EndIf
	If KeyDown(32)
		MoveEntity vcam,-1,0,0
	EndIf
	TurnEntity test,0,5,0
	rayTrace(vcam,res,res)
	;Flip
;Else
	;RayTrace(vcam,64,64)
	;EndIf
	
	Flip False
Until KeyDown(1)
SaveBuffer(BackBuffer(),"RayTrace.bmp")
WaitKey
End


;End
Type prim
	Field id
End Type
Type light
	Field x,y,z
	Field r#,g#,b#
End Type
Function DotProd#(vecA#[3], vecB#[3])
   Return(vecA[0]*vecB[0] +vecA[1]*vecB[1] +vecA[2]*vecB[2]);
End Function

Function vecNormalize#(vec#[3])
   mag# = Sqr(vec[0]*vec[0] +vec[1]*vec[1] +vec[2]*vec[2]);

   ;// don't divide by zero
   If (mag=0)
      vec[0] = 0.0;f;
      vec[1] = 0.0;f;
      vec[2] = 0.0;f;
      Return(0.0);
   EndIf

   vec[0] =vec[0]/mag;
   vec[1] =vec[1]/mag;
   vec[2] =vec[2]/mag;

   Return(mag);
End Function
Function rayTrace(cam,xRes=160,yRes=160,pixelRes=1)
	fov#=5;in units
	xScan#=fov/XRes;/fov;/fov*2
	yScan#=fov/yRes;/fov;/fov*2
;	Stop
Local vecA#[3],vecB#[3]
	xo#=-2.5
	yo#=2.5
	cx#=EntityX(cam)
	cy#=EntityY(cam)
	cz#=EntityZ(cam)
LockBuffer 
	While x<xRes
		x=x+pixelRes
		xo=xo+xScan
		While y<yRes
			y=y+pixelRes
			yo=yo-yScan
			TFormVector xo*20,yo*20,100,cam,0
			totr=0
			totg=0
			totb=0
			vx#=TFormedX()
			vy#=TFormedY()
			vz#=TFormedZ()
			hit=LinePick(cx,cy,cz,TFormedX(),TFormedY(),TFormedZ(),0.2)
			If hit
			
				px#=PickedX()
				py#=PickedY()
				pz#=PickedZ()
				nx#=PickedNX()
				ny#=PickedNY()
				nz#=PickedNZ()
				Veca[0]=PickedNX()
				veca[1]=PickedNY()
				veca[2]=PickedNZ()
			HideEntity hit
			
			For l.light =Each light
				dx#=l\x-px
				dy#=l\y-py
				dz#=l\z-pz
				vecB[0]=dx
				VecB[1]=dy
				Vecb[2]=dz
				vecNormalize(vecb)
					dot#=dotProd(veca,vecb)
				If dot>0
					hit2=LinePick(px,py,pz,dx,dy,dz,0.2)
					If hit2
					Else
						totr=totR+Float(l\r*dot);*hit2
						totg=totG+Float(l\g*dot);*hit2
						totb=totB+Float(l\b*dot);*hit2
					EndIf
				EndIf
			
			Next
			ShowEntity hit

			totr=totr/3.
			totg=totg/3.
			totb=totb/3.

				If veca[0]<>0 ox#=-vx Else ox=vx
				If veca[1]<>0 oy#=-vy Else oy=vy
				If veca[2]<>0 oz#=-vz Else oz=vz

				If totr>255 totr=255
				If totg>255 totg=255
				If totb>255 totb=255
			rgb=totb Or (totg Shl 8) Or (totr Shl 16)
			
					WritePixelFast x,y,rgb
				
			EndIf
		Wend
		y=0
		yo=2.5
	Wend
UnlockBuffer
End Function

Function newLight(x,y,z,r=128,g=128,b=128)
	l.light=New light
	l\x=x
	l\y=y
	l\z=z
	l\r=r
	l\g=g
	l\b=b
End Function

Function newPrim(ent,mode)
	p.prim=New prim
	p\id=ent
	EntityPickMode ent,mode,True
	
End Function



High quality version, too hi-res to be real time.(Well, on my cput. Yours may be powerful enough).
;Infini.
;
;
;High Quality. SLOW.
Global res=512

Graphics3D res+60,res+60,32,3
SetBuffer BackBuffer()


test=CreateCube()

;test=LoadMesh("tmedia\jeep1.3ds")
If Not test End
;FitMesh test,-3,-1,-3,6,1,6
other=CreateCube()
FitMesh other,-20,-1,-20,40,20,40
FlipMesh other
newPrim(other,2)
newPrim(test,2)
;EntityPickMode

vcam=CreateCamera()
PositionEntity vcam,3,10,-5
PointEntity vcam,test
UpdateNormals other
UpdateNormals test
TurnEntity test,0,0,-45


newLight(10,8,4,0,0,512)
;newLight(-10,8,4,255,255,-100)
newLight(0,3.5,-6,412,412,412)






Repeat


Cls
	;RenderWorld
  PositionEntity test,0,10+Cos(aa)*4,0
	aa=aa+20
	
	TurnEntity vcam,MouseYSpeed(),-MouseXSpeed(),0
	RotateEntity vcam,EntityPitch(vcam),EntityYaw(vcam),0
	MoveMouse res/2,res/2
	PointEntity vcam,test
	FlushMouse
	If MouseDown(2)
		MoveEntity vcam,0,0,0.6
		EndIf
		TurnEntity test,0,30,0

	rayTrace(vcam,res,res)
	;Flip
;Else
	;RayTrace(vcam,64,64)
	;EndIf
	
	Flip False
Until KeyDown(1)
SaveBuffer(BackBuffer(),"RayTrace.bmp")
WaitKey
End


;End
Type prim
	Field id
End Type
Type light
	Field x,y,z
	Field r#,g#,b#
End Type
Function DotProd#(vecA#[3], vecB#[3])
   Return(vecA[0]*vecB[0] +vecA[1]*vecB[1] +vecA[2]*vecB[2]);
End Function

Function vecNormalize#(vec#[3])
   mag# = Sqr(vec[0]*vec[0] +vec[1]*vec[1] +vec[2]*vec[2]);

   ;// don't divide by zero
   If (mag=0)
      vec[0] = 0.0;f;
      vec[1] = 0.0;f;
      vec[2] = 0.0;f;
      Return(0.0);
   EndIf

   vec[0] =vec[0]/mag;
   vec[1] =vec[1]/mag;
   vec[2] =vec[2]/mag;

   Return(mag);
End Function
Function rayTrace(cam,xRes=160,yRes=160,pixelRes=1)
	fov#=5;in units
	xScan#=fov/XRes;/fov;/fov*2
	yScan#=fov/yRes;/fov;/fov*2
;	Stop
Local vecA#[3],vecB#[3]
	xo#=-2.5
	yo#=2.5
	cx#=EntityX(cam)
	cy#=EntityY(cam)
	cz#=EntityZ(cam)
LockBuffer 
	While x<xRes
		x=x+pixelRes
		xo=xo+xScan
		While y<yRes
			y=y+pixelRes
			yo=yo-yScan
			TFormVector xo*20,yo*20,100,cam,0
			totr=0
			totg=0
			totb=0
			vx#=TFormedX()
			vy#=TFormedY()
			vz#=TFormedZ()
			hit=LinePick(cx,cy,cz,TFormedX(),TFormedY(),TFormedZ(),0.2)
			If hit
			
				px#=PickedX()
				py#=PickedY()
				pz#=PickedZ()
				nx#=PickedNX()
				ny#=PickedNY()
				nz#=PickedNZ()
				Veca[0]=PickedNX()
				veca[1]=PickedNY()
				veca[2]=PickedNZ()
			HideEntity hit
			
			For l.light =Each light
				dx#=l\x-px
				dy#=l\y-py
				dz#=l\z-pz
				vecB[0]=dx
				VecB[1]=dy
				Vecb[2]=dz
				vecNormalize(vecb)
					dot#=dotProd(veca,vecb)
				If dot>0
					hit2=LinePick(px,py,pz,dx,dy,dz,0.2)
					If hit2
					Else
						totr=totR+Float(l\r*dot);*hit2
						totg=totG+Float(l\g*dot);*hit2
						totb=totB+Float(l\b*dot);*hit2
					EndIf
				EndIf
			
			Next
			ShowEntity hit

			totr=totr/3.
			totg=totg/3.
			totb=totb/3.

				If veca[0]<>0 ox#=-vx Else ox=vx
				If veca[1]<>0 oy#=-vy Else oy=vy
				If veca[2]<>0 oz#=-vz Else oz=vz

				If totr>255 totr=255
				If totg>255 totg=255
				If totb>255 totb=255
			rgb=totb Or (totg Shl 8) Or (totr Shl 16)
			
					WritePixelFast x,y,rgb
				
			EndIf
		Wend
		y=0
		yo=2.5
	Wend
UnlockBuffer
End Function

Function newLight(x,y,z,r=128,g=128,b=128)
	l.light=New light
	l\x=x
	l\y=y
	l\z=z
	l\r=r
	l\g=g
	l\b=b
End Function

Function newPrim(ent,mode)
	p.prim=New prim
	p\id=ent
	EntityPickMode ent,mode,True
	
End Function