RAYTRACING, COME GODO :-)
Corso di Ray-Tracing per principianti
Parte 1/7

                                   di Alfonso Martone (alfmar)

"Papa' ora che abbiamo una piastra Doppio Pentium (Doppio Bug)
a 120MHz, si puo' sapere che ce ne facciamo?"
--> "Zitto che sto lanciando Wordstar 3.3".

Non  staro' a  fare  una  discussione  computerfilosofica  del
raytracing, mi limito a dire solo un  paio di cosucce a chi si
sente   preso  da  un   brivido  ancestrale  di  sentirsi   un
"incompetente in materia", prima di entrare in azione.

Raytracing per fortuna non e' il diminutivo di Raymond Tracing
l'americano che ha inventato l'algoritmo e ha scritto il primo
programma  a risoluzione 240x120  in bianco e nero su Apple II
nel lontano 1983 in una notte di pioggia.

Il  raytracing,  che  io  sappia, e' il  processo  di  disegno
(bidimensionale) di  una scena (tridimensionale) descritta per
"primitive" (cubi, sfere, coni, etc).
Ad  ogni  oggetto  e' associata  una  posizione  nello  spazio
(quindi   le   coordinate   3D)    nonche'   altri   parametri
caratteristici (riflettenza, brillanza, etc).
L'osservatore  della  scena e'  in  una certa posizione  dello
spazio e guarda in una certa direzione; nello  spazio esistono
uno o  piu' punti  dove "comincia" la  luce che forma, con gli
oggetti, i vari giochi di ombre, trasparenza, etc.

Un "normale" programma  di disegno 3D  (e pressoche'  tutti  i
giochi  in grafica  vettoriale  3D) si  preoccupa al  piu'  di
ricolorare in modo uniforme le zone  ombrate e di eliminare le
superfici  nascoste;  il  raytracing  e'  assai  piu'  evoluto
perche' prevede appunto  ombre (superfici opache), trasparenza
(acqua),  riflessione (specchi), rifrazione  (vetro), etc, per
cui "modellando" i parametri si puo' ottenere un disegno di un
realismo estremo.

Il raytracing  si basa su  un concetto  tanto semplice  quanto
dispendioso in  termini  di potenza  di calcolo richiesta: per
ogni  punto  vengono  generati  i  raggi (rays)  da  tutte  le
sorgenti di luce e a furia  di intersezioni e  riflessioni con
gli  oggetti (chi  ha studiato  ottica sapra'  di  riflessione
diffusa,   speculare,   luce   ritrasmessa,   specchi   "quasi
perfetti", rifrazione, etc) si  determina il colore finale del
pixel nell'immagine.

Un programma di raytracing fa proprio tutto questo.
Fa  definire  gli  oggetti  (in  termini  di  posizioni  e  di
caratteristiche) nello  spazio tridimensionale; fa definire la
posizione dell'osservatore e delle  sorgenti di luce ed infine
calcola l'immagine (rendering).
Non conosco 3D-Studio ma so che lo fa :-)... quello che invece
vi presento  in questo  messaggio e' il POVray (Persistence Of
Vision raytracer, v2.2), per gli amici: POV.

I risultati  migliori, per  la  visualizzazione, li  ottengo -
inutile a dirsi - con una scheda truecolor (24 bit per pixel);
con  una scheda  hicolor  a 32000 o 64000 colori  si ottengono
ancora  dei risultati  decenti, ma a  256  colori non si  vede
proprio niente.
I miei lavori sono tutti a  640x480 a 16 milioni di colori per
punto - ho una  2-The-Max con  Tseng ET4000  e AcuMos  ADAC1 a
15-16-24  bit   per  pixel,  comprata  un   paio  di  anni  fa
abbondanti;  il monitor e' un Mitsubishi a colori (14 pollici)
e i risultati sono eccellenti.
POV  mi genera delle immagini in formato Targa-uncompressed di
oltre 900k l'una (640x480x3=...), passandole in JPEG si scende
fino a 20k,  ma si rischia  di perdere qualcosa  per la solita
storiaccia  della compressione  "lossy" (le  immagini generate
sono di  una  perfezione  da  paranoia)...  ma  questo  e'  un
problema che tratteremo a parte - e comunque si tratta solo di
spazio su hard disk.

In  area P_UNIX do'  qualche consiglio per  compilare ed usare
massicciamente il POV  sotto  Linux;  chi  ha  un  DX4/100  si
deliziera' con al piu' qualche  ora  di  calcolo;  io  ho  uno
stupido 386/40 senza coprocessore e per un rendering "pesante"
(con molti oggetti) devo far girare il programma anche per una
quindicina di giorni.

POV fa semplicemente il "calcolo".
Vuole in input  un file ascii  in una specie  di linguaggio di
programmazione che  descrive la  scena e  genera -  previo uso
intensivo   della  cpu  per  un  mostruoso  numero  di  ore  -
l'immagine     in    formato     Targa-uncompressed    (.TGA),
visualizzabile sotto DOS col  CSHOW  8.xx  (per  il  Linux  ho
scritto un  programmino io per  la mia scheda,  ne parliamo in
P_UNIX).
Vediamo l'esempio piu' semplice (il mio mitico "pittura.pov"),
di appena quattro righe:

  #include "colors.inc"
  camera  { location <0, 2, -3> look_at <0, 1, 2> }
  sphere  { <0, 1, 2>, 2  texture { pigment {color Yellow} } }
  light_source { <2, 4, -3> color White }

(gli spazi non sono troppo importanti).

All'inizio  includo ovviamente il  file che ha  tutti i colori
predefiniti (ho usato solo Yellow e White).
La seconda riga definisce dov'e' l'osservatore, pardon, dov'e'
la  sua telecamera: alla locazione  x=0, y=2, z=-3 (prendeteli
per metri, centimetri, quello che volete) e guarda esattamente
il punto x=0, y=1, z=2(che dunque nel rendering corrispondera'
proprio al centro dell'immagine).

Nella terza riga finalmente ci metto un oggetto: una sfera, di
centro x=0, y=1, z=2 (proprio dove sto puntando la telecamera)
di  raggio 2  (centimetri, metri  o quel  che vi  pare: stessa
unita' di misura  per  tutti),  che  ha  uno  stupendo  colore
giallognolo.
Nella quarta  riga dico che la  lampadina (pardon, sorgente di
luce di colore bianco) e' posizionata a x=2, y=4, z=-3.

L'asse x e' l'asse orizzontale del video che abbiamo davanti.
L'asse  y e' quello verticale (quindi il video pare proprio in
coordinate cartesiane) e l'asse z e' quello che parte da noi e
va verso l'interno dello schermo.
Dunque  la sorgente di  luce e' 2  metri piu' a  destra di noi
(2-0=2),  2 metri piu'  su di noi  (4-2=2), e non  e' ne' piu'
avanti ne' piu' indietro ((-3)-(-3)=0).
Spero  non si siano offesi i bimbi delle elementari per questa
considerazione algebrico-matematica.

Il modo preoccupante di definire il colore della sfera:
  sphere { <0, 1, 2>, 2 texture { pigment { color Yellow } } }

era semplicemente perche' il secondo esempio e':
  sphere { <0, 1, 2>, 2 texture { Bronze_Texture } }

Le caratteristiche di  un oggetto  si definiscono  proprio nel
blocco  parametri "texture";  il "pigment"  e' solo  il gruppo
parametri "colore"+"trasparenza".
Nel primo esempio la sfera era gialla e basta (tutti gli altri
hanno un default, nel nostro primo esempio la sfera e' opaca e
sembra  dipinta col  pennarello); aggiungendo  altri parametri
(brillanza,   riflessione)  si  ottiene   un  effetto  "cambio
materiale":  nel secondo  esempio il  materiale e'  appunto il
bronzo, di colore "bronzeo" (55/100 di rosso, 47/100 di verde,
14/100  di blu, nessuna trasparenza), brillanza 6, riflessione
25%, etc.

I parametri su cui si puo' intervenire sono veramente numerosi
e  si possono ovviamente  dare valori assurdi  (un oggetto che
riflette troppo e rifrange ancora di piu'; non so se esista in
natura  un materiale che specchi gli oggetti intorno lasciando
passare la luce da tutti gli altri lati...).

C'e'  per esempio la  finitura "phong" che  fa "specchiare" la
luce in maniera  plastica;  la  caretterizzazione  "metallic",
l'effetto "marble" (marmo?), etc; un oggetto puo' anche essere
ruvido ("roughness"); si puo'  dare  un  po'  di  "turbulence"
nella colorazione o nella definizione dell'oggetto; si possono
cambiare i  gia' citati  parametri di  brillanza, riflettenza,
rifrazione e cambiare,  in POV,  anche l'indice  di rifrazione
che normalmente vale 1.33 per l'acqua, 2.5 per i diamanti etc.

Nei prossimi articoli parlero' un po' piu' diffusamente di POV
e di quel poco  che ho  imparato finora  (il manuale  appare a
prima vista ostico, invece  e'  di  una  chiarezza  e  di  una
semplicita' deliziose).
Nel frattempo  scaldate pure  i processori  perche' finalmente
avrete modo  di usare la CPU per  piu' di venti secondi totali
al giorno (aho', ogni operazione vi finisce in un centesimo di
secondo, sarebbe  pure  ora  di  sfruttare  tanta  potenza  di
calcolo, no?).