RealTime Raytracing in bmax

BlitzMax Forums/BlitzMax Programming/RealTime Raytracing in bmax

Filax(Posted 2005) [#1]
Hi :) I have find a little B3D program on the DBF forum
http://p212.ezboard.com/fdbffrm50.showMessage?topicID=190.topic


Beaker(Posted 2005) [#2]
Try this:
' --------------------------------------------------
' The color rendering is bugged here i dn't know why
' --------------------------------------------------
c3 = (c1 * c) Shr 8

'a = ((argb & $FF000000) * c3) Shr 8
r = ((argb & $00FF0000) * c3) Shr 8
g = ((argb & $0000FF00) * c3) Shr 8
b = ((argb & $000000FF) * c3) Shr 8

'a = a + (c2 Shl 24)
r = r + (c2 Shl 16)
g = g + (c2 Shl 8)
b = b + c2

If argb <> $FF000000 Then argb = ray(ix#,iy#,iz#,rnx#,rny#,rnz#,c - 32)

'a = a + (argb & $FF000000)
r = r + (argb & $00FF0000)
g = g + (argb & $0000FF00)
b = b + (argb & $000000FF)

If r > $00FF0000
        r = $00FF0000
Else
        r = r & $00FF0000
EndIf

If g > $0000FF00
        g = $0000FF00
Else
        g = g & $0000FF00
EndIf

If b > $000000FF
        b = $000000FF
Else
        b = b & $000000FF
EndIf

Return $FF000000 | r | g | b



Filax(Posted 2005) [#3]
Excellent ! here is the full code

** ADMIN REMOVE THIS **


Filax(Posted 2005) [#4]
** ADMIN REMOVE THIS **


Filax(Posted 2005) [#5]
I have find a little stuff to antialias quickly images :) it's not very very
clean, but better than a pixelated image

I compute my image and before draw i make a setscale to reduce the
size a little bit ... :)

Look this example (Thygrion from DBF) that i have translate to work
with bmax.


Framework BRL.GLMax2D
Import BRL.Random
SetGraphicsDriver GLMax2DDriver()


Const width = 320
Const height = 240

Graphics width,height,32,75

SeedRnd MilliSecs()

Global RenderImage:Timage=CreateImage(width,height,DYNAMICIMAGE)
MidHandleImage(RenderIMage)

Global sphere_list:TList=New TList
Global plane_list:TList=New TList

Type TBBType
Field _list:TList
Field _link:TLink

Method Remove()
_list.remove Self
End Method
End Type

Type bbplane Extends TBBType
Field nx#
Field ny#
Field nz#
Field dis#
Field argb
End Type

Type bbsphere Extends TBBType
Field x#
Field y#
Field z#
Field xv#
Field yv#
Field zv#
Field argb
End Type

' ---------------
' FPS Counter var
' ---------------
Global Frames:Int
Global RenderTime:Int
Global Fps:Int

' ---------
' Other var
' ,--------
Global planes = 1
Global spheres = 4

Global p:bbplane[planes+1]
Global s:bbsphere[spheres+1]

Global normalx#[width+1,height+1]
Global normaly#[width+1,height+1]
Global normalz#[width+1,height+1]

Global sphererad# = 80.0
Global sphererad2# = Float(sphererad# * sphererad#)

Global camerax# =0
Global cameray# =0
Global cameraz# = -800.0

Global lightx# = 200.0
Global lighty# = 400.0
Global lightz# = -200.0

Global spec# = 90.0
Global grav# = 1.15
Global fric# = 0.65

' --------------
' Setup 3D scene
' --------------
DrawText "COMPUTING",10,10
Flip

setupplanes()
setupspheres()
setupnormals()

Global RenderScale#=0.90

While Not KeyHit(KEY_ESCAPE)
Cls

raytrace()

SetScale RenderScale#,RenderScale#
DrawImage RenderIMage,GraphicsWidth()/2,GraphicsHeight()/2
SetScale 1,1

' -----------------------
' Apply gravity to sphere
' -----------------------
For i = 0 To spheres - 1
s(i).x# = s(i).x# + s(i).xv#
s(i).y# = s(i).y# + s(i).yv#
s(i).z# = s(i).z# + s(i).zv#
s(i).yv# = s(i).yv# - grav#

' ---------------------------------------
' Detecting if the sphere touch the plane
' ---------------------------------------
If s(i).y# - sphererad# < -p(0).dis#
s(i).y# = -p(0).dis# + sphererad#
s(i).xv# = Float(s(i).xv# * fric#)
s(i).yv# = Float(-s(i).yv# * fric#)
s(i).zv# = Float(s(i).zv# * fric#)

If s(i).xv# > -fric# Or s(i).xv# < fric# Then s(i).xv# = 0
If s(i).zv# > -fric# Or s(i).zv# < fric# Then s(i).zv# = 0
EndIf
Next

If KeyDown(KEY_LEFT) Then camerax# = camerax# - 50.0
If KeyDown(KEY_RIGHT) Then camerax# = camerax# + 50.0

If KeyDown(KEY_UP) Then cameraz# = cameraz# + 50.0
If KeyDown(KEY_DOWN) Then cameraz# = cameraz# - 50.0

If KeyDown(KEY_PAGEUP) Then cameray# = cameray# + 50.0
If KeyDown(KEY_PAGEDOWN) Then cameray# = cameray# - 50.0

' --------------------
' Made jump the sphere
' --------------------
If KeyHit(KEY_SPACE)
For i = 0 To spheres - 1
s(i).yv# = Rnd(16,20)
Next
EndIf

DrawText "FPS "+Fps+" / "+MemUsage(),10,10

RefreshFPS()

FlushMem
Flip
Wend

' --------
' Quit app
' --------
For i = 0 To planes - 1
p(i).Remove()
Next

For i = 0 To spheres - 1
s(i).Remove()
Next

End

' ---------------------
' Setup plane primitive
' ---------------------
Function setupplanes()
For i = 0 To planes - 1
p:bbplane(i) = New bbplane
p(i).ny# = 1.0
p(i).dis# = Float(sphererad# * 4.0)
p(i).argb = Rand($686868,$FFFFFF)
Next
End Function

' ----------------------
' Setup sphere primitive
' ----------------------
Function setupspheres()
Local sr# = Float(sphererad# * 4.5)

For i = 0 To spheres - 1
s:bbsphere(i) = New bbsphere

s(i).x# = Rnd(-sr#,sr#)
s(i).y# = Rnd(0,sphererad#)
s(i).z# = Rnd(-sr#,sr#)

s(i).xv# = Rnd(-10.0,10.0)
s(i).yv# = Rnd(-2.0,7.0)
s(i).zv# = Rnd(-10.0,10.0)

s(i).argb = Rand($111111,$FFFFFF)
Next
End Function

Function setupnormals()
Local nx#
Local ny#
Local nz# = 250.0
Local dis#

For y = 0 To height - 1
ny# = Float(height Shr 1) - Float(y)

For x = 0 To width - 1
nx# = Float(width Shr 1) - Float(x)
dis# = Sqr(Float(nx# * nx#) + Float(ny# * ny#) + Float(nz# * nz#))
normalx#(x,y) = -Float(nx# / dis#)
normaly#(x,y) = Float(ny# / dis#)
normalz#(x,y) = Float(nz# / dis#)
Next
Next
End Function

' ------------------
' Raytrace the image
' ------------------
Function raytrace()
Local argb

Local RenderMap=LockImage(RenderImage)

For y = 0 To ImageHeight(RenderImage) - 1
For x = 0 To ImageWidth(RenderImage)- 1
argb = ray(camerax#,cameray#,cameraz#,normalx#(x,y),normaly#(x,y),normalz#(x,y),256)

If argb <> $00000000 Then WritePixel RenderMap,x,y,argb
Next
Next

UnlockImage (RenderImage)
RenderMap=Null
End Function

' ----------------------
' Raytracing computation
' ----------------------
Function ray(ex#,ey#,ez#,evx#,evy#,evz#,c)
If c <= 32 Then Return
Local plane:bbplane
Local sphere:bbsphere

Local z# = 10000
Local svx#
Local svy#
Local svz#

Local ix#
Local iy#
Local iz#
Local nx#
Local ny#
Local nz#

Local rnx#
Local rny#
Local rnz#

Local lvx#
Local lvy#
Local lvz#

Local dxis#
Local ydis#
Local zdis#

Local dxis2#
Local ydis2#
Local zdis2#

Local dis#
Local dis2#

Local l#

Local c1
Local c2
Local c3

Local a
Local r
Local g
Local b

For i = 0 To planes - 1
plane:bbplane = p(i)
nx# = plane.nx#
ny# = plane.ny#
nz# = plane.nz#
dis# = Float(Float(nx# * evx#) + Float(ny# * evy#) + Float(nz# * evz#))

If dis# < 0
dis2# = Float(-Float(plane.dis# + Float(Float(nx# * ex#) + Float(ny# * ey#) + Float(nz# * ez#))) / dis#)
ix# = ex# + Float(evx# * dis2#)
iy# = ey# + Float(evy# * dis2#)
iz# = ez# + Float(evz# * dis2#)

lvx# = Float(lightx# - ix#)
lvy# = Float(lighty# - iy#)
lvz# = Float(lightz# - iz#)

dis# = Sqr(Float(lvx# * lvx#) + Float(lvy# * lvy#) + Float(lvz# * lvz#))

lvx# = Float(lvx# / dis#)
lvy# = Float(lvy# / dis#)
lvz# = Float(lvz# / dis#)

l# = Float(Float(nx# * lvx#) + Float(ny# * lvy#) + Float(nz# * lvz#))

dis# = Float(Float(Float(nx# * evx#) + Float(ny# * evy#) + Float(nz# * evz#)) * 2.0)

rnx# = evx# - Float(nx# * dis#)
rny# = evy# - Float(ny# * dis#)
rnz# = evz# - Float(nz# * dis#)

c1 = Int(l# * 256.0)
c2 = Int(Float(Float(rnx# * lvx#) + Float(rny# * lvy#) + Float(rnz# * lvz#))^spec# * 256.0)
argb = plane.argb
z# = dis2#
EndIf

Next

For i = 0 To spheres - 1
sphere:bbsphere = s(i)
svx# = sphere.x# - ex#
svy# = sphere.y# - ey#
svz# = sphere.z# - ez#

dis2# = Float(Float(svx# * evx#) + Float(svy# * evy#) + Float(svz# * evz#))
dis# = Float(Float(svx# * svx#) + Float(svy# * svy#) + Float(svz# * svz#)) - Float(dis2# * dis2#)

If dis# <= sphererad2#
dis2# = dis2# - Sqr(sphererad2# - dis#)


If dis2# > 0 And dis2# < z#
ix# = ex# + Float(evx# * dis2#)
iy# = ey# + Float(evy# * dis2#)
iz# = ez# + Float(evz# * dis2#)

nx# = Float(Float(ix# - sphere.x#) / sphererad#)
ny# = Float(Float(iy# - sphere.y#) / sphererad#)
nz# = Float(Float(iz# - sphere.z#) / sphererad#)

lvx# = Float(lightx# - ix#)
lvy# = Float(lighty# - iy#)
lvz# = Float(lightz# - iz#)

dis# = Sqr(Float(lvx# * lvx#) + Float(lvy# * lvy#) + Float(lvz# * lvz#))

lvx# = Float(lvx# / dis#)
lvy# = Float(lvy# / dis#)
lvz# = Float(lvz# / dis#)

l# = Float(Float(nx# * lvx#) + Float(ny# * lvy#) + Float(nz# * lvz#))

dis# = Float(Float(Float(nx# * evx#) + Float(ny# * evy#) + Float(nz# * evz#)) * 2.0)

rnx# = evx# - Float(nx# * dis#)
rny# = evy# - Float(ny# * dis#)
rnz# = evz# - Float(nz# * dis#)

c1 = Int(l# * 256.0)
c2 = Int(Float(Float(rnx# * lvx#) + Float(rny# * lvy#) + Float(rnz# * lvz#))^spec# * 256.0)
argb = sphere.argb
z# = dis2#
EndIf
EndIf
Next

If shadowed(ix#,iy#,iz#)
c1 = 30
c2 = 0
Else
If c1 < 30 Then c1 = 30
If c2 < 0 Then c2 = 0
EndIf

c3 = (c1 * c) Shr 8

r = ((argb & $00FF0000) * c3) Shr 8
g = ((argb & $0000FF00) * c3) Shr 8
b = ((argb & $000000FF) * c3) Shr 8

r = r + (c2 Shl 16)
g = g + (c2 Shl 8)
b = b + c2

'If argb <> $00000000 Then argb = ray(ix#,iy#,iz#,rnx#,rny#,rnz#,c - 82)
If argb <> $00000000 Then argb = ray(ix#,iy#,iz#,rnx#,rny#,rnz#,c - 95)

r = r + (argb & $00FF0000)
g = g + (argb & $0000FF00)
b = b + (argb & $000000FF)

If r > $00FF0000
r = $00FF0000
Else
r = r & $00FF0000
EndIf

If g > $0000FF00
g = $0000FF00
Else
g = g & $0000FF00
EndIf

If b > $000000FF
b = $000000FF
Else
b = b & $000000FF
EndIf

Return $FF000000 | r | g | b
End Function

' --------------
' Compute shadow
' --------------
Function shadowed(x#,y#,z#)
Local plane:bbplane
Local sphere:bbsphere
Local shad = False
Local evx# = Float(lightx# - x#)
Local evy# = Float(lighty# - y#)
Local evz# = Float(lightz# - z#)
Local dis# = Sqr(Float(evx# * evx#) + Float(evy# * evy#) + Float(evz# * evz#))
Local dis2#

evx# = Float(evx# / dis#)
evy# = Float(evy# / dis#)
evz# = Float(evz# / dis#)

For i = 0 To planes - 1
plane:bbplane = p(i)
nx# = plane.nx#
ny# = plane.ny#
nz# = plane.nz#
dis# = Float(Float(nx# * evx#) + Float(ny# * evy#) + Float(nz# * evz#))
If dis# < 0
shad = True
i = planes - 1
EndIf
Next

If shad = False
For i = 0 To spheres - 1
sphere:bbsphere = s(i)
svx# = sphere.x# - x#
svy# = sphere.y# - y#
svz# = sphere.z# - z#
dis2# = Float(Float(svx# * evx#) + Float(svy# * evy#) + Float(svz# * evz#))
dis# = Float(Float(svx# * svx#) + Float(svy# * svy#) + Float(svz# * svz#)) - Float(dis2# * dis2#)
If dis2# > 0 And dis# < sphererad2#
shad = True
i = spheres - 1
EndIf
Next
EndIf

Return shad
End Function

' ------------
' For know FPS
' ------------
Function RefreshFPS()
Frames=Frames+1

If MilliSecs()-RenderTime=>1000 Then
Fps=Frames
Frames=0
RenderTime=MilliSecs()
EndIf
End Function


Matthew Smith(Posted 2005) [#6]
Filax,

Runs 10 fps quicker than the last version for me - well done!