Wenn ich das Beersche Gesetz (Farbabsorption über die Entfernung durch ein Objekt) implementiere, sieht es aus irgendeinem Grund nie sehr gut aus.
Wenn ich die Farbe hinter dem Objekt habe, berechne ich die angepasste Farbe wie folgt:
const vec3 c_absorb = vec3(0.2,1.8,1.8);
vec3 absorb = exp(-c_absorb * (distanceInObject));
behindColor *= absorb;
Das gibt mir etwas, das so aussieht (beachten Sie ein wenig Brechung angewendet):
Und hier ist es ohne Brechung:
Beachten Sie, dass dies hier als Shader-Spielzeug implementiert ist .
Das erfüllt die Beschreibung dessen, was das Gesetz von Beer tut, aber es sieht nicht sehr gut aus, nicht im Vergleich zu solchen Aufnahmen:
Abgesehen von den Glanzlichtern versuche ich, den Unterschied herauszufinden. Könnte es nur sein, dass meine Geometrie zu einfach ist, um sie wirklich gut zur Geltung zu bringen? Oder implementiere ich es falsch?
quelle
Antworten:
Ihr Bild sieht definitiv nicht richtig aus und es scheint, dass Sie den internen Pfad der Lichtstrahlen auf ihrem Weg durch Ihr Netz nicht richtig berechnen. So wie es aussieht, würde ich sagen, dass Sie den Abstand zwischen dem Punkt, an dem der Sichtstrahl zuerst in den Würfel eintritt, und dem Punkt, an dem er zuerst auf die Innenwand trifft, berechnen und diesen als Absorptionsabstand verwenden. Dies setzt im Wesentlichen voraus, dass Licht immer aus dem Glas austritt, wenn es zum ersten Mal auf eine Wand trifft, was eine schlechte Annahme ist.
In der Realität tritt Licht, wenn es aus der Luft in Glas eintritt, häufig nicht sofort aus dem Glas aus. Dies liegt daran, dass beim Auftreffen des Lichts auf die Glas / Luft-Grenzfläche ein Phänomen auftreten kann, das als Total Internal Reflection (TIR) bezeichnet wird. TIR tritt auf, wenn Licht von einem Medium mit einem höheren Brechungsindex (IOR) zu einem Medium mit einem niedrigeren IOR wandert. Dies ist genau der Fall, wenn Licht auf die Innenwand eines Glasobjekts trifft. Dieses Bild aus Wikipedia ist eine gute visuelle Demonstration dessen, wie es aussieht, wenn es auftritt:
Grundsätzlich bedeutet dies, dass das Licht, wenn es in einem flachen Winkel einfällt, vollständig vom Inneren des Mediums reflektiert wird. Um dies zu berücksichtigen, müssen Sie die Fresnel-Gleichungen auswertenJedes Mal, wenn Ihr Lichtstrahl auf eine Glas / Luft-Grenzfläche trifft (AKA die Innenfläche Ihres Netzes). Die Fresnel-Gleichungen geben das Verhältnis von reflektiertem Licht zur Menge an gebrochenem Licht an, während sie bei TIR 1 sind. Sie können dann die entsprechenden Richtungen für reflektiertes und gebrochenes Licht berechnen und den Lichtweg entweder durch das Medium oder außerhalb des Mediums verfolgen. Wenn Sie ein einfaches konvexes Netz mit einem einheitlichen Streukoeffizienten annehmen, ist der für das Beersche Gesetz zu verwendende Abstand die Summe aller internen Pfadlängen vor dem Verlassen des Mediums. So sieht ein Würfel mit Ihren Streukoeffizienten und einem IOR von 1,526 (Natronkalkglas) aus, der mit meinem eigenen Pfad-Tracer gerendert wurde, der sowohl interne als auch externe Reflexionen und Brechungen berücksichtigt:
Letztendlich sind die inneren Reflexionen und Brechungen ein wesentlicher Bestandteil dessen, was Glas wie Glas aussehen lässt. Einfache Annäherungen reichen wirklich nicht aus, wie Sie bereits herausgefunden haben. Es wird noch schlimmer, wenn Sie mehrere Netze und / oder nicht konvexe Netze hinzufügen, da Sie nicht nur interne Reflexionen berücksichtigen müssen, sondern auch Strahlen berücksichtigen müssen, die das Medium verlassen und an einem anderen Punkt eintreten.
quelle
Here is what a cube looks like (...) using my own path tracer.
Haben Sie es zufällig als Open-Source-Lösung?