POV-Ray : Newsgroups : povray.binaries.images : Basic SDL raymarcher : Basic SDL raymarcher Server Time
20 May 2024 06:01:40 EDT (-0400)
  Basic SDL raymarcher  
From: Samuel B 
Date: 9 Aug 2023 20:00:00
Message: <web.64d427081961efb7f8c47d526e741498@news.povray.org>
Hi,

Here's a generic raymarcher in POV-Ray. It consists of a camera looking at a
plane, and a pattern applied to said plane. Only diffuse shading has been
implemented (no shadows, reflections, etc.) The pattern loops through x and y
gradients, and uses various inputs which define the scene.

I would have liked to do this using pure functions (and not pigment_map loops)
but... solutions based on nothing but functions are hard to figure out :P

Sam

/*

BasicRaymarching.pov

2023 Sam Benge

Warning! It takes a long time to parse. For faster parsing, lower the values for
Res and NSteps.

*/

#version 3.7;
global_settings{assumed_gamma 2.2}
#default{ finish{emission 1} }

camera{
 orthographic
 right x up y
 location -z
 look_at 0
}

// a displacement pattern for the plane
#declare FPattern = function{pattern{crackle}}

// Distance Estimate for sphere and plane (This is the scene's geometry.
DE=signed distance function)
#declare DE =
 function{
  min(
   // sphere
   sqrt(x*x+y*y+z*z)-2,

   // plane
   y+1.9

   // displacement for plane
   - .4*FPattern(x, y, z)
  )
 }

//~~~ Raymarching Variables ~~~//

//  x & y resolution (later versions of POV-Ray [or maybe just UberPOV] allow
for more than 256 pigment_map entries)
#declare Res = <256, 256>;

// number of raymarching steps
#declare NSteps = 64;

// camera position
#declare RayBeg = <0, 0, -10>;

// light position
#declare LPos = vnormalize(<1, .5, -.3>);

// raymarching bailout threshold
#declare Threshold = 0.001;

// normal accuracy
#declare NAcc = .001;


//~~~ Rendering ~~~//

// we are just looking at a plane
plane{
 z, 0

 // image is mapped using two gradients: x & y
 pigment{

  // image uv y gradient
  function{min(1, max(0, y))}
  pigment_map{
   #for(Y, 0, Res.y-1)
    [1/Res.y*Y

     // image uv x gradient
     function{min(1, max(0, x))}
     pigment_map{
      #for(X, 0, Res.x-1)
       [1/Res.x*X

        // initialize Ray
        #local Ray = RayBeg;

        // ray direction
        #local RayDir = vnormalize(<X/Res.x-.5, Y/Res.y-.5, 1>);

        // did the ray hit something?
        // -1  = no, it did not
        // >=0 = yeah, it hit something
        #local FDist = -1;

        // march the ray through DE
        #for(I, 0, NSteps-1)

         // functions require all axes to be reduced to single values
         #local RX = Ray.x;
         #local RY = Ray.y;
         #local RZ = Ray.z;

         // value for DE at Ray position
         #local Dist = DE(RX, RY, RZ);

         // if DE at Ray position is below threshold
         #if(Dist<Threshold)

          // the ray hit something, so we give FDist a value
          #local FDist = Dist;

          // and then we get surface normal
          #local Norm =
           vnormalize(
            <
             DE(RX-NAcc, RY, RZ)-DE(RX+NAcc, RY, RZ),
             DE(RX, RY-NAcc, RZ)-DE(RX, RY+NAcc, RZ),
             DE(RX, RY, RZ-NAcc)-DE(RX, RY, RZ+NAcc)
            >
           );

          #break
         #end

         // advance the ray
         #local Ray = Ray + Dist * RayDir;

        #end

        // return color/value based on whether or not the ray hit something
        #if(FDist>=0)

         // diffuse shading
         rgb .875 * max(0, pow(vdot(Norm, -LPos), .75))

        #else

         // background
         rgb .5

        #end
       ]
      #end
     }
    ]
   #end
  }

  // center pattern on screen
  translate -.5*(x+y-1/Res)
 }
}


Post a reply to this message


Attachments:
Download 'basicraymarching.jpg' (68 KB)

Preview of image 'basicraymarching.jpg'
basicraymarching.jpg


 

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.