In Minecraft wird es dunkler, wenn Sie Wasser betrachten, je tiefer Sie es sehen. Weiß jemand, wie man so etwas codiert?
Minecraft mit Wirkung
ähnliches Spiel ohne Wirkung
In Minecraft wird es dunkler, wenn Sie Wasser betrachten, je tiefer Sie es sehen. Weiß jemand, wie man so etwas codiert?
Minecraft mit Wirkung
ähnliches Spiel ohne Wirkung
Antworten:
Grundsätzlich gibt es zwei verschiedene Ansätze, um Wasser je nach Tiefe zu beleuchten:
Minecraft verwendet eine voxelbasierte Beleuchtung, die das Licht auf benachbarte Würfel ausbreitet und die Helligkeit abhängig vom Blocktyp verringert. Dunkle Ozeane sind ein Nebeneffekt dieses Systems.
Wasser blockiert das Sonnenlicht und reduziert das Licht um 3 Stufen pro Block (anstelle der Standardstufe 1). Dies bedeutet, dass die Helligkeit in einem Ozean für jede Entfernung von der Oberfläche wie folgt ist:
0 (surface): 15 (direct sunlight)
1: 12
2: 9
3: 6
4: 3
5 and below: 0 (darkness)
Quelle: Minecraft Wiki - Licht
In Spielen mit einem herkömmlichen Beleuchtungsmodell kann dieser Effekt durch Messen der Wassermenge zwischen der Lichtquelle und dem Meeresboden erzeugt werden. Das Licht wird dann basierend auf dieser Entfernung ausgeblendet. Hierfür gibt es einige Methoden:
Wenn Sie eine flache Oberfläche haben, können Sie leicht die Entfernung berechnen, die das Licht im Wasser zurücklegt, wenn Sie die Oberflächennormale vom Gewässer entfernt und das Skalarprodukt dieser Normale und eine Oberflächenposition in den Geometrie-Shader eingeben.
Die effektive Wasserentfernung beträgt
wo ist die Position des Scheitelpunkts und ist der Winkel zwischen der Lichtrichtung unter der Oberfläche und der Wasseroberfläche normal zum Gewässer.
Bei Sonnenuntergang werden nur etwas weniger als 50 ° erreicht, da das Licht beim Betreten des Wassers gebrochen wird.
Hier ist ein Blog-Beitrag mit einer guten Erklärung: Die Digitalkamera: Total Internal Reflection
Ein weiterer Beitrag mit weiteren Details: Die Digitalkamera: Snells Brechungsgesetz
Wenn Sie eine Höhenkarte auf einer Oberfläche parallel zum Wasser verwenden, wird . Der richtige Faktor ist 1, wenn sich die Sonne direkt über der Wasseroberfläche befindet.
Bei einem Punktlicht müssen Sie für jeden Scheitelpunkt die relative Position zur Lichtquelle berechnen .
Bei einem festgelegten Wasserstand oder einer festgelegten Lichtrichtung sind Teile der Gleichung konstant und sollten aus Leistungsgründen nicht im Shader berechnet werden.
Wenn Sie die Wasseroberfläche in einer separaten Tiefenkarte rendern (von der Lichtquelle aus gesehen), können Sie diese Tiefenstruktur verwenden, um die Entfernung zu berechnen, die das Licht im Wasser zurücklegt, bevor es auf die Oberfläche trifft.
Dazu projizieren Sie jeden Scheitelpunkt in die Ansichtsprojektion der Lichtquelle im Scheitelpunkt-Shader und führen die Textur-Suche im Pixel-Shader durch.
Wenn die Oberfläche relativ flach ist, sollten Sie für bessere Ergebnisse einen gebrochenen Lichtursprung verwenden.
* Sie können die Wassermenge vor der nächsten festen Oberfläche bestimmen, indem Sie die Tiefe des POV des Lichts wie folgt zählen:
Die Ergebnistextur enthält jetzt die Wassermenge vor dem Licht im Lichtsichtraum, sodass der Wert vor der Verwendung zurücktransformiert werden muss. Diese Methode berechnet das gerichtete Licht (minus Brechung), führt jedoch zu falschem Umgebungslicht, wenn die Oberflächen sehr unregelmäßig sind und sich eine große Menge Luft zwischen den Gewässern befindet, die dieselben Fragmente beeinflussen.
Die Vor- und Nachteile sind die gleichen wie bei der normalen Schattenzuordnung, außer dass Sie beim Berechnen der Tiefe einen Puffer mehr benötigen und die Leistung schlechter ist, weil Sie mehr Geometrie zeichnen müssen.
Raytracing ist bei weitem die genaueste, aber auch die teuerste Lösung für das Rendern transparenter Volumes. Dazu gibt es zwei Möglichkeiten: 1. Verfolgung vom Meeresboden zur Oberfläche und 2. Verfolgung von der Lichtquelle zum Wasser. Für jeden Punkt auf dem Boden werden mehrere Strahlen benötigt, um die Helligkeit zu berechnen.
Beim Rendern von Wasser sind noch einige Dinge zu beachten:
Das Licht im Wasser wird auf dem Weg zum Betrachter wieder gestreut, daher sollten Sie es zu einer festen Farbe mischen.
Wenn der Beobachter eingetaucht ist , können Sie den Nebel nur basierend auf dem Endergebnis des Tiefenpuffers rendern. Die Farbe des Nebels, aber nicht seine Dichte, sollte sich mit dem Abstand des Beobachters von der Oberfläche ändern! (Minecraft verwendet nur diesen Teil des Effekts.)
Wenn der Beobachter von oben auf das Wasser schaut , müssen Sie den Nebel anhand des Tiefenunterschieds zwischen der Oberfläche und der Geometrie unter Wasser berechnen. Die Nebelfarbe sollte mit größeren Tiefenunterschieden etwas dunkler werden, sich aber nur bis zu dem Punkt ändern, an dem der Nebel vollständig undurchsichtig ist.
Die Farbe des Nebels sollte auch von der Blickrichtung der einzelnen Pixel abhängen, sodass sie in beiden Fällen etwas dunkler ist, wenn Sie nach unten schauen.
Wenn Sie eine 3D-Textur mit nahtlosen Kacheln anstelle eines Aufklebers für gefälschte Kaustiken verwenden, können Sie vermeiden, dass vertikale Oberflächen gestreckt werden. Die Stärke des gestreuten Lichts in der Nähe der Oberfläche variiert in drei Dimensionen, sodass die Verwendung einer 2D-Textur normalerweise zu einer Dehnung an einer beliebigen Stelle in der Szene führt. Sie können sich ändernde Lichtwinkel modellieren, indem Sie die Eckpunkte des Bodens in ein anderes Koordinatensystem projizieren.
Eine andere Möglichkeit besteht darin, die Lichtdichte basierend auf der Oberflächenposition im Koordinatensystem des Lichts zu berechnen, obwohl dies höchstwahrscheinlich einige Leistung kosten würde.
Die Kaustik sollte mit zunehmender Tiefe schneller verblassen als das diffuse Licht.
Die Farben werden unterschiedlich gestreut, sodass sich die Lichtfarbe mit zunehmender Tiefe ändern sollte. Dies verhindert auch abrupte Kanten, an denen beispielsweise ein Strand die Wasseroberfläche schneidet.
Aufgrund der Lichtbrechung trifft das Licht viel steiler auf den Meeresboden als es normalerweise der Fall wäre. Der Wikipedia-Artikel über das Snell-Gesetz enthält Formeln für Winkel und Vektoren.
Ich glaube, dass der Himmelslichteffekt in Minecraft direkt nach unten gerichtet ist - die Dinge werden durch das, was sich über ihnen befindet, abgeschattet, egal wo die Sonne ist. Dann wird lokales Licht von Fackeln usw. mit einem Dropoff-Effekt angewendet - je weiter ein Würfel von der Lichtquelle entfernt ist, desto weniger Licht erhält er.
Auf diese Weise würde jede Wasserschicht die darunter liegende Schicht kumulativ beschatten, sodass jede Schicht zunehmend dunkler wird. Baumlaub spendet Schatten, ist aber nicht kumulativ. Sie erhalten den gleichen Schatten unter einem Baum, ob es 1 oder 100 Laubwürfel sind.
Ein Hinweis darauf, dass dies die verwendete Methode ist, ist, dass Wasser nicht dunkler wird, wenn es weiter vom Betrachter entfernt ist - nur wenn Sie nach unten gehen. Ja, der Nebeleffekt setzt in der Ferne ein, aber nicht der Wasserdunkeleffekt.
Die Grundformel für die Berechnung der Beleuchtung wäre also so etwas in Pseudocode ...
light_on_cube = 1.0
for each cube above target cube, from lowest to highest {
if cube being examined is tree foliage
light_on_cube = 0.5
else if cube being examined is water
light_on_cube = light_on_cube - 0.1
else if cube being examined is solid
light_on_cube = 0
}
Dies ist nicht perfekt für die Berechnung der Beleuchtung unter Überhängen oder in Höhlen, da es mit dieser Methode unter einem Überhang stockfinster wäre. Man könnte jedoch sowohl lokale Lichtquellen (Fackeln, Feuer usw.) hinzufügen als auch sonnenbeschienene Blöcke als Lichtquellen behandeln. So etwas könnte es tun ...
Die Idee dabei ist, dass, wenn ein Würfel von der Sonne oder einer Fackel beleuchtet wird, der Würfel daneben auch auf irgendeine Weise beleuchtet wird. Und je weiter Sie von diesem beleuchteten Würfel entfernt sind, desto weniger Licht wird es geben. Es ist eine Art Trick, diffuses Licht einzuschätzen, aber ich denke, (?) Es würde funktionieren.
Vielleicht verstehe ich die Frage falsch, aber warum können Sie die Farbe der Blöcke nicht einfach in Abhängigkeit von ihrer Tiefe ändern?
Wenn Sie die Tiefe d haben (in Blöcken, beginnend mit 0), wäre eine sinnvolle Gleichung für die Helligkeit:
L = (1 - m ) e - kd + m
Code: L = (1.0 - m) * exp(-k * d) + m;
k steuert, wie schnell es dunkler wird (höher = schneller). Ein sinnvoller Wert wäre 0,5.
m ist die gewünschte Mindesthelligkeit.
L variiert von 0 bis 1.
Wenn Sie nicht wissen, wie Sie die Farbe der Blöcke in der von Ihnen verwendeten Grafik-API ändern können, stellen Sie dies bitte als separate Frage (unter Angabe der von Ihnen verwendeten API und ob Sie Shader verwenden oder nicht).
e^-kd
Bit ist nur ein exponentieller Abfall, eine Standardfunktion für Dinge, die über einen bestimmten Wert (Tiefe) allmählich gegen Null tendieren. Die Multiplikation mit (1-m)
und Addition von m
skalieren und versetzen den Zerfall so, dass er bei einem Minimum von endet, m
aber immer noch bei beginnt 1
. en.wikipedia.org/wiki/Exponential_decay