Raytracing in One Weekend

Everything related to 3D programming
User avatar
idle
Always Here
Always Here
Posts: 5896
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Raytracing in One Weekend

Post by idle »

looking good keep going!
threedslider
Enthusiast
Enthusiast
Posts: 397
Joined: Sat Feb 12, 2022 7:15 pm

Re: Raytracing in One Weekend

Post by threedslider »

Thank you @idle, I hope to continue it as well :D
SMaag
Enthusiast
Enthusiast
Posts: 325
Joined: Sat Jan 14, 2023 6:55 pm
Location: Bavaria/Germany

Re: Raytracing in One Weekend

Post by SMaag »

If you want to do real raytracing with millions of calculatons you have to much overhad in your code!

as an example the ray_color_n

Code: Select all

Procedure.f ray_color_n(x.f, y.f, z.f, axe)
  
  color1.Vec3
  color2.Vec3
  
  color1\x = x
  color1\y = y
  color1\z = z
  
   
  x.f =  0.5 * color1\x + 1.0

  y.f =  0.5 * color1\y + 1.0
 
  z.f =  0.5 * color1\z + 1.0
  
  If axe = 1
    ProcedureReturn x
  EndIf
  
  If axe = 2
    ProcedureReturn y
  EndIf
  
  If axe = 3
    ProcedureReturn z
  EndIf
   
EndProcedure

the optimized version

Code: Select all

Procedure.f ray_color_n(x.f, y.f, z.f, axe)
  
  Select axe
    Case 1
      ProcedureReturn   (0.5 * x + 1.0)
      
    Case 2
      ProcedureReturn   (0.5 * y + 1.0)
      
    Case 3
      ProcedureReturn   (0.5 * z + 1.0)
      
  EndSelect
  ProcedureReturn 0
EndProcedure

;  and for the Speed a Macro would be much better.

Macro RayColor(value)
  value * 0.5 +1.0  
EndMacro

SMaag
Enthusiast
Enthusiast
Posts: 325
Joined: Sat Jan 14, 2023 6:55 pm
Location: Bavaria/Germany

Re: Raytracing in One Weekend

Post by SMaag »

some other diry code!

Code: Select all

Procedure.f unit_vector_x(*vx.Ray)
    
  ; len.f = v_length(*vx) 
  ;better use Protected, than it is a Procedure local variable 
  Protected len.f
  len = v_length(*vx) 
  
  ;Debug len
  
  If len > 0 ;And Not len < 0
   ; because *vx is a Pointer you change directly the x value in *vx\dir\x
   ; an extra Procedurereturn is not necessary. If you want the result 
   ; only as Return Value, do it direct with ProcedreReturn
    ;*vx\dir\x = *vx\dir\x / len
    ProcedureReturn *vx\dir\x / len
  EndIf
  
  
  ;Debug vv
  
  ; ProcedureReturn *vx\dir\x
  ProcedreReturn 0 ; Retrun 0 if len was 0
  
EndProcedure

threedslider
Enthusiast
Enthusiast
Posts: 397
Joined: Sat Feb 12, 2022 7:15 pm

Re: Raytracing in One Weekend

Post by threedslider »

@SMaag : Thank you for pointed this :) (Have you see my last code ?)

I will see that but actually my code still is quick too :P

And sorry for my late to work to the next chapter, from now I take a pause as well :wink:
infratec
Always Here
Always Here
Posts: 7618
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Raytracing in One Weekend

Post by infratec »

Btw.:

Code: Select all

Macro RayColor(value)
  value * 0.5 +1.0  
EndMacro
Should be written as:

Code: Select all

Macro RayColor(value)
  (value * 0.5 + 1.0)
EndMacro
Because else you can get wrong calculations:

Code: Select all

Debug RayColor(10) * 2
threedslider
Enthusiast
Enthusiast
Posts: 397
Joined: Sat Feb 12, 2022 7:15 pm

Re: Raytracing in One Weekend

Post by threedslider »

Thanks @Infratec :)

Again it should be for my last code :

Code: Select all

Macro RayColor(ray, axe)
  ( 0.5 * (unit_vector_normal(ray, axe)  + 1.0))
EndMacro
[Edit] Now it works so you need to test it if all running which "ray" can be remplaced by a structure pointer as argument :)
threedslider
Enthusiast
Enthusiast
Posts: 397
Joined: Sat Feb 12, 2022 7:15 pm

Re: Raytracing in One Weekend

Post by threedslider »

Hello :)

Come back ... Well I am working this as well too, nice picture but may be a bug something, hope if I can find what issue is that :wink:

Here my last code for two primitive :

Code: Select all

;
; Inspired from Ray Tracing in One Weekend : 
; https://raytracing.github.io/books/RayTracingInOneWeekend.html
;
; Writed and adapted in Purebasic by threedslider
;

N.i = 2

; Vector 
Structure Vec3
  x.f
  y.f
  z.f
EndStructure

; Ray
Structure Ray
  orig.Vec3
  dir.Vec3
EndStructure

;Sphere
Structure Sphere
  center.Vec3
  radius.f
EndStructure

;hit record
Structure hit_record
  p.Vec3
  normal.Vec3
  t.f
EndStructure

Dim A_sph.Sphere(N)
Dim A_hit.hit_record(N)

Procedure init_zero_hit_record()
  Shared A_hit.hit_record()
  
  For i=0 To N-1
    A_hit(i)\t = 0.0
    A_hit(i)\p\x = 0.0
    A_hit(i)\p\y = 0.0
    A_hit(i)\p\z = 0.0
    A_hit(i)\normal\x = 0.0
    A_hit(i)\normal\y = 0.0
    A_hit(i)\normal\z = 0.0
  Next
EndProcedure

Procedure init_sphere()
  Shared A_sph.Sphere()  
 
    A_sph(0)\center\x = 0.0
    A_sph(0)\center\y = 0.0
    A_sph(0)\center\z = -1.0
    A_sph(0)\radius = 0.5
    
    A_sph(1)\center\x = 0.0
    A_sph(1)\center\y = -100.0
    A_sph(1)\center\z = -1.0
    A_sph(1)\radius = 100.0
    
EndProcedure

Procedure.f dot(*v1.Vec3, *v2.Vec3)
  result.f = *v1\x * *v2\x + *v1\y * *v2\y + *v1\z * *v2\z
  
  ProcedureReturn result
EndProcedure

Procedure.f dotN(*v1.Vec3, Array r.hit_record(1), num)
  result.f = *v1\x * r(num)\normal\x + *v1\y * r(num)\normal\y + *v1\z * r(num)\normal\z 
  
  ProcedureReturn result
EndProcedure

Procedure.f v_length(*v.Ray)
  
  result.f = Sqr(*v\dir\x * *v\dir\x + *v\dir\y * *v\dir\y + *v\dir\z * *v\dir\z)
  
  ;Debug result
  
  ProcedureReturn result
EndProcedure

Procedure.f At(*rr.Ray, t.f, axe)
  
  x.f = *rr\orig\x + t * *rr\dir\x
  y.f = *rr\orig\y + t * *rr\dir\y
  z.f = *rr\orig\z + t * *rr\dir\z
  
  If axe = 1
    ProcedureReturn x
  EndIf
  
  If axe = 2
    ProcedureReturn y
  EndIf
  
  If axe = 3
    ProcedureReturn z
  EndIf
EndProcedure

Procedure.f unit_vector_y(*vy.Ray)
    
  len.f = v_length(*vy) 
  
  y.f = 0
  
  If Not len = 0 ;And Not len < 0
    y = *vy\dir\y / len
  EndIf
  
  
  ;Debug vv
  
  ProcedureReturn y
EndProcedure

Procedure.f unit_vector_normal(*rr.Ray, axe)
    
  len.f = Sqr(*rr\dir\x * *rr\dir\x + *rr\dir\y * *rr\dir\y + *rr\dir\z  * *rr\dir\z )
  
  xx.f = 0
  yy.f = 0
  zz.f = 0
  
   If Not len = 0 
    xx = *rr\dir\x / len
  EndIf
  
  If Not len = 0 
    yy = *rr\dir\y / len
  EndIf
  
   If Not len = 0 
     zz = *rr\dir\z  / len
     If axe = 3
      ProcedureReturn zz
    EndIf
  EndIf
  
  If axe = 1
    ProcedureReturn xx
  EndIf
  
  If axe = 2
    ProcedureReturn yy
  EndIf
  
EndProcedure

Procedure.f ray_color_hit(Array r.hit_record(1), axe)
  Shared N
    
For i=0 To N-1

  x.f =  0.5 * ( r(i)\normal\x + 1.0 )

  y.f =  0.5 * ( r(i)\normal\y + 1.0 )
 
  z.f =  0.5 * ( r(i)\normal\z + 1.0 )
  
  
  If axe = 1 And i <= 1 
    ProcedureReturn x 
  EndIf
  
  If axe = 2 And i <= 1
    ProcedureReturn y
  EndIf
  
  If axe = 3 And i <= 1
    ProcedureReturn z
  EndIf
Next

   
EndProcedure

Procedure.f ray_color_n(*rr.Ray, axe)
  Shared p_s.Vec3

  x.f =  0.5 * ((unit_vector_normal(*rr,1) + 1.0) )

  y.f =  0.5 * ((unit_vector_normal(*rr,2) + 1.0) )
 
  z.f =  0.5 * ((unit_vector_normal(*rr,3) + 1.0) )
  
  If axe = 1
    ProcedureReturn x
  EndIf
  
  If axe = 2
    ProcedureReturn y
  EndIf
  
  If axe = 3
    ProcedureReturn z
  EndIf
   
EndProcedure

Procedure.f ray_color(*rr.Ray, axe)
  
  color1.Vec3
  color2.Vec3
  
  color1\x = 1.0
  color1\y = 1.0
  color1\z = 1.0
  
  color2\x = 0.5
  color2\y = 0.7
  color2\z = 1.0
  
  unit_direction.Vec3
    
  unit_direction\x = unit_vector_y(*rr)
  a1.f = 0.5 * (unit_direction\x + 1.0) 
  x.f =  (1.0 - a1) * color1\x + a1 * color2\x 

  unit_direction\y = unit_vector_y(*rr)
  a2.f = 0.5 * (unit_direction\y + 1.0)
  y.f =  (1.0 - a2) * color1\y + a2 * color2\y
 
  unit_direction\z = unit_vector_y(*rr)
  a3.f = 0.5 * (unit_direction\z + 1.0)
  z.f =  (1.0 - a3) * color1\z + a3 * color2\z
  
  If axe = 1
    ProcedureReturn x
  EndIf
  
  If axe = 2
    ProcedureReturn y
  EndIf
  
  If axe = 3
    ProcedureReturn z
  EndIf
   
EndProcedure  
  
; Procedure.f hit_sphere(*posx.Vec3, radius.f, *vx.Ray)
;   oc.Vec3
;   oc\x = *vx\orig\x - *posx\x
;   oc\y = *vx\orig\y - *posx\y
;   oc\z = *vx\orig\z - *posx\z
;   a.f = dot(*vx\dir, *vx\dir)
;   b.f = 2.0 * dot(oc,*vx\dir)
;   c.f = dot(oc,oc) - radius*radius
;   
;   discriminant.f = b*b - 4*a*c
;   
;   If discriminant < 0
;     ProcedureReturn -1.0
;   Else
;     dis.f = (-b - Sqr(discriminant) ) / (2.0*a)
;     ProcedureReturn dis
;    
;   EndIf
;   
; 
; EndProcedure

Procedure set_normal(*vx.Ray, Array r.hit_record(1), num)
  front_face.f = dotN(*vx\dir, r(), num)
  
  If front_face < 0.0
    r(num)\normal\x = r(num)\normal\x 
    r(num)\normal\y = r(num)\normal\y 
    r(num)\normal\z = r(num)\normal\z
  Else
    r(num)\normal\x = -r(num)\normal\x 
    r(num)\normal\y = -r(num)\normal\y 
    r(num)\normal\z = -r(num)\normal\z
  EndIf
  
  ;Debug r(num)\normal\x
  
EndProcedure


Procedure.f hit(Array s.Sphere(1), *vx.Ray, min.f, max.f, Array r.hit_record(1), num)
  oc.Vec3
  root.f = 0.0
  hit_bool.f = 0.0
  oc\x = *vx\orig\x - s(num)\center\x
  oc\y = *vx\orig\y - s(num)\center\y
  oc\z = *vx\orig\z - s(num)\center\z
  a.f = dot(*vx\dir, *vx\dir)
  b.f = dot(oc,*vx\dir)
  c.f = dot(oc,oc) - s(num)\radius * s(num)\radius
  
  discriminant.f = b*b - a*c
  
  ;Debug 
  
  If discriminant < 0.0
    ProcedureReturn 0.0
  EndIf

  
    root = (-b - Sqr(discriminant)) / (a)    
    
    If (root <= min) Or ( max <= root)
      root = (-b + Sqr(discriminant)) / (a)
      If (root <= min) Or (max <= root)
        ProcedureReturn 0.0
      EndIf
    EndIf
     
    
    
    r(num)\t = root
    r(num)\p\x = At(*vx, r(num)\t, 1)
    r(num)\p\y = At(*vx, r(num)\t, 2)
    r(num)\p\z = At(*vx, r(num)\t, 3)
    
    r(num)\normal\x = (r(num)\p\x - s(num)\center\x) / s(num)\radius
    r(num)\normal\y = (r(num)\p\y - s(num)\center\y) / s(num)\radius
    r(num)\normal\z = (r(num)\p\z - s(num)\center\z) / s(num)\radius
    
    set_normal(*vx, r(), num)    
    
    ;Debug r(num)\normal\x
    
    ProcedureReturn 1.0
  

EndProcedure

Procedure.f hittable_list(Array s.Sphere(1), *vx.Ray, ray_min.f, ray_max.f, Array r.hit_record(1))
  Shared N
  Dim temp_rec.hit_record(N)
  hit_anything.f = 0.0
  closest_so_far.f = ray_max
  
  For i = 0 To N-1
    If hit(s(), *vx, ray_min, closest_so_far, r(), i)
      hit_anything = 1.0
      closest_so_far = r(i)\t
      ;Debug r(i)\normal\x
    EndIf
  Next  
  
  
  
  ProcedureReturn hit_anything
  
EndProcedure


aspect_ratio.f = 16.0 / 9.0
image_width = 800

image_height = Int(image_width / aspect_ratio)

If image_height < 1
  image_height = 1
Else
  image_height = image_height
EndIf

Procedure render()
  
  Shared A_sph.Sphere()  
  Shared A_hit.hit_record()
  
Shared image_width
Shared image_height

focal_length.f = 1.0
viewport_height.f = 2.0

i_w.f = image_width
i_h.f = image_height
viewport_width.f = viewport_height * (i_w/i_h)

point3.Vec3

point3\x = 0
point3\y = 0
point3\z = 0

ray_direction.Vec3

ray_direction\x = 0
ray_direction\y = 0
ray_direction\z = 0

viewport_u.Vec3

viewport_u\x = viewport_width
viewport_u\y = 0
viewport_u\z = 0

viewport_v.Vec3

viewport_v\x = 0
viewport_v\y = -viewport_height
viewport_v\z = 0

pixel_delta_u.Vec3

pixel_delta_u\x = viewport_u\x / i_w
pixel_delta_u\y = viewport_u\y / i_w
pixel_delta_u\z = viewport_u\z / i_w

;Debug pixel_delta_u\x

pixel_delta_v.Vec3

pixel_delta_v\x = viewport_v\x / i_h
pixel_delta_v\y = viewport_v\y / i_h
pixel_delta_v\z = viewport_v\z / i_h

;Debug pixel_delta_v\y

viewport_upper_left.Vec3

v_f.Vec3
v_f\x = 0.0
v_f\y = 0.0
v_f\z = focal_length

viewport_upper_left\x = point3\x - v_f\x - viewport_u\x / 2 - viewport_v\x / 2
viewport_upper_left\y = point3\y - v_f\y - viewport_u\y / 2 - viewport_v\y / 2
viewport_upper_left\z = point3\z - v_f\z - viewport_u\z / 2 - viewport_v\z / 2

;Debug viewport_u\x / 2 
;Debug viewport_upper_left\x

pixel_100_loc.Vec3

pixel_100_loc\x = viewport_upper_left\x + 0.5 * (pixel_delta_u\x + pixel_delta_v\x)
pixel_100_loc\y = viewport_upper_left\y + 0.5 * (pixel_delta_u\y + pixel_delta_v\y)
pixel_100_loc\z = viewport_upper_left\z + 0.5 * (pixel_delta_u\z + pixel_delta_v\z)


If StartDrawing(ScreenOutput())

For j = 0 To image_height-1
    For i = 0 To image_width-1
      
      ii.f = i
      jj.f = j
      
      pixel_center.Vec3
      
      Define.Vec3 pixel_color
      
      pixel_center\x = pixel_100_loc\x + (ii * pixel_delta_u\x) + (jj * pixel_delta_v\x)
      pixel_center\y = pixel_100_loc\y + (ii * pixel_delta_u\y) + (jj * pixel_delta_v\y)
      pixel_center\z = pixel_100_loc\z + (ii * pixel_delta_u\z) + (jj * pixel_delta_v\z)
      
      ;Debug pixel_center\x
      
      ray_direction\x = pixel_center\x - point3\x
      ray_direction\y = pixel_center\y - point3\y
      ray_direction\z = pixel_center\z - point3\z
      
      ;Debug ray_direction\x
      
      Define.Ray r
      
      r\orig = point3
      r\dir = ray_direction
      
      Define.Ray myray
      
      myray\orig = point3
      myray\dir = ray_direction
      
      p_s.Vec3
      
      
      
      p_s\x = 0.0 
      
      p_s\y = 0.0
      p_s\z = -1.0
      
      vv.Vec3
      
      vv\x = 0
      vv\y = 0
      vv\z = -1
      
     
      
      ; t.f = hit_sphere(p_s, 0.5, r)
      
      init_sphere()
      init_zero_hit_record()
      
      t.f = hittable_list(A_sph(), r, 0.0, Infinity(), A_hit())  
      
     ; Debug t
      
      ray_direction\x =  At(r,t,1) - p_s\x
      ray_direction\y =  At(r,t,2) - p_s\y
      ray_direction\z =  At(r,t,3) - p_s\z
      
      Define.Ray r_n
      
      r_n\orig = point3
      r_n\dir = ray_direction
      
     ;Debug t
      
      Debug ray_color_hit(A_hit(),1)
      
   ;Debug Int(255.999 * ray_color_n(r_n,1))*2
       If t > 0.0
        Plot(i, j, RGB(Int(255.999 * ray_color_hit(A_hit(),1)), Int(255.999 * ray_color_hit(A_hit(),2)), Int(255.999 * ray_color_hit(A_hit(),3)*0.2)*255))
      Else
        Plot(i, j, RGB(Int(255.999 * ray_color(r,1)),Int(255.999 * ray_color(r,2)),Int(255.999* ray_color(r,3))))
      EndIf
     
      Next
    Next
    
EndIf
  
StopDrawing() 

EndProcedure



InitSprite()
 
 OpenWindow(0, 0, 0, image_width, image_height, "Inspired from Raytracing in One Weekend", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
 OpenWindowedScreen(WindowID(0), 0, 0, image_width, image_height)
  
  ClearScreen(RGB(0,0,0))
  
  
    render()
    
 Repeat
   Event = WindowEvent()
 Until  Event = #PB_Event_CloseWindow
   
 End 
If you found what is this issue I will be highly appreciated by your help :)
threedslider
Enthusiast
Enthusiast
Posts: 397
Joined: Sat Feb 12, 2022 7:15 pm

Re: Raytracing in One Weekend

Post by threedslider »

Ok ! Fixed this issue but I have re-doing a quirks as code :mrgreen:

Nice it works now :)

Here the code as usual :

Code: Select all

;
; Inspired from Ray Tracing in One Weekend : 
; https://raytracing.github.io/books/RayTracingInOneWeekend.html
;
; Writed and adapted in Purebasic by threedslider
;

N.i = 2

iter.i = 0

; Vector 
Structure Vec3
  x.f
  y.f
  z.f
EndStructure

; Ray
Structure Ray
  orig.Vec3
  dir.Vec3
EndStructure

; Color
Structure Color
  r.f
  g.f
  b.f
EndStructure


;Sphere
Structure Sphere
  center.Vec3
  radius.f
  material.Color
EndStructure

;hit record
Structure hit_record
  p.Vec3
  normal.Vec3
  t.f
EndStructure

Dim A_sph.Sphere(N)
Dim A_hit.hit_record(N)

Procedure init_zero_hit_record()
  Shared A_hit.hit_record()
  
  For i=0 To N-1
    A_hit(i)\t = 0.0
    A_hit(i)\p\x = 0.0
    A_hit(i)\p\y = 0.0
    A_hit(i)\p\z = 0.0
    A_hit(i)\normal\x = 0.0
    A_hit(i)\normal\y = 0.0
    A_hit(i)\normal\z = 0.0
  Next
EndProcedure

Procedure init_sphere()
  Shared A_sph.Sphere()  
 
    A_sph(0)\center\x = 0.0
    A_sph(0)\center\y = 0.0
    A_sph(0)\center\z = -1.0
    A_sph(0)\radius = 0.5
    
    A_sph(1)\center\x = 0.0
    A_sph(1)\center\y = -100.0
    A_sph(1)\center\z = -1.0
    A_sph(1)\radius = 100.0
    A_sph(1)\material\r = 0.0
    A_sph(1)\material\g = 1.0
    A_sph(1)\material\b = 0.0
    
    
EndProcedure

Procedure.f dot(*v1.Vec3, *v2.Vec3)
  result.f = *v1\x * *v2\x + *v1\y * *v2\y + *v1\z * *v2\z
  
  ProcedureReturn result
EndProcedure

Procedure.f dotN(*v1.Vec3, Array r.hit_record(1), num)
  result.f = *v1\x * r(num)\normal\x + *v1\y * r(num)\normal\y + *v1\z * r(num)\normal\z 
  
  ProcedureReturn result
EndProcedure

Procedure.f v_length(*v.Ray)
  
  result.f = Sqr(*v\dir\x * *v\dir\x + *v\dir\y * *v\dir\y + *v\dir\z * *v\dir\z)
  
  ;Debug result
  
  ProcedureReturn result
EndProcedure

Procedure.f At(*rr.Ray, t.f, axe)
  
  x.f = *rr\orig\x + t * *rr\dir\x
  y.f = *rr\orig\y + t * *rr\dir\y
  z.f = *rr\orig\z + t * *rr\dir\z
  
  If axe = 1
    ProcedureReturn x
  EndIf
  
  If axe = 2
    ProcedureReturn y
  EndIf
  
  If axe = 3
    ProcedureReturn z
  EndIf
EndProcedure

Procedure.f unit_vector_y(*vy.Ray)
    
  len.f = v_length(*vy) 
  
  y.f = 0
  
  If Not len = 0 ;And Not len < 0
    y = *vy\dir\y / len
  EndIf
  
  
  ;Debug vv
  
  ProcedureReturn y
EndProcedure

Procedure.f unit_vector_normal(*rr.Ray, axe)
    
  len.f = Sqr(*rr\dir\x * *rr\dir\x + *rr\dir\y * *rr\dir\y + *rr\dir\z  * *rr\dir\z )
  
  xx.f = 0
  yy.f = 0
  zz.f = 0
  
   If Not len = 0 
    xx = *rr\dir\x / len
  EndIf
  
  If Not len = 0 
    yy = *rr\dir\y / len
  EndIf
  
   If Not len = 0 
     zz = *rr\dir\z  / len
     If axe = 3
      ProcedureReturn zz
    EndIf
  EndIf
  
  If axe = 1
    ProcedureReturn xx
  EndIf
  
  If axe = 2
    ProcedureReturn yy
  EndIf
  
EndProcedure

Procedure.f ray_color_hit(Array r.hit_record(1), axe, num)
  Shared N
    
;For i=0 To N-1

  x.f =  0.5 * ( r(num)\normal\x + 1.0 )

  y.f =  0.5 * ( r(num)\normal\y + 1.0 )
 
  z.f =  0.5 * ( r(num)\normal\z + 1.0 )
  
  
  If axe = 1 
    ProcedureReturn x 
  EndIf
  
  If axe = 2 
    ProcedureReturn y
  EndIf
  
  If axe = 3 
    ProcedureReturn z
  EndIf
;Next

   
EndProcedure

Procedure.f ray_color_hit_mat(Array s.sphere(1), axe)
  Shared N
    
;For i=0 To N-1

  x.f =  ( s(1)\material\r )

  y.f =  ( s(1)\material\g )
 
  z.f =  ( s(1)\material\b )
  
  
  If axe = 1 
    ProcedureReturn x 
  EndIf
  
  If axe = 2 
    ProcedureReturn y
  EndIf
  
  If axe = 3 
    ProcedureReturn z
  EndIf
;Next

   
EndProcedure

Procedure.f ray_color_n(*rr.Ray, axe)
  Shared p_s.Vec3

  x.f =  0.5 * ((unit_vector_normal(*rr,1) + 1.0) )

  y.f =  0.5 * ((unit_vector_normal(*rr,2) + 1.0) )
 
  z.f =  0.5 * ((unit_vector_normal(*rr,3) + 1.0) )
  
  If axe = 1
    ProcedureReturn x
  EndIf
  
  If axe = 2
    ProcedureReturn y
  EndIf
  
  If axe = 3
    ProcedureReturn z
  EndIf
   
EndProcedure

Procedure.f ray_color(*rr.Ray, axe)
  
  color1.Vec3
  color2.Vec3
  
  color1\x = 1.0
  color1\y = 1.0
  color1\z = 1.0
  
  color2\x = 0.5
  color2\y = 0.7
  color2\z = 1.0
  
  unit_direction.Vec3
    
  unit_direction\x = unit_vector_y(*rr)
  a1.f = 0.5 * (unit_direction\x + 1.0) 
  x.f =  (1.0 - a1) * color1\x + a1 * color2\x 

  unit_direction\y = unit_vector_y(*rr)
  a2.f = 0.5 * (unit_direction\y + 1.0)
  y.f =  (1.0 - a2) * color1\y + a2 * color2\y
 
  unit_direction\z = unit_vector_y(*rr)
  a3.f = 0.5 * (unit_direction\z + 1.0)
  z.f =  (1.0 - a3) * color1\z + a3 * color2\z
  
  If axe = 1
    ProcedureReturn x
  EndIf
  
  If axe = 2
    ProcedureReturn y
  EndIf
  
  If axe = 3
    ProcedureReturn z
  EndIf
   
EndProcedure  
  
; Procedure.f hit_sphere(*posx.Vec3, radius.f, *vx.Ray)
;   oc.Vec3
;   oc\x = *vx\orig\x - *posx\x
;   oc\y = *vx\orig\y - *posx\y
;   oc\z = *vx\orig\z - *posx\z
;   a.f = dot(*vx\dir, *vx\dir)
;   b.f = 2.0 * dot(oc,*vx\dir)
;   c.f = dot(oc,oc) - radius*radius
;   
;   discriminant.f = b*b - 4*a*c
;   
;   If discriminant < 0
;     ProcedureReturn -1.0
;   Else
;     dis.f = (-b - Sqr(discriminant) ) / (2.0*a)
;     ProcedureReturn dis
;    
;   EndIf
;   
; 
; EndProcedure

Procedure set_normal(*vx.Ray, Array r.hit_record(1), num)
  front_face.f = dotN(*vx\dir, r(), num)
  
  If front_face < 0.0
    r(num)\normal\x = r(num)\normal\x 
    r(num)\normal\y = r(num)\normal\y 
    r(num)\normal\z = r(num)\normal\z
  Else
    r(num)\normal\x = -r(num)\normal\x 
    r(num)\normal\y = -r(num)\normal\y 
    r(num)\normal\z = -r(num)\normal\z
  EndIf
  
  ;Debug r(num)\normal\x
  
EndProcedure


Procedure.f hit(Array s.Sphere(1), *vx.Ray, min.f, max.f, Array r.hit_record(1), num)
  oc.Vec3
  root.f = 0.0
  hit_bool.f = 0.0
  oc\x = *vx\orig\x - s(num)\center\x
  oc\y = *vx\orig\y - s(num)\center\y
  oc\z = *vx\orig\z - s(num)\center\z
  a.f = dot(*vx\dir, *vx\dir)
  b.f = dot(oc,*vx\dir)
  c.f = dot(oc,oc) - s(num)\radius * s(num)\radius
  
  discriminant.f = b*b - a*c
  
  ;Debug 
  
  If discriminant < 0.0
    ProcedureReturn 0.0
  EndIf

  
    root = (-b - Sqr(discriminant)) / (a)    
    
    If (root <= min) Or ( max <= root)
      root = (-b + Sqr(discriminant)) / (a)
      If (root <= min) Or (max <= root)
        ProcedureReturn 0.0
      EndIf
    EndIf
     
    
    
    r(num)\t = root
    r(num)\p\x = At(*vx, r(num)\t, 1)
    r(num)\p\y = At(*vx, r(num)\t, 2)
    r(num)\p\z = At(*vx, r(num)\t, 3)
    
    r(num)\normal\x = (r(num)\p\x - s(num)\center\x) / s(num)\radius
    r(num)\normal\y = (r(num)\p\y - s(num)\center\y) / s(num)\radius
    r(num)\normal\z = (r(num)\p\z - s(num)\center\z) / s(num)\radius
    
    set_normal(*vx, r(), num)    
    
    ;Debug r(num)\normal\x
    
    ProcedureReturn 1.0
  

EndProcedure

Procedure.f hittable_list(Array s.Sphere(1), *vx.Ray, ray_min.f, ray_max.f, Array r.hit_record(1), iter)
  Shared N
  Dim temp_rec.hit_record(N)
  hit_anything.f = 0.0
  closest_so_far.f = ray_max
  
  For i = 0 To iter
    If hit(s(), *vx, ray_min, closest_so_far, r(), i)
      hit_anything = 1.0
      closest_so_far = r(i)\t     
    EndIf
  Next  
  
  
  
  ProcedureReturn hit_anything
  
EndProcedure


aspect_ratio.f = 16.0 / 9.0
image_width = 800

image_height = Int(image_width / aspect_ratio)

If image_height < 1
  image_height = 1
Else
  image_height = image_height
EndIf

Procedure render()
  Shared N
  
  Shared A_sph.Sphere()  
  Shared A_hit.hit_record()
  
Shared image_width
Shared image_height

focal_length.f = 1.0
viewport_height.f = 2.0

i_w.f = image_width
i_h.f = image_height
viewport_width.f = viewport_height * (i_w/i_h)

point3.Vec3

point3\x = 0
point3\y = 0
point3\z = 0

ray_direction.Vec3

ray_direction\x = 0
ray_direction\y = 0
ray_direction\z = 0

viewport_u.Vec3

viewport_u\x = viewport_width
viewport_u\y = 0
viewport_u\z = 0

viewport_v.Vec3

viewport_v\x = 0
viewport_v\y = -viewport_height
viewport_v\z = 0

pixel_delta_u.Vec3

pixel_delta_u\x = viewport_u\x / i_w
pixel_delta_u\y = viewport_u\y / i_w
pixel_delta_u\z = viewport_u\z / i_w

;Debug pixel_delta_u\x

pixel_delta_v.Vec3

pixel_delta_v\x = viewport_v\x / i_h
pixel_delta_v\y = viewport_v\y / i_h
pixel_delta_v\z = viewport_v\z / i_h

;Debug pixel_delta_v\y

viewport_upper_left.Vec3

v_f.Vec3
v_f\x = 0.0
v_f\y = 0.0
v_f\z = focal_length

viewport_upper_left\x = point3\x - v_f\x - viewport_u\x / 2 - viewport_v\x / 2
viewport_upper_left\y = point3\y - v_f\y - viewport_u\y / 2 - viewport_v\y / 2
viewport_upper_left\z = point3\z - v_f\z - viewport_u\z / 2 - viewport_v\z / 2

;Debug viewport_u\x / 2 
;Debug viewport_upper_left\x

pixel_100_loc.Vec3

pixel_100_loc\x = viewport_upper_left\x + 0.5 * (pixel_delta_u\x + pixel_delta_v\x)
pixel_100_loc\y = viewport_upper_left\y + 0.5 * (pixel_delta_u\y + pixel_delta_v\y)
pixel_100_loc\z = viewport_upper_left\z + 0.5 * (pixel_delta_u\z + pixel_delta_v\z)


If StartDrawing(ScreenOutput())

For j = 0 To image_height-1
    For i = 0 To image_width-1
      
      ii.f = i
      jj.f = j
      
      pixel_center.Vec3
      
      Define.Vec3 pixel_color
      
      pixel_center\x = pixel_100_loc\x + (ii * pixel_delta_u\x) + (jj * pixel_delta_v\x)
      pixel_center\y = pixel_100_loc\y + (ii * pixel_delta_u\y) + (jj * pixel_delta_v\y)
      pixel_center\z = pixel_100_loc\z + (ii * pixel_delta_u\z) + (jj * pixel_delta_v\z)
      
      ;Debug pixel_center\x
      
      ray_direction\x = pixel_center\x - point3\x
      ray_direction\y = pixel_center\y - point3\y
      ray_direction\z = pixel_center\z - point3\z
      
      ;Debug ray_direction\x
      
      Define.Ray r
      
      r\orig = point3
      r\dir = ray_direction
      
      Define.Ray myray
      
      myray\orig = point3
      myray\dir = ray_direction
      
      p_s.Vec3
      
      
      
      p_s\x = 0.0 
      
      p_s\y = 0.0
      p_s\z = -1.0
      
      vv.Vec3
      
      vv\x = 0
      vv\y = 0
      vv\z = -1
      
     
      
      ; t.f = hit_sphere(p_s, 0.5, r)
      
      init_sphere()
      init_zero_hit_record()
      
      Dim t.f(2)
      
      For Next_to = 0 To N-1
      t(Next_to)  = hittable_list(A_sph(), r, 0.0, Infinity(), A_hit(),Next_to)  
      Next
      
     ; Debug t
      
      ray_direction\x =  At(r,t,1) - p_s\x
      ray_direction\y =  At(r,t,2) - p_s\y
      ray_direction\z =  At(r,t,3) - p_s\z
      
      Define.Ray r_n
      
      r_n\orig = point3
      r_n\dir = ray_direction
      
     ;Debug t
      
      Debug ray_color_hit(A_hit(),1)
      
   ;Debug Int(255.999 * ray_color_n(r_n,1))*2
      If t(0) > 0.0
        
          Plot(i, j, RGB(Int(255.999 * ray_color_hit(A_hit(),1,iter)), Int(255.999 * ray_color_hit(A_hit(),2,iter)), Int(255.999 * ray_color_hit(A_hit(),3,iter))))
        ElseIf t(1) > 0.0
      
          Plot(i, j, RGB(Int(255.999 * ray_color_hit(A_hit(),1,1)), Int(255.999 * ray_color_hit(A_hit(),2,1)), Int(255.999 * ray_color_hit(A_hit(),3,1))))
      ;EndIf
       
      Else
        Plot(i, j, RGB(Int(255.999 * ray_color(r,1)),Int(255.999 * ray_color(r,2)),Int(255.999* ray_color(r,3))))
      EndIf
     
      Next
    Next
    
EndIf
  
StopDrawing() 

EndProcedure



InitSprite()
 
 OpenWindow(0, 0, 0, image_width, image_height, "Inspired from Raytracing in One Weekend", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
 OpenWindowedScreen(WindowID(0), 0, 0, image_width, image_height)
  
  ClearScreen(RGB(0,0,0))
  
  
    render()
    
 Repeat
   Event = WindowEvent()
 Until  Event = #PB_Event_CloseWindow
   
 End 
threedslider
Enthusiast
Enthusiast
Posts: 397
Joined: Sat Feb 12, 2022 7:15 pm

Re: Raytracing in One Weekend

Post by threedslider »

Heya ! Come back ! :)

After a break I hope to continue this work for all your pleasure ;) I am reworking a little my source code so wait and see this coming new feature !

Thanks

Happy coding
threedslider
Enthusiast
Enthusiast
Posts: 397
Joined: Sat Feb 12, 2022 7:15 pm

Re: Raytracing in One Weekend

Post by threedslider »

Hi,

Ok, I was talking for my loop thread here : https://www.purebasic.fr/english/viewtopic.php?t=84468 and here is my code for loop to render multiple object as correctly but no ! It is not working well thought :? See here my dirty code :

Code: Select all

;
; Inspired from Ray Tracing in One Weekend : 
; https://raytracing.github.io/books/RayTracingInOneWeekend.html
;
; Writed and adapted in Purebasic by threedslider
;

N.i = 2

iter.i = 0

; Vector 
Structure Vec3
  x.f
  y.f
  z.f
EndStructure

; Ray
Structure Ray
  orig.Vec3
  dir.Vec3
EndStructure

; Color
Structure Color
  r.f
  g.f
  b.f
EndStructure


;Sphere
Structure Sphere
  center.Vec3
  radius.f
  material.Color
EndStructure

;hit record
Structure hit_record
  p.Vec3
  normal.Vec3
  t.f
EndStructure

Dim A_sph.Sphere(N)
Dim A_hit.hit_record(N)

Procedure init_zero_hit_record()
  Shared A_hit.hit_record()
  
  For i=0 To N-1
    A_hit(i)\t = 0.0
    A_hit(i)\p\x = 0.0
    A_hit(i)\p\y = 0.0
    A_hit(i)\p\z = 0.0
    A_hit(i)\normal\x = 0.0
    A_hit(i)\normal\y = 0.0
    A_hit(i)\normal\z = 0.0
  Next
EndProcedure

Procedure init_sphere()
  Shared A_sph.Sphere()  
 
    A_sph(0)\center\x = 0.0
    A_sph(0)\center\y = 0.0
    A_sph(0)\center\z = -1.0
    A_sph(0)\radius = 0.5
    
    A_sph(1)\center\x = -1.
    A_sph(1)\center\y = 0.0
    A_sph(1)\center\z = -1.0
    A_sph(1)\radius = 0.15
    A_sph(1)\material\r = 0.0
    A_sph(1)\material\g = 1.0
    A_sph(1)\material\b = 0.0
    
    A_sph(2)\center\x = 0.0
    A_sph(2)\center\y = -100.0
    A_sph(2)\center\z = -1.0
    A_sph(2)\radius = 100.0
    A_sph(2)\material\r = 0.0
    A_sph(2)\material\g = 1.0
    A_sph(2)\material\b = 0.0
    
    
EndProcedure

Procedure.f dot(*v1.Vec3, *v2.Vec3)
  result.f = *v1\x * *v2\x + *v1\y * *v2\y + *v1\z * *v2\z
  
  ProcedureReturn result
EndProcedure

Procedure.f dotN(*v1.Vec3, Array r.hit_record(1), num)
  result.f = *v1\x * r(num)\normal\x + *v1\y * r(num)\normal\y + *v1\z * r(num)\normal\z 
  
  ProcedureReturn result
EndProcedure

Procedure.f v_length(*v.Ray)
  
  result.f = Sqr(*v\dir\x * *v\dir\x + *v\dir\y * *v\dir\y + *v\dir\z * *v\dir\z)
  
  ;Debug result
  
  ProcedureReturn result
EndProcedure

Procedure.f At(*rr.Ray, t.f, axe)
  
  x.f = *rr\orig\x + t * *rr\dir\x
  y.f = *rr\orig\y + t * *rr\dir\y
  z.f = *rr\orig\z + t * *rr\dir\z
  
  If axe = 1
    ProcedureReturn x
  EndIf
  
  If axe = 2
    ProcedureReturn y
  EndIf
  
  If axe = 3
    ProcedureReturn z
  EndIf
EndProcedure

Procedure.f unit_vector_y(*vy.Ray)
    
  len.f = v_length(*vy) 
  
  y.f = 0
  
  If Not len = 0 ;And Not len < 0
    y = *vy\dir\y / len
  EndIf
  
  
  ;Debug vv
  
  ProcedureReturn y
EndProcedure

Procedure.f unit_vector_normal(*rr.Ray, axe)
    
  len.f = Sqr(*rr\dir\x * *rr\dir\x + *rr\dir\y * *rr\dir\y + *rr\dir\z  * *rr\dir\z )
  
  xx.f = 0
  yy.f = 0
  zz.f = 0
  
   If Not len = 0 
    xx = *rr\dir\x / len
  EndIf
  
  If Not len = 0 
    yy = *rr\dir\y / len
  EndIf
  
   If Not len = 0 
     zz = *rr\dir\z  / len
     If axe = 3
      ProcedureReturn zz
    EndIf
  EndIf
  
  If axe = 1
    ProcedureReturn xx
  EndIf
  
  If axe = 2
    ProcedureReturn yy
  EndIf
  
EndProcedure

Procedure.f ray_color_hit(Array r.hit_record(1), axe, num)
  Shared N
    
;For i=0 To N-1

  x.f =  0.5 * ( r(num)\normal\x + 1.0 )

  y.f =  0.5 * ( r(num)\normal\y + 1.0 )
 
  z.f =  0.5 * ( r(num)\normal\z + 1.0 )
  
  
  If axe = 1 
    ProcedureReturn x 
  EndIf
  
  If axe = 2 
    ProcedureReturn y
  EndIf
  
  If axe = 3 
    ProcedureReturn z
  EndIf
;Next

   
EndProcedure

Procedure.f ray_color_hit_mat(Array s.sphere(1), axe)
  Shared N
    
;For i=0 To N-1

  x.f =  ( s(1)\material\r )

  y.f =  ( s(1)\material\g )
 
  z.f =  ( s(1)\material\b )
  
  
  If axe = 1 
    ProcedureReturn x 
  EndIf
  
  If axe = 2 
    ProcedureReturn y
  EndIf
  
  If axe = 3 
    ProcedureReturn z
  EndIf
;Next

   
EndProcedure

Procedure.f ray_color_n(*rr.Ray, axe)
  Shared p_s.Vec3

  x.f =  0.5 * ((unit_vector_normal(*rr,1) + 1.0) )

  y.f =  0.5 * ((unit_vector_normal(*rr,2) + 1.0) )
 
  z.f =  0.5 * ((unit_vector_normal(*rr,3) + 1.0) )
  
  If axe = 1
    ProcedureReturn x
  EndIf
  
  If axe = 2
    ProcedureReturn y
  EndIf
  
  If axe = 3
    ProcedureReturn z
  EndIf
   
EndProcedure

Procedure.f ray_color(*rr.Ray, axe)
  
  color1.Vec3
  color2.Vec3
  
  color1\x = 1.0
  color1\y = 1.0
  color1\z = 1.0
  
  color2\x = 0.5
  color2\y = 0.7
  color2\z = 1.0
  
  unit_direction.Vec3
    
  unit_direction\x = unit_vector_y(*rr)
  a1.f = 0.5 * (unit_direction\x + 1.0) 
  x.f =  (1.0 - a1) * color1\x + a1 * color2\x 

  unit_direction\y = unit_vector_y(*rr)
  a2.f = 0.5 * (unit_direction\y + 1.0)
  y.f =  (1.0 - a2) * color1\y + a2 * color2\y
 
  unit_direction\z = unit_vector_y(*rr)
  a3.f = 0.5 * (unit_direction\z + 1.0)
  z.f =  (1.0 - a3) * color1\z + a3 * color2\z
  
  If axe = 1
    ProcedureReturn x
  EndIf
  
  If axe = 2
    ProcedureReturn y
  EndIf
  
  If axe = 3
    ProcedureReturn z
  EndIf
   
EndProcedure  
  
; Procedure.f hit_sphere(*posx.Vec3, radius.f, *vx.Ray)
;   oc.Vec3
;   oc\x = *vx\orig\x - *posx\x
;   oc\y = *vx\orig\y - *posx\y
;   oc\z = *vx\orig\z - *posx\z
;   a.f = dot(*vx\dir, *vx\dir)
;   b.f = 2.0 * dot(oc,*vx\dir)
;   c.f = dot(oc,oc) - radius*radius
;   
;   discriminant.f = b*b - 4*a*c
;   
;   If discriminant < 0
;     ProcedureReturn -1.0
;   Else
;     dis.f = (-b - Sqr(discriminant) ) / (2.0*a)
;     ProcedureReturn dis
;    
;   EndIf
;   
; 
; EndProcedure

Procedure set_normal(*vx.Ray, Array r.hit_record(1), num)
  front_face.f = dotN(*vx\dir, r(), num)
  
  If front_face < 0.0
    r(num)\normal\x = r(num)\normal\x 
    r(num)\normal\y = r(num)\normal\y 
    r(num)\normal\z = r(num)\normal\z
  Else
    r(num)\normal\x = -r(num)\normal\x 
    r(num)\normal\y = -r(num)\normal\y 
    r(num)\normal\z = -r(num)\normal\z
  EndIf
  
  ;Debug r(num)\normal\x
  
EndProcedure


Procedure.f hit(Array s.Sphere(1), *vx.Ray, min.f, max.f, Array r.hit_record(1), num)
  oc.Vec3
  root.f = 0.0
  hit_bool.f = 0.0
  oc\x = *vx\orig\x - s(num)\center\x
  oc\y = *vx\orig\y - s(num)\center\y
  oc\z = *vx\orig\z - s(num)\center\z
  a.f = dot(*vx\dir, *vx\dir)
  b.f = dot(oc,*vx\dir)
  c.f = dot(oc,oc) - s(num)\radius * s(num)\radius
  
  discriminant.f = b*b - a*c
  
  ;Debug 
  
  If discriminant < 0.0
    ProcedureReturn 0.0
  EndIf

  
    root = (-b - Sqr(discriminant)) / (a)    
    
    If (root <= min) Or ( max <= root)
      root = (-b + Sqr(discriminant)) / (a)
      If (root <= min) Or (max <= root)
        ProcedureReturn 0.0
      EndIf
    EndIf
     
    
    
    r(num)\t = root
    r(num)\p\x = At(*vx, r(num)\t, 1)
    r(num)\p\y = At(*vx, r(num)\t, 2)
    r(num)\p\z = At(*vx, r(num)\t, 3)
    
    r(num)\normal\x = (r(num)\p\x - s(num)\center\x) / s(num)\radius
    r(num)\normal\y = (r(num)\p\y - s(num)\center\y) / s(num)\radius
    r(num)\normal\z = (r(num)\p\z - s(num)\center\z) / s(num)\radius
    
    set_normal(*vx, r(), num)    
    
    ;Debug r(num)\normal\x
    
    ProcedureReturn 1.0
  

EndProcedure

Procedure.f hittable_list(Array s.Sphere(1), *vx.Ray, ray_min.f, ray_max.f, Array r.hit_record(1), iter)
  Shared N
  Dim temp_rec.hit_record(N)
  hit_anything.f = 0.0
  closest_so_far.f = ray_max
  
  For i = 0 To iter
    If hit(s(), *vx, ray_min, closest_so_far, r(), i)
      hit_anything = 1.0
      closest_so_far = r(i)\t     
    EndIf
  Next  
  
  
  
  ProcedureReturn hit_anything
  
EndProcedure


aspect_ratio.f = 16.0 / 9.0
image_width = 800

image_height = Int(image_width / aspect_ratio)

If image_height < 1
  image_height = 1
Else
  image_height = image_height
EndIf

Procedure render()
  Shared N
  
  Shared A_sph.Sphere()  
  Shared A_hit.hit_record()
  
Shared image_width
Shared image_height

focal_length.f = 1.0
viewport_height.f = 2.0

i_w.f = image_width
i_h.f = image_height
viewport_width.f = viewport_height * (i_w/i_h)

point3.Vec3

point3\x = 0
point3\y = 0
point3\z = 0

ray_direction.Vec3

ray_direction\x = 0
ray_direction\y = 0
ray_direction\z = 0

viewport_u.Vec3

viewport_u\x = viewport_width
viewport_u\y = 0
viewport_u\z = 0

viewport_v.Vec3

viewport_v\x = 0
viewport_v\y = -viewport_height
viewport_v\z = 0

pixel_delta_u.Vec3

pixel_delta_u\x = viewport_u\x / i_w
pixel_delta_u\y = viewport_u\y / i_w
pixel_delta_u\z = viewport_u\z / i_w

;Debug pixel_delta_u\x

pixel_delta_v.Vec3

pixel_delta_v\x = viewport_v\x / i_h
pixel_delta_v\y = viewport_v\y / i_h
pixel_delta_v\z = viewport_v\z / i_h

;Debug pixel_delta_v\y

viewport_upper_left.Vec3

v_f.Vec3
v_f\x = 0.0
v_f\y = 0.0
v_f\z = focal_length

viewport_upper_left\x = point3\x - v_f\x - viewport_u\x / 2 - viewport_v\x / 2
viewport_upper_left\y = point3\y - v_f\y - viewport_u\y / 2 - viewport_v\y / 2
viewport_upper_left\z = point3\z - v_f\z - viewport_u\z / 2 - viewport_v\z / 2

;Debug viewport_u\x / 2 
;Debug viewport_upper_left\x

pixel_100_loc.Vec3

pixel_100_loc\x = viewport_upper_left\x + 0.5 * (pixel_delta_u\x + pixel_delta_v\x)
pixel_100_loc\y = viewport_upper_left\y + 0.5 * (pixel_delta_u\y + pixel_delta_v\y)
pixel_100_loc\z = viewport_upper_left\z + 0.5 * (pixel_delta_u\z + pixel_delta_v\z)


If StartDrawing(ScreenOutput())

For j = 0 To image_height-1
    For i = 0 To image_width-1
      
      ii.f = i
      jj.f = j
      
      pixel_center.Vec3
      
      Define.Vec3 pixel_color
      
      pixel_center\x = pixel_100_loc\x + (ii * pixel_delta_u\x) + (jj * pixel_delta_v\x)
      pixel_center\y = pixel_100_loc\y + (ii * pixel_delta_u\y) + (jj * pixel_delta_v\y)
      pixel_center\z = pixel_100_loc\z + (ii * pixel_delta_u\z) + (jj * pixel_delta_v\z)
      
      ;Debug pixel_center\x
      
      ray_direction\x = pixel_center\x - point3\x
      ray_direction\y = pixel_center\y - point3\y
      ray_direction\z = pixel_center\z - point3\z
      
      ;Debug ray_direction\x
      
      Define.Ray r
      
      r\orig = point3
      r\dir = ray_direction
      
      Define.Ray myray
      
      myray\orig = point3
      myray\dir = ray_direction
      
      p_s.Vec3
      
      
      
      p_s\x = 0.0 
      
      p_s\y = 0.0
      p_s\z = -1.0
      
      vv.Vec3
      
      vv\x = 0
      vv\y = 0
      vv\z = -1
      
     
      
      ; t.f = hit_sphere(p_s, 0.5, r)
      
      init_sphere()
      init_zero_hit_record()
      
      Dim t.f(2)
      
      For Next_to = 0 To N
      t(Next_to)  = hittable_list(A_sph(), r, 0.0, Infinity(), A_hit(),Next_to)  
      Next
      
     ; Debug t
      
      ray_direction\x =  At(r,t,1) - p_s\x
      ray_direction\y =  At(r,t,2) - p_s\y
      ray_direction\z =  At(r,t,3) - p_s\z
      
      Define.Ray r_n
      
      r_n\orig = point3
      r_n\dir = ray_direction
      
     ;Debug t
      
     ; Debug ray_color_hit(A_hit(),1)
     For o= 0 To 2 
   ;Debug Int(255.999 * ray_color_n(r_n,1))*2
       If t(o) > 0.0
         
        
          Plot(i, j, RGB(Int(255.999 * ray_color_hit(A_hit(),1,o)), Int(255.999 * ray_color_hit(A_hit(),2,o)), Int(255.999 * ray_color_hit(A_hit(),3,o))))
       ; ElseIf t(o) > 0.0
         
         ; Plot(i, j, RGB(Int(255.999 * ray_color_hit(A_hit(),1,o)), Int(255.999 * ray_color_hit(A_hit(),2,o)), Int(255.999 * ray_color_hit(A_hit(),3,o))))
        ;EndIf
        
          
       
      Else
        Plot(i, j, RGB(Int(255.999 * ray_color(r,1)),Int(255.999 * ray_color(r,2)),Int(255.999* ray_color(r,3))))
      EndIf
    Next
    
     
      Next
    Next
    
EndIf
  
StopDrawing() 

EndProcedure



InitSprite()
 
 OpenWindow(0, 0, 0, image_width, image_height, "Inspired from Raytracing in One Weekend", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
 OpenWindowedScreen(WindowID(0), 0, 0, image_width, image_height)
  
  ClearScreen(RGB(0,0,0))
  
  
    render()
    
 Repeat
   Event = WindowEvent()
 Until  Event = #PB_Event_CloseWindow
   
 End 

In line 573 :

Code: Select all

 For o= 0 To 2 
   ;Debug Int(255.999 * ray_color_n(r_n,1))*2
       If t(o) > 0.0
         
        
          Plot(i, j, RGB(Int(255.999 * ray_color_hit(A_hit(),1,o)), Int(255.999 * ray_color_hit(A_hit(),2,o)), Int(255.999 * ray_color_hit(A_hit(),3,o))))
       ; ElseIf t(o) > 0.0
         
         ; Plot(i, j, RGB(Int(255.999 * ray_color_hit(A_hit(),1,o)), Int(255.999 * ray_color_hit(A_hit(),2,o)), Int(255.999 * ray_color_hit(A_hit(),3,o))))
        ;EndIf
        
          
       
      Else
        Plot(i, j, RGB(Int(255.999 * ray_color(r,1)),Int(255.999 * ray_color(r,2)),Int(255.999* ray_color(r,3))))
      EndIf
    Next
the code doesn't work well for rendering, so I want to make the same behavior for "If" and "ElseIf" to loop, how to make this one ?

the previous code work without loop :

Code: Select all

 ;Debug Int(255.999 * ray_color_n(r_n,1))*2
      If t(0) > 0.0
        
          Plot(i, j, RGB(Int(255.999 * ray_color_hit(A_hit(),1,iter)), Int(255.999 * ray_color_hit(A_hit(),2,iter)), Int(255.999 * ray_color_hit(A_hit(),3,iter))))
        ElseIf t(1) > 0.0
      
          Plot(i, j, RGB(Int(255.999 * ray_color_hit(A_hit(),1,1)), Int(255.999 * ray_color_hit(A_hit(),2,1)), Int(255.999 * ray_color_hit(A_hit(),3,1))))
      ;EndIf
       
      Else
        Plot(i, j, RGB(Int(255.999 * ray_color(r,1)),Int(255.999 * ray_color(r,2)),Int(255.999* ray_color(r,3))))
      EndIf
Do you know how to make a behavior in loop for a similar to "If" and "ElseIf" instead of manual hand ?

Thanks
threedslider
Enthusiast
Enthusiast
Posts: 397
Joined: Sat Feb 12, 2022 7:15 pm

Re: Raytracing in One Weekend

Post by threedslider »

Yay ! It works now ! Phew !

My problem was technically no good in coding so I review the system from rendering and now it looks like right :mrgreen:

Now I can work for the next subchapter to Raytracing in one weekend :wink:

See you soon

Happy coding !

Here the code now (better, more shorter than before and less dirty code) :

Code: Select all

;
; Inspired from Ray Tracing in One Weekend : 
; https://raytracing.github.io/books/RayTracingInOneWeekend.html
;
; Writed and adapted in Purebasic by threedslider
;

N.i = 3

; Vector 
Structure Vec3
  x.f
  y.f
  z.f
EndStructure

; Ray
Structure Ray
  orig.Vec3
  dir.Vec3
EndStructure

; Color
Structure Color
  r.f
  g.f
  b.f
EndStructure


;Sphere
Structure Sphere
  center.Vec3
  radius.f
  material.Color
EndStructure

;hit record
Structure hit_record
  p.Vec3
  normal.Vec3
  t.f
EndStructure

Dim pix_co.Vec3(2)

Dim A_sph.Sphere(N)
Dim A_hit.hit_record(N)

Procedure init_zero_hit_record()
  Shared A_hit.hit_record()
  
  For i=0 To N-1
    A_hit(i)\t = 0.0
    A_hit(i)\p\x = 0.0
    A_hit(i)\p\y = 0.0
    A_hit(i)\p\z = 0.0
    A_hit(i)\normal\x = 0.0
    A_hit(i)\normal\y = 0.0
    A_hit(i)\normal\z = 0.0
  Next
EndProcedure

Procedure init_sphere()
  Shared A_sph.Sphere()  
 
    A_sph(0)\center\x = 0.0
    A_sph(0)\center\y = 0.0
    A_sph(0)\center\z = -1.0
    A_sph(0)\radius = 0.5
    
    A_sph(1)\center\x = -1.0
    A_sph(1)\center\y = 0.0
    A_sph(1)\center\z = -1.0
    A_sph(1)\radius = 0.15
    A_sph(1)\material\r = 0.0
    A_sph(1)\material\g = 1.0
    A_sph(1)\material\b = 0.0
    
    A_sph(2)\center\x = 1.0
    A_sph(2)\center\y = 0.0
    A_sph(2)\center\z = -1.0
    A_sph(2)\radius = 0.15
    A_sph(2)\material\r = 0.0
    A_sph(2)\material\g = 1.0
    A_sph(2)\material\b = 0.0
    
    A_sph(3)\center\x = 0.0
    A_sph(3)\center\y = -100.0
    A_sph(3)\center\z = -1.0
    A_sph(3)\radius = 100.0
    A_sph(3)\material\r = 0.0
    A_sph(3)\material\g = 1.0
    A_sph(3)\material\b = 0.0
    
EndProcedure

Procedure.f dot(*v1.Vec3, *v2.Vec3)
  result.f = *v1\x * *v2\x + *v1\y * *v2\y + *v1\z * *v2\z
  
  ProcedureReturn result
EndProcedure

Procedure.f dotN(*v1.Vec3, Array r.hit_record(1), num)
  result.f = *v1\x * r(num)\normal\x + *v1\y * r(num)\normal\y + *v1\z * r(num)\normal\z 
  
  ProcedureReturn result
EndProcedure

Procedure.f v_length(*v.Ray)
  
  result.f = Sqr(*v\dir\x * *v\dir\x + *v\dir\y * *v\dir\y + *v\dir\z * *v\dir\z)
  
  ProcedureReturn result
EndProcedure

Procedure.f At(*rr.Ray, t.f, axe)
  
  x.f = *rr\orig\x + t * *rr\dir\x
  y.f = *rr\orig\y + t * *rr\dir\y
  z.f = *rr\orig\z + t * *rr\dir\z
  
  If axe = 1
    ProcedureReturn x
  EndIf
  
  If axe = 2
    ProcedureReturn y
  EndIf
  
  If axe = 3
    ProcedureReturn z
  EndIf
EndProcedure

Procedure.f unit_vector_y(*vy.Ray)
    
  len.f = v_length(*vy) 
  
  y.f = 0
  
  If Not len = 0 
    y = *vy\dir\y / len
  EndIf
  
  ProcedureReturn y
EndProcedure

Declare.f hittable_list(Array s.Sphere(1), *vx.Ray, ray_min.f, ray_max.f, Array r.hit_record(1), iter)
Declare.f ray_color(*rr.Ray, axe)

Procedure.f ray_color_hit(*vx.Ray, axe, num)
 
  Shared A_sph.Sphere()
  Shared A_hit.hit_record()
  
For mynum = 0 To num
    
If hittable_list(A_sph(), *vx, 0.0, Infinity(), A_hit(), mynum)

  x.f =  0.5 * ( A_hit(mynum)\normal\x + 1.0 )

  y.f =  0.5 * ( A_hit(mynum)\normal\y + 1.0 )
 
  z.f =  0.5 * ( A_hit(mynum)\normal\z + 1.0 )
  
  
  If axe = 1 
    ProcedureReturn x 
  EndIf
  
  If axe = 2 
    ProcedureReturn y
  EndIf
  
  If axe = 3 
    ProcedureReturn z
  EndIf
EndIf

Next
 
 ProcedureReturn ray_color(*vx, axe)
 
EndProcedure

Procedure.f ray_color(*rr.Ray, axe)
  
  color1.Vec3
  color2.Vec3
  
  color1\x = 1.0
  color1\y = 1.0
  color1\z = 1.0
  
  color2\x = 0.5
  color2\y = 0.7
  color2\z = 1.0
  
  unit_direction.Vec3
    
  unit_direction\x = unit_vector_y(*rr)
  a1.f = 0.5 * (unit_direction\x + 1.0) 
  x.f =  (1.0 - a1) * color1\x + a1 * color2\x 

  unit_direction\y = unit_vector_y(*rr)
  a2.f = 0.5 * (unit_direction\y + 1.0)
  y.f =  (1.0 - a2) * color1\y + a2 * color2\y
 
  unit_direction\z = unit_vector_y(*rr)
  a3.f = 0.5 * (unit_direction\z + 1.0)
  z.f =  (1.0 - a3) * color1\z + a3 * color2\z
  
  If axe = 1
    ProcedureReturn x
  EndIf
  
  If axe = 2
    ProcedureReturn y
  EndIf
  
  If axe = 3
    ProcedureReturn z
  EndIf
   
EndProcedure  

Procedure set_normal(*vx.Ray, Array r.hit_record(1), num)
  front_face.f = dotN(*vx\dir, r(), num)
  
  If front_face < 0.0
    r(num)\normal\x = r(num)\normal\x 
    r(num)\normal\y = r(num)\normal\y 
    r(num)\normal\z = r(num)\normal\z
  Else
    r(num)\normal\x = -r(num)\normal\x 
    r(num)\normal\y = -r(num)\normal\y 
    r(num)\normal\z = -r(num)\normal\z
  EndIf

EndProcedure


Procedure.f hit(Array s.Sphere(1), *vx.Ray, min.f, max.f, Array r.hit_record(1), num)
  Shared pix_co.Vec3()
  
  oc.Vec3
  root.f = 0.0
  hit_bool.f = 0.0
  oc\x = *vx\orig\x - s(num)\center\x
  oc\y = *vx\orig\y - s(num)\center\y
  oc\z = *vx\orig\z - s(num)\center\z
  a.f = dot(*vx\dir, *vx\dir)
  b.f = dot(oc,*vx\dir)
  c.f = dot(oc,oc) - s(num)\radius * s(num)\radius
  
  discriminant.f = b*b - a*c
  
  If discriminant < 0.0
    ProcedureReturn 0.0
  EndIf

  
    root = (-b - Sqr(discriminant)) / (a)    
    
    If (root <= min) Or ( max <= root)
      root = (-b + Sqr(discriminant)) / (a)
      If (root <= min) Or (max <= root)
        ProcedureReturn 0.0
      EndIf
    EndIf
     
    r(num)\t = root
    r(num)\p\x = At(*vx, r(num)\t, 1)
    r(num)\p\y = At(*vx, r(num)\t, 2)
    r(num)\p\z = At(*vx, r(num)\t, 3)
    
    r(num)\normal\x = (r(num)\p\x - s(num)\center\x) / s(num)\radius
    r(num)\normal\y = (r(num)\p\y - s(num)\center\y) / s(num)\radius
    r(num)\normal\z = (r(num)\p\z - s(num)\center\z) / s(num)\radius
    
    set_normal(*vx, r(), num)    
        
    ProcedureReturn 1.0
  
EndProcedure

Procedure.f hittable_list(Array s.Sphere(1), *vx.Ray, ray_min.f, ray_max.f, Array r.hit_record(1), iter)
  Dim temp_rec.hit_record(N)
  hit_anything.f = 0.0
  closest_so_far.f = ray_max
  
    If hit(s(), *vx, ray_min, closest_so_far, r(), iter)
      hit_anything = 1.0
      closest_so_far = r(iter)\t     
    EndIf
  
  ProcedureReturn hit_anything
  
EndProcedure


aspect_ratio.f = 16.0 / 9.0
image_width = 800

image_height = Int(image_width / aspect_ratio)

If image_height < 1
  image_height = 1
Else
  image_height = image_height
EndIf

Procedure render()
Shared N
Shared A_sph.Sphere()  
Shared A_hit.hit_record()
  
Shared image_width
Shared image_height

focal_length.f = 1.0
viewport_height.f = 2.0

i_w.f = image_width
i_h.f = image_height
viewport_width.f = viewport_height * (i_w/i_h)

point3.Vec3

point3\x = 0
point3\y = 0
point3\z = 0

ray_direction.Vec3

ray_direction\x = 0
ray_direction\y = 0
ray_direction\z = 0

viewport_u.Vec3

viewport_u\x = viewport_width
viewport_u\y = 0
viewport_u\z = 0

viewport_v.Vec3

viewport_v\x = 0
viewport_v\y = -viewport_height
viewport_v\z = 0

pixel_delta_u.Vec3

pixel_delta_u\x = viewport_u\x / i_w
pixel_delta_u\y = viewport_u\y / i_w
pixel_delta_u\z = viewport_u\z / i_w

pixel_delta_v.Vec3

pixel_delta_v\x = viewport_v\x / i_h
pixel_delta_v\y = viewport_v\y / i_h
pixel_delta_v\z = viewport_v\z / i_h

viewport_upper_left.Vec3

v_f.Vec3
v_f\x = 0.0
v_f\y = 0.0
v_f\z = focal_length

viewport_upper_left\x = point3\x - v_f\x - viewport_u\x / 2 - viewport_v\x / 2
viewport_upper_left\y = point3\y - v_f\y - viewport_u\y / 2 - viewport_v\y / 2
viewport_upper_left\z = point3\z - v_f\z - viewport_u\z / 2 - viewport_v\z / 2

pixel_100_loc.Vec3

pixel_100_loc\x = viewport_upper_left\x + 0.5 * (pixel_delta_u\x + pixel_delta_v\x)
pixel_100_loc\y = viewport_upper_left\y + 0.5 * (pixel_delta_u\y + pixel_delta_v\y)
pixel_100_loc\z = viewport_upper_left\z + 0.5 * (pixel_delta_u\z + pixel_delta_v\z)


If StartDrawing(ScreenOutput())

For j = 0 To image_height-1
    For i = 0 To image_width-1
      
      ii.f = i
      jj.f = j
      
      pixel_center.Vec3
      
      pixel_center\x = pixel_100_loc\x + (ii * pixel_delta_u\x) + (jj * pixel_delta_v\x)
      pixel_center\y = pixel_100_loc\y + (ii * pixel_delta_u\y) + (jj * pixel_delta_v\y)
      pixel_center\z = pixel_100_loc\z + (ii * pixel_delta_u\z) + (jj * pixel_delta_v\z)
      
      ray_direction\x = pixel_center\x - point3\x
      ray_direction\y = pixel_center\y - point3\y
      ray_direction\z = pixel_center\z - point3\z
      
      Define.Ray r
      
      r\orig = point3
      r\dir = ray_direction
      
      init_sphere()
      init_zero_hit_record()
           
      Plot(i, j, RGB(Int(255.999 * ray_color_hit(r,1,3)), Int(255.999 * ray_color_hit(r,2,3)), Int(255.999 * ray_color_hit(r,3,3))))
     
      Next
    Next
    
EndIf
  
StopDrawing() 

EndProcedure


InitSprite()
 
 OpenWindow(0, 0, 0, image_width, image_height, "Inspired from Raytracing in One Weekend", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
 OpenWindowedScreen(WindowID(0), 0, 0, image_width, image_height)
  
  ClearScreen(RGB(0,0,0))
  
  
  render()
    
 Repeat
   Event = WindowEvent()
 Until  Event = #PB_Event_CloseWindow
   
 End 
Thanks
threedslider
Enthusiast
Enthusiast
Posts: 397
Joined: Sat Feb 12, 2022 7:15 pm

Re: Raytracing in One Weekend

Post by threedslider »

New thing in 3D Rendering : Antialiasing !

Now it looks like more better and more smooth for 3d models :mrgreen:

Here is the source code :

Code: Select all

;
; Inspired from Ray Tracing in One Weekend : 
; https://raytracing.github.io/books/RayTracingInOneWeekend.html
;
; Writed and adapted in Purebasic by threedslider
;

N.i = 3

; Vector 
Structure Vec3
  x.f
  y.f
  z.f
EndStructure

; Ray
Structure Ray
  orig.Vec3
  dir.Vec3
EndStructure

; Color
Structure Color
  r.f
  g.f
  b.f
EndStructure


;Sphere
Structure Sphere
  center.Vec3
  radius.f
  material.Color
EndStructure

;hit record
Structure hit_record
  p.Vec3
  normal.Vec3
  t.f
EndStructure

Structure interval
  min.f
  max.f
EndStructure

my_interval.interval

my_interval\min = 0.000
my_interval\max = 0.999

Dim A_sph.Sphere(N)
Dim A_hit.hit_record(N)

Procedure init_zero_hit_record()
  Shared A_hit.hit_record()
  
  For i=0 To N-1
    A_hit(i)\t = 0.0
    A_hit(i)\p\x = 0.0
    A_hit(i)\p\y = 0.0
    A_hit(i)\p\z = 0.0
    A_hit(i)\normal\x = 0.0
    A_hit(i)\normal\y = 0.0
    A_hit(i)\normal\z = 0.0
  Next
EndProcedure

Procedure init_sphere()
  Shared A_sph.Sphere()  
 
    A_sph(0)\center\x = 0.0
    A_sph(0)\center\y = 0.0
    A_sph(0)\center\z = -1.0
    A_sph(0)\radius = 0.5
    
    A_sph(1)\center\x = -1.0
    A_sph(1)\center\y = 0.0
    A_sph(1)\center\z = -1.0
    A_sph(1)\radius = 0.15
    A_sph(1)\material\r = 0.0
    A_sph(1)\material\g = 1.0
    A_sph(1)\material\b = 0.0
    
    A_sph(2)\center\x = 1.0
    A_sph(2)\center\y = 0.0
    A_sph(2)\center\z = -1.0
    A_sph(2)\radius = 0.15
    A_sph(2)\material\r = 0.0
    A_sph(2)\material\g = 1.0
    A_sph(2)\material\b = 0.0
    
    A_sph(3)\center\x = 0.0
    A_sph(3)\center\y = -100.0
    A_sph(3)\center\z = -1.0
    A_sph(3)\radius = 100.0
    A_sph(3)\material\r = 0.0
    A_sph(3)\material\g = 1.0
    A_sph(3)\material\b = 0.0
    
EndProcedure
  
Procedure.f size(*_i.interval)
  r.f = *_i\max - *_i\min
  ProcedureReturn r
EndProcedure

Procedure contains(x.f, *_i.interval)
  ProcedureReturn Bool(*_i\min <= x And x <= *_i\max)
EndProcedure

Procedure surrounds(x.f, *_i.interval)
  ProcedureReturn Bool(*_i\min < x And x < *_i\max)
EndProcedure

Procedure.f clamp(x.f, *_i.interval)
  If(x < *_i\min)
    ProcedureReturn *_i\min
  EndIf
  If(x > *_i\max)
    ProcedureReturn *_i\max
  EndIf
  ProcedureReturn x
EndProcedure


Procedure.f degrees_to_radians(degrees.f) 
  degrees = degrees * #PI / 180.0
  ProcedureReturn degrees
EndProcedure

Procedure.f random_float()   
    r.f = Random(#MAXDWORD) / #MAXDWORD  
    ProcedureReturn r
EndProcedure
    


Procedure.f random_min_max_float(min.f, max.f)     
    ProcedureReturn min + (max-min) * random_float()
EndProcedure

Procedure.f dot(*v1.Vec3, *v2.Vec3)
  result.f = *v1\x * *v2\x + *v1\y * *v2\y + *v1\z * *v2\z
  
  ProcedureReturn result
EndProcedure

Procedure.f dotN(*v1.Vec3, Array r.hit_record(1), num)
  result.f = *v1\x * r(num)\normal\x + *v1\y * r(num)\normal\y + *v1\z * r(num)\normal\z 
  
  ProcedureReturn result
EndProcedure

Procedure.f v_length(*v.Ray)
  
  result.f = Sqr(*v\dir\x * *v\dir\x + *v\dir\y * *v\dir\y + *v\dir\z * *v\dir\z)
  
  ProcedureReturn result
EndProcedure

Procedure.f At(*rr.Ray, t.f, axe)
  
  x.f = *rr\orig\x + t * *rr\dir\x
  y.f = *rr\orig\y + t * *rr\dir\y
  z.f = *rr\orig\z + t * *rr\dir\z
  
  If axe = 1
    ProcedureReturn x
  EndIf
  
  If axe = 2
    ProcedureReturn y
  EndIf
  
  If axe = 3
    ProcedureReturn z
  EndIf
EndProcedure

Procedure.f unit_vector_y(*vy.Ray)
    
  len.f = v_length(*vy) 
  
  y.f = 0
  
  If Not len = 0 
    y = *vy\dir\y / len
  EndIf
  
  ProcedureReturn y
EndProcedure

Declare.f hittable_list(Array s.Sphere(1), *vx.Ray, *ray_t.interval, Array r.hit_record(1), iter)
Declare.f ray_color(*rr.Ray, axe)

Procedure.f ray_color_hit(*vx.Ray, axe, num)
 
  Shared A_sph.Sphere()
  Shared A_hit.hit_record()
  Shared my_interval.interval
  
For mynum = 0 To num
    
If hittable_list(A_sph(), *vx, my_interval, A_hit(), mynum)

  x.f =  0.5 * ( A_hit(mynum)\normal\x + 1.0 )

  y.f =  0.5 * ( A_hit(mynum)\normal\y + 1.0 )
 
  z.f =  0.5 * ( A_hit(mynum)\normal\z + 1.0 )
  
  
  If axe = 1 
    ProcedureReturn x 
  EndIf
  
  If axe = 2 
    ProcedureReturn y
  EndIf
  
  If axe = 3 
    ProcedureReturn z
  EndIf
EndIf

Next
 
 ProcedureReturn ray_color(*vx, axe)
 
EndProcedure

Procedure.f ray_color(*rr.Ray, axe)
  
  color1.Vec3
  color2.Vec3
  
  color1\x = 1.0
  color1\y = 1.0
  color1\z = 1.0
  
  color2\x = 0.5
  color2\y = 0.7
  color2\z = 1.0
  
  unit_direction.Vec3
    
  unit_direction\x = unit_vector_y(*rr)
  a1.f = 0.5 * (unit_direction\x + 1.0) 
  x.f =  (1.0 - a1) * color1\x + a1 * color2\x 

  unit_direction\y = unit_vector_y(*rr)
  a2.f = 0.5 * (unit_direction\y + 1.0)
  y.f =  (1.0 - a2) * color1\y + a2 * color2\y
 
  unit_direction\z = unit_vector_y(*rr)
  a3.f = 0.5 * (unit_direction\z + 1.0)
  z.f =  (1.0 - a3) * color1\z + a3 * color2\z
  
  If axe = 1
    ProcedureReturn x
  EndIf
  
  If axe = 2
    ProcedureReturn y
  EndIf
  
  If axe = 3
    ProcedureReturn z
  EndIf
   
EndProcedure  

Procedure set_normal(*vx.Ray, Array r.hit_record(1), num)
  front_face.f = dotN(*vx\dir, r(), num)
  
  If front_face < 0.0
    r(num)\normal\x = r(num)\normal\x 
    r(num)\normal\y = r(num)\normal\y 
    r(num)\normal\z = r(num)\normal\z
  Else
    r(num)\normal\x = -r(num)\normal\x 
    r(num)\normal\y = -r(num)\normal\y 
    r(num)\normal\z = -r(num)\normal\z
  EndIf

EndProcedure


Procedure.f hit(Array s.Sphere(1), *vx.Ray, *_inter.interval, Array r.hit_record(1), num)
  
  oc.Vec3
  root.f = 0.0
  hit_bool.f = 0.0
  oc\x = *vx\orig\x - s(num)\center\x
  oc\y = *vx\orig\y - s(num)\center\y
  oc\z = *vx\orig\z - s(num)\center\z
  a.f = dot(*vx\dir, *vx\dir)
  b.f = dot(oc,*vx\dir)
  c.f = dot(oc,oc) - s(num)\radius * s(num)\radius
  
  discriminant.f = b*b - a*c
  
  If discriminant < 0.0
    ProcedureReturn 0.0
  EndIf

    root = (-b - Sqr(discriminant)) / (a)    
    
;     If (root <= min) Or ( max <= root)
;       root = (-b + Sqr(discriminant)) / (a)
;       If (root <= min) Or (max <= root)
;         ProcedureReturn 0.0
;       EndIf
;     EndIf
    
    If (Not surrounds(root, *_inter))
      root = (-b + Sqr(discriminant)) / (a)
         
     If ( Not surrounds(root, *_inter))
       ProcedureReturn 0    
    EndIf
  
    
    EndIf
     
    r(num)\t = root
    r(num)\p\x = At(*vx, r(num)\t, 1)
    r(num)\p\y = At(*vx, r(num)\t, 2)
    r(num)\p\z = At(*vx, r(num)\t, 3)
    
    r(num)\normal\x = (r(num)\p\x - s(num)\center\x) / s(num)\radius
    r(num)\normal\y = (r(num)\p\y - s(num)\center\y) / s(num)\radius
    r(num)\normal\z = (r(num)\p\z - s(num)\center\z) / s(num)\radius
    
    set_normal(*vx, r(), num)    
        
    ProcedureReturn 1.0
  
EndProcedure

Procedure.f hittable_list(Array s.Sphere(1), *vx.Ray, *ray_t.interval, Array r.hit_record(1), iter)
  Dim temp_rec.hit_record(N)
  hit_anything.f = 0.0
  closest_so_far.f = *ray_t\max
  
    If hit(s(), *vx, *ray_t, r(), iter)
      hit_anything = 1.0
      closest_so_far = r(iter)\t  
      ;r(inter) = temp_rec(iter)
    EndIf
  
  ProcedureReturn hit_anything
  
EndProcedure


aspect_ratio.f = 16.0 / 9.0
image_width = 800

image_height = Int(image_width / aspect_ratio)

If image_height < 1
  image_height = 1
Else
  image_height = image_height
EndIf

Procedure render()
Shared N
Shared A_sph.Sphere()  
Shared A_hit.hit_record()
  
Shared image_width
Shared image_height

Shared my_interval.interval

focal_length.f = 1.0
viewport_height.f = 2.0

i_w.f = image_width
i_h.f = image_height
viewport_width.f = viewport_height * (i_w/i_h)

point3.Vec3

point3\x = 0
point3\y = 0
point3\z = 0

ray_direction.Vec3

ray_direction\x = 0
ray_direction\y = 0
ray_direction\z = 0

viewport_u.Vec3

viewport_u\x = viewport_width
viewport_u\y = 0
viewport_u\z = 0

viewport_v.Vec3

viewport_v\x = 0
viewport_v\y = -viewport_height
viewport_v\z = 0

pixel_delta_u.Vec3

pixel_delta_u\x = viewport_u\x / i_w
pixel_delta_u\y = viewport_u\y / i_w
pixel_delta_u\z = viewport_u\z / i_w

pixel_delta_v.Vec3

pixel_delta_v\x = viewport_v\x / i_h
pixel_delta_v\y = viewport_v\y / i_h
pixel_delta_v\z = viewport_v\z / i_h

viewport_upper_left.Vec3

v_f.Vec3
v_f\x = 0.0
v_f\y = 0.0
v_f\z = focal_length

viewport_upper_left\x = point3\x - v_f\x - viewport_u\x / 2 - viewport_v\x / 2
viewport_upper_left\y = point3\y - v_f\y - viewport_u\y / 2 - viewport_v\y / 2
viewport_upper_left\z = point3\z - v_f\z - viewport_u\z / 2 - viewport_v\z / 2

pixel_100_loc.Vec3

pixel_100_loc\x = viewport_upper_left\x + 0.5 * (pixel_delta_u\x + pixel_delta_v\x)
pixel_100_loc\y = viewport_upper_left\y + 0.5 * (pixel_delta_u\y + pixel_delta_v\y)
pixel_100_loc\z = viewport_upper_left\z + 0.5 * (pixel_delta_u\z + pixel_delta_v\z)

sample_per_pixel.i = 100
pixel_sample_scale.f = 1.0 / sample_per_pixel


init_sphere()
init_zero_hit_record()

If StartDrawing(ScreenOutput())

For j = 0 To image_height-1
    For i = 0 To image_width-1
      
      ii.f = i
      jj.f = j
      
;       pixel_center.Vec3
;             
;       pixel_center\x = pixel_100_loc\x + (ii * pixel_delta_u\x) + (jj * pixel_delta_v\x)
;       pixel_center\y = pixel_100_loc\y + (ii * pixel_delta_u\y) + (jj * pixel_delta_v\y)
;       pixel_center\z = pixel_100_loc\z + (ii * pixel_delta_u\z) + (jj * pixel_delta_v\z)
      
      
;       ray_direction\x = pixel_center\x - point3\x
;       ray_direction\y = pixel_center\y - point3\y
;       ray_direction\z = pixel_center\z - point3\z
      
      x.f =  0.0
      y.f =  0.0
      z.f =  0.0
      
      For sample = 0 To sample_per_pixel
      
      offset.Vec3
      
      offset\x = random_float() -0.5 
      offset\y = random_float() -0.5 
      offset\z = 0.0
      
      
      pixel_sample.Vec3
      
      pixel_sample\x = pixel_100_loc\x + ( (ii+offset\x) * pixel_delta_u\x) + ( (jj+offset\y) * pixel_delta_v\x)
      pixel_sample\y = pixel_100_loc\y + ( (ii+offset\x) * pixel_delta_u\y) + ( (jj+offset\y) * pixel_delta_v\y)
      pixel_sample\z = pixel_100_loc\z + ( (ii+offset\x) * pixel_delta_u\z) + ( (jj+offset\y) * pixel_delta_v\z)
      
      ray_direction\x = pixel_sample\x - point3\x
      ray_direction\y = pixel_sample\y - point3\y
      ray_direction\z = pixel_sample\z - point3\z
      
      Define.Ray r
      
      r\orig = point3
      r\dir = ray_direction          
      
      x =  x + ray_color_hit(r,1,3)
      y =  y + ray_color_hit(r,2,3)
      z =  z + ray_color_hit(r,3,3) 
      
      Next
     
      Plot(i, j, RGB(Int(255.999 * clamp(pixel_sample_scale  * x, my_interval) ), Int(255.999 * clamp(pixel_sample_scale * y, my_interval) ), Int(255.999 * clamp(pixel_sample_scale * z, my_interval) )))
      
     
      Next
    Next
    
EndIf
  
StopDrawing() 

EndProcedure


InitSprite()
 
 OpenWindow(0, 0, 0, image_width, image_height, "Inspired from Raytracing in One Weekend", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
 OpenWindowedScreen(WindowID(0), 0, 0, image_width, image_height)
  
  ClearScreen(RGB(0,0,0))
  
  render()
    
 Repeat
   Event = WindowEvent()
 Until  Event = #PB_Event_CloseWindow
   
 End 
Yeah, it takes some time to finish the render, so please wait a bit to see that.

Enjoy !
threedslider
Enthusiast
Enthusiast
Posts: 397
Joined: Sat Feb 12, 2022 7:15 pm

Re: Raytracing in One Weekend

Post by threedslider »

Same source code but a new thing is for rendering on display as real time !

It is working now !

**** Warnings It is for windows only ****

Yeah sorry.... :?

Here the code :

Code: Select all

;
; Inspired from Ray Tracing in One Weekend : 
; https://raytracing.github.io/books/RayTracingInOneWeekend.html
;
; Writed and adapted in Purebasic by threedslider
;

CompilerIf #PB_Compiler_OS <> #PB_OS_Windows
  CompilerError "This example is Windows only"
CompilerEndIf


N.i = 3

; Vector 
Structure Vec3
  x.f
  y.f
  z.f
EndStructure

; Ray
Structure Ray
  orig.Vec3
  dir.Vec3
EndStructure

; Color
Structure Color
  r.f
  g.f
  b.f
EndStructure


;Sphere
Structure Sphere
  center.Vec3
  radius.f
  material.Color
EndStructure

;hit record
Structure hit_record
  p.Vec3
  normal.Vec3
  t.f
EndStructure

Structure interval
  min.f
  max.f
EndStructure

my_interval.interval

my_interval\min = 0.000
my_interval\max = 0.999

Dim A_sph.Sphere(N)
Dim A_hit.hit_record(N)

Procedure init_zero_hit_record()
  Shared A_hit.hit_record()
  
  For i=0 To N-1
    A_hit(i)\t = 0.0
    A_hit(i)\p\x = 0.0
    A_hit(i)\p\y = 0.0
    A_hit(i)\p\z = 0.0
    A_hit(i)\normal\x = 0.0
    A_hit(i)\normal\y = 0.0
    A_hit(i)\normal\z = 0.0
  Next
EndProcedure

Procedure init_sphere()
  Shared A_sph.Sphere()  
 
    A_sph(0)\center\x = 0.0
    A_sph(0)\center\y = 0.0
    A_sph(0)\center\z = -1.0
    A_sph(0)\radius = 0.5
    
    A_sph(1)\center\x = -1.0
    A_sph(1)\center\y = 0.0
    A_sph(1)\center\z = -1.0
    A_sph(1)\radius = 0.15
    A_sph(1)\material\r = 0.0
    A_sph(1)\material\g = 1.0
    A_sph(1)\material\b = 0.0
    
    A_sph(2)\center\x = 1.0
    A_sph(2)\center\y = 0.0
    A_sph(2)\center\z = -1.0
    A_sph(2)\radius = 0.15
    A_sph(2)\material\r = 0.0
    A_sph(2)\material\g = 1.0
    A_sph(2)\material\b = 0.0
    
    A_sph(3)\center\x = 0.0
    A_sph(3)\center\y = -100.0
    A_sph(3)\center\z = -1.0
    A_sph(3)\radius = 100.0
    A_sph(3)\material\r = 0.0
    A_sph(3)\material\g = 1.0
    A_sph(3)\material\b = 0.0
    
EndProcedure
  
Procedure.f size(*_i.interval)
  r.f = *_i\max - *_i\min
  ProcedureReturn r
EndProcedure

Procedure contains(x.f, *_i.interval)
  ProcedureReturn Bool(*_i\min <= x And x <= *_i\max)
EndProcedure

Procedure surrounds(x.f, *_i.interval)
  ProcedureReturn Bool(*_i\min < x And x < *_i\max)
EndProcedure

Procedure.f clamp(x.f, *_i.interval)
  If(x < *_i\min)
    ProcedureReturn *_i\min
  EndIf
  If(x > *_i\max)
    ProcedureReturn *_i\max
  EndIf
  ProcedureReturn x
EndProcedure


Procedure.f degrees_to_radians(degrees.f) 
  degrees = degrees * #PI / 180.0
  ProcedureReturn degrees
EndProcedure

Procedure.f random_float()   
    r.f = Random(#MAXDWORD) / #MAXDWORD  
    ProcedureReturn r
EndProcedure
    


Procedure.f random_min_max_float(min.f, max.f)     
    ProcedureReturn min + (max-min) * random_float()
EndProcedure

Procedure.f dot(*v1.Vec3, *v2.Vec3)
  result.f = *v1\x * *v2\x + *v1\y * *v2\y + *v1\z * *v2\z
  
  ProcedureReturn result
EndProcedure

Procedure.f dotN(*v1.Vec3, Array r.hit_record(1), num)
  result.f = *v1\x * r(num)\normal\x + *v1\y * r(num)\normal\y + *v1\z * r(num)\normal\z 
  
  ProcedureReturn result
EndProcedure

Procedure.f v_length(*v.Ray)
  
  result.f = Sqr(*v\dir\x * *v\dir\x + *v\dir\y * *v\dir\y + *v\dir\z * *v\dir\z)
  
  ProcedureReturn result
EndProcedure

Procedure.f At(*rr.Ray, t.f, axe)
  
  x.f = *rr\orig\x + t * *rr\dir\x
  y.f = *rr\orig\y + t * *rr\dir\y
  z.f = *rr\orig\z + t * *rr\dir\z
  
  If axe = 1
    ProcedureReturn x
  EndIf
  
  If axe = 2
    ProcedureReturn y
  EndIf
  
  If axe = 3
    ProcedureReturn z
  EndIf
EndProcedure

Procedure.f unit_vector_y(*vy.Ray)
    
  len.f = v_length(*vy) 
  
  y.f = 0
  
  If Not len = 0 
    y = *vy\dir\y / len
  EndIf
  
  ProcedureReturn y
EndProcedure

Declare.f hittable_list(Array s.Sphere(1), *vx.Ray, *ray_t.interval, Array r.hit_record(1), iter)
Declare.f ray_color(*rr.Ray, axe)

Procedure.f ray_color_hit(*vx.Ray, axe, num)
 
  Shared A_sph.Sphere()
  Shared A_hit.hit_record()
  Shared my_interval.interval
  
For mynum = 0 To num
    
If hittable_list(A_sph(), *vx, my_interval, A_hit(), mynum)

  x.f =  0.5 * ( A_hit(mynum)\normal\x + 1.0 )

  y.f =  0.5 * ( A_hit(mynum)\normal\y + 1.0 )
 
  z.f =  0.5 * ( A_hit(mynum)\normal\z + 1.0 )
  
  
  If axe = 1 
    ProcedureReturn x 
  EndIf
  
  If axe = 2 
    ProcedureReturn y
  EndIf
  
  If axe = 3 
    ProcedureReturn z
  EndIf
EndIf

Next
 
 ProcedureReturn ray_color(*vx, axe)
 
EndProcedure

Procedure.f ray_color(*rr.Ray, axe)
  
  color1.Vec3
  color2.Vec3
  
  color1\x = 1.0
  color1\y = 1.0
  color1\z = 1.0
  
  color2\x = 0.5
  color2\y = 0.7
  color2\z = 1.0
  
  unit_direction.Vec3
    
  unit_direction\x = unit_vector_y(*rr)
  a1.f = 0.5 * (unit_direction\x + 1.0) 
  x.f =  (1.0 - a1) * color1\x + a1 * color2\x 

  unit_direction\y = unit_vector_y(*rr)
  a2.f = 0.5 * (unit_direction\y + 1.0)
  y.f =  (1.0 - a2) * color1\y + a2 * color2\y
 
  unit_direction\z = unit_vector_y(*rr)
  a3.f = 0.5 * (unit_direction\z + 1.0)
  z.f =  (1.0 - a3) * color1\z + a3 * color2\z
  
  If axe = 1
    ProcedureReturn x
  EndIf
  
  If axe = 2
    ProcedureReturn y
  EndIf
  
  If axe = 3
    ProcedureReturn z
  EndIf
   
EndProcedure  

Procedure set_normal(*vx.Ray, Array r.hit_record(1), num)
  front_face.f = dotN(*vx\dir, r(), num)
  
  If front_face < 0.0
    r(num)\normal\x = r(num)\normal\x 
    r(num)\normal\y = r(num)\normal\y 
    r(num)\normal\z = r(num)\normal\z
  Else
    r(num)\normal\x = -r(num)\normal\x 
    r(num)\normal\y = -r(num)\normal\y 
    r(num)\normal\z = -r(num)\normal\z
  EndIf

EndProcedure


Procedure.f hit(Array s.Sphere(1), *vx.Ray, *_inter.interval, Array r.hit_record(1), num)
  
  oc.Vec3
  root.f = 0.0
  hit_bool.f = 0.0
  oc\x = *vx\orig\x - s(num)\center\x
  oc\y = *vx\orig\y - s(num)\center\y
  oc\z = *vx\orig\z - s(num)\center\z
  a.f = dot(*vx\dir, *vx\dir)
  b.f = dot(oc,*vx\dir)
  c.f = dot(oc,oc) - s(num)\radius * s(num)\radius
  
  discriminant.f = b*b - a*c
  
  If discriminant < 0.0
    ProcedureReturn 0.0
  EndIf

    root = (-b - Sqr(discriminant)) / (a)    
    
;     If (root <= min) Or ( max <= root)
;       root = (-b + Sqr(discriminant)) / (a)
;       If (root <= min) Or (max <= root)
;         ProcedureReturn 0.0
;       EndIf
;     EndIf
    
    If (Not surrounds(root, *_inter))
      root = (-b + Sqr(discriminant)) / (a)
         
     If ( Not surrounds(root, *_inter))
       ProcedureReturn 0    
    EndIf
  
    
    EndIf
     
    r(num)\t = root
    r(num)\p\x = At(*vx, r(num)\t, 1)
    r(num)\p\y = At(*vx, r(num)\t, 2)
    r(num)\p\z = At(*vx, r(num)\t, 3)
    
    r(num)\normal\x = (r(num)\p\x - s(num)\center\x) / s(num)\radius
    r(num)\normal\y = (r(num)\p\y - s(num)\center\y) / s(num)\radius
    r(num)\normal\z = (r(num)\p\z - s(num)\center\z) / s(num)\radius
    
    set_normal(*vx, r(), num)    
        
    ProcedureReturn 1.0
  
EndProcedure

Procedure.f hittable_list(Array s.Sphere(1), *vx.Ray, *ray_t.interval, Array r.hit_record(1), iter)
  Dim temp_rec.hit_record(N)
  hit_anything.f = 0.0
  closest_so_far.f = *ray_t\max
  
    If hit(s(), *vx, *ray_t, r(), iter)
      hit_anything = 1.0
      closest_so_far = r(iter)\t  
      ;r(inter) = temp_rec(iter)
    EndIf
  
  ProcedureReturn hit_anything
  
EndProcedure


aspect_ratio.f = 16.0 / 9.0
image_width = 800

image_height = Int(image_width / aspect_ratio)

If image_height < 1
  image_height = 1
Else
  image_height = image_height
EndIf

Procedure render()
Shared N
Shared A_sph.Sphere()  
Shared A_hit.hit_record()
  
Shared image_width
Shared image_height

Shared my_interval.interval

focal_length.f = 1.0
viewport_height.f = 2.0

i_w.f = image_width
i_h.f = image_height
viewport_width.f = viewport_height * (i_w/i_h)

point3.Vec3

point3\x = 0
point3\y = 0
point3\z = 0

ray_direction.Vec3

ray_direction\x = 0
ray_direction\y = 0
ray_direction\z = 0

viewport_u.Vec3

viewport_u\x = viewport_width
viewport_u\y = 0
viewport_u\z = 0

viewport_v.Vec3

viewport_v\x = 0
viewport_v\y = -viewport_height
viewport_v\z = 0

pixel_delta_u.Vec3

pixel_delta_u\x = viewport_u\x / i_w
pixel_delta_u\y = viewport_u\y / i_w
pixel_delta_u\z = viewport_u\z / i_w

pixel_delta_v.Vec3

pixel_delta_v\x = viewport_v\x / i_h
pixel_delta_v\y = viewport_v\y / i_h
pixel_delta_v\z = viewport_v\z / i_h

viewport_upper_left.Vec3

v_f.Vec3
v_f\x = 0.0
v_f\y = 0.0
v_f\z = focal_length

viewport_upper_left\x = point3\x - v_f\x - viewport_u\x / 2 - viewport_v\x / 2
viewport_upper_left\y = point3\y - v_f\y - viewport_u\y / 2 - viewport_v\y / 2
viewport_upper_left\z = point3\z - v_f\z - viewport_u\z / 2 - viewport_v\z / 2

pixel_100_loc.Vec3

pixel_100_loc\x = viewport_upper_left\x + 0.5 * (pixel_delta_u\x + pixel_delta_v\x)
pixel_100_loc\y = viewport_upper_left\y + 0.5 * (pixel_delta_u\y + pixel_delta_v\y)
pixel_100_loc\z = viewport_upper_left\z + 0.5 * (pixel_delta_u\z + pixel_delta_v\z)

sample_per_pixel.i = 10
pixel_sample_scale.f = 1.0 / sample_per_pixel


init_sphere()
init_zero_hit_record()

;If StartDrawing(ScreenOutput())

*DC = GetDC_(WindowID(0))

For j = 0 To image_height-1
    For i = 0 To image_width-1
      
      ii.f = i
      jj.f = j
      
;       pixel_center.Vec3
;             
;       pixel_center\x = pixel_100_loc\x + (ii * pixel_delta_u\x) + (jj * pixel_delta_v\x)
;       pixel_center\y = pixel_100_loc\y + (ii * pixel_delta_u\y) + (jj * pixel_delta_v\y)
;       pixel_center\z = pixel_100_loc\z + (ii * pixel_delta_u\z) + (jj * pixel_delta_v\z)
      
      
;       ray_direction\x = pixel_center\x - point3\x
;       ray_direction\y = pixel_center\y - point3\y
;       ray_direction\z = pixel_center\z - point3\z
      
      x.f =  0.0
      y.f =  0.0
      z.f =  0.0
      
      For sample = 0 To sample_per_pixel
      
      offset.Vec3
      
      offset\x = random_float() -0.5 
      offset\y = random_float() -0.5 
      offset\z = 0.0
      
      
      pixel_sample.Vec3
      
      pixel_sample\x = pixel_100_loc\x + ( (ii+offset\x) * pixel_delta_u\x) + ( (jj+offset\y) * pixel_delta_v\x)
      pixel_sample\y = pixel_100_loc\y + ( (ii+offset\x) * pixel_delta_u\y) + ( (jj+offset\y) * pixel_delta_v\y)
      pixel_sample\z = pixel_100_loc\z + ( (ii+offset\x) * pixel_delta_u\z) + ( (jj+offset\y) * pixel_delta_v\z)
      
      ray_direction\x = pixel_sample\x - point3\x
      ray_direction\y = pixel_sample\y - point3\y
      ray_direction\z = pixel_sample\z - point3\z
      
      Define.Ray r
      
      r\orig = point3
      r\dir = ray_direction          
      
      x =  x + ray_color_hit(r,1,3)
      y =  y + ray_color_hit(r,2,3)
      z =  z + ray_color_hit(r,3,3) 
      
      Next
      
      ;Plot(i, j, RGB(Int(255.999 * clamp(pixel_sample_scale  * x, my_interval) ), Int(255.999 * clamp(pixel_sample_scale * y, my_interval) ), Int(255.999 * clamp(pixel_sample_scale * z, my_interval) )))
      
      SetPixel_(*DC, i, j, RGB(Int(255.999 * clamp(pixel_sample_scale  * x, my_interval) ), Int(255.999 * clamp(pixel_sample_scale * y, my_interval) ), Int(255.999 * clamp(pixel_sample_scale * z, my_interval) )) ) 
      Next
    Next
    
   ReleaseDC_(WindowID(0), *DC)  
    
;EndIf
  
;StopDrawing() 

EndProcedure


InitSprite()
 
 OpenWindow(0, 0, 0, image_width, image_height, "Inspired from Raytracing in One Weekend", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
 ;OpenWindowedScreen(WindowID(0), 0, 0, image_width, image_height)
  
  ;ClearScreen(RGB(0,0,0))
  
 render()
    
 Repeat
   Event = WindowEvent()
   
 Until  Event = #PB_Event_CloseWindow
   
 End 
pjay
Enthusiast
Enthusiast
Posts: 252
Joined: Thu Mar 30, 2006 11:14 am

Re: Raytracing in One Weekend

Post by pjay »

Well done for persevering with this :)

I'd avoid using SetPixel(), not so much because of the Windows dependancy, but moreso that it is *very* slow; it takes the rendering time from ~2 seconds to ~5.5 seconds on my PC.

Have you tried using a Startdrawing / Stopdrawing on each horizontal line if you need to see the render progress.

I.e:

Code: Select all

  For j = 0 To image_height-1
    StartDrawing()
    For i = 0 To image_width-1
       Plot...
    Next
    Stopdrawing()...
Next
Post Reply