Das Problem bei den Ringen ist schlicht und einfach das es keine Kugel ist. Wären die Ringe kugelförmig könnten sie durchaus Schatten werfen. Wenn dir eine Methode einfällt wie du ausgehend von Position der Lichtquelle und den Daten der Scheibe im Shader mit wenigen Berechnungen herausbekommst ob ein Objekt im Schatten liegt oder nicht, dann sollte das gehen.
Ok, wie wäre es mit dem folgenden. Würde zumindest für Punktlichtquellen funktionieren: Gegeben sind:
Position L der Lichtquelle (Sonne)
Ebene auf der sich die Scheibe befindet, sowie der Mittelpunkt M und Radius r der Scheibe.
die Lichtdurchlässigkeit der Ringe als 1D-Textur, also so was hier aber nur ein Texel in der Höhe: Dabei sollte die Texcoord 0 innen sein und 1 außen.
Postion P des gerade berechneten Pixels
(alle Daten im selben Koordinatensystem, z.B. Viewspace)
Berechne den Schnittpunkt S der Gerade P--L mit der Ebene. Berechne den Abstand d zwischen S und M. Mit einem Texturlookup an der Koordinate d / r erhältst du die Lichtdurchlässigkeit der Scheibe. Ist die Koordinate größer als 1, bist du außerhalb der Scheibe. Genauso kannst du auch einen inneren Bereich definieren und die Texturkoordinate entsprechend transformieren.
( Edit: Zu beachten ist natürlich der Spezialfall wenn die Gerade parallel zur Ebene der Scheibe liegt. )
Vielleicht kann man diese Idee auch irgendwie auf Kugel-Lichtquellen verallgemeinern. Mir fällt dazu aber gerade nix ein.
Variante 3 ist speziell für deine Szene zugeschnitten. Da Kugeln relativ einfache Objekte sind kann man den Schatten auch direkt im Shader berechnen. Den das Schattenvolumen kann man durch Kegelstümpfe beschreiben. Ein Kegelstumpf besteht aus einer Spitze, einer Richtung und einem Radius. Die Spitze ist die Lichtquelle, die Richtung ist Planet-Lichtquelle und der Radius, der Radius des Planeten. Der Shader bekommt eine Liste dieser Kegelstümpfe und testet für jeden Pixel ob er sich in einem der Kegelstümpfe befindet. Deine Ringe können so leider nur Schatten empfangen und nicht werfen, da die Ringe eine viel kompliziertere Struktur haben. Man kann die Lichtquelle auch als Kugel (nicht nur Punkt) annehmen und weiche Schatten berechnen. Dafür braucht man dann immer jeweils zwei Kegel. Das wäre bei den anderen beidem Methoden extrem aufwendig! Ich werde das wahrscheinlich in UC so implementieren, weiß aber noch nicht wie schnell das sein wird.
Im IRC-Kanal kam raus, dass man einen PerPixelLightning-Shader um einen Schattentest erweitern könnte, um die Variante 3 umzusetzen. Das habe ich auch schon probiert, doch wie schafft man es, zu prüfen, ob nun ein Objekt (sagen wir mal als Beispiel Saturn) im Kegelstumpf eines anderen (zum Beispiel der Mond Titan) liegt ? Ich überlege schon die ganze Zeit, aber weiß nicht wie man das am einfachsten ausformuliert. Man müsste irgendwie prüfen, ob "obj" sich in einem aus "l" und "r" ergebenden Kegelstumpf befindet. Und genau da hänge ich. Vertex-Shader:
(vec3) der normalisierte Vektor von Lichtquelle zum Schattenwerfer S, ebenfalls im Viewspace. Einfach normalize(S-L), im folgenden A genannt.
(float) die Länge von S-L, genannt e.
(float) Radius r des Kegels beim Schattenwerfer...entspricht dem Radius des Planeten an dieser Stelle
Im Viewspace bedeutet das die Positionen mit der zugehörigen Modelview-Matrix multipliziert werden müssen. Bei der Lichtquelle die Modelview-Matrix der Sonne, beim Schattenwerfer dessen ModelView-Matrix. Das sollte nach Möglichkeit nicht erst im Shader passieren.
Außerdem brauchst du die Fragmentposition ebenfalls im Viewspace. Bei dir im Shader ist dies das varying vec3 v, bei mir P.
So...im Fragmentshader berechnest du den Vektor B = P - L. Mittels Dot-Produkt f = dot(A, B) lässt sich B auf A projizieren, denn da A normalisiert ist gilt P' = f * A. Ist f < e, dann liegt das Fragment vor dem Schattenwerfer. D.h. es gibt kein Schatten und wir sind fertig.
Die Entfernung d ergibt sich aus der Distanz von P und P'. Nun etwas Dreisatz: Der Kegelradius bei P' beträgt r' = (r / e) * f. Ist d > r' sind wir außerhalb des Kegels und es gibt wieder keinen Schatten. Gilt dagegen d <= r' befinden wir und innerhalb des Kegels und damit im Schatten.
Die Variante für Kugellichtquellen kaue ich aber nicht so kleinschrittig vor, sry
Edit: Die Variablen hätte man teilweise etwas sinnvoller nennen können, aber dafür bin ich jetzt zu faul.
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Immerhin sehe ich jetzt endlich woran es die ganze Zeit liegt. Wir rechnen im Physik-LK auch ständig mit Vektoren rum, allerdings werden diese grundsätzlich algebraisch aufgelöst. Zum Beispiel beim Magnetfeld wäre auch eine Vektormultiplikation drinnen, die dann über sin(alpha) umgangen wird, so dass man am Ende ein simples F = Q*v*B für die Lorentzkraft hat. Abgesehen von etwas Vektorzerlegung und Addition hatten wir bisher was das angeht nichts damit zu tun. Deshalb ist es auch schwierig für mich, so etwas zu lösen. Mit dem mathematischen Denken das ich bis jetzt in der Schule gelernt habe kommt man also nicht weit. Aber gut, ich habe mal versucht alles nachzuvollziehen. Mit langem Überlegen konnte ich immerhin den ersten Teil nachvollziehen, natürlich leider nicht voll mathematisch, aber ich glaube das kann man wohl nicht ändern. Jedenfalls ist das Prinzip wie man vorgeht dabei verstanden. Durch Vektormultiplikation kann man den B auf den A projizieren und kommt auf eine Zwischenvariable f. Dann mit A multipliziert hat man P' - keine Ahnung warum das so mathematisch ist, ich denke ich muss das erstmal einfach so hinnehmen. Aber gut, wenn f kleiner der Distanz zwischen S und L, dann kein Schatten, logisch. Dass sich d aus der Distanz ergibt ist klar, ich habe mal geschlussfolgert, dass man P' über die f-Gleichung kriegt und P schon hat. Dann subtrahieren und gut ist, hoffe ich. Der Dreisatz ist wiederum einfach, warum auch keinen Dreisatz an dieser Stelle. d > r' ist auch klar.
Gut, das Prinzip habe ich immerhin verstanden. Die mathematischen Geschichten leider nicht so sehr. Ich verlange nicht und kann auch gar nicht verlangen, dass mir jemand diese Lücken, die ich habe, schließt. Das kann ich vermutlich auch nicht komplett selbstständig, jedoch wird das noch kommen in der Schule, also Kopf hoch.... Ich habe den ersten Teil dieses Beitrags nur geschrieben um klarzustellen, woran es liegt. Denn die letzten beiden Zeilen bei Dir klingen so nach "Oh Nils, ich will jetzt mal nett sein, aber eigentlich müsstest Du das alles auch selbst hinkriegen können - egal wie lange es dauert." Der zeitliche Einwand ist natürlich berechtigt, würde ich mir Vektorrechnung nun beibringen könnte ich es bestimmt auch selbst schaffen, aber das ist so ohne weiteres natürlich auch problematisch, habe ja auch noch für Schule etc. zu tun. Es ist halt einfach ein verdammt hohes Level, Shader zu schreiben und ich werde versuchen in Zukunft falls möglich drum herum zu kommen.
Ich habe mal einen Code daraus gebastelt. Ich tippe mal, er ist total unperformant und schlecht, aber was soll's. Ich habe die Variablenbezeichnungen mal alle angepasst, sonst steigt hier am Ende keiner mehr durch - so schlecht sind Deine finde ich nicht mal.
Das kann ich vermutlich auch nicht komplett selbstständig, jedoch wird das noch kommen in der Schule, also Kopf hoch....
Derartiges kam bei um in Klasse 12 dran glaube ich, Geometrie halt. Aber zumindest damals wurde Geometrie nicht überall gemacht, in anderen Schulen wurde sich dann mehr auf Analysis konzentriert, was für die meisten Studiengänge auch sicher wichtiger ist. Mittlerweile gibt es ja (zumindest in NRW) ein Zentralabi, keine Ahnung ob das da drankommt.
Denn die letzten beiden Zeilen bei Dir klingen so nach "Oh Nils, ich will jetzt mal nett sein, aber eigentlich müsstest Du das alles auch selbst hinkriegen können - egal wie lange es dauert."
Ich hatte mir dieses Kegelprinzip einfach in 2min anhand einer Skizze überlegt und fand das jetzt nicht sonderlich kompliziert. Sorry, wenn du im 11. Semester Informatik studierst und dir tagtäglich Wissen in den Kopf saugst wird es schwierig einzuschätzen wie schwierig etwas ist. An der Uni machst du in einer Woche das was du in der Oberstufe in einem halben Jahr machst... (Falls dies jemand liest der darüber nachdenkt an eine Uni zu gehen...lasst euch nicht abschrecken, es ist schaffbar und macht Spaß )
Zitat:
habe ja auch noch für Schule etc. zu tun.
Ach...Schule...da hatte man noch richtig viel Freizeit
Dann machen wir die Vektoren vermutlich noch in Physik richtig, denn ohne das gemacht zu haben wird es später denke ich nicht mehr gehen. Zumal der Kurs sowieso knallhart ist, es geht deutlich über die Schule hinaus. Und gerade da muss man eben auch Zeit reinstecken. Absolut betrachtet stimmt es, dass ich mehr Zeit habe als Du, aber relativ gesehen nicht. Es kommt immer auf die Lebenssituation an, ich glaube einfach, dass man im Studium die Freizeit vielleicht gar nicht mal mehr so braucht wie in der Schulzeit (weil man reifer ist) - muss man sich eh dran gewöhnen. Jedenfalls ist das hier ja auch keine Pflicht, das was ich hier mache, mache ich mit Spaß in meiner Freizeit. Man muss halt auch sehen, dass sich die Schule leider zum Negativen ändert. Früher hatte jeder maximal einmal pro Woche lang, heute haben bei uns alle mindestens dreimal und die lieben Informatiker kriegen einen Plan mit fünfmal lang. Dann noch Klausuren und gewisse Hausaufgaben, die man mal lieber machen sollte, was daran dann noch viel Freizeit ist musst Du mir erklären Und vor dem Studium braucht man denke ich wirklich keine Angst haben, dass es Spaß macht glaube ich auch Aber das ist alles auch nebensächlich hier, das wichtigste ist nur, dass Du weißt, woran es gelegen hat - und das weißt Du ja seit vorhin schon. Genug Off-Topic, mal weiter: Das Tutorial war echt eine Wohltat. Es ist dank dem Tutorial alles viel klarer geworden, erstmal danke für den Hinweis, echt super. Ich habe den Code noch nicht getestet (nur kompiliert um zu schauen ob die Syntax stimmt). Denn ich hatte mindestens einen Punkt beim Schreiben entdeckt, weshalb er nicht laufen kann. Nämlich mal ganz grundlegend: Sind die Variablen so überhaupt hinnehmbar ? Sind das nicht viel zu viele, ist das wirklich nötig ? Sind die Variablen welche dem Shader übergeben werden in Ordnung ? Bin ich nicht 1. gezwungen, die varyings welche die Positionen angeben durch uniforms im Fragment-Shader abzulösen und 2. dazu verpflichtet, wenn schon varying dann auch das vec3 S im Vertex-Shader zu befüllen - falls es nicht in 1. schon ersetzt wird.
Ich habe jedenfalls das Gefühl, dass jetzt immerhin der entscheidende Schritt gemacht ist. Jetzt liegt es "nur" noch am Programmieren.
Bin ich nicht 1. gezwungen, die varyings welche die Positionen angeben durch uniforms im Fragment-Shader abzulösen
Da der Kegel nichts mit der gerade gerenderten Geometrie zu tun hat musst du diesen als Uniform übergeben. Die Fragmentposition ist aber (für ein Objekt) nicht konstant, daher musst du hier ein varying nehmen.
Durch Vektormultiplikation kann man den B auf den A projizieren und kommt auf eine Zwischenvariable f. Dann mit A multipliziert hat man P' - keine Ahnung warum das so mathematisch ist,
Das Dot-Produkt (zu deutsch: Skalarprodukt) ist wie folgt definiert
Code:
dot(a,b) := a.x*b.x + a.y*b.y + a.z*b.z
und hat die folgende Eigenschaft:
Code:
dot(a,b) = |a| * |b| * cos(w)
Dabei sind a und b zwei beliebige Vektoren und w der Winkel zwischen diesen beiden Vektoren. Die Norm |a| eines Vektors a ist einfach die Länge, also im 3D-Fall:
Code:
|a| = sqrt(a.x^2+a.y^2+a.z^2)
Außerdem gilt im rechtwinkligen Dreieck:
Code:
cos(w) = Ankathete / Hypotenuse
(Ankathete / Hypotenuse ist hoffentlich irgendwo aus der Mittelstufe hängen geblieben? Sonst hilft Wikipedia sicher weiter...)
Ein normalisierter Vektor hat die Länge 1. Wenn also a normalisiert ist, dann gilt für beliebige b:
Code:
dot(a,b) = |b| * cos(w)
Die Länge der Hypotenuse ist |b| und wir wollen die Länge der Ankathete f berechnen:
Code:
cos(w) = Ankathete / Hypotenuse
<=> cos(w) = f / |b|
<=> |b| * cos(w) = f
<=> dot(a,b) = f
Da a normalisiert ist, kann man P' einfach mit P' = a * f berechnen. => a * f ist die senkrechte Projektion von b auf a.
(Trigonometrie kann ich, zählt auch wohl zu den wichtigsten Dingen die man können sollte überhaupt.) So habe ich es jetzt noch besser verstanden, danke!
Ich habe mal probiert, Deine Hinweise zu befolgen. Also so wie ich es verstanden habe, müsste man die Kegeldaten über uniform in den Vertex-Shader übergeben und dann weitereichen an den Fragment-Shader oder liege ich da vollkommen daneben ? Was ich gerade gesagt habe wäre in Code (u als Präfix steht für uniform): Vertex-Shader:
Hier eine Beschreibung meines Programmcodes, den Code zu posten würde dieses Thema glaube ich sonst endgültig sprengen. Ich poste ihn natürlich noch, falls Folgendes nicht so leicht nachzuvollziehen ist, aber ich denke es geht: Ich habe die Kamera in die Lichtquelle gesetzt, alle Uniforms gesetzt und den Shader angewendet. Dann den Saturn mit einem Testmond einfach in die FBO-Textur gezeichnet, Shader wieder deaktiviert und anschließend zur Standardperspektive gewechselt und abschließend die FBO-Textur gezeichnet. Es kommt ein Farbverlauf von grau nach schwarz auf den Bildschirm (von unten nach oben). Natürlich nicht schön glatt, sondern sehr unsauber (also nicht mit einem schönen, normalen Farbverlauf verwechseln). Ich nehme an, es befindet sich da noch ein schwerwiegender Fehler im Shader. Könnte es sein, dass meine Interpretation mit den uniforms falsch ist ?
müsste man die Kegeldaten über uniform in den Vertex-Shader übergeben und dann weitereichen an den Fragment-Shader oder liege ich da vollkommen daneben ?
Ich würde jetzt nicht sagen das du vollkommen daneben liegst...aber da Uniforms auch im Fragmentshader verfügbar sind ist das etwas sinnlos. Insbesondere, weil der Vertexshader ja immer für die drei Vertices jedes Dreiecks ausgeführt wird. Das varying, welches du dann im Fragmentshader erhältst ist die Interpolation zwischen diesen drei Werten (*).
Zitat:
Ich habe die Kamera in die Lichtquelle gesetzt, alle Uniforms gesetzt und den Shader angewendet. Dann den Saturn mit einem Testmond einfach in die FBO-Textur gezeichnet, Shader wieder deaktiviert und anschließend zur Standardperspektive gewechselt und abschließend die FBO-Textur gezeichnet. Es kommt ein Farbverlauf von grau nach schwarz auf den Bildschirm (von unten nach oben). Natürlich nicht schön glatt, sondern sehr unsauber (also nicht mit einem schönen, normalen Farbverlauf verwechseln). Ich nehme an, es befindet sich da noch ein schwerwiegender Fehler im Shader. Könnte es sein, dass meine Interpretation mit den uniforms falsch ist ?
Äh, das mit der Kamera bei der Lichtquelle war bei den ShadowMaps...den FBO brauchst du nicht mehr.
(*) Zumindest sofern du nicht explizit angibst, was mit den drei Werten passieren soll. (geht mit ShaderModel 4)
Es sieht absolut schlecht aus, aber ich sehe erste Schattenerscheinungen Hattest Recht, ich war im Gedanken noch bei den anderen Schatten, habe das alles rausgenommen. Nun stimmen die Farben zwar noch nicht, aber man erkennt schon ganz gut, dass gezielte Flächen ausgeschwärzt werden etc. Nun erstmal einen Screenshot. Denn so sieht es natürlich auch noch nicht gut aus. Und hier erstmal der aktuelle Code. Ich habe die uniforms wieder in den Fragment-Shader gezogen, hast natürlich vollkommen Recht, nur vorhin hatte ich unerklärliche Speicherzugriffsverletzungen bei dem Versuch eine Fragment-Shader-Uniform zu setzen aus dem Programm raus. Dieser Fehler ist jetzt immer noch da. Es kracht wenn ich zum Beispiel die uniform S setzen will. Vertex-Shader:
Und hier die kompltte Render-Prozedur, schön klein, perfekt für das Forum und zum Testen. Die Prozedur InitLights setzt die Lichtquelle, DrawSaturn zeichnet Saturn und seine bisher eingebauten Monde.
Und ein angekündigter kleiner Screenshot. Woran könnte das blau liegen, eventuell an nicht gesetzten Uniforms ? Wie man Sie dort sieht, sehen sie aus, wenn ich die uniforms nicht setze, da es sonst zu den besagten Zugriffsverletzungen kommt. Das Bild ist extra so zurechtgeschnitten, denn mehr sieht man an sich nicht. Was man nur nicht wahrnehmen kann: Die Schatten sind von der Positionierung her richtig gesetzt, denn die Lichtquelle befindet sich in der Mitte, während der Bildausschnitt die Ecke unten links zeigt, wenn der Saturn dort vorbeikommt. Die Schatten variieren auch schön. Es ist auch kein wirklicher Schatten, welcher eventuell vom Licht hervorgerufen wird, denn dafür ist der Schatten auf der Rückseite des Saturn viel zu scharf - die normale Lichtquelle produziert andere, etwas weichere Schatten.
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Woran könnte das blau liegen, eventuell an nicht gesetzten Uniforms ?
Versuche erstmal sicherzustellen, dass deine lokale Beleuchtung funktioniert: 1. Baue deine Schattenabfrage so um das nirgendwo globaler Schatten ist: "if (true) { ...", entsprechend sollte es dann auch nur lokalen Schatten geben und dieser auch der Lichtquelle entspricht. 2. Genau umgekehrt...."if (false) {..."....es sollte nur ambient-Beleuchtung geben und diese sollte ebenfalls korrekt sein.
Der Farbfehler muss irgendwo daher kommen. Vielleicht ist irgendwo eine Material oder Lichtfarbe falsch gesetzt?
Die Farbfehler sind beseitigt. Aber es entstehen keine Schatten. Der Shader rechnet mit der Lichtposition und daher in einem anderen Koordinatensystem als ich. Wäre es nun sinnvoll mit dem Shader die Werte für r oder e umzurechnen oder müsste man das im Programm machen ?
Mitglieder in diesem Forum: 0 Mitglieder und 2 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.