• Welcome to Dark Bit Factory & Gravity.
 

Raytracer :) [Update : objs/triangles make me mad]

Started by Hezad, August 16, 2009

Previous topic - Next topic

0 Members and 0 Guests are viewing this topic.

Hezad

Hey everyone :)

I'm currently working on a raytracer engine. I already coded one which worked but it was far from well designed. So I started a new one to handle scene better.

The problem is it doesn't raytrace the only sphere I added to the scene. I'm totally stuck right now, I looked everywhere in the code and I don't get why and where it don't work. Here is the code :

''
'' Raytracer
''

#include "vector.bi"

Const PRECISION = .1
Const MAX_RAY_LENGTH = 100

Const MAX_PRIMITIVES = 20
Const MAX_LIGHTS     = 10

Const PRIM_SPHERE = 1
Const PRIM_PLANE  = 2

Type ColorT
as single r,g,b
End Type

Type MaterialT
as ColorT Diffuse,BaseColor
End type

Type Ray
as vector O,d

as single x,y,z,t

Declare Sub Update()
Declare Function Lengthpow2() as single
End Type

Function Ray.Lengthpow2() as single
return (this.x-this.O.x)*(this.x-this.O.x) + (this.y-this.O.y)*(this.y-this.O.y) + (this.z-this.O.z)*(this.z-this.O.z)
End Function


Sub Ray.Update()

this.x = this.O.x + this.d.x*this.t
this.y = this.O.y + this.d.y*this.t
this.z = this.O.z + this.d.z*this.t

this.t += PRECISION

End Sub

Type Primitive
as integer TypeFlag

as MaterialT Material

'' for planes
as single A,B,C,D

'' for spheres
as single R, x,y,z


'' functions
Declare function GetNormal(CRay as Ray) as Vector
Declare function GetIntersection(CRay as Ray) as integer
End type

Function Primitive.GetIntersection(CRay as Ray) as integer

Select case This.TypeFlag
Case PRIM_SPHERE

if (this.x - CRay.x)*(this.x - CRay.x) + (this.y - CRay.y)*(this.y - CRay.y) + (this.z - CRay.z)*(this.z - CRay.z) <= R*R + PRECISION then
return 1
else
return 0
end if

Case PRIM_PLANE

if (this.A*CRay.x + this.B*CRay.y + this.C*CRay.z - this.D < PRECISION) and (this.A*CRay.x + this.B*CRay.y + this.C*CRay.z - this.D > -PRECISION) then
return 1
else
return 0
end if

End Select
End Function

Function Primitive.GetNormal(CRay as Ray) as Vector

static as Vector normal

Select case This.TypeFlag
Case PRIM_SPHERE

normal.x = CRay.x - this.x
normal.y = CRay.y - this.y
normal.z = CRay.z - this.z

Normalize(normal)

return normal

Case PRIM_PLANE

normal.x = -A
normal.y = -B
normal.z = -C

Normalize(Normal)

return normal

End Select
End Function

Type LightT
as single x,y,z
as ColorT l_color
end type

Type SceneT

as Primitive ptr s_Primitive
as integer nb_primitives

as LightT ptr s_light
as integer nb_lights

Declare Constructor()
Declare Destructor()

Declare Sub Add_Sphere(cx as single, cy as single,cz as single, cR as single, Mat as MaterialT)
Declare Sub Add_Plane (cA as single, cB as single,cC as single, cD as single, Mat as MaterialT)

Declare Sub Add_Light(cx as single, cy as single, cz as single,col as ColorT)

End Type

Sub SceneT.Add_Light(cx as single, cy as single, cz as single,col as ColorT)

if this.nb_lights>=MAX_LIGHTS then exit sub

this.s_light[this.nb_lights].x = cx
this.s_light[this.nb_lights].y = cy
this.s_light[this.nb_lights].z = cz

this.s_light[this.nb_lights].l_color = col

this.nb_lights += 1

end sub


Sub SceneT.Add_Sphere(cx as single, cy as single,cz as single, cR as single, Mat as MaterialT)

If this.nb_primitives >= MAX_PRIMITIVES then exit sub

this.s_primitive[this.nb_primitives].typeflag = prim_sphere

this.s_primitive[this.nb_primitives].x = cx
this.s_primitive[this.nb_primitives].y = cy
this.s_primitive[this.nb_primitives].z = cz
this.s_primitive[this.nb_primitives].R = cR

this.s_primitive[this.nb_primitives].Material = Mat

this.nb_primitives += 1

end sub

Sub SceneT.Add_Plane(cA as single, cB as single,cC as single, cD as single, Mat as MaterialT)

If this.nb_primitives >= MAX_PRIMITIVES then exit sub

this.s_primitive[this.nb_primitives].typeflag = prim_plane

this.s_primitive[this.nb_primitives].A = cA
this.s_primitive[this.nb_primitives].B = cB
this.s_primitive[this.nb_primitives].C = cC
this.s_primitive[this.nb_primitives].D = cD

this.s_primitive[this.nb_primitives].Material = Mat

this.nb_primitives += 1

end sub


Constructor SceneT()

this.s_Primitive = Callocate(MAX_PRIMITIVES,Sizeof(Primitive))
this.s_light = Callocate(MAX_LIGHTS,Sizeof(LightT))

End Constructor

Destructor SceneT()

deallocate(this.s_Primitive)
deallocate(this.s_light)

End Destructor





'' main loop


Dim as SceneT Scene
Dim as MaterialT sphereMat

SphereMat.Diffuse = type(.8,.7,.75)
SphereMat.BaseColor = type(.8,.8,.8)

Scene.Add_Light(-5,5,-5,type(1,1,1))

Scene.Add_Sphere(0,2,5,3,SphereMat)

Screenres 640,480,32,2

'' send ray

Dim as Ray MainRay
Dim as integer IntersectedPrimitive

For j as integer = 0 to 479
For i as integer = 0 to 639

MainRay.O = type( 0, 0, -5 )
MainRay.d = type( i-320, j-240,150)
Normalize(MainRay.d)

intersectedprimitive = -1

Do

MainRay.update()

If MainRay.z > 0 then

For k as integer = 0 to Scene.nb_primitives-1
if Scene.s_primitive[k].GetIntersection(MainRay) then

IntersectedPrimitive = k
pset(i,j),rgb(255,255,255)
exit do

End If
next

end if

Loop until MainRay.Lengthpow2 >= MAX_RAY_LENGTH*MAX_RAY_LENGTH

'' calc color !
if intersectedprimitive <> -1 then

static as ColorT MatCol = type(0,0,0)

for k as integer = 0 to scene.nb_lights - 1

static as Vector N, L
static as single dotted

L = type(Scene.s_light[k].x,Scene.s_light[k].y,Scene.s_light[k].z) - Type(MainRay.x,MainRay.y,MainRay.z)
Normalize(L)

N = Scene.s_primitive[intersectedprimitive].GetNormal(MainRay)

dotted = dot(N,L)

if dotted > 0 then
MatCol.r += dotted * Scene.s_primitive[intersectedprimitive].Material.Diffuse.r * Scene.s_primitive[intersectedprimitive].Material.BaseColor.r * Scene.s_light[k].l_color.R
MatCol.g += dotted * Scene.s_primitive[intersectedprimitive].Material.Diffuse.g * Scene.s_primitive[intersectedprimitive].Material.BaseColor.g * Scene.s_light[k].l_color.G
MatCol.b += dotted * Scene.s_primitive[intersectedprimitive].Material.Diffuse.b * Scene.s_primitive[intersectedprimitive].Material.BaseColor.b * Scene.s_light[k].l_color.B
end if
next

Pset(i,j),rgb(MatCol.r*255, MatCol.G*255,MatCol.b*255)
else
Pset(i,j),rgb(25,25,25)
end if
next
next

sleep


The point is, I tested the intersection functions with this part :

Do

MainRay.update()

If MainRay.z > 0 then

For k as integer = 0 to Scene.nb_primitives-1
if Scene.s_primitive[k].GetIntersection(MainRay) then

IntersectedPrimitive = k
pset(i,j),rgb(255,255,255)
exit do

End If
next

end if

Loop until MainRay.Lengthpow2 >= MAX_RAY_LENGTH*MAX_RAY_LENGTH


It should draw a white point if the ray intersect the primitive, but it looks like the program skips this part and directly draw the background color ...

I replaced pointers with arrays but it didn't change anything, I checked and checked again the intersection functions, the ray.update() function but everything looks okay to me ..

Does anyone have an idea of what's wrong here ?

Thanks a lot in advance :)


(oh and here is the vector.bi file if you want to compile this code :
''
'' Vectors Library
'' for raytracer
''

Type Vector
as single x,y,z
End Type

Operator +(L as Vector, R as Vector) as Vector
return type(L.x+R.x,L.y+R.y,L.z+R.z)
End operator

Operator -(L as Vector, R as Vector) as Vector
return type(L.x-R.x,L.y-R.y,L.z-R.z)
End Operator

Operator *(L as Vector, R as Vector) as Vector
return type( L.y*R.z + L.z*R.y , _
L.z*R.x + L.x*R.z , _
L.x*R.y + L.y*R.x )
End operator

Function Dot(V1 as vector, V2 as vector) as single
return V1.x*V2.x + V1.y*v2.y + v1.z*v2.z
End function

Sub Normalize(ByRef V as Vector)
static as single _norm

_norm = 1/sqr(V.x*v.x + V.y*v.y + v.z*v.z)

V.x *= _norm
V.y *= _norm
V.z *= _norm
End Sub

Music + Coding :
http://Hezad.no-ip.org

Hosting / Hébergement :
www.hezad.com

Voltage

Hey Hezad,

Is there a reson you are attempting to detect intersections this way?

So you are:
1) calculating the end point of your ray
2) Checking if the endpoint is within the sphere
3) increasing the length of the ray

I would think about the ray differently.  A ray has an Origin and a Direction but it has no end point.

Feed that infinate ray into a function that tells you the closest intersection point with the sphere.

Here is some code that checks for a ray to sphere intersection:

Function SphereIntersect(R As RayType, S As SphereType) As IntersectionType
  Dim Result as IntersectionType
  Dim As VectorType rayToSphereCentre
  Dim As Single SquaredDistToCentre, ClosestApproach, HalfCord2
 
  rayToSphereCentre = Vec_Subtract(S.Centre, R.Origin)
  SquaredDistToCentre = Vec_DotProduct(rayToSphereCentre, rayToSphereCentre)

  ClosestApproach = Vec_DotProduct(rayToSphereCentre, R.Dir)
  If ClosestApproach<0 Then
    Result.Dist=-1
    SphereIntersect = Result
    Exit Function
  End If

  HalfCord2 = (S.Radius * S.Radius) - SquaredDistToCentre + (ClosestApproach * ClosestApproach)

  If HalfCord2 < 0 Then
    Result.Dist=-1
    SphereIntersect = Result
    Exit Function
  End If
   
  Result.Dist = ClosestApproach - Sqr(Halfcord2)
  SphereIntersect = Result
End Function
Challenge Trophies Won:

Hezad

Thanks for your answer :)

Well right now, I'm "following" the ray to experiment some stuff, but thanks a lot for your intersection function it will be very useful for the next functions :)

Oh, someone on freebasic forums found why my code weren't working : I forgot to initialize the ray time variable to 0 on each loop ><
Music + Coding :
http://Hezad.no-ip.org

Hosting / Hébergement :
www.hezad.com

Hezad

#3
Some news :) Some huge optimizations (Ray experimentation has ended :P the intersections are now calculated with an algebraic method => HUGE speed improvement :D )

Current problems :
- shadows (the third "line" of spheres has an incorrect shadow)
- phong is wrong : there are highlights on both sides of spheres and that's totally anormal.
- plane intersection is wrong : It's totally impossible to put a plane at another place, it generates very (very very) ugly artefacts

Anyway, here is the code if you wanna take a look at it :)

raytracer :
''
'' Raytracer
''

#include "vector.bi"

Const PRECISION = .1

Const MAX_PRIMITIVES = 200
Const MAX_LIGHTS     = 10

Const PRIM_SPHERE = 1
Const PRIM_PLANE  = 2

Const MAX_REFLECTIONS = 5

Const CALC_SHADOWS = 1


Type ColorT
as single r,g,b
End Type

Type MaterialT
as ColorT Diffuse, Specular
as single Reflection, Highlight
End type

Type Ray
as vector O,d

as single x,y,z

Declare Sub Update(t as single)
Declare Function Lengthpow2() as single
End Type

Function Ray.Lengthpow2() as single
return (this.x-this.O.x)*(this.x-this.O.x) + (this.y-this.O.y)*(this.y-this.O.y) + (this.z-this.O.z)*(this.z-this.O.z)
End Function


Sub Ray.Update(t as single)

this.x = this.O.x + this.d.x*t
this.y = this.O.y + this.d.y*t
this.z = this.O.z + this.d.z*t

End Sub

Type Primitive
as integer TypeFlag
as integer LightFlag

as MaterialT Material

'' for planes
as single A,B,C,D

'' for spheres
as single R, x,y,z


'' functions
Declare function GetNormal(CRay as Ray) as Vector
Declare function GetIntersection(CRay as Ray,ByRef returnT as single) as integer
End type

Function Primitive.GetIntersection(CRay as Ray,ByRef returnT as single) as integer

Select case This.TypeFlag
Case PRIM_SPHERE

dim as single a = dot(Cray.d, Cray.d)
dim as single b = 2 * dot((Cray.o - type(this.x,this.y,this.z)),Cray.d )
dim as single c = dot((Cray.o - type(this.x,this.y,this.z)), (Cray.o - type(this.x,this.y,this.z))) - (this.r * this.r)

dim as single disc = b * b - 4 * a * c

if disc < PRECISION then return 0

dim as single distSqrt = sqr(disc)
dim as single q

if b < 0 then
q = (-b - distSqrt)*.5
else
q = (-b + distSqrt)*.5
end if

dim as single t0 = q / a
dim as single t1 = c / q

if t0>t1 then swap t0,t1

if t1 < PRECISION then return 0

if t0 < PRECISION then
returnT = t1
return 1
else
returnT = t0
return 1
end if

Case PRIM_PLANE

dim as single tempT, num, denum

num = (this.A*CRay.O.x + this.B*CRay.O.y + this.C*CRay.O.z + D)
denum = (this.A*CRay.d.x + this.B*CRay.d.y + this.C*CRay.d.z)

TempT = num/denum

if TempT<PRECISION then
return 0
else
returnT = TempT
return 1
End if

End Select
End Function

Function Primitive.GetNormal(CRay as Ray) as Vector

static as Vector normal

Select case This.TypeFlag
Case PRIM_SPHERE

normal.x = CRay.x - this.x
normal.y = CRay.y - this.y
normal.z = CRay.z - this.z

Normalize(normal)

return normal

Case PRIM_PLANE

normal.x = A
normal.y = B
normal.z = C

Normalize(Normal)

return normal

End Select
End Function

Type LightT
as single x,y,z
as ColorT l_color
end type

Type SceneT

as Primitive ptr s_Primitive
as integer nb_primitives

as LightT ptr s_light
as integer nb_lights

Declare Constructor()
Declare Destructor()

Declare Sub Add_Sphere(cx as single, cy as single,cz as single, cR as single, Mat as MaterialT, lightf as integer=0)
Declare Sub Add_Plane (cA as single, cB as single,cC as single, cD as single, Mat as MaterialT)

Declare Sub Add_Light(cx as single, cy as single, cz as single,col as ColorT)

End Type

Sub SceneT.Add_Light(cx as single, cy as single, cz as single,col as ColorT)

if this.nb_lights>=MAX_LIGHTS then exit sub

this.s_light[this.nb_lights].x = cx
this.s_light[this.nb_lights].y = cy
this.s_light[this.nb_lights].z = cz

this.s_light[this.nb_lights].l_color = col

this.nb_lights += 1

end sub


Sub SceneT.Add_Sphere(cx as single, cy as single,cz as single, cR as single, Mat as MaterialT, lightf as integer=0)

If this.nb_primitives >= MAX_PRIMITIVES then exit sub

this.s_primitive[this.nb_primitives].typeflag = prim_sphere

this.s_primitive[this.nb_primitives].x = cx
this.s_primitive[this.nb_primitives].y = cy
this.s_primitive[this.nb_primitives].z = cz
this.s_primitive[this.nb_primitives].R = cR

this.s_primitive[this.nb_primitives].lightflag = lightf

this.s_primitive[this.nb_primitives].Material = Mat

this.nb_primitives += 1

end sub

Sub SceneT.Add_Plane(cA as single, cB as single,cC as single, cD as single, Mat as MaterialT)

If this.nb_primitives >= MAX_PRIMITIVES then exit sub

this.s_primitive[this.nb_primitives].typeflag = prim_plane

this.s_primitive[this.nb_primitives].A = cA
this.s_primitive[this.nb_primitives].B = cB
this.s_primitive[this.nb_primitives].C = cC
this.s_primitive[this.nb_primitives].D = cD

this.s_primitive[this.nb_primitives].Material = Mat

this.nb_primitives += 1

end sub


Constructor SceneT()

this.s_Primitive = Callocate(MAX_PRIMITIVES,Sizeof(Primitive))
this.s_light = Callocate(MAX_LIGHTS,Sizeof(LightT))

End Constructor

Destructor SceneT()

deallocate(this.s_Primitive)
deallocate(this.s_light)

End Destructor

Dim shared as SceneT Scene

Function RayTrace(ByVal R as Ray,ByVal CurReflection as integer = 0) as ColorT
Dim as Ray MainRay
Dim as integer IntersectedPrimitive
dim as single calcT=10000000, oldCalcT=10000000

MainRay = R

intersectedprimitive = -1

For k as integer = 0 to Scene.nb_primitives-1

oldCalcT=calcT

if Scene.s_primitive[k].GetIntersection(MainRay, calcT) then
if oldCalcT>CalcT then
MainRay.Update(calcT)
IntersectedPrimitive = k
end if
End If
next

'' calc Diffuse and specular colors !
if intersectedprimitive <> -1 then

dim as ColorT MatCol = type(0,0,0)

for k as integer = 0 to scene.nb_lights - 1

dim as Vector N, L, V, R
dim as single dotSpec, dotDiff

L = type<vector>(Scene.s_light[k].x,Scene.s_light[k].y,Scene.s_light[k].z) - Type<vector>(MainRay.x,MainRay.y,MainRay.z)
Normalize(L)

N = Scene.s_primitive[intersectedprimitive].GetNormal(MainRay)

V = MainRay.d
R = GetReflectionVector(V,N)

dotDiff = dot(N,L)
dotSpec = dot(R,L)^Scene.s_primitive[intersectedprimitive].Material.Highlight

'' Calculating Shadow

dim as single shade = 1
if CALC_SHADOWS then
dim as single shadowT
dim as Ray ShadowRay

ShadowRay.O = type(MainRay.x,MainRay.y,MainRay.z)
ShadowRay.d = L

for f as integer = 0 to Scene.nb_primitives-1
if (f<>IntersectedPrimitive) and Scene.s_primitive[f].GetIntersection(ShadowRay, ShadowT) then

shade = .1 : ShadowRay.Update(ShadowT) ' : exit for

End If
next
end if

'' Final Color shading
if dotDiff > 0 then
MatCol.r += dotDiff * Scene.s_primitive[intersectedprimitive].Material.Diffuse.r * Scene.s_light[k].l_color.r * shade
MatCol.g += dotDiff * Scene.s_primitive[intersectedprimitive].Material.Diffuse.g * Scene.s_light[k].l_color.g * shade
MatCol.b += dotDiff * Scene.s_primitive[intersectedprimitive].Material.Diffuse.b * Scene.s_light[k].l_color.b * shade
end if

if dotSpec > 0 then
MatCol.r += dotSpec * Scene.s_primitive[intersectedprimitive].Material.Specular.r * Scene.s_light[k].l_color.r * shade
MatCol.g += dotSpec * Scene.s_primitive[intersectedprimitive].Material.Specular.g * Scene.s_light[k].l_color.g * shade
MatCol.b += dotSpec * Scene.s_primitive[intersectedprimitive].Material.Specular.b * Scene.s_light[k].l_color.b * shade
end if

next

'' Calc reflections

if Scene.s_Primitive[intersectedprimitive].Material.reflection > 0 then
If CurReflection < MAX_REFLECTIONS then
Dim as ColorT refCol
Dim as Ray ReflectionRay
Dim as vector refNormal

refNormal = Scene.s_Primitive[intersectedprimitive].GetNormal(MainRay)

ReflectionRay.O = type(MainRay.x,MainRay.y,MainRay.z)
ReflectionRay.d = GetReflectionVector(MainRay.d,refNormal)
Normalize(ReflectionRay.d)

'' !!! Recursion !!!
refcol = Raytrace(ReflectionRay,CurReflection+1)
'' !!! --------- !!!

MatCol.r += Scene.s_Primitive[intersectedprimitive].Material.reflection*refcol.r
MatCol.g += Scene.s_Primitive[intersectedprimitive].Material.reflection*refcol.g
MatCol.b += Scene.s_Primitive[intersectedprimitive].Material.reflection*refcol.b
end if
end if

if Scene.s_Primitive[intersectedprimitive].lightflag then
matcol = Scene.s_Primitive[intersectedprimitive].Material.diffuse
end if

if MatCol.r>1 then MatCol.r = 1 : if MatCol.r<0 then MatCol.r = 0
if MatCol.g>1 then MatCol.g = 1 : if MatCol.g<0 then MatCol.g = 0
if MatCol.b>1 then MatCol.b = 1 : if MatCol.b<0 then MatCol.b = 0

return type(MatCol.r, MatCol.G,MatCol.b)
else
return type(.05,.05,.05)
end if

End Function

'' main loop


Dim as MaterialT sphereMat, PlaneMat

PlaneMat.Diffuse = type(1,1,1)
PlaneMat.Reflection = .4

SphereMat.Diffuse = type(1,.1,.1)
SphereMat.Reflection = .3
SphereMat.Specular = type(1,1,1)
SphereMat.Highlight = 60

Scene.Add_Light(-15,7,-5,type(.8,.8,.8))
Scene.Add_Light(15,5,20,type(.7,.7,.7))

Scene.Add_Sphere(0,-6.5,15,3,SphereMat)
Scene.Add_Sphere(-4,-6.5,10,3,SphereMat)
Scene.Add_Sphere(4,-6.5,10,3,SphereMat)
Scene.Add_Sphere(0,0,15,3,SphereMat)
Scene.Add_Sphere(-4,0,10,3,SphereMat)
Scene.Add_Sphere(4,0,10,3,SphereMat)
Scene.Add_Sphere(0,7,15,3,SphereMat)
Scene.Add_Sphere(-4,7,10,3,SphereMat)
Scene.Add_Sphere(4,7,10,3,SphereMat)
Scene.Add_Sphere(0,14,15,3,SphereMat)
Scene.Add_Sphere(-4,14,10,3,SphereMat)
Scene.Add_Sphere(4,14,10,3,SphereMat)

Scene.Add_Plane(0,1,0,-10,PlaneMat)


Screenres 640,480,32,2

Dim as colorT finCol
Dim as Ray MainRay

For j as integer = 0 to 479
For i as integer = 0 to 639

MainRay.O = type( 0, 0, -10 )
MainRay.d = type( i-320, 480-j-240,350)
Normalize(MainRay.d)

finCol = Raytrace(MainRay)

Pset(i,j),rgb(finCol.r*255,finCol.g*255,finCol.b*255)

Next
Next

sleep


vector.bi :
''
'' Vectors Library
'' for raytracer
''

Type Vector
as single x,y,z
End Type

Operator +(L as Vector, R as Vector) as Vector
return type(L.x+R.x,L.y+R.y,L.z+R.z)
End operator

Operator -(L as Vector, R as Vector) as Vector
return type(L.x-R.x,L.y-R.y,L.z-R.z)
End Operator

Operator *(L as Vector, R as Vector) as Vector
return type( L.y*R.z + L.z*R.y , _
L.z*R.x + L.x*R.z , _
L.x*R.y + L.y*R.x )
End operator

Operator *(L as Single, R as Vector) as Vector
return type( L*R.x, L*R.y, L*R.z )
End operator

Operator -(V as Vector) as Vector
return type(-V.x,-V.y,-V.z)
End Operator

Function Dot(V1 as vector, V2 as vector) as single
return V1.x*V2.x + V1.y*v2.y + v1.z*v2.z
End function

Sub Normalize(ByRef V as Vector)
static as single _norm

_norm = 1/sqr(V.x*v.x + V.y*v.y + v.z*v.z)

V.x *= _norm
V.y *= _norm
V.z *= _norm
End Sub

Function GetReflectionVector(InVec as Vector, Normal as Vector) as Vector
return Invec - 2*dot(Normal,InVec) * Normal
End Function

Music + Coding :
http://Hezad.no-ip.org

Hosting / Hébergement :
www.hezad.com

TinDragon

While I may not be able to help with the code, tho i will take a look see if i spot something, I must say that image you posted even with the faults looks very nice :)

I always liked raytracing, the amiga took hours to render even a simple scene but was always amazing to see the end result.

Clyde

That screenie looks amazing, congrats on your efforts Hezad dude :)
Will try the code out in a bit :D
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.


Challenge Trophies Won:

TinDragon

Wow that renders that scene really fast, its half draw by the time the window comes into view. Really impressive stuff and in such few lines of code :D

Voltage

Looking really good Hezad. :)
Challenge Trophies Won:

ferris

Lookin' great :) Any thoughts about going realtime at some point? ;) There are some great threads sitting round here for that if you're ever curious...Voltage and I and some others talked quite a bit about it, and if I'm not mistaken it was also freebasic :)
http://iamferris.com/
http://youth-uprising.com/

Where the fun's at.
Challenge Trophies Won:

Hezad

Thanks a lot everyone for your answers :)

Ferris > Yep I saw Real time raytracing was more and more discussed and worked on  forums(like here :p) /scientific papers, etc.. For now, my objective is to render nice images, I don't have a realtime objective (Also, I'd like to implement different global illumination algorithms in the future => definitively not for realtime purposes  ;D)
Music + Coding :
http://Hezad.no-ip.org

Hosting / Hébergement :
www.hezad.com

Shockwave

It looks lovely Hezad, thanks for posting the screen shot, I agree with Ferris too, freebasic can do this in realtime ;)
Shockwave ^ Codigos
Challenge Trophies Won:

va!n

@Hezad:
Wow, screenshot looks amazing! Any chance of an exe? :)
- hp EliteBook 8540p, 4 GB RAM, Windows 8.1 x64
- Asus P5Q, Intel Q8200, 6 GB DDR2, Radeon 4870, Windows 8.1 x64
http://www.secretly.de
Challenge Trophies Won:

TinDragon

I think Hezad runs linux, so I have compiled the exe and attach'd it.


va!n

#13
@Hezad:
Very nice work! K++ for source

@TinDragon:
Cool! Thanks a lot! K++
- hp EliteBook 8540p, 4 GB RAM, Windows 8.1 x64
- Asus P5Q, Intel Q8200, 6 GB DDR2, Radeon 4870, Windows 8.1 x64
http://www.secretly.de
Challenge Trophies Won:

Hezad

Thanks a lot :) and thanks TinDragon for the exe ;)

Shockie > Yep, I guess it could  run in real time too at this stage, but there will be -hopefully- more and more possibilities like Global Illumination, so it won't be in real-time in the future anyway :)
Music + Coding :
http://Hezad.no-ip.org

Hosting / Hébergement :
www.hezad.com

ferris

http://iamferris.com/
http://youth-uprising.com/

Where the fun's at.
Challenge Trophies Won:

Hezad

Quote from: Ferris on August 21, 2009
Go AO! GO AO! :D

uh ?


Some (little) news : Added antialiasing. I'm still looking for why there are two phong highlights for one light on each sphere ... (I lost a lot of hair right now :P). Also, there is a problem with the plane intersection function.. I guess I could work on the plane problem but I'm totally stuck on the phong ... Anyway, a new image and the "almost" new code :) (vector.bi hasn't changed)

''
'' Raytracer
''

#include "vector.bi"

Const PRECISION = .1

Const MAX_PRIMITIVES = 200
Const MAX_LIGHTS     = 10

Const PRIM_SPHERE = 1
Const PRIM_PLANE  = 2

Const MAX_REFLECTIONS = 5

Const CALC_SHADOWS = 0


Type ColorT
as single r,g,b
End Type

Type MaterialT
as ColorT Diffuse, Specular
as single Reflection, Highlight
as single Refraction, RefractionIndex
End type

Type Ray
as vector O,d

as single x,y,z

Declare Sub Update(t as single)
Declare Function Lengthpow2() as single
End Type

Function Ray.Lengthpow2() as single
return (this.x-this.O.x)*(this.x-this.O.x) + (this.y-this.O.y)*(this.y-this.O.y) + (this.z-this.O.z)*(this.z-this.O.z)
End Function


Sub Ray.Update(t as single)

this.x = this.O.x + this.d.x*t
this.y = this.O.y + this.d.y*t
this.z = this.O.z + this.d.z*t

End Sub

Type Primitive
as integer TypeFlag

as MaterialT Material

'' for planes
as single A,B,C,D

'' for spheres
as single R, x,y,z


'' functions
Declare function GetNormal(CRay as Ray) as Vector
Declare function GetIntersection(CRay as Ray,ByRef returnT as single) as integer
End type

Function Primitive.GetIntersection(CRay as Ray,ByRef returnT as single) as integer

Select case This.TypeFlag
Case PRIM_SPHERE

dim as single a = dot(Cray.d, Cray.d)
dim as single b = 2 * dot((Cray.o - type<vector>(this.x,this.y,this.z)),Cray.d )
dim as single c = dot((Cray.o - type<vector>(this.x,this.y,this.z)), (Cray.o - type<vector>(this.x,this.y,this.z))) - (this.r * this.r)

dim as single disc = b * b - 4 * a * c

if disc < PRECISION then return 0

dim as single distSqrt = sqr(disc)
dim as single q

if b < PRECISION then
q = (-b - distSqrt)*.5
else
q = (-b + distSqrt)*.5
end if

dim as single t0 = q / a
dim as single t1 = c / q

if t0>t1 then swap t0,t1

if t1 < PRECISION then return 0

if t0 < PRECISION then
returnT = t1
return 1
else
returnT = t0
return 1
end if

Case PRIM_PLANE

dim as single tempT, num, denum

num = (this.A*CRay.O.x + this.B*CRay.O.y + this.C*CRay.O.z + D)
denum = (this.A*CRay.d.x + this.B*CRay.d.y + this.C*CRay.d.z)

TempT = num/denum

if TempT<PRECISION then
return 0
else
returnT = TempT
return 1
End if

End Select
End Function

Function Primitive.GetNormal(CRay as Ray) as Vector

dim as Vector normal

Select case This.TypeFlag
Case PRIM_SPHERE

normal.x = CRay.x - this.x
normal.y = CRay.y - this.y
normal.z = CRay.z - this.z

Normalize(normal)

return normal

Case PRIM_PLANE

normal.x = A
normal.y = B
normal.z = C

Normalize(Normal)

return normal

End Select
End Function

Type LightT
as single x,y,z
as ColorT l_color
end type

Type SceneT

as Primitive ptr s_Primitive
as integer nb_primitives

as LightT ptr s_light
as integer nb_lights

Declare Constructor()
Declare Destructor()

Declare Sub Add_Sphere(cx as single, cy as single,cz as single, cR as single, Mat as MaterialT)
Declare Sub Add_Plane (cA as single, cB as single,cC as single, cD as single, Mat as MaterialT)

Declare Sub Add_Light(cx as single, cy as single, cz as single,col as ColorT)

End Type

Sub SceneT.Add_Light(cx as single, cy as single, cz as single,col as ColorT)

if this.nb_lights>=MAX_LIGHTS then exit sub

this.s_light[this.nb_lights].x = cx
this.s_light[this.nb_lights].y = cy
this.s_light[this.nb_lights].z = cz

this.s_light[this.nb_lights].l_color = col

this.nb_lights += 1

end sub


Sub SceneT.Add_Sphere(cx as single, cy as single,cz as single, cR as single, Mat as MaterialT)

If this.nb_primitives >= MAX_PRIMITIVES then exit sub

this.s_primitive[this.nb_primitives].typeflag = prim_sphere

this.s_primitive[this.nb_primitives].x = cx
this.s_primitive[this.nb_primitives].y = cy
this.s_primitive[this.nb_primitives].z = cz
this.s_primitive[this.nb_primitives].R = cR

this.s_primitive[this.nb_primitives].Material = Mat

this.nb_primitives += 1

end sub

Sub SceneT.Add_Plane(cA as single, cB as single,cC as single, cD as single, Mat as MaterialT)

If this.nb_primitives >= MAX_PRIMITIVES then exit sub

this.s_primitive[this.nb_primitives].typeflag = prim_plane

this.s_primitive[this.nb_primitives].A = cA
this.s_primitive[this.nb_primitives].B = cB
this.s_primitive[this.nb_primitives].C = cC
this.s_primitive[this.nb_primitives].D = cD

this.s_primitive[this.nb_primitives].Material = Mat

this.nb_primitives += 1

end sub


Constructor SceneT()

this.s_Primitive = Callocate(MAX_PRIMITIVES,Sizeof(Primitive))
this.s_light = Callocate(MAX_LIGHTS,Sizeof(LightT))

End Constructor

Destructor SceneT()

deallocate(this.s_Primitive)
deallocate(this.s_light)

End Destructor

Dim shared as SceneT Scene

Function RayTrace(ByVal R as Ray,ByVal CurReflection as integer = 0) as ColorT
Dim as Ray MainRay
Dim as integer IntersectedPrimitive
dim as single calcT=10000000, oldCalcT=10000000

MainRay = R

intersectedprimitive = -1

For k as integer = 0 to Scene.nb_primitives-1

oldCalcT=calcT

if Scene.s_primitive[k].GetIntersection(MainRay, calcT) then
if oldCalcT>CalcT then
MainRay.Update(calcT)
IntersectedPrimitive = k
end if
End If
next

'' calc color !
if intersectedprimitive <> -1 then

dim as ColorT MatCol = type(0,0,0)

'' Diffuse, specular and shadows
for k as integer = 0 to scene.nb_lights - 1

dim as Vector N, L, V, R
dim as single dotSpec, dotDiff

L = type<vector>(Scene.s_light[k].x,Scene.s_light[k].y,Scene.s_light[k].z) - Type<vector>(MainRay.x,MainRay.y,MainRay.z)
Normalize(L)

N = Scene.s_primitive[intersectedprimitive].GetNormal(MainRay)

V = MainRay.d
R = GetReflectionVector(V,N)

dotDiff = dot(N,L)
dotSpec = dot(L,R)^Scene.s_primitive[intersectedprimitive].Material.Highlight

'' Calculating Shadow

dim as single shade = 1
if CALC_SHADOWS then
dim as single shadowT
dim as Ray ShadowRay

ShadowRay.O = type<vector>(MainRay.x,MainRay.y,MainRay.z) + L*PRECISION
ShadowRay.d = L

for f as integer = 0 to Scene.nb_primitives-1
if Scene.s_primitive[f].GetIntersection(ShadowRay, ShadowT) then

shade = .1 : exit for

End If
next
end if

'' Final Color shading
if dotDiff > 0 then
MatCol.r += dotDiff * Scene.s_primitive[intersectedprimitive].Material.Diffuse.r * Scene.s_light[k].l_color.r * shade
MatCol.g += dotDiff * Scene.s_primitive[intersectedprimitive].Material.Diffuse.g * Scene.s_light[k].l_color.g * shade
MatCol.b += dotDiff * Scene.s_primitive[intersectedprimitive].Material.Diffuse.b * Scene.s_light[k].l_color.b * shade
end if

if dotSpec > 0 then
MatCol.r += dotSpec * Scene.s_primitive[intersectedprimitive].Material.Specular.r * Scene.s_light[k].l_color.r * shade
MatCol.g += dotSpec * Scene.s_primitive[intersectedprimitive].Material.Specular.g * Scene.s_light[k].l_color.g * shade
MatCol.b += dotSpec * Scene.s_primitive[intersectedprimitive].Material.Specular.b * Scene.s_light[k].l_color.b * shade
end if

next

'' Calc reflections
if Scene.s_Primitive[intersectedprimitive].Material.reflection > 0 then
If CurReflection < MAX_REFLECTIONS then
Dim as ColorT refCol
Dim as Ray ReflectionRay
Dim as vector refNormal

refNormal = Scene.s_Primitive[intersectedprimitive].GetNormal(MainRay)

ReflectionRay.O = type <vector> (MainRay.x,MainRay.y,MainRay.z)
ReflectionRay.d = GetReflectionVector(MainRay.d,refNormal)
Normalize(ReflectionRay.d)

'' !!! Recursion !!!
refcol = Raytrace(ReflectionRay,CurReflection+1)
'' !!! --------- !!!

MatCol.r += Scene.s_Primitive[intersectedprimitive].Material.reflection*refcol.r
MatCol.g += Scene.s_Primitive[intersectedprimitive].Material.reflection*refcol.g
MatCol.b += Scene.s_Primitive[intersectedprimitive].Material.reflection*refcol.b
end if
end if

if MatCol.r>1 then MatCol.r = 1 : if MatCol.r<0 then MatCol.r = 0
if MatCol.g>1 then MatCol.g = 1 : if MatCol.g<0 then MatCol.g = 0
if MatCol.b>1 then MatCol.b = 1 : if MatCol.b<0 then MatCol.b = 0

return type(MatCol.r, MatCol.G,MatCol.b)
else
return type(.05,.05,.05)
end if

End Function

'' main loop


Dim as MaterialT sphereMat, PlaneMat

PlaneMat.Diffuse = type(.8,.8,.8)
PlaneMat.Reflection = .5

SphereMat.Diffuse = type(1,.1,.1)
SphereMat.Reflection = .5
SphereMat.Specular = type(1,1,1)
SphereMat.Highlight = 100

Scene.Add_Light(-10,0,0,type(.6,.6,.6))
'Scene.Add_Light(10,0,15,type(.5,.5,.5))


for i as integer = -2 to 2
for j as integer = -2 to 2
SphereMat.Diffuse = type(abs(i)*.5,abs(j)*.5,abs(i*j)*.25)
Scene.Add_Sphere(i*5,j*5,10,2.4,Spheremat)
next
next


'Scene.Add_Plane(0,1,0,-10,PlaneMat)


Screenres 640,480,32,2

Dim as colorT finCol(4)
Dim as Ray MainRay

For j as integer = 0 to 479
For i as integer = 0 to 639

MainRay.O = type( 0, 0, -10 )
MainRay.d = type( i-320, 480-j-240,350)
Normalize(MainRay.d)

finCol(1) = Raytrace(MainRay)

MainRay.O = type( 0, 0, -10 )
MainRay.d = type( i+.5-320, 480-j-240,350)
Normalize(MainRay.d)

finCol(2) = Raytrace(MainRay)

MainRay.O = type( 0, 0, -10 )
MainRay.d = type( i-320, 480-j+.5-240,350)
Normalize(MainRay.d)

finCol(3) = Raytrace(MainRay)

MainRay.O = type( 0, 0, -10 )
MainRay.d = type( i+.5-320, 480-j+.5-240,350)
Normalize(MainRay.d)

finCol(4) = Raytrace(MainRay)

finCol(0).r = (finCol(1).r+finCol(2).r+finCol(3).r+finCol(4).r) * .25
finCol(0).g = (finCol(1).g+finCol(2).g+finCol(3).g+finCol(4).g) * .25
finCol(0).b = (finCol(1).b+finCol(2).b+finCol(3).b+finCol(4).b) * .25

Pset(i,j),rgb(finCol(0).r*255,finCol(0).g*255,finCol(0).b*255)

Next
Next

sleep
Music + Coding :
http://Hezad.no-ip.org

Hosting / Hébergement :
www.hezad.com

Shockwave

Looks delicious. As for the highlights problem, I dont know man, it looks lovely to me.
Shockwave ^ Codigos
Challenge Trophies Won:

Hezad

Thanks shockie :)

The highlight problem has just been resolved (thanks to ROMAECURSORES from freebasic forums). here is a little screen to see the difference (with shadows) ;) I can work on the plane intersection now ;D
Music + Coding :
http://Hezad.no-ip.org

Hosting / Hébergement :
www.hezad.com

TinDragon

That looks great, I look forward to seeing your progress this is one of those things that always impress me, raytracing is such an interesting subject :)
:updance: