2012-11-08 13 views
12

Quando uso le mie shader ottengo seguenti risultati: enter image description hereGLSL illuminazione speculare

enter image description here

Un problema è che luce speculare è una sorta di deformato e si poteva vedere triangoli sfera, un altro è, che posso vedi speculare dove non dovrei (seconda immagine). Una luce specifica viene eseguita in vertex shader, altri in frammento.

Ecco come la mia luce vertex shader assomiglia: Vertex:

// Material data. 
uniform vec3 uAmbient; 
uniform vec3 uDiffuse; 
uniform vec3 uSpecular; 
uniform float uSpecIntensity; 
uniform float uTransparency; 

uniform mat4 uWVP; 
uniform mat3 uN; 
uniform vec3 uSunPos; 
uniform vec3 uEyePos; 
attribute vec4 attrPos; 
attribute vec3 attrNorm; 
varying vec4 varColor; 

void main(void) 
{ 
    vec3 N = uN * attrNorm; 
    vec3 L = normalize(uSunPos); 
    vec3 H = normalize(L + uEyePos); 
    float df = max(0.0, dot(N, L)); 
    float sf = max(0.0, dot(N, H)); 
    sf = pow(sf, uSpecIntensity); 

    vec3 col = uAmbient + uDiffuse * df + uSpecular * sf; 
    varColor = vec4(col, uTransparency); 
    gl_Position = uWVP * attrPos; 
} 

Frammento:

varying vec4 varColor; 

void main(void) 
{ 

    //vec4 col = texture2D(texture_0, varTexCoords); 
    //col.r += uLightDir.x; 
    //col.rgb = vec3(pow(gl_FragCoord.z, 64)); 
    gl_FragColor = varColor; 

} 

E 'possibile, che i miei dati forniti dal codice è sbagliato. uN è la matrice del mondo (non invertita e non trasposta, anche se farlo sembra non fare nulla di diverso). UWVP - matrice di proiezione di visualizzazione del mondo.

Tutte le idee su dove potrebbe essere il problema, sarebbero apprezzate.

[EDIT] Ecco i miei calcoli di luce fatto in frammento: Vertex di file Shader:

uniform mat4 uWVP; 
uniform mat3 uN; 
attribute vec4 attrPos; 
attribute vec3 attrNorm; 
varying vec3 varEyeNormal; 

void main(void) 
{ 
    varEyeNormal = uN * attrNorm; 
    gl_Position = uWVP * attrPos; 
} 

Frammento di file dello shader:

// Material data. 
uniform vec3 uAmbient; 
uniform vec3 uDiffuse; 
uniform vec3 uSpecular; 
uniform float uSpecIntensity; 
uniform float uTransparency; 

uniform vec3 uSunPos; 
uniform vec3 uEyePos; 
varying vec3 varEyeNormal; 

void main(void) 
{ 
    vec3 N = varEyeNormal; 
    vec3 L = normalize(uSunPos); 
    vec3 H = normalize(L + uEyePos); 

    float df = max(0.0, dot(N, L)); 
    float sf = max(0.0, dot(N, H)); 
    sf = pow(sf, uSpecIntensity); 

    vec3 col = uAmbient + uDiffuse * df + uSpecular * sf; 

    gl_FragColor = vec4(col, uTransparency); 
} 

[EDIT2] Come Joakim ha sottolineato, non ero' t normalizzare varEyeNormal in framment shader. Dopo averlo risolto, il risultato è molto meglio in framment shader. Ho anche usato la funzione di normalizzazione su uEyePos, quindi speculare non va più al lato oscuro. Grazie per tutto l'aiuto.

enter image description here

+0

credo che si dovrebbe negare le vostre normali.(punti luminosi sul lato oscuro) –

+0

In questo modo: vec3 negNormal = vec3 (-attrNorm.x, -attrNorm.y, -attrNorm.z); vec3 N = uN * negNormal; ? Con questo non vedo per niente speculare. – SMart

+0

Stavo parlando della seconda immagine, in cui la luce diffusa dovrebbe essere positiva se anche la riflessione speculare è positiva. Puoi fare un jsfiddle fuori da questo? –

risposta

19

Risposta breve: Hai bisogno di normalizzare varEyeNormal nello shader frammento, invece che nel vertex shader.

Risposta più lunga: Per ottenere un'illuminazione uniforme, è necessario calcolare le normali per pixel anziché per vertice. Le variazioni calcolate nel vertex shader vengono interpolate linearmente prima di passare allo shader dei frammenti, che funziona in alcuni casi come una scorciatoia, ma peggio in altre.

La ragione per cui si vedono i bordi del triangolo è dovuta all'interpolazione tra le normali risultante inferiore a 1.0 normali in tutti i pixel tra i vertici.

Per correggere questo, è necessario normalizzare le normali nello shader del frammento anziché nel vertex shader.

La matrice normale dovrebbe essere 3x3 superiore del trasposta l'inverso della matrice Modelview, che è equivalente alla 3x3 superiore della matrice Modelview se il Modelview contiene solo rotazioni e traslazioni (senza scala)

per di più la matrice normale, vedi: http://www.lighthouse3d.com/tutorials/glsl-tutorial/the-normal-matrix/

(a cura per la correttezza in base al commento qui sotto.)

+5

I punti relativi alla matrice normale sono errati. È la trasposizione inversa ** e ** del 3x3 superiore della matrice modelview. Quindi se la matrice modelview ha solo rotazioni e traslazioni, è esattamente la stessa 3x3 superiore della matrice modelview (perché l'inversione e la trasposizione si annullano per la rotazione e la traduzione è comunque ingerita), che è probabilmente il motivo per cui non ha funzionato t fare la differenza per l'OP invertire la trasposizione o meno. –

+2

Hai ragione, ho modificato la mia risposta –