Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: So Jul 06, 2025 19:39

Foren-Übersicht » Programmierung » Shader
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 7 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Oberfläche einer Kugel
BeitragVerfasst: So Okt 07, 2012 09:22 
Offline
DGL Member

Registriert: Sa Okt 06, 2012 20:03
Beiträge: 3
Programmiersprache: Java
Hi,

uns wurde zur Prüfungsvorbereitung die folgende Aufgabe gegeben und ich tue mich mit Shadern leider noch sehr schwer. Es wäre sehr nett, wenn mir jemand unter die Arme greifen könnte.

"Die beiden Shader beschreiben die Oberfläche einer Kugel. Erklären Sie die Variablen, die verwendet werden sowie jeweils die Ausgabe der Shader. Wie wird die Kugel wahrscheinlich aussehen?"

Vertex-Shader:
Code:
  1. varying vec3 vNormal;
  2. varying vec4 pos;
  3.  
  4. void main()
  5. {
  6.     gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
  7.     pos = modelViewMatrix * vec4(position, 1.0);
  8.     vNormal = normalize(normalMatrix * normal);
  9. }


Fragment-Shader:
Code:
  1. varying vec3 vNormal;
  2. varying vec4 pos;
  3.  
  4. void main()
  5. {
  6.     vec4 to_camera = normalize(-pos);
  7.     float intensity = max(dot(to_camera, vec4(vNormal, 1.0)), 0.0);
  8.     gl_FragColor = vec4(intensity, intensity, intensity, 1.0);
  9. }


Ich schreibe mal, was ich verstehe und wo ich Probleme habe:
varying ist eine Variable, die der Kommunikationsrichtung Vertex-Shader -> Fragment-Shader dient, wobei für letzteren read-only gilt.
vec3 bzw. vec4 ist ein Vektor mit 3 bzw. 4 float-Werten.

Jetzt beginnen auch schon die Probleme:
gl_Position wurde nirgendwo deklariert, warum kann man dieser Variablen einfach einen Wert zuweisen und was bedeutet die Zeile hinter "gl_Position = "?
pos und vNormal wurden bereits deklariert und sie erhalten jetzt einen Wert. Was wird hier aber gemacht?

Also ich habe mir auch schon das Tutorial http://zach.in.tu-clausthal.de/teaching ... _tutorial/ durchgelesen, aber die Probleme bleiben.

Thanks für die Hilfe!!!

Grüße,
gargado


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Oberfläche einer Kugel
BeitragVerfasst: So Okt 07, 2012 09:55 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Erstmal vorweg: Der Shader, so wie er da steht, würde nicht funktionieren. Da fehlen sämtliche Uniform Deklarationen. Ich vermute ihr benutzt da irgendein Framework was dies automatisch erledigt.

Zitat:
gl_Position wurde nirgendwo deklariert

gl_Position ist eine Variable die fest eingebaut ist. Ich quote mal das Wiki:
DGLWiki hat geschrieben:
Dieser Variable muss im Vertexshader ein Wert zugewiesen werden, wird dies nicht getan ist das Ergebnis (sprich die Position des Vertex) undefiniert. Vorgesehen ist diese Variable für die homogene Position des Vertex und wird u.a. zum Clipping und Culling verwendet. Sie darf natürlich auch (mehrfach) geschrieben und ausgelesen werden.
( http://wiki.delphigl.com/index.php/Tuto ... tex_Shader )

Kurz: Nach der Division durch W enthält gl_Position.xyz die Bildschirmposition des Vertex in NDC (Normalized device coordinates = Würfel von -1 bis 1).

Zitat:
was bedeutet die Zeile hinter "gl_Position = "?

Die Vertexposition wird zunächst ins Kamerakoordinatensystem transformiert und dann wird die Kameraprojektion angewendet. Die dafür nötige Division durch W passiert später.

Zitat:
pos und vNormal wurden bereits deklariert und sie erhalten jetzt einen Wert. Was wird hier aber gemacht?

Hier werden ja augenscheinlich Dreiecke gerendert (vermutlich ein billschirmfüllendes Quad), daher solltest du im Kopf behalten das der Vertexshader jeweils dreimal ausgeführt wird (für jeden Vertex des Dreiecks einmal). D.h. du bekommst je drei Werte für gl_Position, vNormal und pos. Der Rasterizer interpoliert diese Werte (mit Hilfe von gl_Position) und ruft für jedes Fragment (=Pixel auf dem Bildschirm) den Fragmentshader mit den entsprechenden Werten auf.

pos im Vertexshader ist die Vertexposition im Koordinatensystem der Kamera. D.h. der Punkt 0,0,0 ist die Position der Kamera, die negative Z-Achse (per Konvention) entspricht der Blickrichtung. Im Fragmentshader wird durch die interpolation daraus die Position des jeweiligen Fragments im selben Koordinatensystem.

vNormal ist die Normale des Vertex bzw. im Fragmentshader die Normale des Fragments.

to_camera ist ein Vektor vom Fragment zur Kamera. (Zur Erinnerung: Kamera steht an 0,0,0)

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Oberfläche einer Kugel
BeitragVerfasst: So Okt 07, 2012 13:07 
Offline
DGL Member

Registriert: Sa Okt 06, 2012 20:03
Beiträge: 3
Programmiersprache: Java
Danke erstmal für die schnelle Antwort.

Für die Übungen wurde uns eine Datei namens Three.js gegeben sowie eine HTML-Datei in der wir den Code für die Vertex-/Fragment-Shader einfügen können. Die hier gepostete Aufgabe entspricht aber einer Klausuraufgabe, für die uns nur Papier und Stift zur Verfügung stehen würde.

Den Vertex-Shader habe ich jetzt verstanden, Probleme habe ich aber noch mit dem Fragment-Shader:

1.) Mir ist klar, dass die Kamera im Ursprung ist und über die negative z-Achse in die Welt blickt. Aber warum -pos?
2.) Mir ist auch klar, dass die Formel für die Berechnung der Lichtintensität Skalarprodukt(Richtung, Normale) / (Betrag(Richtung)*Betrag(Normale)) ist, wobei der Nenner aufgrund der vorherigen Normalisierung wegfällt. Wozu aber die Funktion max(..., 0.0)?
3.) Das fertige Bild sieht dann so aus:

Bild

Für die gegebene Aufgabe muss man denke ich die Variablen derart beschreiben, wie du es gemacht hast. Was ist aber mit "Ausgabe der Shader" gemeint und woran kann man am Quellcode erkennen, dass die Kugel so aussehen wird wie auf dem geposteten Bild?

Vielen Dank für die Hilfe!


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Oberfläche einer Kugel
BeitragVerfasst: So Okt 07, 2012 14:08 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Zu 1):
pos ist die Position des Fragments. 0,0,0 die Kamera. Daher ist (0,0,0) - pos der Vektor vom Fragment zur Kamera.

Zu 2):
Nun es gibt ja Fälle bei denen du ein negatives Ergebnis beim Skalarprodukt bekommst. Etwa wenn die Normale von der Kamera weg zeigt. Eine negative Intensity macht eher weniger Sinn, darum setzt man die dann einfach Null.

Zitat:
woran kann man am Quellcode erkennen, dass die Kugel so aussehen wird wie auf dem geposteten Bild?

Naja, man kann sich anhand der Oberfläche der Kugel und der jeweiligen Position der Fragmente zur Kamera darauf schließen wo die Kugel hell und wo sie dunkel sein wird. Eben da hell wo die Normale zur Kamera zeigt.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Oberfläche einer Kugel
BeitragVerfasst: So Okt 07, 2012 16:12 
Offline
DGL Member

Registriert: Sa Okt 06, 2012 20:03
Beiträge: 3
Programmiersprache: Java
Coolcat hat geschrieben:
Naja, man kann sich anhand der Oberfläche der Kugel und der jeweiligen Position der Fragmente zur Kamera darauf schließen wo die Kugel hell und wo sie dunkel sein wird. Eben da hell wo die Normale zur Kamera zeigt.


Es ist vermutlich trivial, aber irgendwie "steige" ich da noch nicht ganz dahinter...

Bei einer anderen Aufgabe hatten wir den Code:

Code:
  1. // switch on high precision floats
  2. #ifdef GL_ES
  3. precision highp float;
  4. #endif
  5.  
  6. varying vec3 vNormal;
  7. varying vec3 lightingDirection;
  8. varying vec4 v;
  9. varying float intensity;
  10.  
  11. void main()
  12. {
  13.     gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
  14.     vNormal = normalize(normalMatrix*normal);
  15.     v = modelViewMatrix*vec4(position,1.0);
  16.    
  17.     vec4 ld = vec4(10.0,10.0,-80.0,1.0) - v;
  18.     lightingDirection = normalize(vec3(ld));
  19.     intensity = dot(lightingDirection,vNormal);
  20. }


Code:
  1. #ifdef GL_ES
  2. precision highp float;
  3. #endif
  4.  
  5. varying float intensity;
  6. void main()
  7. {
  8.     vec4 color;
  9.  
  10.     if (intensity > 0.95)
  11.         color = vec4(1.0,0.5,0.5,1.0);
  12.     else if (intensity > 0.5)
  13.         color = vec4(0.6,0.3,0.3,1.0);
  14.     else if (intensity > 0.25)
  15.         color = vec4(0.4,0.2,0.2,1.0);
  16.     else
  17.         color = vec4(0.2,0.1,0.1,1.0);
  18.            
  19.     gl_FragColor = color;
  20. }


Mit dem Ergebnis:

Bild

Wie würde man sich hier eine Antwort auf die Frage "Wie wird die Kugel vermutlich aussehen?" erschließen?

Vielen Dank!


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Oberfläche einer Kugel
BeitragVerfasst: Do Okt 11, 2012 22:30 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Nov 08, 2010 18:41
Beiträge: 769
Programmiersprache: Gestern
Das ist eigentlich ganz einfach (und übrigens falsch :P):

Die Theorie ist folgende, ein Punkt (hier v) erhält weniger Photonen von einer Lichtquelle desto weiter er von ihr entfernt liegt. Stell dir nun dein
Polygon als eine Ansammlung von Punkten auf der gleichen Ebene (E) und deine Lichtquelle als Punkt vor. Aus den gängigen Quellen wissen wir das der
kürzeste Weg zwischen Beiden eine Gerade (g) beschreibt die Senkrecht zur Ebene steht. Der Richtungsvektor dieser Geraden ist die Normale.
Nun bilden wir ein Dreieck aus dem Punkt (v) unserer Lichtquelle und dem Schnittpunkt von (E und v) um den Weg (d) unseres Photons zu sehen. Dabei
stellt man fest das der Weg länger wird wenn auch der Winkel zwischen den beiden geraden größer wird. Glücklicherweise kennen wir vom Dreieck
ein ähnliches Verhalten. Und zwar den Cosinus und wir wissen das der Cosinus Richtung A * Richtung B entspricht. Und eine Richtung ergibt sich wiederum
aus Ende - Start.

Allerdings verändert sich unser Punkt durch die ModelView Matrix. Daher muss auch die Normale geändert werden um noch Senkrecht zu unserer Ebene (e) zu
stehen. Da die Normal ein Vektor der länge 3 ist der nicht skaliert wird, brauchen wir nur den ersten 3*3 Block unserer ModelView Matrix zu berücksichtigen.
Da stellen wir allerdings fest das unsere Normale nicht immer senkrecht steht. Allerdings sieht man auch das dieser Effekt nicht bei den Tangenten unserer Ebene
auftritt :). Da wir wissen das die Normale Senkrecht zur Tangente steht und der Cosinus in diesen Fall 0 ist, können wir die folgendes Gleichungsystem aufstellen:

(n * matX) * (t * matMV[0..3][0..3]) = 0
t*n = 0
=> (n * matX) * (t * matMV[0..3][0..3]) = t*n

Wenn man sich eine Matrix als Menge von Vektoren vorstellt dann müssen alle Vektoren a) die gleiche Länge haben und b) orthogonal zueinander sein, wie zum
Beispiel {(1,0,0),(0,1,0),(0,0,1)}. Da wir aber mit Variablen arbeiten solls lieber so aussehen {(a1,b1,c1),(a2,b2,c2),(a3,b3,c3)}, unsere Bedingungen eingesetzt
ergeben dann dein Ergebniss:


M ^ -1 => 1 / (a x b) * c * {(b2 * c3 - c2 * b3, c1*b3 - b1*c3, b1*c2 - c1*b2), (c2 * a3 - a2 * c3, a1*c3 - c1 * a3, c1*a2 - a1 * c2), (a2*b3 - b2*a3, b1 * a3 - a1 * b3, a1*b2 - b1*a2)}
M ^ T => {(a1,a2,a3),(b1,b2,b3),(c1,c2,c3)}
// also: matX ^ T * matMV[0..3][0..3] = X ^ -1

normal => (matMV[0..3][0..3]^ -1) ^ T * n ;
intensity => normalize(normal) * normalize((10.0,10.0,-80.0,1.0 - (p * matMV)[0..3]))

_________________
Meine Homepage


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Oberfläche einer Kugel
BeitragVerfasst: Fr Okt 12, 2012 19:27 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
yunharla hat geschrieben:
Die Theorie ist folgende, ein Punkt (hier v) erhält weniger Photonen von einer Lichtquelle desto weiter er von ihr entfernt liegt.[…]Dabei stellt man fest das der Weg länger wird wenn auch der Winkel zwischen den beiden geraden größer wird.[…]

Wenn ich das richtig verstehe (und ich bin mir dessen ziemlich sicher) ist das blank inkorrekt (eventuell wolltest du darauf aber auch hinweisen, dann habe ich aber nicht verstanden warum…).

Der Grund für die Abschwächung bei unpassender Normale ist nicht der verlängerte Weg, sondern die Tatsache, dass dadurch, dass die Fläche vom Licht wegzeigt, also weniger Photonen erhalten kann:

Dateianhang:
foo.png
foo.png [ 3.77 KiB | 6763-mal betrachtet ]


In der Skizze siehst du zwei Flächen die von parallelem Licht beschienen werden. Aus sicht des parallelen Lichtes nimmt die obere, schräge Fläche ungefähr die gleiche Fläche ein wie die untere, gerade Fläche. Das heißt, dass ca. die gleiche Anzahl an Photonen auf die Fläche trifft. Der Unterschied ist bloß, dass sich die bei der oberen Fläche auf eine viel größere Fläche verteilen (eben eine cos(α) Abhängigkeit), damit ist die Fläche insgesamt weniger stark ausgeleuchtet.

grüße

_________________
If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung.
current projects: ManiacLab; aioxmpp
zombofant networkmy photostream
„Writing code is like writing poetry“ - source unknown


„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 7 Beiträge ] 
Foren-Übersicht » Programmierung » Shader


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 12 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.010s | 18 Queries | GZIP : On ]