RayTracer Theory and Practice

Everything else that doesn't fall into one of the other PB categories.
Dreglor
Enthusiast
Enthusiast
Posts: 759
Joined: Sat Aug 02, 2003 11:22 pm
Location: OR, USA

Post by Dreglor »

Well heres code update.

ive heres a small list of what ive changed
added the adptive subsampling code (theres a slight bug some were in it thought) it renders at 4 fps :shock: even at 0.98 accuracy

changed the rendering code so it can still do perfect renderings

opmitimized the 1:1 rendering code (got rid of alot of nasty usless stuff) now it renders under a second here ;)


now about the bug

when you render you get alot of blocks my guess is that i missed a few parts when duplicating code its just reading wrong pixels in the array and trying to average them :?
the textured triangle gets the worst of it

heres a pic to show what im talking about

Image

and heres a pic of what triangles are accally being rendered
its just for fun ;)

Image

and here is the download for the source code and executes

>>>PBRay7-30-05.zip<<<
Image
~Dreglor
User avatar
Hades
Enthusiast
Enthusiast
Posts: 188
Joined: Tue May 17, 2005 8:39 pm

Post by Hades »

Wow, nice first try. :D

That bug should be a minor one, but I must admit, I don't really understand what you are doing at the moment. :?

Wouldn' it be better to split the screen into 4x4(or whatever) tiles, subsampling them if necessary, and let the quads be rendered by OpenGL, before starting the next tile ?


PS: Your exe finishes here after 187ms . Go on. I want to see those 60 fps :D
User avatar
Hades
Enthusiast
Enthusiast
Posts: 188
Joined: Tue May 17, 2005 8:39 pm

Post by Hades »

While testing your new code I have accidently overwritten that old code with that new triangle intersection procedures. I have already recoded it in PureBasic, but for now I am not motivated to start ASM conversion again. :(

I just post what I have at the moment, so you can integrate it. For me it is also easier to convert it to ASM, if I see how you have integrated it.

You didn't call AddTriangleObject from LoadWaveFrontModel. You should change that, or you have to do all changes for triangles always twice.


Code: Select all

Structure Triangle
  v1.xyz
  v2.xyz
  v3.xyz
  nu.f
  nv.f
  nd.f
  bnu.f
  bnv.f
  cnu.f
  cnv.f
  tv1.uv
  tv2.uv
  tv3.uv
EndStructure

Code: Select all

Procedure PrecalcTriangle(*Triangle.Object, *v1.xyz, *v2.xyz, *v3.xyz) ; Call this after moving the triangle again
  *Tri.Triangle = *Triangle\Primitive
  *Tri\v1\x = *v1\x
  *Tri\v1\y = *v1\y
  *Tri\v1\z = *v1\z
  *Tri\v2\x = *v2\x
  *Tri\v2\y = *v2\y
  *Tri\v2\z = *v2\z
  *Tri\v3\x = *v3\x
  *Tri\v3\y = *v3\y
  *Tri\v3\z = *v3\z
  *v2\x - *v1\x
  *v2\y - *v1\y
  *v2\z - *v1\z
  *v3\x - *v1\x
  *v3\y - *v1\y
  *v3\z - *v1\z
  *Tri.Triangle = *Triangle\Primitive
  VectorCrossMuiltply(*v2, *v3, *Triangle\Normal) ; Calculate 
  VectorNormalizeFPU(*Triangle\Normal)            ; Normal
  
  If Abs(*Triangle\Normal\x) > Abs(*Triangle\Normal\y)
    If Abs(*Triangle\Normal\x) > Abs(*Triangle\Normal\z)
      ; X
      *Tri\nu = *Triangle\Normal\y / *Triangle\Normal\x
      *Tri\nv = *Triangle\Normal\z / *Triangle\Normal\x 
      *Tri\nd = (*Triangle\Normal\x * *Tri\v1\x + *Triangle\Normal\y * *Tri\v1\y + *Triangle\Normal\z * *Tri\v1\z) / *Triangle\Normal\x
      vcp.f = 1.0 / (*v2\y * *v3\z - *v2\z * *v3\y)
      *Tri\bnu = *v2\y * vcp
      *Tri\bnv = -*v2\z * vcp
      *Tri\cnu = *v3\z * vcp
      *Tri\cnv = -*v3\y * vcp
      *Triangle\IntersectionMethod=@TestTriangleX()
    Else
      ; Z
      *Tri\nu = *Triangle\Normal\x / *Triangle\Normal\z
      *Tri\nv = *Triangle\Normal\y / *Triangle\Normal\z 
      *Tri\nd = (*Triangle\Normal\x * *Tri\v1\x + *Triangle\Normal\y * *Tri\v1\y + *Triangle\Normal\z * *Tri\v1\z) / *Triangle\Normal\z
      vcp.f = 1.0 / (*v2\x * *v3\y - *v2\y * *v3\x)
      *Tri\bnu = *v2\x * vcp
      *Tri\bnv = -*v2\y * vcp
      *Tri\cnu = *v3\y * vcp
      *Tri\cnv = -*v3\x * vcp
      *Triangle\IntersectionMethod=@TestTriangleZ()
    EndIf
  Else 
    If Abs(*Triangle\Normal\y) > Abs(*Triangle\Normal\z)
      ; Y
      *Tri\nu = *Triangle\Normal\z / *Triangle\Normal\y
      *Tri\nv = *Triangle\Normal\x / *Triangle\Normal\y 
      *Tri\nd = (*Triangle\Normal\x * *Tri\v1\x + *Triangle\Normal\y * *Tri\v1\y + *Triangle\Normal\z * *Tri\v1\z) / *Triangle\Normal\y
      vcp.f = 1.0 / (*v2\z * *v3\x - *v2\x * *v3\z)
      *Tri\bnu = *v2\z * vcp
      *Tri\bnv = -*v2\x * vcp
      *Tri\cnu = *v3\x * vcp
      *Tri\cnv = -*v3\z * vcp
      *Triangle\IntersectionMethod=@TestTriangleY()
    Else
      ; Z
      *Tri\nu = *Triangle\Normal\x / *Triangle\Normal\z
      *Tri\nv = *Triangle\Normal\y / *Triangle\Normal\z 
      *Tri\nd = (*Triangle\Normal\x * *Tri\v1\x + *Triangle\Normal\y * *Tri\v1\y + *Triangle\Normal\z * *Tri\v1\z) / *Triangle\Normal\z
      vcp.f = 1.0 / (*v2\x * *v3\y - *v2\y * *v3\x)
      *Tri\bnu = *v2\x * vcp
      *Tri\bnv = -*v2\y * vcp
      *Tri\cnu = *v3\y * vcp
      *Tri\cnv = -*v3\x * vcp
      *Triangle\IntersectionMethod=@TestTriangleZ()
    EndIf
  EndIf
EndProcedure

Code: Select all

Procedure.l AddTriangleObject(*Triangle.Object,*v1.xyz,*v2.xyz,*v3.xyz)
  ; stime.l=ElapsedMilliseconds()
  ; Debug "Entering AddTriangleObject() With"+Hex(*Triangle)+", "+Hex(*v1)+", "+Hex(*v2)+", "+Hex(*v3)+", "+Hex(*Normal)
  If CountList(ObjectList())>0
    *Old_Element = @ObjectList()
  EndIf
  AddElement(ObjectList())
  ;copy object data into the new object
  CopyMemory(*Triangle,@ObjectList(),SizeOf(Object))
  ;put any primtive specific data into there places
  ObjectList()\Primitive=AllocateMemory(SizeOf(Triangle))
  ObjectList()\Type=#ObjectType_Triangle
  PrecalcTriangle(@ObjectList(), *v1, *v2, *v3)
  result.l=@ObjectList()
  If *Old_Element<>#Null
    ChangeCurrentElement(ObjectList(), *Old_Element)
  EndIf
  result.l=@ObjectList()
  ; Debug "Leaving AddTriangleObject() With"+Hex(result)
  ; etime.l=ElapsedMilliseconds()
  ; LastProcedureTime=etime-stime
  ProcedureReturn result
EndProcedure

Code: Select all

Procedure TestTriangleX(*Origin.xyz,*Direction.xyz,*Triangle.Object,*result.IntersectReturn)
  *Tri.Triangle = *Triangle\Primitive
  Det.f = 1.0 / (*Direction\x + *Tri\nu * *Direction\y - *Tri\nv * *Direction\z)
  *result\result=#Miss
  t.f = (*Tri\nd - *Origin\x - *Tri\nu * *Origin\y - *Tri\nv * *Origin\z) * Det
  If t < #EPSILON
    *result\t=0.0
    ProcedureReturn 
  EndIf
  Pu.f = *Origin\y + t * *Direction\y - *Tri\v1\y
  Pv.f = *Origin\z + t * *Direction\z - *Tri\v1\z
  u.f = Pv * *Tri\bnu + Pu * *Tri\bnv
  If u < 0.0
    *result\t=0.0
    ProcedureReturn  
  EndIf
  v.f = Pu * *Tri\cnu + Pv * *Tri\cnv
  If v < 0.0 Or u + v > 1.0
    *result\t=0.0
    ProcedureReturn  
  EndIf
  *result\result=#Hit
  *result\TextureCoords\u = u    ; texture coordinates
  *result\TextureCoords\v = v    ;
  *result\t=t
  ProcedureReturn
EndProcedure

Procedure TestTriangleY(*Origin.xyz,*Direction.xyz,*Triangle.Object,*result.IntersectReturn)
  *Tri.Triangle = *Triangle\Primitive
  Det.f = 1.0 / (*Direction\y + *Tri\nu * *Direction\z - *Tri\nv * *Direction\x)
  *result\result=#Miss
  t.f = (*Tri\nd - *Origin\y - *Tri\nu * *Origin\z - *Tri\nv * *Origin\x) * Det
  If t < #EPSILON
    *result\t=0.0
    ProcedureReturn 
  EndIf
  Pu.f = *Origin\z + t * *Direction\z - *Tri\v1\z
  Pv.f = *Origin\x + t * *Direction\x - *Tri\v1\x
  u.f = Pv * *Tri\bnu + Pu * *Tri\bnv
  If u < 0.0
    *result\t=0.0
    ProcedureReturn  
  EndIf
  v.f = Pu * *Tri\cnu + Pv * *Tri\cnv
  If v < 0.0 Or u + v > 1.0
    *result\t=0.0
    ProcedureReturn  
  EndIf
  *result\result=#Hit
  *result\TextureCoords\u = u    ; texture coordinates
  *result\TextureCoords\v = v    ;
  *result\t=t
  ProcedureReturn
EndProcedure

Procedure TestTriangleZ(*Origin.xyz,*Direction.xyz,*Triangle.Object,*result.IntersectReturn)
  *Tri.Triangle = *Triangle\Primitive
  Det.f = 1.0 / (*Direction\z + *Tri\nu * *Direction\x - *Tri\nv * *Direction\y)
  *result\result=#Miss
  t.f = (*Tri\nd - *Origin\z - *Tri\nu * *Origin\x - *Tri\nv * *Origin\y) * Det
  If t < #EPSILON
    *result\t=0.0
    ProcedureReturn 
  EndIf
  Pu.f = *Origin\x + t * *Direction\x - *Tri\v1\x
  Pv.f = *Origin\y + t * *Direction\y - *Tri\v1\y
  u.f = Pv * *Tri\bnu + Pu * *Tri\bnv
  If u < 0.0
    *result\t=0.0
    ProcedureReturn  
  EndIf
  v.f = Pu * *Tri\cnu + Pv * *Tri\cnv
  If v < 0.0 Or u + v > 1.0
    *result\t=0.0
    ProcedureReturn  
  EndIf
  *result\result=#Hit
  *result\TextureCoords\u = u    ; texture coordinates
  *result\TextureCoords\v = v    ;
  *result\t=t
  ProcedureReturn
EndProcedure

Additionaly you should consider to change this to get always the correct normal:

Code: Select all

        If ObjectList()\Type=#ObjectType_Sphere ;normal Calulations are diffrent per object
          radius.f=PeekF(ObjectList()\Primitive)
          Normal\x=((Intersection\x-ObjectList()\Origin\x)/radius)
          Normal\y=((Intersection\y-ObjectList()\Origin\y)/radius)
          Normal\z=((Intersection\z-ObjectList()\Origin\z)/radius)
          ;other cases will be added
        Else
          Normal\x = ObjectList()\Normal\x
          Normal\y = ObjectList()\Normal\y
          Normal\z = ObjectList()\Normal\z
          If Normal\x * *Direction\x + Normal\y * *Direction\y + Normal\z * *Direction\z > 0.0
            Normal\x = -Normal\x
            Normal\y = -Normal\y
            Normal\z = -Normal\z
          EndIf
        EndIf
Dreglor
Enthusiast
Enthusiast
Posts: 759
Joined: Sat Aug 02, 2003 11:22 pm
Location: OR, USA

Post by Dreglor »

ive got one question in implementing the code, how do you test a intersection?
~Dreglor
User avatar
Hades
Enthusiast
Enthusiast
Posts: 188
Joined: Tue May 17, 2005 8:39 pm

Post by Hades »

As always.
After calling the new AddTriangleObject procedure everything is set up, so you can do your "CallFunctionFast(ObjectList()\IntersectionMethod, *Origin,*Direction,@ObjectList(),IntersectionResults)"

Do you experience problems?
Dreglor
Enthusiast
Enthusiast
Posts: 759
Joined: Sat Aug 02, 2003 11:22 pm
Location: OR, USA

Post by Dreglor »

*smacks him self in the head*
i knew that
forgot i changed the structure :P
~Dreglor
Dreglor
Enthusiast
Enthusiast
Posts: 759
Joined: Sat Aug 02, 2003 11:22 pm
Location: OR, USA

Post by Dreglor »

well i tested it with the triangle.obj and it is faster than the old one i noticed that the uv are correct now (they were mirrored and upside down in my version).

then i tried loading the cube.obj insted of the triangle to see if it would show

and i got 8 scambled textured triangles but in my old triangle test code i got a black cube (but at least it was a cube)
im not sure what exectly going that making it do that :\

so here is the implemtated code maybe you can see whats going on

>>>PBRay7-31-05.zip<<<
Image

im going to relax for most of the day i need a break ;)
~Dreglor
User avatar
Hades
Enthusiast
Enthusiast
Posts: 188
Joined: Tue May 17, 2005 8:39 pm

Post by Hades »

At the moment I feel like those triangles. :?

I have to do some tests to find that bug, but not today.
It's late here and I have to sleep... so tired...
User avatar
Hades
Enthusiast
Enthusiast
Posts: 188
Joined: Tue May 17, 2005 8:39 pm

Post by Hades »

Ok, I've found that nasty little bug. Was a very stupid one made by me.
Please replace:

Code: Select all

Procedure PrecalcTriangle(*Triangle.Object, *v1.xyz, *v2.xyz, *v3.xyz) ; Call this after moving the triangle again
  Edge1.xyz
  Edge2.xyz
  *Tri.Triangle = *Triangle\Primitive
  *Tri\v1\x = *v1\x
  *Tri\v1\y = *v1\y
  *Tri\v1\z = *v1\z
  *Tri\v2\x = *v2\x
  *Tri\v2\y = *v2\y
  *Tri\v2\z = *v2\z
  *Tri\v3\x = *v3\x
  *Tri\v3\y = *v3\y
  *Tri\v3\z = *v3\z
  Edge1\x = *v2\x - *v1\x
  Edge1\y = *v2\y - *v1\y
  Edge1\z = *v2\z - *v1\z
  Edge2\x = *v3\x - *v1\x
  Edge2\y = *v3\y - *v1\y
  Edge2\z = *v3\z - *v1\z
  *Tri.Triangle = *Triangle\Primitive
  VectorCrossMuiltply(Edge1, Edge2, *Triangle\Normal) ; Calculate
  VectorNormalizeFPU(*Triangle\Normal)            ; Normal
  
  If Abs(*Triangle\Normal\x) > Abs(*Triangle\Normal\y)
    If Abs(*Triangle\Normal\x) > Abs(*Triangle\Normal\z)
      ; X
      *Tri\nu = *Triangle\Normal\y / *Triangle\Normal\x
      *Tri\nv = *Triangle\Normal\z / *Triangle\Normal\x
      *Tri\nd = (*Triangle\Normal\x * *Tri\v1\x + *Triangle\Normal\y * *Tri\v1\y + *Triangle\Normal\z * *Tri\v1\z) / *Triangle\Normal\x
      vcp.f = 1.0 / (Edge1\y * Edge2\z - Edge1\z * Edge2\y)
      *Tri\bnu = Edge1\y * vcp
      *Tri\bnv = -Edge1\z * vcp
      *Tri\cnu = Edge2\z * vcp
      *Tri\cnv = -Edge2\y * vcp
      *Triangle\IntersectionMethod=@TestTriangleX()
    Else
      ; Z
      *Tri\nu = *Triangle\Normal\x / *Triangle\Normal\z
      *Tri\nv = *Triangle\Normal\y / *Triangle\Normal\z
      *Tri\nd = (*Triangle\Normal\x * *Tri\v1\x + *Triangle\Normal\y * *Tri\v1\y + *Triangle\Normal\z * *Tri\v1\z) / *Triangle\Normal\z
      vcp.f = 1.0 / (Edge1\x * Edge2\y - Edge1\y * Edge2\x)
      *Tri\bnu = Edge1\x * vcp
      *Tri\bnv = -Edge1\y * vcp
      *Tri\cnu = Edge2\y * vcp
      *Tri\cnv = -Edge2\x * vcp
      *Triangle\IntersectionMethod=@TestTriangleZ()
    EndIf
  Else
    If Abs(*Triangle\Normal\y) > Abs(*Triangle\Normal\z)
      ; Y
      *Tri\nu = *Triangle\Normal\z / *Triangle\Normal\y
      *Tri\nv = *Triangle\Normal\x / *Triangle\Normal\y
      *Tri\nd = (*Triangle\Normal\x * *Tri\v1\x + *Triangle\Normal\y * *Tri\v1\y + *Triangle\Normal\z * *Tri\v1\z) / *Triangle\Normal\y
      vcp.f = 1.0 / (Edge1\z * Edge2\x - Edge1\x * Edge2\z)
      *Tri\bnu = Edge1\z * vcp
      *Tri\bnv = -Edge1\x * vcp
      *Tri\cnu = Edge2\x * vcp
      *Tri\cnv = -Edge2\z * vcp
      *Triangle\IntersectionMethod=@TestTriangleY()
    Else
      ; Z
      *Tri\nu = *Triangle\Normal\x / *Triangle\Normal\z
      *Tri\nv = *Triangle\Normal\y / *Triangle\Normal\z
      *Tri\nd = (*Triangle\Normal\x * *Tri\v1\x + *Triangle\Normal\y * *Tri\v1\y + *Triangle\Normal\z * *Tri\v1\z) / *Triangle\Normal\z
      vcp.f = 1.0 / (Edge1\x * Edge2\y - Edge1\y * Edge2\x)
      *Tri\bnu = Edge1\x * vcp
      *Tri\bnv = -Edge1\y * vcp
      *Tri\cnu = Edge2\y * vcp
      *Tri\cnv = -Edge2\x * vcp
      *Triangle\IntersectionMethod=@TestTriangleZ()
    EndIf
  EndIf
EndProcedure 
Dreglor
Enthusiast
Enthusiast
Posts: 759
Joined: Sat Aug 02, 2003 11:22 pm
Location: OR, USA

Post by Dreglor »

i fixed the adaptive subsampling code :)

here is the replacement procedure

Code: Select all

Procedure RenderScene(*Scene.Scene,*ViewPort.Camera)
  Width.w=*Scene\ScreenWidth
  hieght.w=*Scene\ScreenHeight
  If *Scene\SamplingAccuracy=1 ;1:1 method
    Color.Color
    y=0
    While y<hieght
      x=0
      While x<Width
        RayCounter+1
        ;Plot(x,y,#White) ;debug
        *ViewPort\Direction\x = CameraVectors(x,y)\x
        *ViewPort\Direction\y = CameraVectors(x,y)\y
        *ViewPort\Direction\z = CameraVectors(x,y)\z
        TraceRay(*ViewPort\Origin,*ViewPort\Direction,0,1.0,Color) ;refract must be set to 1 for air unless your underwater or somthing...
        ;(1-Pow(#E,-(Color\Red**ViewPort\Apature)))*255
        ;(1-Pow(#E,-(Color\Green**ViewPort\Apature)))*255
        ;(1-Pow(#E,-(Color\Blue**ViewPort\Apature)))*255 ;exposure
        Plot(x,y,RGB(Color\Red*255,Color\Green*255,Color\Blue*255))
        x+1
      Wend ;next x
      y+1
    Wend ;next y
  Else
    ;render the standard grid
    Accuracy.f=*Scene\SamplingAccuracy
    Spacing.b=*Scene\SamplingSpacing
    Dim Plots.Color(Width+Spacing,hieght+Spacing)
    I1.Color
    I2.Color
    I3.Color
    I4.Color
    ;calulate even grid
    y=0
    While y<hieght
      x=0
      While x<Width
        RayCounter+1
        ;Plot(x,y,#White) ;debug
        *ViewPort\Direction\x = CameraVectors(x,y)\x
        *ViewPort\Direction\y = CameraVectors(x,y)\y
        *ViewPort\Direction\z = CameraVectors(x,y)\z
        TraceRay(*ViewPort\Origin,*ViewPort\Direction,0,1.0,Plots(x,y))
        x+Spacing
      Wend ;next x
      y+Spacing
    Wend ;next y
    Repeat
      Threshold.f=Pow(Accuracy, Spacing)
      ;vert halfways
      HalfSpacing.b=Spacing*0.5
      y=HalfSpacing
      While y<=hieght+HalfSpacing
        x=HalfSpacing
        While x<=Width+HalfSpacing
          x1=x
          y1=y-HalfSpacing
          
          I1\Red=Plots(x1+HalfSpacing,y1)\Red
          I1\Green=Plots(x1+HalfSpacing,y1)\Green
          I1\Blue=Plots(x1+HalfSpacing,y1)\Blue
          
          I2\Red=Plots(x1-HalfSpacing,y1)\Red
          I2\Green=Plots(x1-HalfSpacing,y1)\Green
          I2\Blue=Plots(x1-HalfSpacing,y1)\Blue
          
          If Ratio2(I1\Red,I2\Red)>Threshold Or Ratio2(I1\Green,I2\Green)>Threshold Or Ratio2(I1\Blue,I2\Blue)>Threshold
            Plots(x1,y1)\Red=(I1\Red+I2\Red)*0.5
            Plots(x1,y1)\Green=(I1\Green+I2\Green)*0.5
            Plots(x1,y1)\Blue=(I1\Blue+I2\Blue)*0.5
          Else
            Ray1Counter+1
            ;Plot(x1,y1,#White) ;debug
            *ViewPort\Direction\x = CameraVectors(x1,y1)\x
            *ViewPort\Direction\y = CameraVectors(x1,y1)\y
            *ViewPort\Direction\z = CameraVectors(x1,y1)\z
            TraceRay(*ViewPort\Origin,*ViewPort\Direction,0,1.0,Plots(x1,y1))
          EndIf
          ;horz halfway
          x1=x-HalfSpacing
          y1=y
          
          I1\Red=Plots(x1,y1+HalfSpacing)\Red
          I1\Green=Plots(x1,y1+HalfSpacing)\Green
          I1\Blue=Plots(x1,y1+HalfSpacing)\Blue
          
          I2\Red=Plots(x1,y1-HalfSpacing)\Red
          I2\Green=Plots(x1,y1-HalfSpacing)\Green
          I2\Blue=Plots(x1,y1-HalfSpacing)\Blue
          
          If Ratio2(I1\Red,I2\Red)>Threshold Or Ratio2(I1\Green,I2\Green)>Threshold Or Ratio2(I1\Blue,I2\Blue)>Threshold
            Plots(x1,y1)\Red=(I1\Red+I2\Red)*0.5
            Plots(x1,y1)\Green=(I1\Green+I2\Green)*0.5
            Plots(x1,y1)\Blue=(I1\Blue+I2\Blue)*0.5
          Else
            Ray1Counter+1
            ;Plot(x1,y1,#White) ;debug
            *ViewPort\Direction\x = CameraVectors(x1,y1)\x
            *ViewPort\Direction\y = CameraVectors(x1,y1)\y
            *ViewPort\Direction\z = CameraVectors(x1,y1)\z
            TraceRay(*ViewPort\Origin,*ViewPort\Direction,0,1.0,Plots(x1,y1))
          EndIf
          ;center
          ;from vert
          I1\Red=Plots(x+HalfSpacing,y-HalfSpacing)\Red
          I1\Green=Plots(x+HalfSpacing,y-HalfSpacing)\Green
          I1\Blue=Plots(x+HalfSpacing,y-HalfSpacing)\Blue
          
          I2\Red=Plots(x-HalfSpacing,y-HalfSpacing)\Red
          I2\Green=Plots(x-HalfSpacing,y-HalfSpacing)\Green
          I2\Blue=Plots(x-HalfSpacing,y-HalfSpacing)\Blue
          ;from horz
          I3\Red=Plots(x-HalfSpacing,y+HalfSpacing)\Red
          I3\Green=Plots(x-HalfSpacing,y+HalfSpacing)\Green
          I3\Blue=Plots(x-HalfSpacing,y+HalfSpacing)\Blue
          
          I4\Red=Plots(x-HalfSpacing,y-HalfSpacing)\Red
          I4\Green=Plots(x-HalfSpacing,y-HalfSpacing)\Green
          I4\Blue=Plots(x-HalfSpacing,y-HalfSpacing)\Blue
          
          If Ratio4(I1\Red,I2\Red,I3\Red,I4\Red)>Threshold Or Ratio4(I1\Green,I2\Green,I3\Green,I4\Green)>Threshold Or Ratio4(I1\Blue,I2\Blue,I3\Blue,I4\Blue)>Threshold
            Plots(x,y)\Red=(I1\Red+I2\Red+I3\Red+I4\Red)*0.25
            Plots(x,y)\Green=(I1\Green+I2\Green+I3\Green+I4\Green)*0.25
            Plots(x,y)\Blue=(I1\Blue+I2\Blue+I3\Blue+I4\Blue)*0.25
          Else
            RayCounter+1
            ;Plot(x,y,#White) ;debug
            *ViewPort\Direction\x = CameraVectors(x,y)\x
            *ViewPort\Direction\y = CameraVectors(x,y)\y
            *ViewPort\Direction\z = CameraVectors(x,y)\z
            TraceRay(*ViewPort\Origin,*ViewPort\Direction,0,1.0,Plots(x,y))
          EndIf
          x+Spacing
        Wend ;next x
        y+Spacing
      Wend ;next y
      Spacing*0.5
    Until Spacing=1
    For y=0 To hieght-1
      For x=0 To Width-1
        ;(1-Pow(#E,-(Color\Red**ViewPort\Apature)))*255
        ;(1-Pow(#E,-(Color\Green**ViewPort\Apature)))*255
        ;(1-Pow(#E,-(Color\Blue**ViewPort\Apature)))*255 ;exposure
        Plot(x,y,RGB(Plots(x,y)\Red*255,Plots(x,y)\Green*255,Plots(x,y)\Blue*255))
      Next x
    Next y
  EndIf
  ; Debug "Leaving RenderScene()"
  ; etime.l=ElapsedMilliseconds()
  ; LastProcedureTime=etime-stime
EndProcedure
~Dreglor
User avatar
Hades
Enthusiast
Enthusiast
Posts: 188
Joined: Tue May 17, 2005 8:39 pm

Post by Hades »

Wow, nice and very fast. :D
keep it up. :wink:
Dreglor
Enthusiast
Enthusiast
Posts: 759
Joined: Sat Aug 02, 2003 11:22 pm
Location: OR, USA

Post by Dreglor »

I been thinking about The SSE 4 Ray method

and i decided to look up some articals on it and i didn't find very many but there was a one that told how you could order 8 xyz vectors in 6 (of eight) regisiters. it also said in this ordering you could normilize all of them :O!

heres the table that showed how they would be ordered

Code: Select all

4 element  	3 element  	2 element  	1 element  	SSE register
VectorB4.x 	VectorB3.x 	VectorB2.x 	VectorB1.x 	XMM5
VectorB4.y 	VectorB3.y 	VectorB2.y 	VectorB1.y 	XMM4
VectorB4.z 	VectorB3.z 	VectorB2.z 	VectorB1.z 	XMM3
VectorA4.x 	VectorA3.x 	VectorA2.x 	VectorA1.x 	XMM2
VectorA4.y 	VectorA3.y 	VectorA2.y 	VectorA1.y 	XMM1
VectorA4.z 	VectorA3.z 	VectorA2.z 	VectorA1.z 	XMM0
if we could do the same with other operations then we could have a 8 rays insted of 4 and you wouldn't need the xyzw way too!

so i got a few questions,

1. do you think that its possible to make a version of the vector math using this method?

2. could you access registers like XMM0+4 to get VectorA2.z using the method above?

3. I'm intrested in the inline assembly its working it magic pretty well, could you point me to a few documents that are good reading for the assembly beginner ;)

im changing the structure around alot for speed and readablitiy
and im adding a few features...
~Dreglor
User avatar
Hades
Enthusiast
Enthusiast
Posts: 188
Joined: Tue May 17, 2005 8:39 pm

Post by Hades »

1. This method is only possible if you have enough vectors to compute. So if you would reorganize parts of your code so at least 4 vectors would be calculated, it would be very efficient. But to work really nice, the vectors have to be stored like this :
x[0],x[1],x[2],x[3], ...

y[0],y[1],y[2],y[3], ...

z[0],z[1],z[2],z[3], ...
Else one would have to do a lot of shuffeling.


2. Yes, but it is faster to access all vectors at the same time.


3. I would concentrate on assembly for PB. Because there are some differences in accessing vars.

In PBs Help section there is a little bit about PB and ASM.

Check out purearea, within the code section. Especially the math procedures contain some ASM.

Search the PB forums for assembly,
and check out the site of flat assembler (FAsm), the assembler used by PB, for reference.

Be aware of the different syntax of microsoft assembly!
deadmoap
User
User
Posts: 79
Joined: Sun Feb 22, 2004 11:45 pm
Location: Riverdale, Utah
Contact:

Post by deadmoap »

Damn, Hades, you sure answered my question pretty thoroughly (sp?). That explains why on this slow computer, the resolution hardly has an impact on the fps of most of my higher-end games (FF9 funs at 45 fps whether it's at 1024x768 or 640x480). At first I thought raytracing was just a half assed way to render, while now I think rasterizing is more half assed.

One more question though... just out of curiousity, would it be harder to write a raytracer or a rasterizer?
Dreglor
Enthusiast
Enthusiast
Posts: 759
Joined: Sat Aug 02, 2003 11:22 pm
Location: OR, USA

Post by Dreglor »

most of the real time raytracing stuff is done with subsampling which makes the quality "half-assed"

but renders which use non-subsampling approch althought slower are nice looking

Raytracer is alot harder than rasterizing...

alot of it is high level vector math when your calulating for light and stuff but some of the objects are descriped mathimaticly (not so much in my raytracer) so you can't just put a few numbers in and know how it going to come out
the other issue is you have to do diffrent code for diffrent objects the intersections are handled very diffrently you can't intersect a sphere with the same method as you do with a triangle it just doesn't work (infact it would crash)

you get a ease when doing lighting calulations were everything is ray based and is unified it makes it easy to implement somthing new and have it apply to something new
~Dreglor
Post Reply