Ein bisschen über Phong-Schattierung


„Wir können nicht erwarten, dass wir das Objekt genau so anzeigen können, wie es in Wirklichkeit ist, mit Texturen, Schatten usw. Wir hoffen nur, ein Bild zu schaffen, das nah genug ist, um ein gewisses Maß an Realismus zu erreichen. "

Bui Tyong Fong

Bui Thuong Fong wurde 1941 geboren und wurde während des Vietnamkrieges Informatiker. Es muss für ihn schwierig gewesen sein, seine Studien in der toxischen Umgebung der 60er Jahre abzuschließen, ganz zu schweigen von der Tatsache, dass er an die Front gerufen wurde! Aber er konnte überleben und überleben bis 1975, bevor Leukämie nur zwei Jahre nach dem Grundstein für die Welt der modernen Theorie von Beleuchtung und Beschattung, Fongs Shader, ums Leben kam . Vietnamesische Namen bestehen aus drei Teilen: Nachname, zweiter Vorname und persönlicher Name. Das heißt, wenn Leute "Fong Shader" sagen, nennen sie den persönlichen Namen Bui Tyong. Weitere Informationen zu Personennamen finden Sie auf Wikipedia .


Ich bin mir nicht sicher, ob dies Phong ist, aber laut Google ja.

„Lass sanft den milden Sonnenschein
Spiel um mein sterbendes Bett herum,
E'er das schwach beleuchtete Tal
Ich mit einsamen Füßen muss treten. „

Let The Light Enter - ein Gedicht von Francis Harper

Der Shader von Phong basiert auf einer äußerst präzisen Mathematik. Was Sie in der Tat nicht wissen müssen, es sei denn, Sie möchten aufrichtig Grafikprogrammierer werden. Auf lange Sicht wird ihr Wissen jedoch nützlich sein. Nachfolgend finden Sie Auszüge aus dem OpenGL Superbible, der 7. Ausgabe von Graham Sellers und der ARB Foundation der Kronos Group.

A) Einige Konzepte


Lassen Sie uns zunächst die Konzepte herausfinden. Wenn Sie sich schon eine Minute lang mit 3D-Modellierung oder Spieleentwicklung beschäftigt haben, müssen Sie ihnen bereits begegnet sein, aber die Wiederholung hat niemanden gestört.

A-1) Umgebungslicht

Die meisten Bücher, insbesondere Bücher von geringer Qualität, vergleichen diese Beleuchtung mit Sonnenlicht, aber dies ist völlig falsch. Umgebungsbeleuchtung ist kein Sonnenlicht. Es kommt aus allen Richtungen , das heißt, es ist allgegenwärtig, aber in Berechnungen ist es nur ein Vektor mit drei Komponenten. In der Schattierung von Phong wird es am Ende hinzugefügt, ändert sich aber nicht.

A-2) Diffuses / diffuses Licht

Diffuse Beleuchtung hat eine Richtung. Dies ist tatsächlich eine Richtungskomponente der Lichtquelle . Im Kino wird Licht mit einer Softbox gestreut, und in der Computergrafik wird Licht mit einer Formel gestreut, die wir unten zeigen werden. Die Größe, d. H. Die Größe der diffusen Beleuchtung, hängt von der Oberfläche ab. Wenn die Oberfläche beispielsweise matt ist, dh mehr absorbiert als Licht reflektiert, ist der Wert größer als bei einer glatten Oberfläche.


Gestreutes / absorbiertes Umgebungslicht von einem mattierten Bildschirm

A-3) Spiegelhighlight

Wie diffuses Licht ist reflektiertes Licht gerichtet, basiert jedoch auf dem Oberflächenglanz. es hinterlässt ein Highlight namens Glanz . Im wirklichen Leben ist Glanz kein wesentlicher Bestandteil des Materials. Tatsächlich trägt eine Filmbeschichtung oder ein Tropfen Wachs viel mehr zum Glanz bei als alles andere. Der reflektierte Glanz ist ein Faktor im Bereich von 0 bis 128, da er bei Werten über 128 den Shader nicht stark beeinflusst.


Film mit Film - dickes farbiges Papier mit einer glänzenden Filmbeschichtung, ein echtes Geschenk für ein Kind.

A-4) Albedo

Dies ist der Anteil des von der Oberfläche reflektierten einfallenden Lichts.

A-5) Phong-Formel

Die Formel zur Berechnung des Materials nach Phong lautet wie folgt:

Ip=kaia+kd left( vecL. VecN right)id+ks left( vecR. VecV right) alphais


Wo:

ka: Umgebungsmaterial

kd: Diffuses Material

ks: Spiegelmaterial und  alpha: Glanzwert

ia: Umgebungsbeleuchtung

id: diffuse Beleuchtung

is: indirekte Beleuchtung

Sie fragen sich vielleicht, was ist mit Vektoren? Mach dir keine Sorgen, jetzt werden wir über sie erzählen:

 vecN: normal zur Oberfläche

 vecL: der Einheitsvektor vom schattierten Punkt zur Lichtquelle (mit anderen Worten der Lichtvektor)

 vecR: Reflexion des negativen Wertes des Lichtvektors

 overrightarrowV: Vektor auf den Betrachter gerichtet


B) Gouraud-Schattierung


Bevor Sie mit Fongs Shader beginnen, wollen wir sehen, wie Sie Gouro-Shading auf GLSL erhalten können. Bitte beachten Sie, dass ich die Version GLSL 4.1 wie in Superbible verwende. Wenn Sie jedoch ein Fan von www.learnopengl.com sind , können Sie 3.3 verwenden. Das ist nicht wichtig. Mal sehen, was Gouraud-Schattierung ist.

Diese Schattierungsmethode wurde 1971 von Henri Gouraud erfunden. Es ist der Phong-Schattierung keineswegs überlegen und wird heute hauptsächlich als GPU-freie Ladevorschau in Paketen wie Cinema 4D verwendet. Sein Problem ist, dass die Fackel, die er erzeugt, wie ein Funke aussieht:


Dieses Problem wird durch die Interpolation von Farben zwischen Scheitelpunkten verursacht, und Lücken zwischen Dreiecken treten auf, weil Farben linear interpoliert werden. Dieses Problem wurde nur im Phong-Shader gelöst. Mal sehen, wie Sie Gouro Shading in GLSL 4.1 implementieren können.

Listing 1 : Gourox-Scheitelpunktschattierung in GLSL 4.1

#version 410 core // Per-vertex inputs layout (location = 0) in vec4 position; layout (location = 1) in vec3 normal; // Matrices we'll need layout (std140) uniform constants { mat4 mv_matrix; mat4 view_matrix; mat4 proj_matrix; }; // Light and material properties uniform vec3 light_pos = vec3(100.0, 100.0, 100.0); uniform vec3 diffuse_albedo = vec3(0.5, 0.2, 0.7); uniform vec3 specular_albedo = vec3(0.7); uniform float specular_power = 128.0; uniform vec3 ambient = vec3(0.1, 0.1, 0.1); // Outputs to the fragment shader out VS_OUT { vec3 color; } vs_out; void main(void) { // Calculate view-space coordinate vec4 P = mv_matrix * position; // Calculate normal in view space vec3 N = mat3(mv_matrix) * normal; // Calculate view-space light vector vec3 L = light_pos - P.xyz; // Calculate view vector (simply the negative of the view-space position) vec3 V = -P.xyz; // Normalize all three vectors N = normalize(N); L = normalize(L); V = normalize(V); // Calculate R by reflecting -L around the plane defined by N vec3 R = reflect(-L, N); // Calculate the diffuse and specular contributions vec3 diffuse = max(dot(N, L), 0.0) * diffuse_albedo; vec3 specular = pow(max(dot(R, V), 0.0), specular_power) * specular_albedo; // Send the color output to the fragment shader vs_out.color = ambient + diffuse + specular; // Calculate the clip-space position of each vertex gl_Position = proj_matrix * P; } 

Und jetzt der Fragment-Shader.

Listing 2: Der Fragment-Shader desselben Konzepts.

 #version 410 core // Output layout (location = 0) out vec4 color; // Input from vertex shader in VS_OUT { vec3 color; } fs_in; void main(void) { // Write incoming color to the framebuffer color = vec4(fs_in.color, 1.0); } 

C) Phong-Schattierung


Bevor wir fortfahren, denken wir daran, dass Phong- Schattierung und Phong- Beleuchtung zwei verschiedene Konzepte sind. Sie können die "Schneeflocke" von Gouros Fackel loswerden, indem Sie weitere Eckpunkte hinzufügen. Aber warum, wenn wir in Fong Schattierungen haben? Im Phong-Shader wird die Farbe nicht zwischen den Scheitelpunkten interpoliert (wie in Listing 1 und 2). Wir interpolieren zwischen den Scheitelpunkten der Normalen zur Oberfläche und verwenden die generierte Normalen, um alle Beleuchtungsberechnungen für jedes Pixel und nicht für den Scheitelpunkt durchzuführen. Dies bedeutet jedoch, dass der Fragment-Shader mehr Arbeit leisten muss, wie in Listing 4 gezeigt. Schauen wir uns zunächst den Vertex-Shader an.


Listing 3: Der Vertex-Shader des Phong-Shaders unter GLSL 4.1.

 #version 410 core // Per-vertex inputs layout (location = 0) in vec4 position; layout (location = 1) in vec3 normal; // Matrices we'll need layout (std140) uniform constants { mat4 mv_matrix; mat4 view_matrix; mat4 proj_matrix; }; // Inputs from vertex shader out VS_OUT { vec3 N; vec3 L; vec3 V; } vs_out; // Position of light uniform vec3 light_pos = vec3(100.0, 100.0, 100.0); void main(void) { // Calculate view-space coordinate vec4 P = mv_matrix * position; // Calculate normal in view-space vs_out.N = mat3(mv_matrix) * normal; // Calculate light vector vs_out.L = light_pos - P.xyz; // Calculate view vector vs_out.V = -P.xyz; // Calculate the clip-space position of each vertex gl_Position = proj_matrix * P; } 

Fast nichts hat sich geändert. Im Fragment-Shader ist die Situation jedoch völlig anders.

Listing 4: Fong Fragment Shader Shader.

 #version 410 core // Output layout (location = 0) out vec4 color; // Input from vertex shader in VS_OUT { vec3 N; vec3 L; vec3 V; } fs_in; // Material properties uniform vec3 diffuse_albedo = vec3(0.5, 0.2, 0.7); uniform vec3 specular_albedo = vec3(0.7); uniform float specular_power = 128.0; uniform vec3 ambient = vec3(0.1, 0.1, 0.1); void main(void) { // Normalize the incoming N, L and V vectors vec3 N = normalize(fs_in.N); vec3 L = normalize(fs_in.L); vec3 V = normalize(fs_in.V); // Calculate R locally vec3 R = reflect(-L, N); // Compute the diffuse and specular components for each fragment vec3 diffuse = max(dot(N, L), 0.0) * diffuse_albedo; vec3 specular = pow(max(dot(R, V), 0.0), specular_power) * specular_albedo; // Write final color to the framebuffer color = vec4(ambient + diffuse + specular, 1.0); } 

Nun, dies ist das Ende des Artikels, ich hoffe es hat euch gefallen. Wenn es bei Ihnen ein Interesse an OpenGL geweckt hat, können Sie OpenGL Superbible bei Amazon kaufen oder learnopengl.com erkunden. Wenn Sie nicht mit Shadern umgehen können, empfehle ich Book of Shaders .

Source: https://habr.com/ru/post/de441862/


All Articles