2014-12-16 19 views
5

Voglio rendere un pianeta come una sfera. L'idea generale è la seguente:Normali analitici a una sfera spostata con rumore simplex

  • Generare un gruppo di vertici di lunghezza unitaria che costituiscono una sfera.
  • Durante il rendering della sfera, lo shader valuta il rumore simplex 3D nel punto della sfera unitaria.
  • Il risultato viene utilizzato come "altezza" per spostare il vertice corrente lungo la sua direzione.

Fino a qui tutto funziona come dovrebbe.

Ora voglio aggiungere l'illuminazione e quindi ho bisogno delle normali alla superficie.

Nell'attuare le parti correlate illuminazione ho aggiunto rapidamente un metodo per stimare le normali terreno utilizzando derivate parziali nello shader frammento simili:

vec3 X = dFdx(ins.position); 
vec3 Y = dFdy(ins.position); 
vec3 normal = normalize(cross(X,Y)); 

dove ins.position è la posizione mondo interpolato.

Mentre questo funziona non sembra molto buono, perché essenzialmente si traduce in normali per-faccia.

Bad normal approximation

Ora alle domande attuali:

  • Calcolo normali per vertice si tradurrebbe in normali lisci, a differenza nella foto, giusto?
  • Uno dei vantaggi di Simplex Noise rispetto a Perlin Noise è che ha un "gradiente costante e ben definito ovunque che può essere calcolato abbastanza a buon mercato" (per citare l'eccellente Simplex Noise demystified) e con il gradiente si dovrebbe essere in grado di calcolare il normale, corretto?

Se la domanda secondi è un "sì" Ho due problemi:

  • L'algoritmo rumore simplex è stato preso da un popular source, che purtroppo non include il calcolo del gradiente. Pubblicherò il mio tentativo di aggiungerlo di seguito, ma non ho idea se sia corretto.
  • Anche se avessi il gradiente, sono bloccato a ricavare il normale da lì.

Qualsiasi aiuto è molto apprezzato!

mio colpo al implementazione gradiente (sostituito le ultime righe di snoise):

float snoise(vec3 v, out vec3 grad) 
{ 
    ...... 

    // Mix final noise value 
    vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0); 
    vec4 m2 = m * m; 
    vec4 m4 = m2 * m2; 

    vec4 pdotx = vec4(dot(p0,x0), dot(p1,x1), dot(p2,x2), dot(p3,x3)); 

    vec4 temp = m2 * m * pdotx; 
    grad = -8.0 * (temp.x * x0 + temp.y * x1 + temp.z * x2 + temp.w * x3); 
    grad += m4.x * p0 + m4.y * p1 + m4.z * p2 + m4.w * p3; 
    grad *= 42.0; 

    return 42.0 * dot(m4, pdotx); 
} 

UPDATE:

La parte relative al calcolo della superficie normale dal gradiente è stato risposto qui: Surface normal to point on displaced sphere.

La domanda rimanente ora è come implementare il calcolo del gradiente nella versione GLSL del 3D Simplex Noise, perché la mia implementazione sembra avere problemi.

UPDATE 2:

Il calcolo del gradiente sembra essere quasi destra, appena la scala sembra essere spento.
Invece di moltiplicare per 42, la divisione per 5 dà risultati piuttosto buoni, ma è stato scoperto per tentativi ed errori. Un corretto fattore di ridimensionamento sarebbe bello.

+0

Per rispondere alla tua prima domanda: sì e no. Le normali per per vertice possono essere lisce se si hanno informazioni sui triangoli adiacenti, oppure possono essere piatte se le si calcola usando un singolo triangolo. Usando gli shader geometrici e una striscia triangolare con adiacenza puoi ottenere fino a 4 triangoli condivisi per-vertice, il che *** potrebbe *** (considerando che * non * è effettivamente il numero di triangoli a cui ogni vertice appartiene) essere sufficiente per calcolare un normale per vertice omogeneo approssimativo. Dovrai strutturare gli indici dei vertici di input in un ordine molto particolare per ottenere questo risultato e richiede GL 3.2+. –

+0

Se ho capito bene, le normali risultanti saranno lisce se la normale per un dato vertice è la stessa, indipendentemente da quale faccia è attualmente elaborata. Supponendo che il calcolo funzioni come descritto in precedenza, perché le normali dipendono solo dall'informazione del singolo vertice a cui appartengono. – Gigo

+0

Bene, la normale (perpendicolare) per vertice dipende dagli altri 2 vertici in ogni triangolo che condivide quel vertice. Osservo la tua mesh e noto alcuni vertici con ben 10 triangoli che condividono lo stesso vertice. Se si desidera uniformare correttamente le normali dei per- vertice, è necessario calcolare la faccia normale per tutti e 10 i triangoli. Ecco perché non sembra pratico. –

risposta

1

OK, il mio problema era quasi puramente legato alla matematica.

Se qualcuno è interessato:
L'implementazione GLSL del calcolo del gradiente pubblicato nella domanda è completamente corretta.
È possibile calcolare le normali direttamente dal gradiente come descritto in here.

E il risultato appare esattamente come avrei voluto che fosse, io sono felice;)

Smooth per-vertex normals