I've played with the idea of posting a tutorial for ray tracing for many years now, but wasn't quite happy with what I was coming up with. Explaining stuff and neat, simple coding aren't my strong suit...
But whatever, I will just give it a try.
I will focus on making the individual programs as simple and easy to understand as possible. The downside of this is, that to add more functionality, I will have to change a lot of code between programs.
So, please, use this just as a means to understand ray tracing, not as a reference how to best implement it.
Code: Select all
ScreenWidth = 600 : ScreenHeight = 400
If OpenWindow(0, 0, 0, ScreenWidth, ScreenHeight, "Ray Tracing Tutorial 1", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
If CreateImage(0, ScreenWidth, ScreenHeight)
If StartDrawing(ImageOutput(0))
ScreenZ = ScreenWidth ; Distance between the (virtual) eye and screen = width of screen for a 45 degrees horizontal field of view
; A sphere straight ahead and as high as the screen, but slightly further away
SphereRadius.f = ScreenHeight / 2
SphereX.f = 0
SphereY.f = 0
SphereZ.f = ScreenWidth * 1.2
; For every pixel on the screen
For ScreenY = 0 To ScreenHeight - 1
For ScreenX = 0 To ScreenWidth - 1
; Create a ray from the eye to the screen.
RayOriginX.f = 0 ; Position
RayOriginY.f = 0 ; of the
RayOriginZ.f = 0 ; eye
RayVecX.f = ScreenX - ScreenWidth / 2 ; Shift 0,0 to the center of the screen
RayVecY.f = ScreenHeight / 2 - ScreenY ; and making sure that up is positive
RayVecZ.f = ScreenZ
; Rays have a starting point and a direction (vector). When doing math with vectors the result will
; be in multiples of the length of the vector, so we need to make sure the lenght is 1, or it gets messy.
; This is called normalizing:
RayLenght.f = Sqr(RayVecX * RayVecX + RayVecY * RayVecY + RayVecZ * RayVecZ)
RayVecX = RayVecX / RayLenght
RayVecY = RayVecY / RayLenght
RayVecZ = RayVecZ / RayLenght
; Let's check if the ray hits the sphere.
RelPosX.f = RayOriginX - SphereX
RelPosY.f = RayOriginY - SphereY
RelPosZ.f = RayOriginZ - SphereZ
b.f = RayVecX * RelPosX + RayVecY * RelPosY + RayVecZ * RelPosZ
c.f = (RelPosX * RelPosX + RelPosY * RelPosY + RelPosZ * RelPosZ) - SphereRadius * SphereRadius
d.f = b * b - c
If d > 0.0 ; Ray vector intersects sphere. (Not testing if the sphere is in front or behind the ray origin for now)
Plot(ScreenX, ScreenY, RGB(200, 0 ,0))
EndIf
Next
Next
StopDrawing()
EndIf
EndIf
ImageGadget(0, 0, 0, 0, 0, ImageID(0))
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
EndIf
End