Aparece una iluminación especular en ambos lados del objeto, que miran hacia los ojos y en la parte posterior.

StackOverflow https://stackoverflow.com//questions/20008089

Pregunta

Estoy escribiendo una pequeña prueba de sombreado Phong y me golpeo la cabeza contra una pared de ladrillos tratando de hacer funcionar el componente especular.Parece funcionar correctamente, excepto que la luz especular se aplica tanto al frente como a la parte trasera del objeto.(El objeto en sí es transparente, con caras ordenadas manualmente en el lado de la CPU).

Tenga en cuenta que el componente difuso funciona perfectamente (solo aparece en el lado que mira hacia la fuente de luz), lo que creo que parece descartar un problema con las normales que llegan al sombreador de fragmentos.

Según tengo entendido, el componente especular es proporcional al cos del ángulo entre el vector del ojo y el vector de luz reflejada.

Para mantener las cosas ultra simples, mi código de prueba intenta hacer esto en el espacio mundial.La posición de la cámara y el vector de luz están codificados (lo siento) como (0,0,4) y (-0.707, 0, -0.707) respectivamente.El vector del ojo es por lo tanto (0,0,4) - fragPosition.

Dado que la matriz del modelo solo realiza rotación, el sombreador de vértices simplemente transforma la normal del vértice mediante la matriz del modelo.(Nota: Esta no es una buena práctica ya que muchos tipos de transformación no conservan la ortogonalidad normal.Generalmente para la matriz normal, Deberías usar la transpuesta inversa del 3x3 superior izquierdo de la matriz del modelo). Para simplificar las cosas, el sombreador de fragmentos opera en un único canal de color flotante y omite el exponente especular (/usa un exponente de 1).

Sombreador de vértices:

#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)); 
}

Sombreador de fragmentos:

#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);

}

No puedo encontrar un error aquí;¿Alguien puede explicar por qué el componente especular aparece tanto en la parte trasera como en el lado luminoso del objeto?

Muchas gracias.

¿Fue útil?

Solución

Su contribución especular en realidad será la misma para las caras frontal y posterior porque GLSL reflect es insensible al signo de lo normal.De esta referencia:

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

entonces, invertir el signo de N introduce dos signos menos que se cancelan.En palabras, ¿qué reflect lo que hace es invertir el signo del componente de I que está a lo largo del mismo eje que N.Esto no depende de qué manera N se enfrenta a.

Si desea eliminar el componente especular de sus caras posteriores, creo que deberá verificar explícitamente su dot(vE,vN).

Otros consejos

intente cambiar

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

a

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

Porque http://www.opengl-tutorial.org / principiantes-tutoriales / tutorial-3-matrices / # homogeneous_coordinates

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top