Raytracing in One Weekend

Programmation d'applications complexes
Avatar de l’utilisateur
threedslider
Messages : 452
Inscription : dim. 01/juil./2018 22:38

Raytracing in One Weekend

Message par threedslider »

Hello à tous

Je m'inspire le code en C++ avec l'article de Raytracing in One Weekend, voici son lien : https://raytracing.github.io/books/RayT ... ekend.html

Donc j'ai déjà avancé sur le forum anglais mais je poste ici mes derniers travaux, une sphère rouge sur le ciel bleu pas mal non ? Et c'est grâce au l'article que j'ai adapté en PB :mrgreen:

Voici le code :

Code : Tout sélectionner

aspect_ratio.f = 16.0 / 9.0
image_width = 800

;Debug aspect_ratio

image_height = Int(image_width / aspect_ratio)

;Debug image_height

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

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)

;Debug i_w/i_h
;Debug viewport_width


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

; Ray
Structure Ray
  orig.Vec3
  dir.Vec3
EndStructure

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)

;Debug pixel_100_loc\x

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 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 unit_vector_x(*vx.Ray)
    
  len.f = v_length(*vx) 
  
  ;Debug len
  
  If Not len = 0 ;And Not len < 0
    *vx\dir\x = *vx\dir\x / len
  EndIf
  
  
  ;Debug vv
  
  ProcedureReturn *vx\dir\x
EndProcedure

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

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

Procedure.f ray_color_sphere()
  
  color1.f = 1.0
  
  
  ProcedureReturn color1

  
EndProcedure

Procedure.f ray_color_x(*rx.Ray)
  
  color1.f = 1.0
  color2.f = 0.5
  
  
    unit_direction.Vec3
  

  unit_direction\y = unit_vector_y(*rx)

  
  ;Debug unit_direction\y
  
  a.f = 0.5 * (unit_direction\y + 1.0)
  
  ;Debug a
  

  
  x.f =  (1.0 - a) * color1 + a * color2
  
   
    

     ProcedureReturn x

  
EndProcedure

Procedure.f ray_color_y(*ry.Ray)
  
  color1.f = 1.0
  color2.f = 0.7
  
   unit_direction.Vec3
  

  unit_direction\y = unit_vector_y(*ry)

  
  ;Debug unit_direction\y
  
  a.f = 0.5 * (unit_direction\y + 1.0)
  
  ;Debug a
  
  
  y.f =  (1.0 - a) * color1 + a * color2
  
  ProcedureReturn y;
  
EndProcedure

Procedure.f ray_color_z(*rz.Ray)
  
  color1.f = 1.0
  color2.f = 1.0
  
  unit_direction.Vec3
  

  unit_direction\y = unit_vector_y(*rz)

  
  ;Debug unit_direction\y
  
  a.f = 0.5 * (unit_direction\y + 1.0)
  
  ;Debug a
  
  z.f =  (1.0 - a) * color1 + a * color2
  

    ProcedureReturn z


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
  
ProcedureReturn Bool(discriminant >= 0)

EndProcedure

; Write the translated [0,255] value of each color component.
Procedure write_color()
  Shared pixel_color.Vec3
  
  WriteString(0, Str(Int(255.999 * pixel_color\x)))
  WriteString(0, " ")
  WriteString(0, Str(Int(255.999 * pixel_color\y)))
  WriteString(0, " ")
  WriteString(0, Str(Int(255.999 * pixel_color\z)))
  WriteStringN(0, " ")
  
  ;Debug Str(Int(255.999 * pixel_color\x))
EndProcedure

; Output the image in PPM
; If CreateFile(0, "image_test4.ppm")
;   WriteStringN(0,"P3")
;   WriteString(0,Str(image_width))
;   WriteString(0," ")
;   WriteString(0,Str(image_height))
;   WriteStringN(0," ")
;   WriteStringN(0,"255")
;   WriteStringN(0," ")
;   
;   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
;       p_s\y = 0
;       p_s\z = -1
;       
;       If hit_sphere(p_s, 0.5, r)
;         pixel_color\x = 1.0
;         pixel_color\y = 0
;         pixel_color\z = 0
;       Else
;         pixel_color\x = ray_color_x(r)
;         pixel_color\y = ray_color_y(r)
;         pixel_color\z = ray_color_z(r)
;       EndIf
;     
;       ;Debug pixel_color\x
;       write_color()    
;      
;      
;     Next
;   Next
;    CloseFile(0)
;  EndIf
 
 If 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, 800, 600)
 
  If CreateImage(0, image_width, image_height) And StartDrawing(ImageOutput(0))
    
    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
      p_s\y = 0
      p_s\z = -1
      
      Debug ray_color_x(r)
      
      If hit_sphere(p_s, 0.5, r)
        Plot(i, j , RGB(255, 0.0, 0.0))
       Else
        Plot(i, j, RGB(Int(255.999 * ray_color_x(r)),Int(255.999 * ray_color_y(r)),Int(255.999* ray_color_z(r))))
      EndIf
      
      Next
  Next
    
   
   StopDrawing() 
   ImageGadget(0, 0, 0, image_width, image_height, ImageID(0))
  EndIf
 
   Repeat
      Event = WaitWindowEvent()
    Until Event = #PB_Event_CloseWindow
EndIf
Et c'est à l'origine en rendu à partir d'un fichier image sous PPM comme extension mais je l'ai rendu plus facilement avec PB :wink:

Voilà et merci

Happy coding
Avatar de l’utilisateur
threedslider
Messages : 452
Inscription : dim. 01/juil./2018 22:38

Re: Raytracing in One Weekend

Message par threedslider »

Voilà un autre code rendu avec la sphère du couleur "normale" :mrgreen:

Voici ici :

Code : Tout sélectionner

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

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

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)

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

; Ray
Structure Ray
  orig.Vec3
  dir.Vec3
EndStructure

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)

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 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_at(*rr.Ray, t.f, axe)
  Shared p_s.Vec3
  
   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) 
  
  
  len.f = Sqr(x*x + y*y + z*z)
  
  xx.f = 0
  yy.f = 0
  zz.f = 0
  
   If Not len = 0 
    xx = x  / len
  EndIf
  
  If Not len = 0 
    yy = y / len
  EndIf
  
   If Not len = 0 
    zz = z / len
  EndIf
  
  If axe = 1
    ProcedureReturn xx
  EndIf
  
  If axe = 2
    ProcedureReturn yy
  EndIf
  
  If axe = 3
    ProcedureReturn zz
  EndIf
  
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_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


; Write the translated [0,255] value of each color component.
Procedure write_color()
  Shared pixel_color.Vec3
  
  WriteString(0, Str(Int(255.999 * pixel_color\x)))
  WriteString(0, " ")
  WriteString(0, Str(Int(255.999 * pixel_color\y)))
  WriteString(0, " ")
  WriteString(0, Str(Int(255.999 * pixel_color\z)))
  WriteStringN(0, " ")
  
  ;Debug Str(Int(255.999 * pixel_color\x))
EndProcedure

; Output the image in PPM
; If CreateFile(0, "image_test4.ppm")
;   WriteStringN(0,"P3")
;   WriteString(0,Str(image_width))
;   WriteString(0," ")
;   WriteString(0,Str(image_height))
;   WriteStringN(0," ")
;   WriteStringN(0,"255")
;   WriteStringN(0," ")
;   
;   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
;       p_s\y = 0
;       p_s\z = -1
;       
;       If hit_sphere(p_s, 0.5, r)
;         pixel_color\x = 1.0
;         pixel_color\y = 0
;         pixel_color\z = 0
;       Else
;         pixel_color\x = ray_color_x(r)
;         pixel_color\y = ray_color_y(r)
;         pixel_color\z = ray_color_z(r)
;       EndIf
;     
;       ;Debug pixel_color\x
;       write_color()    
;      
;      
;     Next
;   Next
;    CloseFile(0)
;  EndIf

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))
  
  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)
      
      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 Int(255.999 * ray_color_n(r_n,1))+155
          
      If t > 0.0
        Plot(i, j, RGB(Int(255.999 * ray_color_n(r_n,1)), Int(255.999 * ray_color_n(r_n,2)), Int(255.999 * ray_color_n(r_n,1)*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
   
  
  StopDrawing() 
  
EndIf
 Repeat
   Event = WindowEvent()
 Until  Event = #PB_Event_CloseWindow
   
 End 
Je me suis cassé la tête pour l'avoir exactement comme article cité :P

Allez Happy coding !
Avatar de l’utilisateur
threedslider
Messages : 452
Inscription : dim. 01/juil./2018 22:38

Re: Raytracing in One Weekend

Message par threedslider »

Voilà un autre ! J'ai galéré ce code mais bien réussi à faire marcher bien :mrgreen:

Voici le code que je vous partage :

Code : Tout sélectionner

;
; 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 
Avatar de l’utilisateur
threedslider
Messages : 452
Inscription : dim. 01/juil./2018 22:38

Re: Raytracing in One Weekend

Message par threedslider »

Hello !

Je suis revenu et j'espère continuer mes travaux sur ce rendu passionant :)

Voilà et à bientôt

Happy coding
Avatar de l’utilisateur
threedslider
Messages : 452
Inscription : dim. 01/juil./2018 22:38

Re: Raytracing in One Weekend

Message par threedslider »

Hello,

J'ai mis du temps à comprendre sur comment le rendre le rendu en plusieurs objets 3D, c'est fait et c'est résolu maintenant :mrgreen:

Voici le code :

Code : Tout sélectionner

;
; 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 
Merci

Happy coding !
Avatar de l’utilisateur
Guillot
Messages : 672
Inscription : jeu. 25/juin/2015 16:18

Re: Raytracing in One Weekend

Message par Guillot »

salut,

t'as vu les travaux de hades sur le forum anglosaxon ?
je pense que c'est lui qui est allé le plus loin dans le domaine
je crois qu'il avait même fait un didacticiel
Avatar de l’utilisateur
threedslider
Messages : 452
Inscription : dim. 01/juil./2018 22:38

Re: Raytracing in One Weekend

Message par threedslider »

Salut Guillot :)

Oui je le connais ce type pour ses travaux en raytracing simple et c'est assez vieux mais fonctionnel, j'ai appris par sa methode mais là je vais plus loin sur l'article de Raytracing in one Weekend par Peter Shirley (un salarié de NVIDIA) avec un avancé de rendu de type Pathtracing car plus complexe sur les couleurs avec des lumières hyper réalistes, cela inclut aussi l'antialiasing, la reflexion et la refraction plus poussé :mrgreen:

Mais j'ai pas terminé donc cela vient tout doucement :wink:

Donc voilà, j'ai fini le rendu système antialiasing :mrgreen:

Voici le code :

Code : Tout sélectionner

;
; 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 

Yay ! Il est plutôt lisse les objets 3D maintenant :mrgreen:
Bon ça prend un peu de temps de calcul ... Donc faut patienter un tout petit peu

Happy coding
Avatar de l’utilisateur
threedslider
Messages : 452
Inscription : dim. 01/juil./2018 22:38

Re: Raytracing in One Weekend

Message par threedslider »

Et aussi, savez vous comment faire un rendu moteur 3D sur startdrawing afin qu'il achiffe en temps réel avec les données d'images?

Je cherche ce type de rendu temps réel sur la fenetre, que me conseillez vous ?

Merci
Avatar de l’utilisateur
threedslider
Messages : 452
Inscription : dim. 01/juil./2018 22:38

Re: Raytracing in One Weekend

Message par threedslider »

Yay ! Trop bon j'ai trouvé la technique de rendu en temps réel grâce à sur l'internet à partir d'un tutoriel :mrgreen:

Je vous partage la dernière modification :D :

** Attention c'est sur que windows qui fonctionne seulement ! "

Code : Tout sélectionner

;
; 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 
Bonne nouvelle ça va plus vite maintenant car j'ai diminué le sample :idea:

Amusez vous bien !
Avatar de l’utilisateur
SPH
Messages : 4937
Inscription : mer. 09/nov./2005 9:53

Re: Raytracing in One Weekend

Message par SPH »

Ton dernier code fonctionne (contrairement à un autre).
Bon, c'est sûr, tu ne feras pas d'anim à cette vitesse d'affichage. Mais c'est bien de maitriser (tu maitrises au fait ?) cet effet.

🤗

!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.12LTS- 64 bits
Avatar de l’utilisateur
threedslider
Messages : 452
Inscription : dim. 01/juil./2018 22:38

Re: Raytracing in One Weekend

Message par threedslider »

Hello SPH

Merci et pour ce qui est la maîtrise bah ça va c'est juste que j'apprends beaucoup les possibilités offertes par PB :mrgreen:

Ok oui c'est sur que ça fait pas de rendu d'animation car le raytracing demande beaucoup de calcul mathématique donc sa ralentit tout dépend de la complexité des objets 3D même étant simple scene 3D, historiquement le raytracing fait jamais de rendu d'animation en temps réel mais uniquemement image par image dont la durée de calcul peut être importante 8O

Voilà

Prochainement je vais m'attaquer mon premier moteur de rendu 3D ave PB c'est le système "Pathtracer" avec la matière diffuse qui absorbe la lumière en créant l'ombre réaliste en générant le nombre aléatoire ! :idea:

Cela va être super, je le sens 8O :mrgreen:
Avatar de l’utilisateur
SPH
Messages : 4937
Inscription : mer. 09/nov./2005 9:53

Re: Raytracing in One Weekend

Message par SPH »

Good luck alors :wink:

!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.12LTS- 64 bits
Avatar de l’utilisateur
threedslider
Messages : 452
Inscription : dim. 01/juil./2018 22:38

Re: Raytracing in One Weekend

Message par threedslider »

Merci SPH !

J'ai eu trop de probleme pour faire le système rendu Pathtracer, je me dis que c'est peut être mon code mal codé donc j'ai dû réécrit tout en entier... Maintenat c'est plus clean et plus rapide qu'avant :mrgreen:

Bon j'ai pas intégré le Pathtracer encore mais vous pouvez voir et constater la vitesse est grandement améliorée :D

Voici le dernier code modifié :

Code : Tout sélectionner

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


;; Rewritten by threedslider Jun 10 2024
;; Added to color for sphere and background Jun 11 2024

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


; Vector for 3D Macros
Macro rt_zero(v)
  v\x = 0.0
  v\y = 0.0
  v\z = 0.0
EndMacro

Macro rt_clamp(v, m1, m2)
  v = clamp(v, m1, m2)
EndMacro

Macro rt_surround(x, m1, m2)
  surrounds(x, m1, m2)
EndMacro

Macro rt_norm(v,n)
  n = Sqr(v\x * v\x + v\y * v\y + v\z * v\z)
  
  If n <> 0.0
    n = 1.0/n
    v\x * n
    v\y * n
    v\z * n
  EndIf
  
EndMacro
  
Macro v_length(v)
  Sqr(v\dir\x * v\dir\x + v\dir\y * v\dir\y + v\dir\z * v\dir\z)
EndMacro
  
Macro rt_dot(v1, v2)
  (v1\x * v2\x + v1\y * v2\y + v1\z * v2\z)
EndMacro

Macro rt_copy(v, v1)
  v\x = v1\x
  v\y = v1\y
  v\z = v1\z
EndMacro

Macro rt_add(v, v1, v2)
  v\x = v1\x + v2\x
  v\y = v1\y + v2\y
  v\z = v1\z + v2\z
EndMacro

Macro rt_sub(v, v1, v2)
  v\x = v1\x - v2\x
  v\y = v1\y - v2\y
  v\z = v1\z - v2\z
EndMacro

Macro rt_mul(v, v1, v2)
  v\x = v1\x * v2\x
  v\y = v1\y * v2\y
  v\z = v1\z * v2\z
EndMacro

Macro rt_scale(v, v1, s)
  v\x = v1\x * s
  v\y = v1\y * s
  v\z = v1\z * s
EndMacro  

Macro rt_neg(v, v1)
  v\x = -v1\x
  v\y = -v1\y
  v\z = -v1\z
EndMacro

; Ray
Structure Ray
  orig.Vec3
  dir.Vec3
EndStructure


; Sphere
Structure Sphere
  center.Vec3
  radius.f
  color.Vec3
EndStructure

; Clamp
Procedure.f clamp(x.f, min.f, max.f)
  If(x < min)
    ProcedureReturn min
  EndIf
  If(x > max)
    ProcedureReturn max
  EndIf
  ProcedureReturn x
EndProcedure

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

; Surrounds
Procedure surrounds(x.f, min.f, max.f)
  ProcedureReturn Bool( min < x And x < max)
EndProcedure

; Create Sphere primitve
Macro m_Sphere(id, center_x, center_y, center_z, radius_, color_x, color_y, color_z)
  scene(id)\center\x = center_x
  scene(id)\center\y = center_y
  scene(id)\center\z = center_z
  scene(id)\radius = radius_
  scene(id)\color\x = color_x
  scene(id)\color\y = color_y
  scene(id)\color\z = color_z
EndMacro


Global Dim scene.Sphere(3)
m_Sphere(0, 0.0, 0.0, -1.0, 0.5, 1.0, 1.0, 1.0)
m_Sphere(1, -1.0, 0.0, -1.0, 0.35, 1.0, 1.0, 1.0)
m_Sphere(2, 1.0, 0.0, -1.0, 0.35, 1.0, 1.0, 1.0)
m_Sphere(3, 0.0, -100.0, -1.0, 100.0, 1.0, 1.0, 1.0)


; Hit for 3D objects
Procedure.f hit( *_s.Sphere, *_r.Ray, mx.f)
  
  Protected oc.Vec3
  Protected root.f = 0.0
  Protected min.f = 0.0
  Protected max.f = mx
  
  rt_sub(oc, *_r\orig, *_s\center) 
   
  Protected a.f = rt_dot(*_r\dir, *_r\dir)
  Protected b.f = rt_dot(oc,*_r\dir)
  Protected c.f = rt_dot(oc,oc) - *_s\radius *  *_s\radius
  
  Protected discriminant.f = b*b - a*c
  
  
  If discriminant < 0.0
    ProcedureReturn 0.0
  EndIf

    root = (-b - Sqr(discriminant)) / (a)    
    
    If (Not rt_surround(root, min, max))
      root = (-b + Sqr(discriminant)) / (a)
         
     If ( Not rt_surround(root, min, max))
       ProcedureReturn 0.0   
    EndIf
  
    
    EndIf 
        
    ProcedureReturn root
  
EndProcedure


; Hit for intersection
Procedure.b intersect( *_r.Ray, *t.Float, *id.Integer )
  Protected d.f, inf.f = 0.999
  Protected i.i = ArraySize(scene())
  *t\f = inf
  While i >= 0
    d = hit( scene(i), *_r, inf )
    If d 
      *t\f  = d
      *id\i = i
    EndIf
    i - 1
  Wend
  ProcedureReturn Bool( *t\f < inf )
EndProcedure

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

Procedure.f ray_color(*rr.Ray, *in.Vec3)
  Protected a.f
  Static color1.Vec3, color2.Vec3, unit_direction.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\x = unit_vector_y(*rr)
  a = 0.5 * (unit_direction\x + 1.0) 
  *in\x =  (1.0 - a) * color1\x + a * color2\x 
  
  unit_direction\y = unit_vector_y(*rr)
  a = 0.5 * (unit_direction\y + 1.0)
  *in\y =  (1.0 - a) * color1\y + a * color2\y
  
  unit_direction\z = unit_vector_y(*rr)
  a = 0.5 * (unit_direction\z + 1.0)
  *in\z =  (1.0 - a) * color1\z + a * color2\z
  
EndProcedure  

Procedure.f ray_color_hit(*_r.Ray, *in.Vec3)
  Protected x.Vec3
  Protected ntemp.f
  Protected t.f = 0.0
  Protected id.i = 0
  
    
  If intersect(*_r, @t, @id)
    Protected *obj.Sphere = scene(id)
    
    ; Point at parameter
    x\x = *_r\orig\x + t * *_r\dir\x
    x\y = *_r\orig\y + t * *_r\dir\y
    x\z = *_r\orig\z + t * *_r\dir\z
    
    ; Norm
    Protected n.Vec3
    rt_sub( n, x, *obj\center)
    rt_norm( n, ntemp )
    
    ; Set to normal
    Protected nl.Vec3
    If rt_dot( n, *_r\dir ) < 0.0
      rt_copy( nl, n )
    Else
      rt_neg( nl, n )
    EndIf
    
    *in\x = 0.5 * (nl\x + 1.0)
    *in\y = 0.5 * (nl\y + 1.0)
    *in\z = 0.5 * (nl\z + 1.0)
    
  Else
    
    ray_color(*_r, *in)
    
  EndIf
  
EndProcedure


Define aspect_ratio.f = 16.0 / 9.0
Define image_width = 800

Define image_height = Int(image_width / aspect_ratio)

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

; Render engine
Procedure render()
   
Shared image_width
Shared image_height

Static focal_length.f = 1.0
Static viewport_height.f = 2.0

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

Protected point3.Vec3

point3\x = 0.0
point3\y = 0.0
point3\z = 0.0

Protected ray_direction.Vec3

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

Protected viewport_u.Vec3

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

Protected viewport_v.Vec3

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

Protected 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

Protected 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

Protected viewport_upper_left.Vec3

Protected 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

Protected 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)

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

Protected depth.i = 10

Protected x.f, y.f, z.f, v.vec3

Static offset.Vec3, pixel_sample.Vec3

If StartDrawing(ScreenOutput())

For j = 0 To image_height-1
  For i = 0 To image_width-1
      
      ii.f = i
      jj.f = j
      
      x = 0.0
      y = 0.0
      z = 0.0
      
      ;Protected pixel_center.Vec3
      
      For sample = 0 To sample_per_pixel
            
;       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
        
      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          
    
      ray_color_hit(r, @v) 
      
      x = x + v\x
      y = y + v\y
      z = z + v\z
      
      Next
      
        Plot(i, j, RGB(Int(255.999 * clamp(pixel_sample_scale * x, 0.0, 0.999)),Int(255.999 * clamp(pixel_sample_scale*  y, 0.0, 0.999)),Int(255.999 * clamp(pixel_sample_scale * z, 0.0, 0.999))))
     
       
        
      Next
    
    Next
    
EndIf
  
StopDrawing() 

EndProcedure




InitSprite()
 
 OpenWindow(0, 0, 0, image_width / DesktopResolutionX(), image_height / DesktopResolutionY(), "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))
  
Define time = ElapsedMilliseconds()
render()
time = ElapsedMilliseconds() - time
SetWindowTitle(0,"Inspired from Raytracing in One Weekend - RenderTime: "+Str(time)+"ms")

Define Event

 Repeat
   Event = WindowEvent()
   
 Until  Event = #PB_Event_CloseWindow
   
 End 
Avatar de l’utilisateur
threedslider
Messages : 452
Inscription : dim. 01/juil./2018 22:38

Re: Raytracing in One Weekend

Message par threedslider »

Voici un nouveau code ! Grâce au forum anglais un type dont pjay m'a grandement aidé il a tout de même refactoriser mon code 8O

J'étais sur le point de reussir mais c'est bon, c'est régler. :)

Ici le code et c'est correct et rapide comme rendu :

Code : Tout sélectionner

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

EnableExplicit

#Samples_per_pixel = 10
#Max_Depth = 10
#Sample_scale = 1.0 / #Samples_per_pixel

; Vector
Structure Vec3d : x.d : y.d : z.d : EndStructure
Procedure vec3_normalize(*v.vec3d)
  Protected n.d = Sqr(*v\x * *v\x + *v\y * *v\y + *v\z * *v\z)
  If n <> 0.0 : n = 1.0/n : *v\x * n : *v\y * n : *v\z * n : EndIf
EndProcedure

Macro vec3_zero(v) : v\x = 0.0 : v\y = 0.0 : v\z = 0.0 : EndMacro
Macro vec3_length(v) : Sqr(v\direction\x * v\direction\x + v\direction\y * v\direction\y + v\direction\z * v\direction\z) : EndMacro
Macro vec3_length_squared(v) : (v\x * v\x + v\y * v\y + v\z * v\z) : EndMacro
Macro vec3_dot(v1, v2) : (v1\x * v2\x + v1\y * v2\y + v1\z * v2\z) : EndMacro
Macro vec3_copy(v, v1) : v\x = v1\x : v\y = v1\y : v\z = v1\z : EndMacro
Macro vec3_add(v, v1, v2) : v\x = v1\x + v2\x : v\y = v1\y + v2\y : v\z = v1\z + v2\z : EndMacro
Macro vec3_subtract(v, v1, v2) : v\x = v1\x - v2\x : v\y = v1\y - v2\y : v\z = v1\z - v2\z : EndMacro
Macro vec3_mul(v, v1, v2) : v\x = v1\x * v2\x : v\y = v1\y * v2\y : v\z = v1\z * v2\z : EndMacro
Macro vec3_scale(v, v1, s) : v\x = v1\x * s : v\y = v1\y * s : v\z = v1\z * s : EndMacro  
Macro vec3_set(v, vx, vy, vz) : v\x = vx : v\y = vy : v\z = vz : EndMacro
Macro vec3_negate(v, v1) : v\x = -v1\x : v\y = -v1\y : v\z = -v1\z : EndMacro
Macro random_double() : Random(#MAXDWORD) / #MAXDWORD : EndMacro
Macro random_min_max(min, max) : min + (max-min) * random_double() : EndMacro

Structure Ray ; Ray
  origin.vec3d : direction.vec3d
EndStructure
Structure Sphere ; Sphere
  center.vec3d
  color.vec3d
  radius.d
EndStructure
Structure Material ; Material
  albedo.vec3d
EndStructure

Procedure.d clamp(x.d, min.d, max.d)
  If x < min
    ProcedureReturn min
  ElseIf x > max
    ProcedureReturn max
  EndIf
  ProcedureReturn x
EndProcedure
Procedure unit_vector_vec3(*v.vec3d)
  vec3_normalize(*v)
EndProcedure  
Procedure random_in_unit_sphere(*v.vec3d)
  Repeat
    *v\x = random_min_max(-1.0, 1.0)
    *v\y = random_min_max(-1.0, 1.0)
    *v\z = random_min_max(-1.0, 1.0)
    If vec3_length_squared(*v) < 1.0 : ProcedureReturn : EndIf
  ForEver
EndProcedure
Procedure random_unit_vector(*v.vec3d)
  random_in_unit_sphere(*v)
  unit_vector_vec3(*v)
EndProcedure

Macro surrounds(x, min, max) : Bool(min <= x And x <= max) : EndMacro

; Create Sphere primitve
Macro m_Sphere(center_x, center_y, center_z, radius_, color_x, color_y, color_z)
  AddElement(scene())
  vec3_set(scene()\center,center_x,center_y,center_z)
  vec3_set(scene()\color,color_x,color_y,color_z)
  scene()\radius = radius_
EndMacro

Global NewList scene.Sphere()

m_Sphere(0.0, -100.5, -1.0, 100.0, 1.0, 1.0, 1.0); ; << - PJ240614 - pushed this down
m_Sphere(0.0, 0.0, -1.0, 0.5, 1.0, 1.0, 1.0)
; m_Sphere(-1.0, 0.0, -1.0, 0.35, 1.0, 1.0, 1.0)
; m_Sphere(1.0, 0.0, -1.0, 0.35, 1.0, 1.0, 1.0)

Procedure near_zero (*v.vec3d) ;Near zero for pathtracing calculation
  Protected e.d = 1e-8
  ProcedureReturn Bool((Abs(*v\x) < e) And (Abs(*v\y) < e) And (Abs(*v\z) < e))
EndProcedure

; Hit for 3D objects
Procedure.d hit(*_s.Sphere, *ray.Ray, max.d)
  
  Protected oc.vec3d
  Protected root.d = 0.0
  Protected min.d = 0.0001
  
  vec3_subtract(oc, *_s\center,*ray\origin) 
  
  Protected a.d = vec3_length_squared(*ray\direction)
  Protected h.d = vec3_dot(*ray\direction,oc)
  Protected c.d = vec3_length_squared(oc) - *_s\radius * *_s\radius
  
  Protected discriminant.d = h * h - a * c
  
  If discriminant < 0.0 : ProcedureReturn #False : EndIf
  
  Protected sqrtd.d = Sqr(discriminant)
  
  root = (h - sqrtd) / a
  
  If Not surrounds(root, min, max)
    root = (h + sqrtd) / a
    If Not surrounds(root, min, max) : ProcedureReturn 0.0 : EndIf
  EndIf 

  ProcedureReturn root
  
EndProcedure

; Hit for intersection
Procedure.b intersect( *ray.Ray, *t.double, *id.Integer )
  Protected d.d, inf.d = 999.999
  *t\d = inf
  ForEach scene()
    d = hit(@scene(), *ray, *t\d)
    If d
      *t\d  = d
      *id\i = ListIndex(scene())
    EndIf
  Next
  ProcedureReturn Bool( *t\d < inf )
EndProcedure

; Unit vector Y for background
Procedure.d unit_vector_y(*vy.Ray)
  Protected len.d
  Static y.d : y.d = 0
  len = vec3_length(*vy)
  If len <> 0.0 : y = *vy\direction\y / len  : EndIf
  ProcedureReturn y
EndProcedure

Procedure.d ray_color(*rr.Ray, *in.vec3d)
  Protected a.d
  Static color1.vec3d, color2.vec3d, unit_directionection.vec3d
  
  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_directionection\y = unit_vector_y(*rr)
  a = 0.5 * (unit_directionection\y + 1.0) 
  *in\x + ((1.0 - a) * color1\x + a * color2\x)
  *in\y + ((1.0 - a) * color1\y + a * color2\y)
  *in\z + ((1.0 - a) * color1\z + a * color2\z)
EndProcedure  

Procedure.d ray_color_hit(*ray.Ray, *in.vec3d, depth)
  Protected.vec3d x, p
  Protected t.d = 0.0
  Protected id.i = 0
  Protected.ray rr, unit_vector
  
  If depth < 0
    vec3_set(*in,0.0,0.0,0.0) : ProcedureReturn
  EndIf
  Protected.vec3d ruv, n, nl
  If intersect(*ray, @t, @id)
    SelectElement(scene(),id)
    Protected *obj.Sphere = scene()
    
    ; Point at parameter
    x\x = *ray\origin\x + t * *ray\direction\x
    x\y = *ray\origin\y + t * *ray\direction\y
    x\z = *ray\origin\z + t * *ray\direction\z
    
    ; Norm
    vec3_subtract(n, x, *obj\center)
    vec3_normalize(n)
    
    ; Set to normal
    If vec3_dot(n, *ray\direction ) < 0.0
      vec3_copy(nl, n)
    Else
      vec3_negate(nl, n)
    EndIf

    vec3_copy(rr\origin, x)

    random_unit_vector(@ruv) 
    vec3_add(rr\direction,nl,ruv) 

    ray_color_hit(rr, *in , depth-1)
    *in\x * 0.5 : *in\y * 0.5 : *in\z * 0.5
  Else
    
    ray_color(*ray, *in)
    *in\x * 0.5 : *in\y * 0.5 : *in\z * 0.5
  EndIf
  
EndProcedure

Define aspect_ratio.d = 16.0 / 9.0
Define image_width = 800

Define image_height = Int(image_width / aspect_ratio)

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

; Render engine
Procedure render()
  Shared image_width, image_height
  Static focal_length.d = 1.0, viewport_height.d = 2.0
  Protected i_w.d = image_width, i_h.d = image_height
  Protected viewport_width.d = viewport_height * (i_w/i_h)
  
  Protected.vec3d point3, ray_direction, viewport3_u, viewport3_v, pixel_delta_u, pixel_delta_v, v_f, viewport_upper_left, pixel_100_loc
  
  vec3_set(point3, 0,0,0)
  vec3_set(ray_direction, 0,0,0)
  vec3_set(viewport3_u, viewport_width,0,0)
  vec3_set(viewport3_v, 0,-viewport_height,0)
  vec3_set(pixel_delta_u, viewport3_u\x / i_w, viewport3_u\y / i_w, viewport3_u\z / i_w)
  vec3_set(pixel_delta_v, viewport3_v\x / i_h, viewport3_v\y / i_h, viewport3_v\z / i_h)
  vec3_set(v_f, 0,0,focal_length)
  vec3_set(viewport_upper_left,
           point3\x - v_f\x - viewport3_u\x / 2 - viewport3_v\x / 2,
           point3\y - v_f\y - viewport3_u\y / 2 - viewport3_v\y / 2,
           point3\z - v_f\z - viewport3_u\z / 2 - viewport3_v\z / 2)
  vec3_set(pixel_100_loc, 0,0,focal_length)

  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)
  
  Protected x.d, y.d, z.d, v.vec3d
  Protected ray.ray
  Static offset.vec3d, pixel_sample.vec3d
  Protected j,i,jj.d, ii.d, sample
  
  For j = 0 To image_height-1
    glBegin_(#GL_POINTS)
    For i = 0 To image_width-1
      x = 0.0 : y = 0.0 : z = 0.0
      For sample = 1 To #Samples_per_pixel
        ii = i + random_double() - 0.5 
        jj = j + random_double() - 0.5 
        
        pixel_sample\x = pixel_100_loc\x + ii * pixel_delta_u\x +  jj * pixel_delta_v\x
        pixel_sample\y = pixel_100_loc\y + ii * pixel_delta_u\y +  jj * pixel_delta_v\y
        pixel_sample\z = pixel_100_loc\z + ii * pixel_delta_u\z +  jj * pixel_delta_v\z
        
        vec3_subtract(ray_direction,pixel_sample,point3)

        ray\origin = point3
        ray\direction = ray_direction          
        
        ray_color_hit(@ray, @v, #Max_Depth) 
        x = x + v\x : y = y + v\y : z = z + v\z
      Next
      
      glColor3f_(#Sample_scale * x, #Sample_scale * y, #Sample_scale * z) : glVertex2s_(i,j)

    Next
    glEnd_() : glFlush_()
  Next
  
EndProcedure

OpenWindow(0, 0, 0, image_width / DesktopResolutionX(), image_height / DesktopResolutionY(), "Inspired from Raytracing in One Weekend", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
OpenGLGadget(0,0,0,image_width / DesktopResolutionX(),image_height / DesktopResolutionY(),#PB_OpenGL_NoFlipSynchronization)
glOrtho_(0,image_width,image_height,0,-1,1)
glDrawBuffer_(#GL_FRONT)  

Define time = ElapsedMilliseconds()
render()
  time = ElapsedMilliseconds() - time
SetWindowTitle(0,"Inspired from Raytracing in One Weekend - RenderTime: "+Str(time)+"ms")

Define Event

Repeat
  Event = WindowEvent()
Until  Event = #PB_Event_CloseWindow

End 
Avatar de l’utilisateur
threedslider
Messages : 452
Inscription : dim. 01/juil./2018 22:38

Re: Raytracing in One Weekend

Message par threedslider »

Hello je suis de retour ^^

Ok j'ai codé la matière de réflexion sur deux sphères et de leur propre couleur aussi :)

Voici le code du petit changement :

Code : Tout sélectionner

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

EnableExplicit

Enumeration Shading
  #None
  #Lambertian
  #Metal
EndEnumeration


#Samples_per_pixel = 35
#Max_Depth = 2
#Sample_scale = 1.0 / #Samples_per_pixel

; Vector
Structure Vec3d : x.d : y.d : z.d : EndStructure

Procedure vec3_normalize(*v.vec3d)
  Protected n.d = Sqr(*v\x * *v\x + *v\y * *v\y + *v\z * *v\z)
  If n <> 0.0 : n = 1.0/n : *v\x * n : *v\y * n : *v\z * n : EndIf
EndProcedure

Macro vec3_zero(v) : v\x = 0.0 : v\y = 0.0 : v\z = 0.0 : EndMacro
Macro vec3_length(v) : Sqr(v\direction\x * v\direction\x + v\direction\y * v\direction\y + v\direction\z * v\direction\z) : EndMacro
Macro vec3_length_squared(v) : (v\x * v\x + v\y * v\y + v\z * v\z) : EndMacro
Macro vec3_dot(v1, v2) : (v1\x * v2\x + v1\y * v2\y + v1\z * v2\z) : EndMacro
Macro vec3_copy(v, v1) : v\x = v1\x : v\y = v1\y : v\z = v1\z : EndMacro
Macro vec3_add(v, v1, v2) : v\x = v1\x + v2\x : v\y = v1\y + v2\y : v\z = v1\z + v2\z : EndMacro
Macro vec3_subtract(v, v1, v2) : v\x = v1\x - v2\x : v\y = v1\y - v2\y : v\z = v1\z - v2\z : EndMacro
Macro vec3_mul(v, v1, v2) : v\x = v1\x * v2\x : v\y = v1\y * v2\y : v\z = v1\z * v2\z : EndMacro
Macro vec3_scale(v, v1, s) : v\x = v1\x * s : v\y = v1\y * s : v\z = v1\z * s : EndMacro  
Macro vec3_set(v, vx, vy, vz) : v\x = vx : v\y = vy : v\z = vz : EndMacro
Macro vec3_negate(v, v1) : v\x = -v1\x : v\y = -v1\y : v\z = -v1\z : EndMacro
Macro random_double() : Random(#MAXDWORD) / #MAXDWORD : EndMacro
Macro random_min_max(min, max) : min + (max-min) * random_double() : EndMacro
Macro reflect(v, v1, n1) : v\x  = v\x - 2 * vec3_dot(v1, n1) * n1\x : v\y  = v\y - 2 * vec3_dot(v1, n1) * n1\y : v\z  = v\z - 2 * vec3_dot(v1, n1) * n1\z : EndMacro

Structure Ray ; Ray
  origin.vec3d : direction.vec3d
EndStructure

Structure Sphere ; Sphere
  center.vec3d
  color.vec3d
  radius.d
  Shading.i
EndStructure

Structure Material ; Material
  albedo.vec3d
EndStructure

Procedure.d clamp(x.d, min.d, max.d)
  If x < min
    ProcedureReturn min
  ElseIf x > max
    ProcedureReturn max
  EndIf
  ProcedureReturn x
EndProcedure

Procedure unit_vector_vec3(*v.vec3d)
  vec3_normalize(*v)
EndProcedure  

Procedure random_in_unit_sphere(*v.vec3d)
  Repeat
    *v\x = random_min_max(-1.0, 1.0)
    *v\y = random_min_max(-1.0, 1.0)
    *v\z = random_min_max(-1.0, 1.0)
    If vec3_length_squared(*v) < 1.0 : ProcedureReturn : EndIf
  ForEver
EndProcedure
Procedure random_unit_vector(*v.vec3d)
  random_in_unit_sphere(*v)
  unit_vector_vec3(*v)
EndProcedure

Macro surrounds(x, min, max) : Bool(min <= x And x <= max) : EndMacro

; Create Sphere primitve
Macro m_Sphere(center_x, center_y, center_z, radius_, color_x, color_y, color_z, shading_)
  AddElement(scene())
  vec3_set(scene()\center,center_x,center_y,center_z)
  vec3_set(scene()\color,color_x,color_y,color_z)
  scene()\radius = radius_
  scene()\Shading = shading_
EndMacro

Global NewList scene.Sphere()

m_Sphere(0.0, -100.5, -1.0, 100.0, 0.8, 0.8, 0.0, #Lambertian); ; << - PJ240614 - pushed this down
m_Sphere(0.0, 0.0, -1.2, 0.5, 0.1, 0.2, 0.5, #Lambertian)
m_Sphere(-1.0, 0.0, -1.0, 0.5, 0.8, 0.8, 0.8, #Metal)
m_Sphere(1.0, 0.0, -1.0, 0.5, 0.8, 0.6, 0.2, #Metal)

Procedure near_zero (*v.vec3d) ;Near zero for pathtracing calculation
  Protected e.d = 1e-8
  ProcedureReturn Bool((Abs(*v\x) < e) And (Abs(*v\y) < e) And (Abs(*v\z) < e))
EndProcedure


; Hit for 3D objects
Procedure.d hit(*_s.Sphere, *ray.Ray, max.d)
  
  Protected oc.vec3d
  Protected root.d = 0.0
  Protected min.d = 0.0001
  
  vec3_subtract(oc, *_s\center,*ray\origin) 
  
  Protected a.d = vec3_length_squared(*ray\direction)
  Protected h.d = vec3_dot(*ray\direction,oc)
  Protected c.d = vec3_length_squared(oc) - *_s\radius * *_s\radius
  
  Protected discriminant.d = h * h - a * c
  
  If discriminant < 0.0 : ProcedureReturn #False : EndIf
  
  Protected sqrtd.d = Sqr(discriminant)
  
  root = (h - sqrtd) / a
  
  If Not surrounds(root, min, max)
    root = (h + sqrtd) / a
    If Not surrounds(root, min, max) : ProcedureReturn 0.0 : EndIf
  EndIf 

  ProcedureReturn root
  
EndProcedure

; Hit for intersection
Procedure.b intersect( *ray.Ray, *t.double, *id.Integer )
  Protected d.d, inf.d = 999.999
  *t\d = inf
  ForEach scene()
    d = hit(@scene(), *ray, *t\d)
    If d
      *t\d  = d
      *id\i = ListIndex(scene())
    EndIf
  Next
  ProcedureReturn Bool( *t\d < inf )
EndProcedure

; Unit vector Y for background
Procedure.d unit_vector_y(*vy.Ray)
  Protected len.d
  Static y.d : y.d = 0
  len = vec3_length(*vy)
  If len <> 0.0 : y = *vy\direction\y / len  : EndIf
  ProcedureReturn y
EndProcedure

Procedure.d ray_color(*rr.Ray, *in.vec3d)
  Protected a.d
  Static color1.vec3d, color2.vec3d, unit_directionection.vec3d
  
  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_directionection\y = unit_vector_y(*rr)
  a = 0.5 * (unit_directionection\y + 1.0) 
  *in\x + ((1.0 - a) * color1\x + a * color2\x)
  *in\y + ((1.0 - a) * color1\y + a * color2\y)
  *in\z + ((1.0 - a) * color1\z + a * color2\z)
EndProcedure  

Procedure.d linear_to_gamma(num.d)
  If num > 0.0
    ProcedureReturn Sqr(num)
  EndIf
  
  ProcedureReturn 0.0
  
EndProcedure


Procedure.d ray_color_hit(*ray.Ray, *in.vec3d, depth)
  Protected.vec3d x, p
  Protected t.d = 0.0
  Protected id.i = 0
  Protected.ray rr, unit_vector, scattered
  Protected.Vec3d out, reflected
  
  If depth < 0
    vec3_set(*in,0.0,0.0,0.0) : ProcedureReturn
  EndIf
  Protected.vec3d ruv, n, nl
  If intersect(*ray, @t, @id)
    SelectElement(scene(),id)
    Protected *obj.Sphere = scene()
    
    ; Point at parameter
    x\x = *ray\origin\x + t * *ray\direction\x
    x\y = *ray\origin\y + t * *ray\direction\y
    x\z = *ray\origin\z + t * *ray\direction\z
    
    ; Norm
    vec3_subtract(n, x, *obj\center)
    vec3_normalize(n)
    
    ; Set to normal
    If vec3_dot(n, *ray\direction ) < 0.0
      vec3_copy(nl, n)
    Else
      vec3_negate(nl, n)
    EndIf
    
    
    If *obj\shading = #Lambertian
      vec3_copy(rr\origin, x)
  
      random_unit_vector(@ruv) 
      vec3_add(rr\direction,nl,ruv) 
      
        
      ray_color_hit(rr, *in , depth-1)
      *in\x * *obj\color\x : *in\y * *obj\color\y : *in\z * *obj\color\z 
    
    ElseIf *obj\shading = #Metal
      
      reflect(reflected, *ray\direction, nl)
    
      vec3_copy(rr\origin, x)
      
      vec3_copy(rr\direction, reflected)
      
      ray_color_hit(rr, *in , depth-1)
      *in\x * *obj\color\x : *in\y * *obj\color\y : *in\z * *obj\color\z 
    
    
    EndIf
;     
;     vec3_set(*in,0.0,0.0,0.0)
    
  Else
    
    ray_color(*ray, *in)
    *in\x * 0.5 : *in\y * 0.5 : *in\z * 0.5
  EndIf
  
EndProcedure

Define aspect_ratio.d = 16.0 / 9.0
Define image_width = 800

Define image_height = Int(image_width / aspect_ratio)

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

; Render engine
Procedure render()
  Shared image_width, image_height
  Static focal_length.d = 1.0, viewport_height.d = 2.0
  Protected i_w.d = image_width, i_h.d = image_height
  Protected viewport_width.d = viewport_height * (i_w/i_h)
  
  Protected.vec3d point3, ray_direction, viewport3_u, viewport3_v, pixel_delta_u, pixel_delta_v, v_f, viewport_upper_left, pixel_100_loc
  
  vec3_set(point3, 0,0,0)
  vec3_set(ray_direction, 0,0,0)
  vec3_set(viewport3_u, viewport_width,0,0)
  vec3_set(viewport3_v, 0,-viewport_height,0)
  vec3_set(pixel_delta_u, viewport3_u\x / i_w, viewport3_u\y / i_w, viewport3_u\z / i_w)
  vec3_set(pixel_delta_v, viewport3_v\x / i_h, viewport3_v\y / i_h, viewport3_v\z / i_h)
  vec3_set(v_f, 0,0,focal_length)
  vec3_set(viewport_upper_left,
           point3\x - v_f\x - viewport3_u\x / 2 - viewport3_v\x / 2,
           point3\y - v_f\y - viewport3_u\y / 2 - viewport3_v\y / 2,
           point3\z - v_f\z - viewport3_u\z / 2 - viewport3_v\z / 2)
  vec3_set(pixel_100_loc, 0,0,focal_length)

  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)
  
  Protected x.d, y.d, z.d, v.vec3d
  Protected ray.ray
  Static offset.vec3d, pixel_sample.vec3d
  Protected j,i,jj.d, ii.d, sample
  
  For j = 0 To image_height-1
    glBegin_(#GL_POINTS)
    For i = 0 To image_width-1
      x = 0.0 : y = 0.0 : z = 0.0
      For sample = 1 To #Samples_per_pixel
        ii = i + random_double() - 0.5 
        jj = j + random_double() - 0.5 
        
        pixel_sample\x = pixel_100_loc\x + ii * pixel_delta_u\x +  jj * pixel_delta_v\x
        pixel_sample\y = pixel_100_loc\y + ii * pixel_delta_u\y +  jj * pixel_delta_v\y
        pixel_sample\z = pixel_100_loc\z + ii * pixel_delta_u\z +  jj * pixel_delta_v\z
        
        vec3_subtract(ray_direction,pixel_sample,point3)

        ray\origin = point3
        ray\direction = ray_direction          
        
        ray_color_hit(@ray, @v, #Max_Depth) 
        x = x + v\x : y = y + v\y : z = z + v\z
      Next
      
      glColor3f_(linear_to_gamma(#Sample_scale * x), linear_to_gamma(#Sample_scale * y), linear_to_gamma(#Sample_scale * z)) : glVertex2s_(i,j)

    Next
    glEnd_() : glFlush_()
  Next
  
EndProcedure

OpenWindow(0, 0, 0, image_width / DesktopResolutionX(), image_height / DesktopResolutionY(), "Inspired from Raytracing in One Weekend", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
OpenGLGadget(0,0,0,image_width / DesktopResolutionX(),image_height / DesktopResolutionY(),#PB_OpenGL_NoFlipSynchronization)
glOrtho_(0,image_width,image_height,0,-1,1)
glDrawBuffer_(#GL_FRONT)  

Define time = ElapsedMilliseconds()
render()
  time = ElapsedMilliseconds() - time
SetWindowTitle(0,"Inspired from Raytracing in One Weekend - RenderTime: "+Str(time)+"ms")

Define Event

Repeat
  Event = WindowEvent()
Until  Event = #PB_Event_CloseWindow

End 
Répondre