Spiegelndes Licht erscheint sowohl auf der dem Auge zugewandten Seite als auch auf der Rückseite des Objekts

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

Frage

Ich schreibe einen kleinen Test der Phong-Schattierung und stoße mit dem Kopf gegen eine Mauer, um die Spiegelkomponente zum Laufen zu bringen.Es scheint korrekt zu funktionieren, außer dass das Spiegellicht sowohl auf die Vorder- als auch auf die Rückseite des Objekts angewendet wird.(Das Objekt selbst ist transparent, die Gesichter werden CPU-seitig manuell sortiert.)

Beachten Sie, dass die diffuse Komponente perfekt funktioniert (sie wird nur auf der Seite angezeigt, die der Lichtquelle zugewandt ist) – was meiner Meinung nach ein Problem mit den Normalen, die am Fragment-Shader ankommen, auszuschließen scheint.

Soweit ich weiß, ist die Spiegelkomponente proportional zum cos des Winkels zwischen dem Augenvektor und dem Vektor des reflektierten Lichts.

Um die Sache möglichst einfach zu halten, versucht mein Testcode, dies im Weltraum zu tun.Kameraposition und Lichtvektor sind fest codiert (sorry). (0,0,4) Und (-0.707, 0, -0.707) jeweils.Der Augenvektor ist daher (0,0,4) - fragPosition.

Da die Modellmatrix nur eine Drehung durchführt, transformiert der Vertex-Shader einfach die Vertexnormale durch die Modellmatrix.(Notiz: Dies ist keine gute Vorgehensweise, da viele Transformationstypen die normale Orthogonalität nicht bewahren.Im Allgemeinen gilt für die Normalmatrix: du solltest benutzen die inverse Transponierte der oberen linken 3x3 der Modellmatrix.) Der Einfachheit halber arbeitet der Fragment-Shader mit einem einzelnen Float-Farbkanal und überspringt den Glanzexponenten (/verwendet einen Exponenten von 1).

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

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

}

Ich kann hier keinen Fehler finden;Kann jemand erklären, warum die Spiegelkomponente sowohl auf der Rückseite als auch auf der dem Licht zugewandten Seite des Objekts erscheint?

Vielen Dank.

War es hilfreich?

Lösung

Ihr Spiegelbeitrag wird wegen GLSL tatsächlich für Vorder- und Rückseite gleich sein reflect ist unempfindlich gegenüber dem Vorzeichen des Normalen.Aus diese Referenz:

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

Das Umdrehen des Vorzeichens von N führt also zu zwei Minuszeichen, die sich aufheben.In Worten, was reflect bewirkt, dass das Vorzeichen der Komponente von umgekehrt wird I was entlang der gleichen Achse liegt wie N.Das kommt nicht darauf an, in welche Richtung N ist mit Blick auf.

Wenn Sie die Spiegelkomponente von Ihren Rückseiten entfernen möchten, müssen Sie dies meiner Meinung nach explizit überprüfen dot(vE,vN).

Andere Tipps

Versuchen Sie es zu ändern

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

Zu

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

Weil http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/#Homogeneous_coordinates

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top