Domanda

Sto scrivendo una piccola prova di ombreggiatura del Phong, e sto colpendo la testa contro un muro di mattoni cercando di far funzionare il componente speculare. Sembra funzionare correttamente, tranne che la luce speculare viene applicata sia alla parte anteriore e posteriore dell'oggetto. (L'oggetto stesso è trasparente, con volti manualmente la CPU ordinata.)

Si noti che il componente diffuso funziona perfettamente (si presenta solo sul lato rivolto verso la sorgente luminosa) - che sembrerebbe escludere un problema con le normali che arrivano al frammento shader, penso.

Come capisco, la componente speculare è proporzionale al cos dell'angolo tra il vettore dell'occhio e il vettore di luce riflesso.

Per mantenere le cose ultra semplici, il mio codice di prova cerca di farlo nello spazio mondiale. La posizione della fotocamera e il vettore della luce sono codificati rigidi (scusate) come (0,0,4) e (-0.707, 0, -0.707) rispettivamente. Il vettore dell'occhio è quindi (0,0,4) - fragPosition.

Poiché il modello Matrix esegue la rotazione, il vertice shader trasforma semplicemente il vertice normale dalla matrice del modello. ( Nota: Questa non è una buona pratica poiché molti tipi di trasformazione non conservono la normale ortogonalità. Generalmente per la normale matrice, Dovresti usare la trasposizione inversa della Top-sinistra 3x3 della matrice del modello.) Le cose semplici, il frammento shader funziona su un singolo canale di colore galleggiante e salta l'esponente speculare (/ utilizza un esponente di 1).

vertice shader:

#version 140

uniform mat4 mvpMtx;
uniform mat4 modelMtx;

in vec3 inVPos;
in vec3 inVNormal;

out vec3 normal_world;
out vec3 fragpos_world;

void main(void) {
  gl_Position = mvpMtx * vec4(inVPos, 1.0);
  normal_world = vec3(modelMtx * vec4(inVNormal, 0.0));
  fragpos_world = vec3(modelMtx * vec4(inVPos, 1.0)); 
}
.

Framment Shader:

#version 140

uniform float
    uLightS,
    uLightD,
    uLightA;

uniform float uObjOpacity;

in vec3 normal_world, fragpos_world;
out vec4 fragOutColour;

void main(void) {

    vec3 vN = normalize(normal_world);
    vec3 vL = vec3(-0.707, 0, -0.707);

    // Diffuse:
    // refl in all directions is proportional to cos(angle between -light vector & normal)
    // i.e. proportional to -l.n
    float df = max(dot(-vL, vN), 0.0);

    // Specular:
    // refl toward eye is proportional to cos(angle between eye & reflected light vectors)
    // i.e. proportional to r.e
    vec3 vE = normalize(vec3(0, 0, 4) - fragpos_world);
    vec3 vR = reflect(vL, vN);
    float sf = max(dot(vR, vE), 0.0);

    float col = uLightA + df*uLightD + sf*uLightS;

    fragOutColour = vec4(col, col, col, uObjOpacity);

}
.

Non riesco a trovare un errore qui; Qualcuno può spiegare perché il componente speculare appare sul retro e il lato rivolto verso l'obiettivo dell'oggetto?

Molte grazie.

È stato utile?

Soluzione

Il tuo contributo speculare è in realtà lo stesso per i front e back faces perché reflect GLSL è insensibile al segno del normale.Da Questo riferimento :

reflect(I, N) = I - 2.0 * dot(N, I) * N
.

Così lanciando il segno di N introduce due segni meno che annullano.A parole, quale reflect fa è invertire il segno del componente del I che è lungo lo stesso asse come N.Questo non dipende da che parte N è rivolto verso il viso.

Se si desidera rimuovere il componente speculare dai volti sul retro, penso che dovrai controllare esattamente il tuo dot(vE,vN).

Altri suggerimenti

prova il cambiamento

fragpos_world = vec3(modelMtx * vec4(inVPos, 0.0)); 
.

a

fragpos_world = vec3(modelMtx * vec4(inVPos, 1.0)); 
.

Perché http://www.opengl-tutorial.org / principianti-tutorial / tutorial-3-matrici / # homogeneous_coordinati

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top