Dans Minecraft, lorsque vous regardez l'eau, plus vous regardez profondément, plus elle devient sombre. Est-ce que quelqu'un sait coder quelque chose comme ça?
Minecraft avec effet
jeu similaire sans effet
Dans Minecraft, lorsque vous regardez l'eau, plus vous regardez profondément, plus elle devient sombre. Est-ce que quelqu'un sait coder quelque chose comme ça?
Minecraft avec effet
jeu similaire sans effet
Réponses:
Il existe essentiellement deux approches différentes pour l'éclairage de l'eau en fonction de la profondeur:
Minecraft utilise un éclairage à base de voxels, qui fonctionne en propageant la lumière vers les cubes adjacents, en réduisant la luminosité en fonction du type de bloc. Les océans sombres sont un effet secondaire de ce système.
L'eau bloque la lumière du soleil et réduit la lumière de 3 niveaux par bloc (au lieu du niveau par défaut 1), ce qui signifie que la luminosité dans un océan pour chaque distance de la surface est:
0 (surface): 15 (direct sunlight)
1: 12
2: 9
3: 6
4: 3
5 and below: 0 (darkness)
Source: Minecraft Wiki - Lumière
Dans les jeux avec un modèle d'éclairage traditionnel, cet effet peut être créé en mesurant la quantité d'eau qui se trouve entre la source de lumière et le fond de l'océan. La lumière s'estompe ensuite en fonction de cette distance. Il existe plusieurs méthodes pour ce faire:
Si vous avez une surface plane, vous pouvez facilement calculer la distance que la lumière parcourt dans l'eau si vous passez la surface normale loin du plan d'eau et le produit scalaire de cette normale et une position de surface dans le shader de géométrie.
La distance effective de l'eau est
où est la position du sommet et est l'angle entre la direction de la lumière sous la surface et la surface de l'eau normale vers le plan d'eau.
Au coucher du soleil, n'atteint qu'un peu moins de 50 ° car la lumière est réfractée en entrant dans l'eau.
Voici un article de blog avec une bonne explication: L'appareil photo numérique: réflexion interne totale
Un autre article avec plus de détails: L'appareil photo numérique: la loi de Snell de la réfraction
Si vous utilisez une carte de hauteur sur une surface parallèle à l'eau, devient . Le bon facteur est égal à 1 si le soleil est directement au-dessus de la surface de l'eau.
Avec une lumière ponctuelle, vous devez calculer pour chaque sommet en fonction de la position relative par rapport à la source de lumière.
Avec un niveau d'eau fixe ou une direction de lumière fixe, des parties de l'équation sont constantes et ne doivent pas être calculées dans le shader pour des raisons de performances.
Si vous rendez la surface de l'eau sur une carte de profondeur distincte (vue depuis la source de lumière), vous pouvez utiliser cette texture de profondeur pour calculer la distance parcourue par la lumière dans l'eau avant de toucher la surface.
Pour ce faire, vous projetez chaque sommet dans la projection de vue de la source lumineuse dans le vertex shader et effectuez la recherche de texture dans le pixel shader.
Si la surface est relativement plate, vous devez utiliser une origine de lumière réfractée pour de meilleurs résultats.
* Vous pouvez déterminer la quantité d'eau devant la surface solide la plus proche en comptant la profondeur du POV de la lumière comme suit:
La texture résultante contient maintenant la quantité d'eau devant la lumière dans l'espace de vision de la lumière, donc la valeur doit être retransformée avant de l'utiliser. Cette méthode fonctionne pour calculer la lumière directionnelle (moins la réfraction), mais conduira à une lumière ambiante incorrecte si les surfaces sont très irrégulières et qu'il y a une grande quantité d'air entre les plans d'eau affectant les mêmes fragments.
Les avantages et les inconvénients sont les mêmes que pour le mappage d'ombres normal, sauf que vous avez besoin d'un tampon supplémentaire lors du calcul de la profondeur et que les performances sont pires car vous devez dessiner plus de géométrie.
Le lancer de rayons est de loin la solution la plus précise mais aussi la plus coûteuse pour le rendu de volumes transparents. Il y a deux façons de procéder: 1. Le traçage depuis le fond de l'océan vers la surface et 2. Le traçage depuis la source lumineuse vers l'eau. Plusieurs rayons sont nécessaires pour chaque point du sol pour calculer la luminosité.
Il y a quelques autres choses à prendre en compte lors du rendu de l'eau:
La lumière dans l'eau est à nouveau diffusée lors du voyage vers l'observateur, vous devez donc la mélanger vers une couleur unie.
Si l'observateur est submergé , vous pouvez simplement rendre le brouillard en fonction du résultat final du tampon de profondeur. La couleur du brouillard, mais pas sa densité, devrait changer avec la distance de l'observateur à la surface! (Minecraft n'utilise que cette partie de l'effet.)
Si l'observateur regarde l'eau d'en haut , vous devez calculer le brouillard en fonction de la différence de profondeur entre la surface et la géométrie sous l'eau. La couleur du brouillard devrait devenir légèrement plus foncée avec des différences de profondeur plus importantes, mais ne devrait changer qu'au point où le brouillard est entièrement opaque.
La couleur du brouillard doit également dépendre de la direction de la vue pour chaque pixel, elle est donc légèrement plus sombre lorsque l'on regarde vers le bas dans les deux cas.
Si vous utilisez une texture 3D en mosaïque transparente au lieu d'un décalque pour les fausses caustiques, vous pouvez éviter de vous étirer sur des surfaces verticales. La force de la lumière diffusée près de la surface varie en trois dimensions, donc l'utilisation d'une texture 2D produit généralement un étirement quelque part dans la scène. Vous pouvez modéliser les angles d'éclairage changeants en projetant les positions des sommets du sol dans un système de coordonnées différent.
Une autre possibilité consiste à calculer la densité de la lumière en fonction de la position de la surface dans le système de coordonnées de la lumière, bien que cela coûterait très probablement des performances.
Les caustiques devraient s'estomper plus rapidement que la lumière diffuse avec une profondeur croissante.
Les couleurs sont dispersées différemment, de sorte que la couleur de la lumière devrait changer avec une profondeur croissante. Cela empêche également les bords abruptes où, par exemple, une plage coupe la surface de l'eau.
En raison de la réfraction, la lumière frappe le fond de l'océan beaucoup plus raide qu'elle ne le ferait normalement. L' article de Wikipedia sur la loi de Snell contient des formules pour les angles et les vecteurs.
Je crois que l'effet d'éclairage du ciel dans Minecraft est direct - les choses sont ombragées par ce qui est au-dessus d'eux, peu importe où se trouve le soleil. Ensuite, l'éclairage local des torches, etc. est appliqué avec un effet de baisse - plus la source de lumière est éloignée, moins le cube reçoit de lumière.
Si cela est fait de cette façon, chaque couche d'eau assombrirait cumulativement la couche en dessous, de sorte que chacune devient progressivement plus sombre. Le feuillage des arbres fournit de l'ombre comme celle-ci, mais il n'est pas cumulatif. Vous obtenez la même ombre sous un arbre que ce soit 1 ou 100 cubes de feuillage.
Un indice que c'est la méthode utilisée est que l'eau ne s'assombrit pas plus loin du spectateur - seulement lorsque vous descendez. Oui, l'effet de brouillard se déclenche à distance, mais pas l'effet sombre de l'eau.
Donc, la formule de base pour calculer l'éclairage serait quelque chose comme ça dans le pseudo-code ...
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
}
Ce n'est pas parfait pour calculer l'éclairage sous les surplombs ou dans les grottes, car il serait très sombre sous un surplomb en utilisant cette méthode. Mais on pourrait ajouter à la fois des sources de lumière locales (torches, incendies, etc.) ainsi que le traitement des blocs éclairés par le soleil comme sources de lumière. Quelque chose comme ça pourrait le faire ...
L'idée ici est que si un cube est éclairé par le soleil ou une torche, le cube à côté de lui sera également allumé d'une manière ou d'une autre. Et plus vous vous éloignez de ce cube éclairé, moins il y aura de lumière. C'est en quelque sorte une manière compliquée d'estimer un éclairage diffus, mais je pense (?) Que cela fonctionnerait.
Peut-être que je comprends mal la question, mais pourquoi ne pouvez-vous pas simplement changer la couleur des blocs en fonction de leur profondeur?
Si vous avez la profondeur d (en blocs, à partir de 0), alors une équation raisonnable pour la luminosité serait:
L = (1- m ) e - kd + m
Code: L = (1.0 - m) * exp(-k * d) + m;
k contrôle la vitesse à laquelle il s'assombrit (plus haut = plus vite). Une valeur raisonnable serait de 0,5.
m est la luminosité minimale souhaitée.
L varie de 0 à 1.
Si vous ne savez pas comment changer la couleur des blocs dans l'API graphique que vous utilisez, veuillez poser cette question séparément (en indiquant quelle API vous utilisez et si vous utilisez ou non des shaders).
e^-kd
bit est juste une décroissance exponentielle, qui est une fonction standard pour les choses qui tendent progressivement vers zéro sur une certaine valeur (profondeur). La multiplication par (1-m)
et l'ajout de m
sont juste à l'échelle et compensent la décroissance de sorte qu'elle se termine au minimum m
mais commence toujours à 1
. en.wikipedia.org/wiki/Exponential_decay