Newsgroup: it.comp.grafica
Titolo: Shaders: aiuto!

Nell'effettuare il rendering di una scena
prodotta con l'open source K-3D
http://k3d.sourceforge.net/
mediante BMRT o AQSIS,
le informazioni riguardanti
le normali (settate smooth),
contenute nel file .rib,
vengono ignorate dagli shaders
del displacement, e nel rendering
i solidi sono sfaccettati.
Qui c'e' il mio problema con
alcune illustrazioni:
http://members.xoom.virgilio.it/_XOOM/bastioni/free3d/01jun2002.htm
Ho scritto ad uno dei ragazzi
che sta sviluppando il progetto, e vi
allego la sua risposta:
[...]
About Your problem with displacement shaders - i'm not
expert in shaders... I have tried some renderings with
BMRT and Aqsis on sphere with k3d_castucco, k3d_stucco,
k3d_dented. In all cases it seems that renderer ignores
normals assigned to polygons in world.rib file. In other
words setting "smooth" mode to e.g sphere has no effect
in rendered image.
With k3d_castucco with default shader parameters
effect is "not very bad" but with k3d_stucco on k3d_dented
it really looks always as in "flat" mode.
When given sphere is rendered as "subdivided mesh" it
is full "smooth" without any displacements.
I suspect that those features of displacement shaders
may be common to all renderers. I think
Vi chiedo, se vi intendete di shaders con
renderman, di dare una mano a risolvere questo
problema a K-3D.
Ciao,
                Manuel

 mediante BMRT o AQSIS,
ciao..
ma il codice del displacement fa i calcoli giusti sulle normali ?
sliker ^__^

 le normali (settate smooth),
un 'altra cosa: RenderMan fa distinzione tra displacement e bumping questo
perchč li tratta diversamente ossia:
il displacement  č una modifica della geometria dell'oggetto, invece il bump
funziona con una perturbazione sulle normali dell'oggetto.
quindi + probabile che tu debba usare un bump
il problema dei bump sono le selfshadowing che nn saranno mai realisitche,
tipo effetto buccia d'arancia...
ciaociao
Spero di esserti stato utile
Sliker

 i solidi sono sfaccettati.
puo' essere che le normali vengano effettivamente
considerate, ma sono sballate... troppa discontinuita'
nella funzione normale.
-- 
"We know Linux to be great...
 it ends infinite loops in 5 seconds only" - Linus Torvalds


http://members.xoom.virgilio.it/_XOOM/bastioni/free3d/01jun2002.htm
Mentre guardavo Sud Corea - Polonia ho provato a pensarci e forse ho
trovato una soluzione. 
Ho notato lo stesso problema quando il parametro ShadingRate è
impostato ad un valore troppo alto.
Non ho usato K3d ma un file creato a mano qualche tempo fa (credo sia
anche più leggibile), si chiama disp-test.rib
Ho usato Aqsis 0.6.3 ed Emacs...no, non è un nuovo programma 3d, è "un
editor di testo" (per essere molto riduttivi... :)) con il supporto
per il syntax highlighting ed altre utili feature per Renderman come
la compilazione degli shader o l'esecuzione di un particolare motore
di rendering sul file rib in finestra. 
disp-test.rib :
----------------------------------------------
Display "tester" "framebuffer" "rgba"
Format 427 240 1
Projection "perspective" "fov" 40
ShadingRate 4  # <----- TROPPO ALTO
Translate 0 0 6
Rotate -120 1 0 0
WorldBegin
  LightSource "ambientlight" 1 "intensity" 0.05
  LightSource "distantlight" 2 "intensity" 1.5 "from" [5 5 5] "to" [0
0 0]
  LightSource "distantlight" 3 "intensity" 1.0 "from" [5 5 -5] "to" [0
0 0]
 
  Surface "plastic" 
# Displacement "castucco"
# Displacement "dented"
 
  Displacement "provadisp" "float Km" [0.2]
  TransformBegin
    Color 0.515 0.509 0.520
    Scale 4 4 4
    Translate -0.5 -0.5 0
    Polygon "P" [0 0 0 0 1 0 1 1 0 1 0 0]
  TransformEnd
 
  TransformBegin
    Translate -0.3 -0.3 0
    Color 0.000 0.484 0.493
    Cylinder 0.5 0 2 355
  TransformEnd
 
  TransformBegin
    Color 0.562 0.005 0.037
    Translate 0.7 1 0.5
    Sphere 0.7 -0.7 0.7 360
  TransformEnd
 
WorldEnd
-------------------------------------------
Ho scritto anche un piccolo shader apposta (leggi : fa schifo !!!) per
questo esempio, comunque anche con gli altri shader come dented e
castucco funziona (prova a commentare Displacement "provadisp" ecc e
togliere il commento dagli altri). Ah...non l'ho provato con il
bump...fammi sapere se funge :))
Si chiama 
provadisp.sl
:
-------------------------------------------
displacement provadisp (float Km = 1;
            float truedisp = 1;)
{
if (truedisp == 0) { /* BUMP */ 
  N = calculatenormal(P + noise(s*5,t*5) * Km * normalize(N));
}
else { /* DISPLACEMENT */
  P += Km * noise(s*5,t*5) * normalize(N);
  N = calculatenormal(P);
}
}
----------------------------------------------
Una volta compilato 
provadisp.sl
 con il comando 
$>aqsl 
provadisp.sl
 
e messo in un path reperibile da Aqsis (io ho /usr/local/shaders)
si passa al rendering con 
$>aqsis disp-test.rib (oppure aqsis-framebuffer-glut)
Le sfaccettature sono evidenti, ma basta cambiare il parametro
ShadingRate da 4 a 1 per avere una superfice smooth (con conseguente
aumento dei tempi di rendering).
Spero di aver risolto il problema :))

> Ho scritto anche un piccolo shader apposta
Beh, adesso vado a tentare l'esperimento...
Onestamente sono sotto zero riguardo gli shader,
ma credo che almeno la prova dovrei riuscire a
farla :-)
Qui invece ti allego la risposta di Paul Gregory
lo sviluppatore di Aqsis. Ti giro la risposta,
per domandarti se sia tu che lui avete individuato
lo stesso problema (io dovro' studiarmi un po'
entrambi le vostre risposte prima di capirlo...):
------------------------------------------------------------------------
Hi Manuel,
    I've taken a closer look at the displacement problem, and it is not
quite as I first thought, but very similar. Basically what happens when
you do a displacement on a primitive, the normal is recalculated using
the partial derivatives of u and v at the point of displacement. In
plain terms this means that the normal is recalculated as a normal at
the 'real' surface, not the smoothed normal provided to make a flat
surface look smooth. The reason it is more noticeable in the dented
shader is because there are lots of areas where the surface isn't
displaces at all, at which point the sureface normal returns to the
geomtric normal hence the flat shaded look.
There are probably a number of ways to overcome this easiest of which is
to use 'subdivision surfaces' as suggested by Wladyslaw. Alternatively
you could alter the shader to take into account the original shading
normal 'N' when calculating the new displaced shading normal. A good
overview of doing this is covered in Steve May's RenderMan Notes...
 
http://www.accad.ohio-state.edu/~smay/RManNotes/WritingShaders/disp.html
If you are uncomfortable getting into shader coding, it may be worth
mentioning this on the K3D list, someone may be willing to add/alter the
displacment shaders for use on smooth shaded polygons.
----------------------------------------------------------------------
Se vuoi puoi postare i tuoi risultati direttamente sulla mailing list
di K-3D, cosi' avrai almeno la riconoscenza della community:
http://sourceforge.net/mailarchive/forum.php?forum_id=7633
Eh Eh...ti voglio far entrare nel tunnel!!

 cosa intendi per normali settate smooth?
C'e' un pulsante che permette di specificare
se un oggetto al momento del rendering
 deve avere un aspetto sfacettato
oppure smussato. Attivandolo, i solidi dovrebbero
apparire smussati, ma questo purtroppo non accade
quando vengono utilizzati degli shaders per il
displacement. Puoi capire il problema dando uno
sguardo alla paginetta che ho preparato appositamente:
http://members.xoom.virgilio.it/bastioni/free3d/01jun2002.htm
Grazie,
                     Manuel

 ma il codice del displacement fa i calcoli giusti sulle normali ?
Il problema si verifica con tutti gli shaders...
ehm...quindi non saprei...dai uno sguardo
agli altri post, forse il problema e' stato
inquadrato...
Ciao,
              Manuel

di K-3D, cosi' avrai almeno la riconoscenza della community:
Non so se ne ho il tempo... se il suggerimento che ti ho dato nel
messaggio precedente funziona, puoi farlo direttamente tu. 

 messaggio precedente funziona, puoi farlo direttamente tu.
Mi ci mettero' nel fine settimana...se dai uno sguardo
al link nel mio messaggio precedente,
http://www.accad.ohio-state.edu/~smay/RManNotes/WritingShaders/disp.html
vedrai che
questo del displace non e' un problema, ma una
caratteristica degli shaders-displace piu' semplici:
" Smooth-shaded polygonal surfaces present a special problem with
displacement shaders. "
che puo' essere aggirata facilemente a livello di codice,
addizionando la differenza tra il vettore delle normali
smussate con quello delle normali "scostate":
-------------------------------------------------------------------
With smooth-shaded polygons, N (shading normal) will contain the smooth
shading normal and Ng (geometric normal) will contain the face normal.
We can solve the displacement problem by saving the difference between N and
Ng
and then adding it back in after we calculate the new normal.
The code fragment below demonstrates this:
 point Ndiff;
 .
 .
 Ndiff = normalize(N) - normalize(Ng);
 P += P * Km * surface_mag * normalize(N);
 N = normalize(calculatenormal(P)) + Ndiff;
---------------------------------------------------------------------------
Sono sicuro che tu lo capirai in un
attimo, io invece non ho nessun background sul
linguaggio di shading e fatico un bel  po'.
Penso che per te sia una cosa facile...fammi
sapere...
Ciao,
                Manuel

   P += Km * noise(s*5,t*5) * normalize(N); N = calculatenormal(P);
non conosco il linguaggio di script usato...
ma qui BUMP e DISPLACEMENT sembra che facciano la stessa cosa,
le istruzioni sembrano scritte in modo equivalente, mi sbaglio
o c'e' qualcosa che mi sfugge?


 after we calculate the new normal. 
ma c'e' una giustificazione a tutto questo? o e' una 
soluzione trovata in maniera euristica... insomma a
capocchia? :-))


 modo equivalente, mi sbaglio o c'e' qualcosa che mi sfugge?
 
e' una mia svista... in DISPLACEMENT viene anche modificata la 
geometria di P :-P


sapere...
aridaje.... :)))
non ho capito perche' funzioni, inoltre per la questione del tipo
(punto) di Ndiff forse e' un semplice problema di semantica dello SL.
Provo a pensarci un po' e se risolvo ti faccio sapere.
Intanto se c'e' qualcuno in ascolto che magari ha qualche
suggerimento...

 o normale ( N ha infatti tipo normal)
non conosco questo linguaggio di script... forse i tipi sono compatibili


per calcolarsi la nuova N.
Perchè dici "calcola la nuova Ng" ? Dove accade questo ?

 Perchè dici "calcola la nuova Ng" ? Dove accade questo ?
non ho riportato qualche passaggio:
P += P * Km * surface_mag * normalize(N); N =
normalize(calculatenormal(P)) + Ndiff; <-
normalize(calculatenormal(P)) non e' la nuova Ng? non e' la normale
geometrica a P visto che P e' cambiato?


geometrica a P visto che P e' cambiato?
beh, si, normalize(calulatenormal(P)) dovrebbe essere Ng normalizzata
a cui viene sommato Ndiff, però continuo a non capire a cosa
serva...anzi devo dire che ho le idee un pò confuse. 
Forse è meglio per me ridare un'occhiata alle specifiche :))

 un'occhiata alle specifiche :))
ok mi scarico un po di documentazione e ci penso un po su :-))


 o normale ( N ha infatti tipo normal)
sembra che i tipi point, vector e normal siano compatibili visto
che accettano terne (x,y,z) di float, come dici tu sarebbe meglio
usare il tipo normal... se non altro per migliorare la leggibilita'
dello script.


> ok mi scarico un po di documentazione e ci penso un po su :-))
Volevo ringraziarvi per il lavoro che state
facendo. Io purtroppo non posso far altro che
guardare...
Grazie,
                     Manuel

 direzione ma lunghezza pari a 1) e aggiunge Ndiff.
dopo aver letto un po' di documentazione di Randerman credo
che:
P += P * Km * surface_mag * normalize(N);
che e' equivalente a 
P += P * Km * surface_mag * normalize(Ng);
Stando a quanto scritto nel documento, sempre che N non venga
differentemente fornita dall'utente, N=Ng
Infine N = normalize(calculatenormal(P));
e' la normale di ombreggiatura dopo il displacement.
Faccio notare che N e' diversa dalla Ng iniziale perche' 
P * Km * surface_mag non e' costante, tuttavia N e' uguale
alla nuova Ng poiche' sempre nel documento c'e' scritto che
ogni volta che P viene modificato, il renderer ricalcola 
automaticamente Ng.
Purtroppo non riesco a capire che senso possa avere calcolare
la differenza tra N ed Ng e sommarla ad N, infatti calcolare
Ndiff prima o dopo del displacement comporta un vettore nullo.
A meno che inizilmente N non venga fornita dall'utente e quindi
prima del displacement N!=Ng, allora Ndiff!=0 e sommare Ndiff
a N puo' servire a perturbare ulteriormente la normale... tutto
cio' non so a che pro, considerato il fatto che quest'ultima
perturbazione puo' introdurre una forte discontinuita' nella
funzione normale.


funzione normale.
Ho un idea...posso provare a fare il "debug" dello shader usando la
printf supportata dallo Shading Language.
Farò delle prove e poi semmai le posto, però non so quando perchè a
breve ho un esame :((