Page 9 of 9

Posted: Thu Aug 04, 2005 3:17 pm
by Hades
deadmoap wrote:One more question though... just out of curiousity, would it be harder to write a raytracer or a rasterizer?
I think there is a simple answer to your question. It is easy to write a fast rasterizer, and it is easy to write a raytraycer that produces really nice pictures.
But it is very hard to write a rasterizer that produces really nice pictures, or a raytracer that is fast. :wink:

Posted: Mon Aug 08, 2005 3:30 am
by Dreglor
well, im really frustrated right now and theres a bug that id like kick but my frustration at is a point i can't contrate :evil:

so im posting the code so maybe you guys can isolate and fix it.

before i tell you what's changed

well the source is split into 6 sources (not including the main file)

  • Vector.pbi - declares the structures and math functions for Vectors
    Color.pbi - declares the structures and math functions for Colors
    Material.pbi - declares the structures and functions for textures and materials and also layers when there implemented
    Light.pbi - declares the structures and functions for Lights
    Object.pbi - declares the structures and functions for Objects
    Scene.pbi - declares the structures and functions for ray, scene, camera and rendering functions (you can think about as the core)
ive also change how materials work with textures and how materials work with objects allowing them to be "switched out" for diffrent textures and materials

changed how lights and objects are added

started to change framework and functions to make it easy to read

got rid of more crushial branching inside of the trace ray procedure

started setting up for new features

got rid of alot of commented old code that wasn't needed

got rid of the matrix functions and structures (they wern't used at all)


i have a big list of things i want to add and then make a "release" in a form of a lib, but thats still up in the air

so about this bug,
right now i know its in the traceray procedure and it with the return color structure (pointer)
its not returing correctly
i get a black screen and 2 weird splotachs of orange were the reflections for the center sphere would be (its not the same scene as last post)
ive encontered that kind of coloring before it was with the same kinda of bug (execpt the hole thing was messed up)

im sure i just copied a few things wrong and its not being picked up by the compiler :\

so heres the code
>>PBRay8-7-05.zip<<
Image

Posted: Mon Aug 08, 2005 4:23 pm
by Hades
I am checking your code, but running out of time for now. The only thing I've found by now is this:

Code: Select all

        ForEach ObjectList()
          If @ObjectList()<>*Old_Element3
            If ObjectList()\IsLight=#False
              CallFunctionFast(ObjectList()\IntersectionMethod,shadow,@ObjectList(),IntersectionResults)
              If IntersectionResults\Result=#Hit Or IntersectionResults\Result=#InPrimitive
                shade=ObjectList()\Material\Refract
                 Break
              EndIf
            EndIf
          EndIf
        Next ;ObjectList() 
Shouldn't this be:

Code: Select all

        ForEach ObjectList()
          If @ObjectList()<>Closest\objectHandle
            If ObjectList()\IsLight=#False
              CallFunctionFast(ObjectList()\IntersectionMethod,shadow,@ObjectList(),IntersectionResults)
              If IntersectionResults\Result=#Hit Or IntersectionResults\Result=#InPrimitive
                shade=ObjectList()\Material\Refract
                 Break
              EndIf
            EndIf
          EndIf
        Next ;ObjectList() 
        ChangeCurrentElement(ObjectList(),Closest\objectHandle)

But it's quit possible I'm wrong on this. It just gives another strange result. :shock:

Posted: Mon Aug 08, 2005 10:22 pm
by Dreglor
one of the mistakes i did was deleteing those revertions
so maybe its thats screwing up the image

i look more into it but the image im getting here is were i think the light would be but (and the spread against the backplane) its quite random in color though

Posted: Thu Aug 11, 2005 12:13 pm
by Dreglor
as hard as this may be but...

I've lost motivation for this project its just so cumbersum to keep working on it.

i've made a decision to turn pbray onto a "back-burner" project and only work on it when im movitatied too. if i do start working on it again Im more and likely going to going to start from scratch, now that i know whats going on and how to do it.
the project has been valuable in the skills i've learned from it, and shows what pb can really do.
i think if i wasn't so focus on speed i could of added a bunch of stuff that would of been nice

Thanks to who helped esspecally: MrMat, Hades, and Fr34k for helping me Fix and optimze my code :D

Im now going to try a bit of game development and try and limit my self in the size and complexity of my projects

not sure how much will be done becasue school starting again at the end of this month and i won't any time to do much... :?

Posted: Thu Aug 11, 2005 3:30 pm
by Hades
:(

But for me it was fun too, even if we didn't get to the point where Asm conversion would make sense.

Good luck for your game development. But what do you mean with "limit my self in the size and complexity of my projects" ??
I am working on a game with a complete, realistic Galaxy, with detail down to rocks on the planets, lots of alien races, economy, science, 3D space flight, strategic level fleet management...

Do you think that's to much for a single person? :D :wink:

Posted: Thu Aug 11, 2005 6:36 pm
by Dreglor
I ment by that is try to do things as this big raytracing.
my problem is managment, i can't seam to keep my code in order :\
so i decided to do little toys till i get teh hang of making my code managable

as for your game, I had a idea like once. sounds cool, big tho
i could problably help in the form of code includes ;) maybe if pm is working for you we could talk a bit more about it

Posted: Thu Aug 11, 2005 7:27 pm
by Hades
I'm sorry, but you seem to misunderstood my post. Ok, I am really working on such a game, but on the other hand it is a joke too. Pacman is something for a single coder, what I try to do is surely not.
But what shall I do, nobody else writes that program for me. :D

Until PB has Doubles I can't do a lot of things. Even my planet creator cripples at maybe 10-20m detail. :(

I've solved a lot of advanced problems, but I still have some unsolved very basic problems. For example precise and efficient collision detection between spaceships.

I've already switched from VB6/DX8 to PB/OpenGL. Who knows what's next...

Posted: Fri Aug 12, 2005 1:11 am
by Dare2
@Dreglor

This was a big and gutsy project, thanks for sharing it. Watching it evolve was v. interesting.

Re: RayTracer Theory and Practice

Posted: Tue May 03, 2011 9:34 am
by c4s
Anyone still has this archive with the latest code: http://www.purebasic.fr/english/viewtop ... 115#p98115

I'm interested what people did 6 years ago with PureBasic. :)

Re: RayTracer Theory and Practice

Posted: Wed Aug 28, 2013 2:58 pm
by dobro
the last code of Dreglor
convert for PureBasic 5.11 ;)

Code: Select all

;/Title: PBRay
;/Author: Dreglor
;/Date: 7-7-05
;/Version: Alpha
;/Function: Renders scenes using raytracing
;/Notes: Special Thanks to MrMat for helping me :)
;/Todo: fix bugs, phong lighting, shadows ,Refractions

;***********************************************
;Titre  :PBRay
;Auteur  : Dreglor
;Date  :28/08/2013
;Heure  :15:56:23
;Version Purebasic :  PureBasic 5.11 (Windows - x86)
;Version de l'editeur :EPB V2.40
; Libairies necessaire : Aucune 
;***********************************************


;- Constants

#Version="Alpha"

#Tolerance=0.0001

#ObjectType_Null=0
#ObjectType_PointLight=1
#ObjectType_Sphere=2
#ObjectType_Plane=3
#ObjectType_Triangle=4

#MaxChildren=6

#EPSILON=0.0001
;#E=2.71828183

;- Structures

Structure xyz
	x.f
	y.f
	z.f
EndStructure

Structure VectorMatrix
	e1.f
	e2.f
	e3.f
EndStructure

Structure Matrix
	e11.f
	e12.f
	e13.f
	e21.f
	e22.f
	e23.f
	e31.f
	e32.f
	e33.f
EndStructure

Structure Camera
	Origin.xyz
	Direction.xyz
	ViewingAngle.xyz
	Apature.f ;exposure control
EndStructure

Structure Color
	Red.f
	Green.f
	Blue.f
EndStructure

Structure Material
	SoildColor.Color
	Diffuse.f
	Specular.f
	Reflect.f
	Refract.f
	Tranlucency.f
EndStructure

Structure PointLight
	Color.Color
	Origin.xyz
EndStructure

Structure Sphere
	radius.f
EndStructure

Structure Plane
	Distance.xyz
EndStructure

Structure Triangle
	v1.xyz
	v2.xyz
	v3.xyz
EndStructure

Structure Object
	Type.b
	Material.Material
	Origin.xyz
	Direction.xyz
	IsLight.b
	Normal.xyz
	Primitive.l ;points to a memory that get[primitive]structure will use to fill a structure with
EndStructure

Structure Scene
	Ambient.Color
	WorldScreenSize.f
	WorldScreenWidth.f
	WorldScreenHieght.f
	WorldScreenHalfWidth.f
	WorldScreenHalfHeight.f
	ScreenWidth.w
	ScreenHeight.w
	HalfScreenWidth.w
	HalfScreenHeight.w
	PixelStep.f
	RealPixelsStep.w
EndStructure

;- Globals

Global MainScene.Scene
Global LastProcedur; etime.l

global NewList ObjectList.Object()

;- Declares
Declare.b ColorScalarMuilply(*a.Color, b.f, *result.Color);returns a pointer to a Color that has been muiltiplied by a scalar
Declare.b ColorMuilply(*a.Color, *b.Color, *result.Color);returns a pointer to a Color that has been muiltiplied
Declare.b ColorAdd(*a.Color, *b.Color, *result.Color);returns a pointer to a Color that has been added
Declare  ColorRangeCheck(*a.Color)
Declare.f VectorMagnitude(*this.xyz);returns the maginitude of a Vector
Declare.f VectorDotProduct(*a.xyz, *b.xyz)
Declare.b VectorNormalize(*this.xyz);normilzes a vector
Declare.b VectorReverse(*this.xyz);reverses a Vector
Declare.b VectorCrossMuiltply(*a.xyz, *b.xyz, *result.xyz);returns a pointer to a vector that has been crossed muiltiplied
Declare.b VectorAdd(*a.xyz, *b.xyz, *result.xyz);returns a pointer to a vector that has been added
Declare.b VectorSubtract(*a.xyz, *b.xyz, *result.xyz);returns a pointer to a vector that has been Subtracted
Declare.b VectorScalarMuilply(*a.xyz, b.f, *result.xyz);returns a pointer to a vector that has been muiltiplied
Declare.b VectorScalarDivide(*a.xyz, b.f, *result.xyz);returns a pointer to a vector that has been divided
Declare.f VectorTripleScalarProduct(*a.xyz, *b.xyz, *c.xyz);returns triple scalar product of 3 vectors
Declare.f MatrixDeterminant(*this.Matrix);returns the determiant of a matrix
Declare.w MatrixTranspose(*this.Matrix, *result.Matrix);returns the transpose of a matrix
Declare.w MatrixInverse(*this.Matrix);returns the inverse of a matrix
Declare.w MatrixAdd(*a.Matrix, *b.Matrix, *result.Matrix);adds 2 matrice together
Declare.w MatrixSubtract(*a.Matrix, *b.Matrix, *result.Matrix);subtract 2 matrice together
Declare.w MatrixScalarMuiltply(*a.Matrix, Scalar.f, *result.Matrix);muiltplies a matrix to a scalar
Declare.w MatrixScalarDivision(*a.Matrix, Scalar.f, *result.Matrix);divides a matrix to a scalar
Declare  AddPointLightObject(*Light.PointLight)
Declare.b AddSphereObject(*Sphere.Object,radius.f)
Declare  AddPlaneObject(*Plane.Object,Distance.f)
Declare.b AddTriangleObject(*Triangle.Object,*v1.xyz,*v2.xyz,*v3.xyz,*Normal.xyz)
Declare.b GetObjectStructure(ObjectPointer,*destination.Object)
Declare.b SetObjectStructure(ObjectPointer,*source.Object)
Declare.b RemoveObject(ObjectPointer)
Declare  Shade(*Intersection.xyz,*Normal.xyz,*Direction.xyz,*Material.Material,depth.b,*Accumalated.Color)
Declare.f TestSphere(*Origin.xyz,*Direction.xyz,*Sphere.Object)
Declare.f TestPlane(*Origin.xyz,*Direction.xyz,*Plane.Object)
Declare.f TestTriangle(*Origin.xyz,*Direction.xyz,*Triangle.Object) ;incomplete
Declare  TraceRay(*Origin.xyz,*Direction.xyz,depth.b,*res.Color)
Declare  RenderScene(*Scene.Scene,*ViewPort.Camera)
Declare  TestLoop() ;tester

;- Procedures

;- Color Math

Procedure.b ColorScalarMuilply(*a.Color, b.f, *result.Color);returns a pointer to a Color that has been muiltiplied by a scalar
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering ColorScalarMuilply() With "+Hex(*a)+", "+Str(b)+", "+Hex(*result)
	*result\Red = *a\Red * b
	*result\Green = *a\Green * b
	*result\Blue = *a\Blue * b
	; Debug "Leaving ColorScalarMuilply()"
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
EndProcedure

Procedure.b ColorMuilply(*a.Color, *b.Color, *result.Color);returns a pointer to a Color that has been muiltiplied
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering ColorMuilply() With "+Hex(*a)+", "+Hex(*b)+", "+Hex(*result)
	*result\Red = *a\Red * *b\Red
	*result\Green = *a\Green * *b\Green
	*result\Blue = *a\Blue * *b\Blue
	; Debug "Leaving ColorMuilply()"
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
EndProcedure

Procedure.b ColorAdd(*a.Color, *b.Color, *result.Color);returns a pointer to a Color that has been added
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering ColorAdd() With"+Hex(*a)+", "+Hex(*b)+", "+Hex(*result)
	*result\Red = *a\Red + *b\Red
	*result\Green = *a\Green + *b\Green
	*result\Blue = *a\Blue + *b\Blue
	; Debug "Leaving ColorAdd()"
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
EndProcedure

Procedure ColorRangeCheck(*a.Color)
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering ColorRangeCheck() With"+Hex(*a)
	If *a\Red>255
		*a\Red=255
	EndIf
	If *a\Green>255
		*a\Green=255
	EndIf
	If *a\Blue>255
		*a\Blue=255
	EndIf
	If *a\Red<0
		*a\Red=0
	EndIf
	If *a\Green<0
		*a\Green=0
	EndIf
	If *a\Blue<0
		*a\Blue=0
	EndIf
	; Debug "Leaving ColorRangeCheck()"
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
EndProcedure

;-Vector Math

Procedure.f VectorMagnitude(*this.xyz);returns the maginitude of a Vector
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering VectorMagnitude() With"+Hex(*this)
	result.f=Sqr(*this\x * *this\x+*this\y * *this\y+*this\z * *this\z)
	; Debug "Leaving VectorMagnitude() With"+ StrF(result)
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
	ProcedureReturn result
EndProcedure

Procedure.f VectorDotProduct(*a.xyz, *b.xyz)
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering VectorDotProduct() With"+Hex(*a)+", "+Hex(*b)
	result.f=*a\x * *b\x + *a\y * *b\y + *a\z * *b\z
	; Debug "Leaving VectorDotProduct() With"+StrF(result)
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
	ProcedureReturn result
EndProcedure

Procedure.b VectorNormalize(*this.xyz);normilzes a vector
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering VectorNormalize() With"+Hex(*this)
	m.f = Sqr(*this\x * *this\x+*this\y * *this\y+*this\z * *this\z)
	If m > #Tolerance
		*this\x=*this\x/m
		*this\y=*this\y/m
		*this\z=*this\z/m
	EndIf
	If  Abs(*this\x) < #Tolerance
		*this\x = 0
	EndIf
	If  Abs(*this\y) < #Tolerance
		*this\y = 0
	EndIf
	If  Abs(*this\z) < #Tolerance
		*this\z = 0
	EndIf
	; Debug "Leaving VectorNormalize()"
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
EndProcedure

Procedure.b VectorReverse(*this.xyz);reverses a Vector
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering VectorReverse() With"+Hex(*this)
	*this\x = -*this\x
	*this\y = -*this\y
	*this\z = -*this\z
	; Debug "Leaving VectorReverse()"
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
EndProcedure

Procedure.b VectorCrossMuiltply(*a.xyz, *b.xyz, *result.xyz);returns a pointer to a vector that has been crossed muiltiplied
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering VectorCrossMuiltply() With"+Hex(*a)+", "+Hex(*b)+", "+Hex(*result)
	*result\x = *a\y * *b\z - *a\z * *b\y
	*result\y = *a\x * *b\z - *a\z * *b\x
	*result\z = *a\x * *b\y - *a\y * *b\x
	; Debug "Leaving VectorCrossMuiltply()"
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
EndProcedure

Procedure.b VectorAdd(*a.xyz, *b.xyz, *result.xyz);returns a pointer to a vector that has been added
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering VectorAdd() With"+Hex(*a)+", "+Hex(*b)+", "+Hex(*result)
	*result\x = *a\x + *b\x
	*result\y = *a\y + *b\y
	*result\z = *a\z + *b\z
	; Debug "Leaving VectorAdd()"
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
EndProcedure

Procedure.b VectorSubtract(*a.xyz, *b.xyz, *result.xyz);returns a pointer to a vector that has been Subtracted
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering VectorSubtract() With"+Hex(*a)+", "+Hex(*b)+", "+Hex(*result)
	*result\x = *a\x - *b\x
	*result\y = *a\y - *b\y
	*result\z = *a\z - *b\z
	; Debug "Leaving VectorSubtract()"
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
EndProcedure

Procedure.b VectorScalarMuilply(*a.xyz, b.f, *result.xyz);returns a pointer to a vector that has been muiltiplied
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering VectorScalarMuilply() With"+Hex(*a)+", "+Str(*b)+", "+Hex(*result)
	*result\x = *a\x * b
	*result\y = *a\y * b
	*result\z = *a\z * b
	; Debug "Leaving VectorScalarMuilply()"
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
EndProcedure

Procedure.b VectorScalarDivide(*a.xyz, b.f, *result.xyz);returns a pointer to a vector that has been divided
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering VectorScalarDivide() With"+Hex(*a)+", "+Str(*b)+", "+Hex(*result)
	*result\x = *a\x / b
	*result\y = *a\y / b
	*result\z = *a\z / b
	; Debug "Leaving VectorScalarDivide()"
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
EndProcedure

Procedure.f VectorTripleScalarProduct(*a.xyz, *b.xyz, *c.xyz);returns triple scalar product of 3 vectors
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering VectorTripleScalarProduct() With"+Hex(*a)+", "+Hex(*b)+", "+Hex(*c)
	result.f=*a\x * (*b\y * *c\z - *b\z * *c\y)+(*a\y * (-*b\x * *c\z + *b\z * *c\x))+(*a\z * (*b\x * *c\y - *b\y * *c\x))
	; Debug "Leaving VectorTripleScalarProduct() With"+StrF(result)
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
	ProcedureReturn result
EndProcedure

;-Matrix Math

Procedure.f MatrixDeterminant(*this.Matrix);returns the determiant of a matrix
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering MatrixDeterminant() With"+Hex(*this)
	result.f=*this\e11 * *this\e22 * *this\e33 - *this\e11 * *this\e32 * *this\e23 + *this\e21 * *this\e32 * *this\e13 - *this\e21 * *this\e12 * *this\e33 + *this\e31 * *this\e12 * *this\e23 - *this\e31 * *this\e22 * *this\e13
	; Debug "Leaving MatrixDeterminant() With"+StrF(result)
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
	ProcedureReturn result
EndProcedure

Procedure.w MatrixTranspose(*this.Matrix, *result.Matrix);returns the transpose of a matrix
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering MatrixTranspose() With"+Hex(*this)+", "+Hex(*result)
	*result\e11 = *this\e11
	*result\e21 = *this\e12
	*result\e31 = *this\e13
	*result\e12 = *this\e21
	*result\e22 = *this\e22
	*result\e32 = *this\e23
	*result\e13 = *this\e31
	*result\e23 = *this\e32
	*result\e33 = *this\e33
	; Debug "Leaving MatrixTranspose()"
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
EndProcedure

Procedure.w MatrixInverse(*this.Matrix);returns the inverse of a matrix
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering MatrixInverse() With"+Hex(*this)
	d.f  = MatrixDeterminant(*this)
	If d  = 0
		d  = 1
	EndIf
	*this\e11 =  (*this\e22  *  *this\e33  -  *this\e23  *  *this\e32)/d
	*this\e21 = -(*this\e12  *  *this\e33  -  *this\e13  *  *this\e32)/d
	*this\e31 =  (*this\e12  *  *this\e23  -  *this\e13  *  *this\e22)/d
	*this\e12 = -(*this\e21  *  *this\e33  -  *this\e23  *  *this\e31)/d
	*this\e22 =  (*this\e11  *  *this\e33  -  *this\e13  *  *this\e31)/d
	*this\e32 = -(*this\e11  *  *this\e23  -  *this\e13  *  *this\e21)/d
	*this\e13 =  (*this\e21  *  *this\e32  -  *this\e12  *  *this\e31)/d
	*this\e23 = -(*this\e11  *  *this\e32  -  *this\e12  *  *this\e31)/d
	*this\e33 =  (*this\e11  *  *this\e22  -  *this\e12  *  *this\e21)/d
	; Debug "Leaving MatrixInverse()"
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
EndProcedure

Procedure.w MatrixAdd(*a.Matrix, *b.Matrix, *result.Matrix);adds 2 matrice together
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering MatrixAdd() With"+Hex(*a)+" ,"+Hex(*b)+" ,"+Hex(*result)
	*result\e11 = *a\e11 + *b\e11
	*result\e12 = *a\e12 + *b\e12
	*result\e13 = *a\e13 + *b\e13
	*result\e21 = *a\e21 + *b\e21
	*result\e22 = *a\e22 + *b\e22
	*result\e23 = *a\e23 + *b\e23
	*result\e31 = *a\e31 + *b\e31
	*result\e32 = *a\e32 + *b\e32
	*result\e33 = *a\e33 + *b\e33
	; Debug "Leaving MatrixAdd()"
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
EndProcedure

Procedure.w MatrixSubtract(*a.Matrix, *b.Matrix, *result.Matrix);subtract 2 matrice together
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering MatrixSubtract() With"+Hex(*a)+" ,"+Hex(*b)+" ,"+Hex(*result)
	*result\e11 = *a\e11 - *b\e11
	*result\e12 = *a\e12 - *b\e12
	*result\e13 = *a\e13 - *b\e13
	*result\e21 = *a\e21 - *b\e21
	*result\e22 = *a\e22 - *b\e22
	*result\e23 = *a\e23 - *b\e23
	*result\e31 = *a\e31 - *b\e31
	*result\e32 = *a\e32 - *b\e32
	*result\e33 = *a\e33 - *b\e33
	; Debug "Leaving MatrixSubtract()"
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
EndProcedure

Procedure.w MatrixScalarMuiltply(*a.Matrix, Scalar.f, *result.Matrix);muiltplies a matrix to a scalar
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering MatrixScalarMuiltply() With"+Hex(*a)+", "+StrF(Scalar)+", "+Hex(*result)
	*result\e11 = *a\e11 * Scalar
	*result\e12 = *a\e12 * Scalar
	*result\e13 = *a\e13 * Scalar
	*result\e21 = *a\e21 * Scalar
	*result\e22 = *a\e22 * Scalar
	*result\e23 = *a\e23 * Scalar
	*result\e31 = *a\e31 * Scalar
	*result\e32 = *a\e32 * Scalar
	*result\e33 = *a\e33 * Scalar
	; Debug "Leaving MatrixScalarMuiltply()"
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
EndProcedure

Procedure.w MatrixScalarDivision(*a.Matrix, Scalar.f, *result.Matrix);divides a matrix to a scalar
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering MatrixScalarDivision() With"+Hex(*a)+", "+StrF(Scalar)+", "+Hex(*result)
	*result\e11 = *a\e11 / Scalar
	*result\e12 = *a\e12 / Scalar
	*result\e13 = *a\e13 / Scalar
	*result\e21 = *a\e21 / Scalar
	*result\e22 = *a\e22 / Scalar
	*result\e23 = *a\e23 / Scalar
	*result\e31 = *a\e31 / Scalar
	*result\e32 = *a\e32 / Scalar
	*result\e33 = *a\e33 / Scalar
	; Debug "Leaving MatrixScalarDivision()"
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
EndProcedure

;-FrameWork

Procedure AddPointLightObject(*Light.PointLight)
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering AddPointLightObject() With"+Hex(*Light)
	If Listsize(ObjectList())>0
		*Old_Element = @ObjectList()
	EndIf
	AddElement(ObjectList())
	ObjectList()\Type=#ObjectType_PointLight
	ObjectList()\Material\SoildColor\Red=*Light\Color\Red
	ObjectList()\Material\SoildColor\Green=*Light\Color\Green
	ObjectList()\Material\SoildColor\Blue=*Light\Color\Blue
	ObjectList()\Origin\x=*Light\Origin\x
	ObjectList()\Origin\y=*Light\Origin\y
	ObjectList()\Origin\z=*Light\Origin\z
	ObjectList()\IsLight=#True
	ObjectList()\Primitive=#Null
	result.l=@ObjectList()
	If *Old_Element<>#Null
		ChangeCurrentElement(ObjectList(), *Old_Element)
	EndIf
	; Debug "Leaving AddPointLightObject()"
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
	ProcedureReturn result
	
EndProcedure

Procedure.b AddSphereObject(*Sphere.Object,radius.f)
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering AddSphereObject() With"+Hex(*Sphere)+", "+StrF(radius)
	If Listsize(ObjectList())>0
		*Old_Element = @ObjectList()
	EndIf
	AddElement(ObjectList())
	;copy object data into the new object
	CopyMemory(*Sphere,@ObjectList(),SizeOf(Object))
	;put any primtive specific data into there places
	ObjectList()\Primitive=AllocateMemory(4)
	PokeF(ObjectList()\Primitive,radius)
	ObjectList()\Type=#ObjectType_Sphere
	result.l=@ObjectList()
	If *Old_Element<>#Null
		ChangeCurrentElement(ObjectList(), *Old_Element)
	EndIf
	; Debug "Leaving AddSphereObject() With"+Hex(result)
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
	ProcedureReturn result
EndProcedure

Procedure AddPlaneObject(*Plane.Object,Distance.f)
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering AddPlaneObject() With"+Hex(*Plane)+StrF(Distance)
	If Listsize(ObjectList())>0
		*Old_Element = @ObjectList()
	EndIf
	AddElement(ObjectList())
	;copy object data into the new object
	CopyMemory(*Plane,@ObjectList(),SizeOf(Object))
	;put any primtive specific data into there places
	ObjectList()\Type=#ObjectType_Plane
	ObjectList()\Primitive=AllocateMemory(4)
	PokeF(ObjectList()\Primitive,Distance)
	result.l=@ObjectList()
	; Debug "Leaving AddPlaneObject() With"+Hex(result)
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
	ProcedureReturn result
EndProcedure

Procedure.b AddTriangleObject(*Triangle.Object,*v1.xyz,*v2.xyz,*v3.xyz,*Normal.xyz)
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering AddTriangleObject() With"+Hex(*Triangle)+", "+Hex(*v1)+", "+Hex(*v2)+", "+Hex(*v3)+", "+Hex(*Normal)
	If Listsize(ObjectList())>0
		*Old_Element = @ObjectList()
	EndIf
	AddElement(ObjectList())
	;copy object data into the new object
	CopyMemory(*Triangle,@ObjectList(),SizeOf(Object))
	;put any primtive specific data into there places
	ObjectList()\Primitive=AllocateMemory(48)
	CopyMemory(*v1,ObjectList()\Primitive,12)
	CopyMemory(*v2,ObjectList()\Primitive+12,12)
	CopyMemory(*v3,ObjectList()\Primitive+24,12)
	CopyMemory(*Normal,ObjectList()\Primitive+36,12)
	ObjectList()\Type=#ObjectType_Triangle
	result.l=@ObjectList()
	If *Old_Element<>#Null
		ChangeCurrentElement(ObjectList(), *Old_Element)
	EndIf
	result.l=@ObjectList()
	; Debug "Leaving AddTriangleObject() With"+Hex(result)
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
	ProcedureReturn result
EndProcedure

Procedure.b GetObjectStructure(ObjectPointer,*destination.Object)
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering GetObjectStructure() With"+Hex(ObjectPointer)+", "+Hex(*destination)
	If Listsize(ObjectList())>0
		*Old_Element = @ObjectList()
	EndIf
	ChangeCurrentElement(ObjectList(), ObjectPointer)
	;copy object data into the new object
	CopyMemory(@ObjectList(),*destination,SizeOf(Object))
	If *Old_Element<>#Null
		ChangeCurrentElement(ObjectList(), *Old_Element)
	EndIf
	; Debug "Leaving GetObjectStructure()"
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
EndProcedure

Procedure.b SetObjectStructure(ObjectPointer,*source.Object)
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering SetObjectStructure() With"+Hex(ObjectPointer)+", "+Hex(*source)
	If Listsize(ObjectList())>0
		*Old_Element = @ObjectList()
	EndIf
	ChangeCurrentElement(ObjectList(), ObjectPointer)
	;copy object data into the new object
	CopyMemory(*source,@ObjectList(),SizeOf(Object))
	If *Old_Element<>#Null
		ChangeCurrentElement(ObjectList(), *Old_Element)
	EndIf
	; Debug "Leaving SetObjectStructure()"
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
EndProcedure

Procedure.b RemoveObject(ObjectPointer)
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering RemoveObject() With"+Hex(ObjectPointer)
	If Listsize(ObjectList())>0
		*Old_Element = @ObjectList()
	EndIf
	ChangeCurrentElement(ObjectList(), ObjectPointer)
	If ObjectList()\Primitive<>#Null
		FreeMemory(ObjectList()\Primitive)
	EndIf
	DeleteElement(ObjectList())
	If Listsize(ObjectList())>0 And *Old_Element<>#Null
		ChangeCurrentElement(ObjectList(), *Old_Element)
	EndIf
	; Debug "Leaving RemoveObject()"
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
EndProcedure

Procedure Shade(*Intersection.xyz,*Normal.xyz,*Direction.xyz,*Material.Material,depth.b,*Accumalated.Color)
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering Shade() With"+Hex(*Intersection)+", "+Hex(*Normal)+", "+Hex(*Direction)+", "+Hex(*Material)+", "+Str(depth)+", "+Hex(*Accumalated)
	*Old_Element=@ObjectList()
	*result.Color
	Color.Color
	Light.xyz
	Relfection.xyz
	reflectcolor.Color
	ReflectOrigin.xyz
	tempvec.xyz
	l.xyz
	rayo.xyz
	rayd.xyz
	ResetList(ObjectList())
	For Object=0 To Listsize(ObjectList()) - 1
		NextElement(ObjectList())
		If ObjectList()\IsLight=#True
			Light\x=ObjectList()\Origin\x-*Intersection\x
			Light\y=ObjectList()\Origin\y-*Intersection\y
			Light\z=ObjectList()\Origin\z-*Intersection\z
			
			VectorNormalize(Light)
			
			;this shadow test only works with point light
			shade.f=1
			tdist.f=Sqr(Light\x * Light\x+Light\y * Light\y+Light\z * Light\z)
			
			l\x=Light\x/tdist
			l\y=Light\y/tdist
			l\z=Light\z/tdist
			
			rayo\x=*Intersection\x+l\x*#EPSILON
			rayo\y=*Intersection\y+l\y*#EPSILON
			rayo\z=*Intersection\z+l\z*#EPSILON
			
			rayd\x=l\x
			rayd\y=l\y
			rayd\z=l\z
			*Old_Element2=@ObjectList()
			ResetList(ObjectList())
			For shadow=0 To Listsize(ObjectList()) - 1
				NextElement(ObjectList())
				If ObjectList()\IsLight=#False
					Select ObjectList()\Type
						Case #ObjectType_Sphere
						t.f=TestSphere(rayo,rayd,@ObjectList())
						Case #ObjectType_Plane
						t.f=TestPlane(rayo,rayd,@ObjectList())
						Case #ObjectType_Triangle
						t.f=TestTriangle(rayo,rayd,@ObjectList())
					EndSelect
					If t>0
						shade=0
						Break
					EndIf
				EndIf
			Next shadow
			ChangeCurrentElement(ObjectList(), *Old_Element2)
			If shade>0
				If *Material\Diffuse > 0
					dot.f=*Normal\x * Light\x + *Normal\y * Light\y + *Normal\z * Light\z
					If dot>0
						diff.f=dot * *Material\Diffuse
						
						*Accumalated\Red=*Accumalated\Red+diff**Material\SoildColor\Red*ObjectList()\Material\SoildColor\Red
						*Accumalated\Green=*Accumalated\Green+diff**Material\SoildColor\Green*ObjectList()\Material\SoildColor\Green
						*Accumalated\Blue=*Accumalated\Blue+diff**Material\SoildColor\Blue*ObjectList()\Material\SoildColor\Blue
					EndIf
					If *Material\Specular>0
						dot.f=*Normal\x * Light\x + *Normal\y * Light\y + *Normal\z * Light\z
						
						tempvec\x=Light\x-2*dot**Normal\x
						tempvec\y=Light\y-2*dot**Normal\y
						tempvec\z=Light\z-2*dot**Normal\z
						
						dot=*Direction\x * tempvec\x + *Direction\y * tempvec\y + *Direction\z * tempvec\z
						If dot>0
							spec.f=Pow(dot,20)**Material\Specular
							
							*Accumalated\Red=*Accumalated\Red+ObjectList()\Material\SoildColor\Red*spec
							*Accumalated\Green=*Accumalated\Green+ObjectList()\Material\SoildColor\Green*spec
							*Accumalated\Blue=*Accumalated\Blue+ObjectList()\Material\SoildColor\Blue*spec
						EndIf
					EndIf
					If *Material\Reflect>0
						r.f=*Direction\x * *Normal\x + *Direction\y * *Normal\y + *Direction\z * *Normal\z
						Relfection\x=*Direction\x-2*r**Normal\x
						Relfection\y=*Direction\y-2*r**Normal\y
						Relfection\z=*Direction\z-2*r**Normal\z
						
						ReflectOrigin\x=*Intersection\x+Relfection\x*#EPSILON
						ReflectOrigin\y=*Intersection\y+Relfection\y*#EPSILON
						ReflectOrigin\z=*Intersection\z+Relfection\z*#EPSILON
						
						TraceRay(ReflectOrigin,Relfection,depth+1,reflectcolor)
						
						*Accumalated\Red=*Accumalated\Red+*Material\Reflect*reflectcolor\Red**Material\SoildColor\Red
						*Accumalated\Green=*Accumalated\Green+*Material\Reflect*reflectcolor\Green**Material\SoildColor\Green
						*Accumalated\Blue=*Accumalated\Blue+*Material\Reflect*reflectcolor\Blue**Material\SoildColor\Blue
					EndIf
				EndIf
			EndIf
		EndIf
	Next Object
	ChangeCurrentElement(ObjectList(), *Old_Element)
	; Debug "Leaving Shade()"
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
EndProcedure

Procedure.f TestSphere(*Origin.xyz,*Direction.xyz,*Sphere.Object)
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering TestSphere() With"+Hex(*Origin)+", "+Hex(*Direction)+", "+Hex(*Sphere)
	offset.xyz
	offset\x=*Origin\x-*Sphere\Origin\x
	offset\y=*Origin\y-*Sphere\Origin\y
	offset\z=*Origin\z-*Sphere\Origin\z
	;VectorSubtract(*Origin, *Sphere\Origin, offset)
	radius.f = PeekF(*Sphere\Primitive)
	b.f = 2 * (*Direction\x * offset\x + *Direction\y * offset\y + *Direction\z * offset\z)
	c.f = (offset\x * offset\x + offset\y * offset\y + offset\z * offset\z) - radius * radius
	d.f = b * b - 4 * c
	If d > 0 ;hit the sphere
		t.f = (-b - Sqr(d)) * 0.5 ; Could return +ve or -ve number!
	EndIf
	; Debug "Leaving TestSphere() With"+StrF(t)
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
	ProcedureReturn t
EndProcedure

Procedure.f TestPlane(*Origin.xyz,*Direction.xyz,*Plane.Object)
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering TestPlane() With"+Hex(*Origin)+", "+Hex(*Direction)+", "+Hex(*Plane)
	Distance.f=PeekF(*Plane\Primitive)
	vd.f=*Plane\Normal\x * *Direction\x + *Plane\Normal\y * *Direction\y + *Plane\Normal\z * *Direction\z
	If vd<>0
		vo.f=-(VectorDotProduct(*Plane\Normal,*Origin)+Distance)
		t.f=vo/vd
		; Debug "Leaving TestPlane() With"+StrF(t)
		; etime.l=ElapsedMilliseconds()
		; LastProcedureTime=etime-stime
		ProcedureReturn t
	EndIf
EndProcedure

Procedure.f TestTriangle(*Origin.xyz,*Direction.xyz,*Triangle.Object) ;incomplete
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering TestTriangle() With"+Hex(*Origin)+", "+Hex(*Direction)+", "+Hex(*Triangle)
	spana.xyz
	spanb.xyz
	vec.xyz
	len.f
	len2.f
	r.f
	s.f
	t.f
	triangle.Triangle
	
	mathtemp.xyz
	
	; triangle\v1\x=PeekF(*Triangle\Primitive)
	; triangle\v1\y=PeekF(*Triangle\Primitive+4)
	; triangle\v1\z=PeekF(*Triangle\Primitive+8)
	; triangle\v2\x=PeekF(*Triangle\Primitive+12)
	; triangle\v2\y=PeekF(*Triangle\Primitive+16)
	; triangle\v2\z=PeekF(*Triangle\Primitive+20)
	; triangle\v3\x=PeekF(*Triangle\Primitive+24)
	; triangle\v3\y=PeekF(*Triangle\Primitive+28)
	; triangle\v3\z=PeekF(*Triangle\Primitive+32)
	; ;triangle\Normal\x=PeekF(*Triangle\Primitive+36)
	; ;triangle\Normal\y=PeekF(*Triangle\Primitive+40)
	; ;triangle\Normal\z=PeekF(*Triangle\Primitive+44)
	;
	; VectorSubtract(triangle\v2,triangle\v1,spana)
	; VectorSubtract(triangle\v3,triangle\v1,spanb)
	; ;triangle\Normal\x=spana\y*spanb\z-spana\z*spanb\y
	; ;triangle\Normal\y=spana\z*spanb\x-spana\x*spanb\z
	; ;triangle\Normal\z=spana\x*spanb\y-spana\y*spanb\x
	; ;VectorCrossMuiltply(spana,spanb,triangle\Normal)
	; len=VectorMagnitude(triangle\Normal)
	; Debug "Leaving TestTriangle() With"+StrF(t)
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
EndProcedure

Procedure TraceRay(*Origin.xyz,*Direction.xyz,depth.b,*res.Color)
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering TraceRay() With"+Hex(*Origin)+", "+Hex(*Direction)+", "+Str(depth)+", "+Hex(*res)
	Intersection.xyz
	Normal.xyz
	*Old_Element=@ObjectList()
	result.Color
	If depth<#MaxChildren
		Closesthandle=-1
		ClosestT.f=-1
		ResetList(ObjectList())
		For Object=0 To Listsize(ObjectList()) - 1
			NextElement(ObjectList())
			Select ObjectList()\Type
				Case #ObjectType_Sphere
				t.f=TestSphere(*Origin,*Direction,@ObjectList())
				If t>0
					If t<ClosestT Or ClosestT=-1
						Closesthandle=Object
						ClosestT=t
					EndIf
				EndIf
				;other cases will be added
				Case #ObjectType_Plane
				t.f=TestPlane(*Origin,*Direction,@ObjectList())
				If t>0
					If t<ClosestT Or ClosestT=-1
						Closesthandle=Object
						ClosestT=t
					EndIf
				EndIf
				Case #ObjectType_Triangle
				t.f=TestTriangle(*Origin,*Direction,@ObjectList())
				If t>0
					If t<ClosestT Or ClosestT=-1
						Closesthandle=Object
						ClosestT=t
					EndIf
				EndIf
			EndSelect
		Next Object
		If ClosestT>0
			t=ClosestT
			SelectElement(ObjectList(),Closesthandle)
			Intersection\x=*Origin\x+*Direction\x*t
			Intersection\y=*Origin\y+*Direction\y*t
			Intersection\z=*Origin\z+*Direction\z*t;Calulate Interesction point with
			If ObjectList()\Type=#ObjectType_Sphere ;normal Calulations are diffrent per object
				radius.f=PeekF(ObjectList()\Primitive)
				Normal\x=(Intersection-ObjectList()\Origin)/radius
				Normal\y=(Intersection-ObjectList()\Origin)/radius
				Normal\z=(Intersection-ObjectList()\Origin)/radius
				VectorSubtract(Intersection ,ObjectList()\Origin,Normal)
				VectorScalarDivide(Normal,PeekF(ObjectList()\Primitive),Normal)
				;other cases will be added
				Else
				Normal\x=ObjectList()\Normal\x
				Normal\y=ObjectList()\Normal\y
				Normal\z=ObjectList()\Normal\z
			EndIf
			Shade(Intersection,Normal,*Direction,ObjectList()\Material,depth,result)
		EndIf
	EndIf
	ChangeCurrentElement(ObjectList(), *Old_Element)
	*res\Red = result\Red
	*res\Green = result\Green
	*res\Blue = result\Blue
	; Debug "Leaving TraceRay()"
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
EndProcedure

Procedure RenderScene(*Scene.Scene,*ViewPort.Camera)
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering RenderScene() With"+Hex(*Scene)+", "+Hex(*ViewPort)
	Color.Color
	sx.f=-*Scene\HalfScreenWidth
	sy.f=-*Scene\HalfScreenHeight
	y.f=-*Scene\WorldScreenHalfHeight
	x.f=-*Scene\WorldScreenHalfWidth
	*ViewPort\Apature+0.01
	While y<*Scene\WorldScreenHalfHeight-1
		While x<*Scene\WorldScreenHalfWidth-1
			*ViewPort\Direction\x = x-*ViewPort\Origin\x
			*ViewPort\Direction\y = -y-*ViewPort\Origin\y
			*ViewPort\Direction\z = -*ViewPort\Origin\z
			VectorNormalize(*ViewPort\Direction)
			TraceRay(*ViewPort\Origin,*ViewPort\Direction,0,Color)
			Light.f=(Color\Red + Color\Green + Color\Blue)*0.33333333
			expose.f=(1-Pow(#E,-(Light**ViewPort\Apature)))*255
			Color\Red=Color\Red*expose
			Color\Green=Color\Green*expose
			Color\Blue=Color\Blue*expose
			ColorRangeCheck(Color)
			If Color\Red<>0 Or Color\Green<>0 Or Color\Blue<>0
				Plot(*Scene\HalfScreenWidth + sx, *Scene\HalfScreenHeight + sy,RGB(Color\Red,Color\Green,Color\Blue))
			EndIf
			x+*Scene\PixelStep
			sx+*Scene\RealPixelsStep
		Wend
		x=-*Scene\WorldScreenHalfWidth
		sx=-*Scene\HalfScreenWidth
		y+*Scene\PixelStep
		sy+*Scene\RealPixelsStep
	Wend
	; Debug "Leaving RenderScene()"
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
EndProcedure

Procedure TestLoop() ;tester
	; stime.l=ElapsedMilliseconds()
	; Debug "Entering TestLoop()"
	;DefType.f
	Sphere1.Object
	Sphere1Radius.f
	Sphere2.Object
	Sphere2Radius.f
	Plane.Object
	PlaneDistance.f
	Light1.PointLight
	light2.PointLight
	MainCamera.Camera
	MainScene.Scene
	
	Sphere1\Origin\x=1
	Sphere1\Origin\y=-0.8
	Sphere1\Origin\z=3
	Sphere1\Material\SoildColor\Red=0.7
	Sphere1\Material\SoildColor\Green=0.7
	Sphere1\Material\SoildColor\Blue=0.7
	Sphere1\Material\Diffuse=1
	Sphere1\Material\Reflect=1
	Sphere1\Material\Refract=0
	Sphere1\Material\Specular=1
	Sphere1Radius=2.5
	
	AddSphereObject(Sphere1,Sphere1Radius)
	
	Sphere2\Origin\x=-5.5
	Sphere2\Origin\y=-0.5
	Sphere2\Origin\z=7
	Sphere2\Material\SoildColor\Red=0.7
	Sphere2\Material\SoildColor\Green=0.7
	Sphere2\Material\SoildColor\Blue=1
	Sphere2\Material\Diffuse=0.1
	Sphere2\Material\Reflect=1
	Sphere2\Material\Refract=0
	Sphere2\Material\Specular=1
	Sphere2Radius=2
	
	AddSphereObject(Sphere2,Sphere2Radius)
	
	Plane\Origin\x=0
	Plane\Origin\y=0
	Plane\Origin\z=0
	Plane\Material\SoildColor\Red=0.4
	Plane\Material\SoildColor\Green=0.3
	Plane\Material\SoildColor\Blue=0.3
	Plane\Material\Diffuse=1
	Plane\Material\Reflect=1
	Plane\Material\Refract=0
	Plane\Normal\x=0
	Plane\Normal\y=1
	Plane\Normal\z=0
	PlaneDistance=4.4
	
	AddPlaneObject(Plane,PlaneDistance)
	
	Light1\Origin\x=0
	Light1\Origin\y=5
	Light1\Origin\z=5
	Light1\Color\Red=0.6
	Light1\Color\Green=0.6
	Light1\Color\Blue=0.6
	
	AddPointLightObject(Light1)
	
	light2\Origin\x=2
	light2\Origin\y=5
	light2\Origin\z=1
	light2\Color\Red=0.7
	light2\Color\Green=0.7
	light2\Color\Blue=0.9
	
	AddPointLightObject(light2)
	
	MainCamera\Origin\x=0
	MainCamera\Origin\y=0
	MainCamera\Origin\z=-5
	MainCamera\ViewingAngle\x=0
	MainCamera\ViewingAngle\y=0
	MainCamera\ViewingAngle\z=0
	MainCamera\Apature=1
	
	; MainScene\Ambient\Red=0.125
	; MainScene\Ambient\Green=0.125 ;not active
	; MainScene\Ambient\Blue=0.125
	MainScene\WorldScreenWidth=8
	MainScene\WorldScreenHieght=6
	MainScene\WorldScreenHalfWidth=MainScene\WorldScreenWidth/2
	MainScene\WorldScreenHalfHeight=MainScene\WorldScreenHieght/2
	MainScene\ScreenWidth=800
	MainScene\ScreenHeight=600
	MainScene\HalfScreenWidth=MainScene\ScreenWidth/2
	MainScene\HalfScreenHeight=MainScene\ScreenHeight/2
	MainScene\PixelStep=0.01
	MainScene\RealPixelsStep=1
	InitSprite()
	OpenWindow(0,0,0,MainScene\ScreenWidth,MainScene\ScreenHeight,"PBRay - FPS: 0",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
	OpenWindowedScreen(WindowID(0),0,0,MainScene\ScreenWidth,MainScene\ScreenHeight,0,0,0)
	
	Repeat
		frame+1
		start=ElapsedMilliseconds()
		;ClearScreen(rgb(0, 0, 0))
		StartDrawing(ScreenOutput())
			
			RenderScene(MainScene,MainCamera)
			
		StopDrawing()
		FlipBuffers()
		stop=ElapsedMilliseconds()
		If (stop-start2)>=1000
			start2=ElapsedMilliseconds()
			fps=frame
			frame=0
		EndIf
		SetWindowTitle(WindowID0,"PBRay - FPS: "+Str(fps)+" RenderTime: "+Str(stop-start))
	Until WindowEvent() = #PB_Event_CloseWindow
	; Debug "Leaving TestLoop()"
	; etime.l=ElapsedMilliseconds()
	; LastProcedureTime=etime-stime
EndProcedure

TestLoop() ; EPB