This content originally appeared on DEV Community and was authored by Tomasz Wegrzanowski
POV-Ray (Persistence of Vision Ray Tracer) is a popular Open Source raytracing program. It takes a text-based description of a scene, then creates a realistic rendering of it.
So of course we'll use it to render a FizzBuzz.
Hello, World!
It's quite difficult to do good looking ray-traced scene, as we're not just setting up what should look how, but how rays of light physically bounce around the scene, and this only translates to the end result indirectly.
#include "colors.inc"
#include "textures.inc"
background { color rgb <0.8, 0.8, 1.0> }
camera {
location <0, 2, -3>
look_at <0, 1, 2>
}
sphere { <0, 0, 2>, 1 texture{Blood_Marble} }
plane { <0, 1, 0>, -1 texture{Brass_Valley} }
light_source { <2, 4, -3> color White }
So what's going on:
- POV-Ray uses CPP-style
#include
directives to include other files - we need to setup
camera
- what's itslocation
and where does itlook_at
- we need to setup some light sources, in this case I setup point light source (like a lamp), at certain location with certain color
- I setup a
background
for where there are no objects - I also added two objects: a
sphere
and an infiniteplane
- position vectors use
<x, y, z>
notation, and color vectors use<r, g, b>
notation - common colors are also defined in
colors.inc
file, we can use named colors instead of RGB - common textures are defined in
textures.inc
file, we can use named textures instead of defining all the texture details - texture details are a major strength of ray tracing systems - and all the reflections and other fancy things they do - we'll be ignoring all of that
Random Checkerboard
For our FizzBuzz to work, we first want to setup a checkerboard. Each tile will correspond to some number.
#include "colors.inc"
#include "textures.inc"
#include "stones.inc"
background { color rgb <0.8, 0.8, 1.0> }
camera {
location <0, 10, -8>
look_at <0, 0, -2>
}
light_source { <2, 4, -3> color White }
plane { <0, 1, 0>, 0 texture{T_Stone10} }
#declare RandomSeed = seed(1);
#for (X,0,9)
#for (Z,0,9)
box {
<X-5, 0.0, Z-5>,
<X-4, 0.1, Z-4>
pigment { color rgb <rand(RandomSeed), rand(RandomSeed), rand(RandomSeed)> }
}
#end
#end
What's going on here:
- I moved camera around until I got what I wanted
-
#for (X,0,9)
is a for loop - POV-Ray directives look sort of like CPP preprocessor, and I'm not really a fan - we can do math expressions like
<X-5, 0.0, Z-5>
-
rand()
is a bit weird in POV-Ray, as it actually wants to make things "reproduceable random" - so random-looking, but always generating the same pattern no matter how many times you run it. What we pass is the RNG sequence ID,rand()
always returns numbers from 0 to 1. If you want a different range, multiple or add some things to it. -
box
is a box, if we don't rotate it, it's aligned with all three axes - The boxes we declare are 1 unit wide, 1 unit deep, and 0.1 units tall, placed directly on the infinite plane.
- I picked a different texture for the plane,
T_Stone10
fromstones.inc
- I'm just trying things at random here
Checkerboard with Objects
Let's number the squares 1 to 100, and put an object proportional to that number on each square. Also let's make the checkerboard pattern just checkerboardy, with two materials.
#include "colors.inc"
#include "metals.inc"
#include "stones.inc"
#include "textures.inc"
#include "woods.inc"
background { color rgb <0.8, 0.8, 1.0> }
camera {
location <0, 10, -8>
look_at <0, 0, -2>
}
light_source { <2, 4, -3> color White }
plane { <0, 1, 0>, 0 texture{T_Stone10} }
#declare RandomSeed = seed(1);
#for (X,0,9)
#for (Z,0,9)
#declare N = 91+X-10*Z;
#declare OE = mod(X+Z, 2);
box {
<X-5, 0.0, Z-5>,
<X-4, 0.1, Z-4>
#if (OE = 0)
texture{T_Stone18}
#else
texture{T_Wood32}
#end
}
box {
<X-4.6, 0.1, Z-4.6>,
<X-4.4, 0.1+0.01*N, Z-4.4>
texture{T_Brass_1B}
}
#end
#end
- we can declare some variables with
#declare
-N
is what we'll be using for FizzBuzz,OE
is for checkerboard pattern -
#if
#else
#end
can do various conditional logic - I picked some random materials from
metals.inc
,stones.inc
, andwoods.inc
- this would be a lot easier if there was an interactive interface for it, but it will do for now - the box on each tile is 0.01*N unit tall, 0.2 units wide and deep, centered on the tile, and placed directly on the tile
Fizz and Buzz
POV-Ray absolutely supports text, so we could engrave some FizzBuzz text on the tiles, but I think it's boring. Let's just have one object symbolize Fizz, another symbolize Buzz, and place both for FizzBuzz. We'll figure out the number tiles later.
#include "colors.inc"
#include "metals.inc"
#include "stones.inc"
#include "textures.inc"
#include "woods.inc"
background { color rgb <0.8, 0.8, 1.0> }
camera {
location <0, 10, -8>
look_at <0, 0, -2>
}
light_source { <2, 4, -3> color White }
plane { <0, 1, 0>, 0 texture{T_Stone10} }
#declare Fizz = cone {
<0, 0.1, 0>, 0.2,
<0, 1.3, 0>, 0.0
texture{T_Copper_4C}
}
#declare Buzz = torus {
0.3, 0.1
translate <0, 0.2, 0>
texture{T_Wood6}
}
#declare RandomSeed = seed(1);
#for (X,0,9)
#for (Z,0,9)
#declare N = 91+X-10*Z;
#declare OE = mod(X+Z, 2);
#declare M3 = mod(N, 3);
#declare M5 = mod(N, 5);
#declare M15 = mod(N, 15);
box {
<X-5, 0.0, Z-5>,
<X-4, 0.1, Z-4>
#if (OE = 0)
texture{T_Stone18}
#else
texture{T_Wood32}
#end
}
#if (M15 = 0)
object { Fizz translate <X-4.5, 0, Z-4.5> }
object { Buzz translate <X-4.5, 0, Z-4.5> }
#elseif (M5 = 0)
object { Buzz translate <X-4.5, 0, Z-4.5> }
#elseif (M3 = 0)
object { Fizz translate <X-4.5, 0, Z-4.5> }
#else
box {
<X-4.6, 0.1, Z-4.6>,
<X-4.4, 0.1+0.01*N, Z-4.4>
texture{T_Brass_1B}
}
#end
#end
#end
What's new here:
- we have new
cone
object, it's declared by its ends, so it's easy - we have new
torus
object ("donut" shape in normal speech) - it's declared in awkward way with just outer and inner radius, and we need to move it to the place we want it to be at - we can
translate
(move) objects - we can
#declare
objects, and thentranslate
them to the place we want them to be at
FizzBuzz
And finally, the FizzBuzz! The most obvious way is to just place N tiny spheres on each non-Fizz non-Buzz tile.
I thought about some fancy stacking, but just placing them flat in the most obvious way will do.
#include "colors.inc"
#include "metals.inc"
#include "stones.inc"
#include "textures.inc"
#include "woods.inc"
background { color rgb <0.8, 0.8, 1.0> }
camera {
location <0, 10, -8>
look_at <0, 0, -2>
}
light_source { <2, 4, -3> color White }
plane { <0, 1, 0>, 0 texture{T_Stone10} }
#declare Fizz = cone {
<0, 0.1, 0>, 0.2,
<0, 1.3, 0>, 0.0
texture{T_Copper_4C}
}
#declare Buzz = torus {
0.3, 0.1
translate <0, 0.2, 0>
texture{T_Wood6}
}
#declare RandomSeed = seed(1);
#for (X,0,9)
#for (Z,0,9)
#declare N = 91+X-10*Z;
#declare OE = mod(X+Z, 2);
#declare M3 = mod(N, 3);
#declare M5 = mod(N, 5);
#declare M15 = mod(N, 15);
box {
<X-5, 0.0, Z-5>,
<X-4, 0.1, Z-4>
#if (OE = 0)
texture{T_Stone18}
#else
texture{T_Wood32}
#end
}
#if (M15 = 0)
object { Fizz translate <X-4.5, 0, Z-4.5> }
object { Buzz translate <X-4.5, 0, Z-4.5> }
#elseif (M5 = 0)
object { Buzz translate <X-4.5, 0, Z-4.5> }
#elseif (M3 = 0)
object { Fizz translate <X-4.5, 0, Z-4.5> }
#else
#for (XX,0,9)
#for (ZZ,0,9)
#declare NN = 91+XX-10*ZZ;
#if (NN <= N)
sphere {
<X-5+0.05+0.1*XX, 0.2 Z-5+0.05+0.1*ZZ>, 0.05
texture{T_Brass_1B}
}
#end
#end
#end
#end
#end
#end
There's nothing here that we haven't done before, it's just a somewhat bigger version.
Should you use POV-Ray?
I have no idea how useful POV-Ray is as rendering engine, but surely preprocessor tricks are not the proper way to model anything.
Assuming you want to render scenes in POV-Ray, it's much better to either create 3D models in some interactive modeling program and then import them into POV-Ray, or to write software for creating those models.
Code
All code examples for the series will be in this repository.
Code for the POV-Ray Assembly episode is available here.
This content originally appeared on DEV Community and was authored by Tomasz Wegrzanowski
Tomasz Wegrzanowski | Sciencx (2022-01-19T23:49:30+00:00) 100 Languages Speedrun: Episode 61: POV-Ray. Retrieved from https://www.scien.cx/2022/01/19/100-languages-speedrun-episode-61-pov-ray/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.