1 points par GN⁺ 2 시간 전 | 1 commentaires | Partager sur WhatsApp
  • Le shader du navigateur combine la diffusion de Rayleigh, la diffusion de Mie et l’absorption par l’ozone pour rendre en temps réel un ciel bleu ainsi que les couchers et levers de soleil
  • Il accumule la profondeur optique du rayon de caméra et la transmittance selon la loi de Beer, puis calcule la distribution de la diffusion selon la direction du soleil à l’aide de fonctions de phase
  • L’effet de coucher de soleil exécute un light-march distinct vers la direction du soleil à chaque échantillon, afin de prendre en compte la quantité de lumière solaire perdue lors de sa traversée de l’atmosphère
  • Le shader de ciel plan devient un effet de post-traitement grâce au depth buffer et à la reconstruction des coordonnées monde, ce qui permet aussi de traiter le brouillard atmosphérique entre les objets de la scène
  • À l’échelle planétaire, l’approche s’étend avec un logarithmic depth buffer, l’intersection rayon-sphère, et des LUT de Transmittance, Sky-view et Aerial Perspective

Objectifs du shader de diffusion atmosphérique et références

  • L’objectif est de reproduire dans un shader de navigateur des couches rappelant les photos de coucher de soleil en orbite basse de la navette spatiale Endeavour, avec la transition entre le orange sombre, le bleu et le noir du fond spatial dans la haute atmosphère terrestre
  • Le périmètre de l’implémentation commence par un sky dome réaliste combinant raymarching, diffusion de Rayleigh, diffusion de Mie et absorption par l’ozone, puis s’étend à une enveloppe atmosphérique autour d’une planète et à des optimisations basées sur des LUT
  • Les principales références sont Three Geospatial, A Scalable and Production Ready Sky and Atmosphere Rendering Technique de Sébastien Hillaire, et Atmospheric Scattering (and also just faking it)

Modèle de base du rendu du ciel

  • Pourquoi un simple dégradé ne suffit pas

    • La couleur du ciel ne doit pas être traitée comme un simple fond bleu, mais comme le résultat de l’interaction de la lumière avec l’air et ses composants
    • Il faut prendre en compte des variables comme l’altitude de l’observateur, la quantité de poussière ou l’heure de la journée, et les calculs se font dans un volume
  • Échantillonnage de la densité atmosphérique

    • L’atmosphère est échantillonnée par raymarching, comme pour les volumetric clouds ou la volumetric light
    • On lance un rayon depuis la position de la caméra et on avance dans le milieu transparent ; on calcule alors la transmittance, c’est-à-dire la lumière qui survit à la traversée de l’atmosphère, ainsi que la diffusion redirigée vers la caméra à chaque échantillon
    • Pour réviser le raymarching, on peut consulter Painting with Math: A Gentle Study of Raymarching
  • Densité de Rayleigh et profondeur optique

    • Pour obtenir la transmittance, il faut accumuler la densité atmosphérique rencontrée par le rayon au fil de sa trajectoire afin de calculer la profondeur optique
    • La fonction de densité de Rayleigh indique la quantité d’« air » présente à l’altitude h, et reflète le fait que l’atmosphère se raréfie quand l’altitude augmente
    • L’implémentation d’exemple utilise RAYLEIGH_SCALE_HEIGHT = 8.0km, ATMOSPHERE_HEIGHT = 100.0km, VIEW_DISTANCE = 200.0km et PRIMARY_STEPS = 24
    • rayleighDensity(h) vaut exp(-max(h, 0.0) / RAYLEIGH_SCALE_HEIGHT), et l’accumulation dans la boucle se fait avec viewOpticalDepth += dR * stepSize
  • Loi de Beer et bleu du ciel en journée

    • À partir de la profondeur optique, on calcule la transmittance T en un point donné ; T=1.0 signifie qu’il n’y a aucune perte de lumière, et T=0.0 que la lumière a complètement disparu
    • La transmittance est calculée avec la loi de Beer, et le code d’exemple utilise vec3 transmittance = exp(-rayleighBeta * viewOpticalDepth)
    • rayleighBeta est le coefficient de diffusion de Rayleigh ; dans le shader, il est stocké sous la forme vec3(0.0058, 0.0135, 0.0331)
    • L’angle entre la direction de la lumière solaire et le rayon de vue est modélisé par la fonction de phase de Rayleigh sous la forme 3.0 / (16.0 * PI) * (1.0 + mu * mu)
    • À cause des coefficients de diffusion de Rayleigh, le rouge est très peu diffusé, le vert l’est davantage, et le bleu l’est le plus, ce qui explique la couleur bleue du ciel en journée
    • Si l’on étend cela à un rayon par pixel, l’horizon traverse davantage d’atmosphère et apparaît comme une brume blanche lumineuse, tandis qu’à plus haute altitude la couleur devient un bleu plus profond et plus sombre

Diffusion de Mie et absorption par l’ozone

  • Effets insuffisants avec Rayleigh seul

    • La diffusion de Rayleigh seule donne déjà des résultats corrects, mais un ciel plus réaliste nécessite des effets atmosphériques supplémentaires
    • La diffusion de Mie représente l’interaction de la lumière avec des particules plus grosses, comme la poussière ou les aérosols, et possède une fonction de densité ainsi qu’une fonction de phase décrivant la redistribution selon la direction
    • L’absorption par l’ozone retire certaines longueurs d’onde du trajet lumineux dans la haute atmosphère sans les diffuser
    • L’absorption par l’ozone approfondit notamment les couleurs du ciel et les décale près de l’horizon, au coucher et au lever du soleil, ainsi que pendant le crépuscule
  • Accumulation de Mie et de l’ozone

    • Une implémentation combinant Rayleigh, Mie et ozone accumule leurs profondeurs optiques respectives dans viewODR, viewODM et viewODO
    • À chaque échantillon, on calcule dR = rayleighDensity(h), dM = mieDensity(h) et dO = ozoneDensity(h), puis on construit tau comme la somme de BETA_R * viewODR, BETA_M_EXT * viewODM et BETA_OZONE_ABS * viewODO
    • La transmittance est calculée via exp(-tau), et sumR, sumM ainsi que sumO accumulent chaque densité, la transmittance et stepSize
    • La diffusion finale est calculée sous la forme SUN_INTENSITY * (phaseR * BETA_R * sumR + phaseM * BETA_M_SCATTER * sumM + BETA_OZONE_SCATTER * sumO)
  • Principales constantes et effets

    • MIE_SCALE_HEIGHT est l’équivalent pour les aérosols de RAYLEIGH_SCALE_HEIGHT ; comme les particules sont généralement concentrées près de l’horizon, sa valeur est plus faible, à 1.2km
    • MIE_BETA_SCATTER contrôle à quel point les particules diffusent la lumière vers la caméra ; comme l’effet est en grande partie indépendant de la longueur d’onde, la valeur choisie est vec3(0.003)
    • MIE_BETA_EXT est le coefficient d’extinction de Mie indiquant la quantité de lumière retirée du trajet, ce qui rend l’atmosphère lointaine plus laiteuse
    • MIE_G contrôle l’anisotropie ; 0.0 signifie une diffusion uniforme, et 1.0 un biais plus marqué vers la diffusion avant
    • OZONE_BETA_ABS prend la valeur vec3(0.00065, 0.00188, 0.00008) et absorbe davantage les tons verts ainsi que jaune-orange, ce qui déplace les couleurs du ciel vers le bleu, le rouge et le violet
    • L’intégration de Mie et de l’ozone produit une teinte « sky blue » plus naturelle ainsi qu’un halo lumineux diffus autour du soleil, avec un effet de diffusion de Mie plus visible lorsque le soleil est proche de l’horizon

Trajet de la lumière et coucher·lever du soleil

  • Limites de l’implémentation existante

    • Le fragment shader du ciel peut rendre des couleurs naturelles à différentes altitudes et prendre en compte les modèles de transmission de Mie, de Rayleigh et de l’ozone
    • Cependant, même si l’on déplace le soleil près de l’horizon, on n’obtient qu’une lueur blanchâtre et diffuse, sans atténuation lumineuse ni effet de coucher ou de lever du soleil
    • Cela venait du fait que la boucle de raymarching existante ne calculait l’atténuation de la lumière que le long du rayon de vue, depuis la caméra jusqu’à chaque échantillon
    • Il faut aussi calculer à quel point la lumière solaire est perdue en traversant l’atmosphère avant d’atteindre le point échantillonné
  • Boucle imbriquée de light-march

    • À chaque point échantillonné, une boucle imbriquée distincte est exécutée dans la direction de la source lumineuse pour échantillonner la transmittance sur ce trajet
    • Cette approche est également utilisée dans real-time cloudscapes et volumetric lighting
    • lightMarch(float start, float sunY) itère LIGHTMARCH_STEPS fois en accumulant odR, odM et odO
    • La profondeur optique dans la direction du soleil sunOD est ajoutée aux profondeurs optiques de l’implémentation existante viewODR, viewODM, viewODO
    • Le tau final est construit en additionnant BETA_R * (viewODR + sunOD.x), BETA_M_EXT * (viewODM + sunOD.y), BETA_OZONE_ABS * (viewODO + sunOD.z)
    • Cette implémentation permet de rendre le ciel au coucher du soleil, au lever du soleil, avec le soleil au zénith, ainsi que dans les conditions d’éclairage intermédiaires
    • Le paramètre uniform sun angle permet de faire varier le bleu du ciel au cours de la journée, et la diffusion de Mie mélange naturellement la lumière avec l’horizon au coucher et au lever du soleil
    • Quand le soleil est bas, l’ozone ajoute une tonalité violacée au ciel

Extension à l’atmosphère planétaire

  • D’un fond plat à un effet de post-traitement

    • Le shader créé précédemment fournit un bon arrière-plan de ciel, mais il reste proche d’un fond plat dans une scène React Three Fiber
    • L’étape suivante consiste à le transformer en effet de post-traitement (post-processing effect) afin de rendre un volume tenant compte de la profondeur de la scène, ainsi qu’une enveloppe atmosphérique autour du mesh de la planète
    • Pour cela, on reconstruit les coordonnées en espace monde à partir des coordonnées screenUV, puis on intègre le depth buffer de la scène au raymarching
  • Reconstruction de l’espace monde et rayons 3D

    • Pour appliquer la diffusion atmosphérique à la scène, il ne suffit pas de dessiner le ciel : il faut remplir l’espace entre la caméra et les objets rendus à l’écran
    • Les données nécessaires sont le depth buffer de la scène, projectionMatrixInverse, matrixWorld et position de la caméra, et ces valeurs sont transmises comme uniforms à l’effet de post-traitement
    • getWorldPosition(vec2 uv, float depth) crée clipZ avec depth * 2.0 - 1.0, construit les coordonnées NDC avec uv * 2.0 - 1.0, puis applique projectionMatrixInverse et viewMatrixInverse
    • Le même procédé est aussi utilisé dans l’effet de post-traitement de volumetric lighting de On Shaping Light
    • Une fois la worldPosition du pixel courant obtenue, rayOrigin prend la position de la caméra et rayDir est calculé avec normalize(worldPosition - rayOrigin), puis on avance le long du rayon 3D propre à chaque pixel à l’écran
  • Ajustement de l’intervalle de raymarch avec le depth buffer

    • Pour prendre en compte la géométrie de la scène, l’intervalle de raymarch du rayon courant doit être déterminé par le depth buffer plutôt que par une valeur fixe stepSize
    • sceneDepth = depthToRayDistance(uv, depth) permet d’obtenir la profondeur de la scène le long du rayon
    • Les pixels d’arrière-plan sont détectés avec depth >= 1.0 - 1e-7, et pour les “sky pixels”, on applique sceneDepth = atmosphereHeight * SKY_MARCH_DISTANCE_MULTIPLIER
    • Si le rayon est orienté vers le bas, l’intersection avec le sol est calculée avec tGround = observerAltitude / max(-rayDir.y, 1e-4) puis limitée avec rayEnd = min(rayEnd, tGround)
    • Le stepSize final est calculé avec (rayEnd - rayStart) / float(PRIMARY_STEPS)
    • Les rayons qui touchent des objets proches ou le sol sont échantillonnés plus précisément avec un stepSize plus petit, tandis que les rayons qui vont plus loin répartissent le même nombre d’échantillons sur une plus grande distance
  • Brouillard atmosphérique dans la scène

    • Le shader implémenté comme effet de post-traitement applique la diffusion atmosphérique à l’ensemble du volume de la scène et permet d’utiliser le sky shader en arrière-plan tout en tenant compte de la géométrie de la scène
    • Les objets proches de la caméra apparaissent plus nets, tandis que les objets éloignés deviennent plus flous
    • Un exemple interactif avec des corps célestes déplaçables via Raycaster est visible dans le tweet de MaximeHeckel

Rendu des planètes

  • Deux étapes nécessaires

    • Pour rendre une atmosphère réaliste autour d’une planète, il faut un logarithmic depth buffer pour gérer les très grandes échelles, ainsi qu’une enveloppe atmosphérique sphérique qui définit où le rayon commence et où il se termine dans l’atmosphère
  • logarithmic depth buffer

    • À l’échelle d’une planète, quand on l’observe de loin, le shader peut avoir du mal à distinguer la différence de profondeur entre l’atmosphère et l’enveloppe de la planète, ce qui peut provoquer du depth fighting
    • Comme la hauteur de l’atmosphère n’est que de quelques km, il faut ajuster à la fois la définition du depth buffer de la scène et la manière dont il est lu dans les effets de post-traitement
    • Dans la prop gl qui enveloppe le Canvas de React Three Fiber, on active logarithmicDepthBuffer: true
    • La configuration d’exemple est de la forme <Canvas shadows gl={{ alpha: true, logarithmicDepthBuffer: true }}>
    • Dans le shader, le calcul de sceneDepth est redéfini pour reconvertir le logarithmic depth buffer en distance le long du rayon
    • logDepthToViewZ(depth) utilise pow(2.0, depth * log2(cameraFar + 1.0)) - 1.0 et renvoie -d
  • Trouver l’intervalle atmosphérique avec ray-sphere intersection

    • On utilise un test de ray-sphere intersection pour trouver les points où le rayon de vue entre dans la sphère atmosphérique (atmospheric sphere) et en sort
    • Une fois les deux points d’intersection obtenus, on évite de gaspiller des échantillons hors de l’atmosphère et on peut limiter la boucle de raymarching à cet intervalle seulement
    • La planète étant un mesh sphérique entouré d’une sphère atmosphérique légèrement plus grande, on applique le même test d’intersection à la planète elle-même
    • Si le rayon touche le sol avant de sortir de l’atmosphère, on utilise le point d’intersection avec le sol comme fin de l’intervalle de raymarching
    • L’implémentation de raySphereIntersect utilisée s’inspire de Ray-Surface intersection functions d’Inigo Quilez
  • Objets de la scène et conditions de fin de l’atmosphère

    • L’atmosphère doit s’arrêter lorsqu’elle atteint la surface de la planète, ou lorsqu’elle rencontre un autre objet de la scène avant d’atteindre le sol
    • En cas d’impact avec la planète, on s’arrête au sol par défaut avec atmosphereFar = min(atmosphereFar, planetHit.x)
    • Si un autre mesh est rendu devant le sol, on le détecte avec la condition sceneDepth < planetHit.x - 2.0 puis on applique atmosphereFar = min(atmosphereFar, sceneDepth)
    • Sans cette logique, la surface de la planète peut apparaître devant l’objet
  • Démo React Three Fiber et glitchs restants

    • Une fois ces deux ajustements intégrés au code, on peut implémenter la diffusion atmosphérique comme effet de post-traitement et rendre l’atmosphère autour de la planète
    • La scène de démonstration rend un simple « Sun - Earth system » dans React Three Fiber et lui applique un effet personnalisé
    • En ajustant la position du soleil et en dézoomant, on peut voir le ciel généré par le shader sous différents angles, du sol jusqu’à l’orbite
    • Le même effet a été utilisé pour l’image d’affiche annonçant l’article de début avril, et le rendu a été partagé dans ce tweet
    • Le torus de la scène peut encore paraître « lit-up » même après le coucher du soleil
    • La cause vient de l’échelle trop petite de la shadow-map ou de la shadow-camera de la directional light principale, qui ne couvre pas le torus trop éloigné
    • Comme solution de contournement, il serait possible de réutiliser l’approche de shadow-mapping de l’article sur le volumetric lighting, mais cela n’a pas été réellement tenté

Gestion des éclipses

  • Quand un gros corps céleste masque le soleil, on peut l’ajouter en appelant la fonction sunVisibility après lightMarch, puis en multipliant la transmittance par la valeur de retour [0, 1]
  • L’idée de base consiste à comparer le produit scalaire entre la direction de la lune et la direction du soleil depuis le point d’échantillonnage courant
  • Si les deux directions sont presque identiques et que le produit scalaire est proche de 1.0, la lune masque le soleil ; si elles sont orthogonales et proches de 0.0, il n’y a pas d’occultation
  • Un simple produit scalaire ne suffit pas à refléter la taille et l’échelle des objets dans la scène ; l’implémentation compare donc la distance angulaire entre le soleil et la lune ainsi que leurs rayons angulaires respectifs
  • sunVisibility gère les cas où la lune ne masque pas le soleil, où elle le masque en paraissant plus grande ou d’une taille comparable au soleil du point de vue de la caméra, et où elle le masque en entrant dans le rayon apparent du soleil vu par la caméra
  • La démo ajoute sunVisibility et un mesh de lune à l’exemple existant de diffusion atmosphérique, afin que le shader d’Atmospheric Scattering gère la situation de manque de lumière lorsque la lune est alignée avec le soleil
  • Une simulation plus poussée des éclipses et de la couronne solaire est abordée dans l’article Physically Based Real-Time Rendering of Eclipses, dont l’implémentation n’a pas été portée vers WebGL

Atmosphère d’autres planètes

  • Le modèle de densité atmosphérique et de diffusion utilisé est principalement déterminé par quelques constantes comme le rayon de la planète et de l’atmosphère, RayleighScaleHeight, RayleighBeta, MieScaleHeight, MieBeta, mieBetaExt, mieG, OzoneHeight, OzoneWidth
  • En ajustant ces valeurs, on peut obtenir un résultat proche d’une atmosphère martienne ou de celle d’autres planètes
  • Les valeurs utilisées pour Mars sont approximatives
    • planetRadius: 3390
    • atmosphereRadius: 3500, soit environ 110 km d’épaisseur
    • rayleighScaleHeight: 11.1
    • rayleighBeta: new THREE.Vector3(0.019, 0.013, 0.0057)
    • mieScaleHeight: 1.5
    • mieBeta: 0.04
    • mieBetaExt: 0.044
    • mieG: 0.65
    • ozoneCenterHeight: 0.0
    • ozoneWidth: 1.0
    • ozoneBetaAbs: new THREE.Vector3(0.0, 0.0, 0.0)
    • sunIntensity: 15.0
    • planetSurfaceColor: '#8B4513'
  • Remplacer les constantes existantes par ces valeurs produit une atmosphère plus poussiéreuse et plus orangée, et permet aussi d’obtenir la teinte bleutée caractéristique des couchers de soleil martiens
  • On peut se référer à l’article Physically Based Rendering of the Martian Atmosphere

Diffusion atmosphérique basée sur des LUT

  • Approche et raccourcis pris

    • Le shader existant permet de rendre de façon intuitive une atmosphère à petite et à grande échelle, mais son coût d’exécution est élevé à cause de la boucle de ray marching avec beaucoup de PRIMARY_STEPS, de la boucle imbriquée de lightmarching et des calculs à la résolution de l’écran entier
    • A Scalable and Production Ready Sky and Atmosphere Rendering Technique de Sebastian Hillaire propose une approche basée sur des Look Up Tables (LUTs) qui stocke dans des textures les calculs de diffusion coûteux, puis échantillonne et compose ces textures précalculées dans le rendu final
    • Les LUT utilisées ici sont la Transmittance LUT, qui stocke la quantité de lumière survivant à la traversée de l’atmosphère, la Sky-view LUT, qui stocke la couleur du ciel pour une position de caméra donnée, et la Aerial Perspective LUT, qui stocke le haze atmosphérique et la lumière diffusée entre la caméra et la géométrie visible de la scène
    • L’implémentation ne reprend pas l’intégralité de l’article à l’identique ; les LUT se prêtent bien aux compute shaders de WebGPU, mais par manque de temps et pour préserver la continuité de l’article, l’auteur a conservé WebGL
    • Dans l’article, la Aerial Perspective LUT est une 3D texture, mais l’implémentation utilise une cible de rendu 2D
    • Cette approche impose de régénérer les textures à chaque déplacement de la caméra afin d’obtenir les bonnes valeurs de pixel, ce qui rend le précalcul difficile
    • Le Multi-Scattering a été omis faute de temps
  • Transmittance LUT

    • Dans le shader précédent, chaque point d’échantillonnage appelait lightmarch pour calculer quelle quantité de lumière solaire arrivait jusqu’à lui, ce qui coûtait cher
    • La Transmittance LUT préstocke ces données à basse résolution pour que les autres LUT puissent ensuite les lire lorsqu’elles ont besoin d’informations lumineuses
    • L’implémentation définit un Frame Buffer Object dédié en résolution 250 x 64, applique un material shader personnalisé sur un quad plein écran d’une scène dédiée transmittanceLUTScene, puis transmet la texture de rendu comme uniform aux LUT downstream
    • À chaque pixel, le ray marching démarre depuis vec3(0.0, radius, 0.0), où radius augmente de planetRadius à atmosphereRadius le long de la coordonnée vUv.y
    • L’axe x de la LUT représente l’angle de la lumière, et l’axe y l’altitude ; le blanc pur correspond à une transmittance de 100%, tandis que les zones noires ou colorées indiquent le sol ou les parties où l’air est le plus dense
    • Les LUT suivantes peuvent alors obtenir « la quantité de lumière qui survit à la traversée de l’atmosphère pour un angle et une altitude donnés » via une simple lecture de texture
  • Sky-view LUT

    • La Sky-view LUT calcule la couleur du ciel lorsqu’on regarde vers le haut depuis le sol dans une direction donnée
    • getSkyViewRayDir mappe vUv.x vers l’azimuth [-PI, PI] et vUv.y vers l’elevation [-PI/2, PI/2] afin de définir la direction du ray marching
    • Pour l’elevation, l’implémentation utilise un mapping quadratique (vUv.y * vUv.y - 0.5) * PI, un contournement destiné à éviter que la vue du ciel ne scintille trop à grande distance
    • Si le rayon n’entre pas dans l’atmosphère, la fonction renvoie du noir ; pour les rayons qui touchent la planète, le ray marching ne parcourt que la portion visible de l’atmosphère et s’arrête plus tôt au contact de la planète
    • La boucle de diffusion reste la même qu’auparavant, mais progresse cette fois dans la direction de la Sky View et utilise la Transmittance LUT pour la lumière solaire
  • Aerial Perspective LUT

    • Contrairement à l’article de Hillaire, le résultat de cette implémentation est une texture 2D, et chaque pixel correspond à un pixel visible de l’écran
    • Le depth buffer de la scène est utilisé pour déterminer jusqu’où avancer le long du rayon et accumuler la diffusion
    • Le code de diffusion existant est presque entièrement réutilisé, mais chaque échantillon récupère la visibilité de la lumière solaire depuis la Transmittance LUT
    • La sortie stocke dans le RGB la diffusion atmosphérique accumulée, et dans l’alpha une valeur de view transmittance compactée à utiliser lors de la composition
    • Le flux d’implémentation consiste à lire la profondeur depuis depthBuffer, reconstruire la position en espace monde du pixel écran avec getWorldPosition(vUv, depth), puis calculer rayDir depuis la position de la caméra jusqu’à cette position monde
    • Ensuite, logDepthToRayDistance(vUv, depth) convertit la profondeur de scène en distance de rayon, puis l’algorithme calcule les intersections avec l’atmosphère et la planète avant de marcher uniquement dans la portion visible de l’atmosphère
  • Composition

    • Une fois la Sky-view LUT et la Aerial Perspective LUT générées, les deux sont combinées dans le dernier pass de post-processing
    • L’opération essentielle consiste à convertir le rayDir courant en coordonnées UV de Sky View
    • La Aerial Perspective LUT est appliquée à la géométrie de la scène ; le canal alpha sert de view transmittance et le canal RGB de lumière diffusée, ce qui donne color = color * aerialPerspective.a + aerialPerspective.rgb
    • Pour les pixels d’arrière-plan, la Sky View LUT est échantillonnée ; si depth >= 1.0 - 1e-7, le pixel est traité comme un arrière-plan et l’on applique color = inputColor.rgb + sampleSkyViewLUT(rayDir, planetCenter)
    • Enfin, ACESFilm(color) puis pow(color, vec3(1.0 / 2.2)) sont appliqués
    • L’ensemble du code de cette implémentation atmosphérique basée sur des LUT est disponible via ce Github link

Conclusion

  • Le résultat de la diffusion atmosphérique basée sur des LUT peut sembler presque identique à la version précédente en ray marching complet, mais le fonctionnement interne est différent
  • Le travail est découpé en LUT plus petites, puis recomposé dans l’effet final, sans recalculer à chaque échantillon un ray marching répété vers le soleil pour déterminer la lumière incidente
  • Comme les informations d’éclairage sont récupérées directement depuis la Transmittance LUT, les coûteuses boucles imbriquées sont remplacées par de simples lectures de texture, ce qui apporte un gain de performance non négligeable dans la scène finale
  • Cette implémentation reste en retrait par rapport à celle de Sébastian Hillaire et à d’autres réalisations du domaine ; elle présente notamment du banding et du flickering dans la Sky View, et les raccourcis pris nuisent à son optimalité
  • Il aurait peut-être fallu partir sur WebGPU dès le début
  • Pour une implémentation réellement de niveau production, l’auteur recommande three-geospatial de Shoda Matsuda(@shotamatsuda)
  • L’auteur a aussi travaillé à y ajouter des volumetric clouds, mais le résultat reste encore mitigé et pas assez satisfaisant pour être montré dans l’article, ce qui demande encore du travail

1 commentaires

 
GN⁺ 2 시간 전
Commentaires sur Hacker News
  • Je l’avais déjà vu, donc ce n’est peut-être pas totalement pertinent, mais la vidéo de Sebastian Lague sur le rendu atmosphérique dans ses expériences de génération de planètes était aussi vraiment passionnante : https://www.youtube.com/watch?v=DxfEbulyFcY
    Il y a quelque chose de particulièrement plaisant à voir des effets visuels se développer et devenir progressivement réalistes, et j’aimerais bien expérimenter moi-même dans ce domaine un jour
    • Le plus étonnant chez Sebastian Lague, c’est à quel point l’algorithme de YouTube peut nuire à quelqu’un
      Avant, ses vidéos faisaient des millions de vues, alors qu’aujourd’hui elles dépassent à peine les 500 000. C’est peut-être aussi lié au fait que pendant le Covid, tout le monde était chez soi et s’intéressait à des choses aléatoires
    • Mon seul reproche à Sebastian Lague, c’est qu’il n’y a pas assez de vidéos
      En général, je les mets pour m’endormir, et j’aimerais qu’il y ait plus de contenus de ce genre, calmes mais fouillés sur des sujets techniques, au point d’avoir déjà envisagé d’en faire moi-même
  • Je ne sais pas si c’est un choix délibéré, mais il vaut la peine de rappeler que, dans un modèle de coucher de soleil, le ciel ne devrait pas devenir noir dès que le soleil passe sous l’horizon
    Après le coucher du soleil, l’atmosphère au-dessus de nos têtes et la zone au-dessus de l’horizon continuent à recevoir la lumière du soleil pendant un moment, et dans l’atmosphère terrestre, un crépuscule visible subsiste jusqu’à ce que le soleil descende à 18 degrés sous l’horizon. Ce n’est peut-être pas pratique à implémenter en ray tracing, mais il existe des algorithmes courants pour modéliser cela
  • Les bons billets sur le graphisme sont toujours les bienvenus. J’ai moi aussi travaillé sur quelque chose de similaire dans un générateur procédural d’univers/planètes, et ce qui est chouette avec la diffusion atmosphérique, c’est qu’en la combinant avec le rendu de nuages volumétriques, on peut produire de superbes scènes de ciel et de coucher de soleil
    https://www.threads.com/@mrsharpoblunto/post/DVS4wfYiG8f?xmt...
    https://www.threads.com/@mrsharpoblunto/post/C6Vc-S1O9mX?xmt...
    https://www.threads.com/@mrsharpoblunto/post/C6apksDRa8q?xmt...
  • C’est vraiment impressionnant de voir ce que les téléphones et les navigateurs peuvent faire de nos jours
    Je me souviens avoir implémenté « Display of The Earth Taking into Account Atmospheric Scattering » de Nishita et al., un article de 1993, quasiment fondateur sur le sujet, et très facile à lire : https://www.researchgate.net/publication/2933032_Display_of_...
    • J’ai repensé dans un autre commentaire à l’article que j’avais lu autrefois en implémentant la diffusion de Rayleigh et la diffusion de Mie, et c’est bien celui-là
      Quand j’ai réussi à le faire fonctionner, j’ai eu ce moment de réalisation : « on peut en fait modéliser assez bien ce phénomène complexe du monde réel avec quelques calculs relativement simples ». On est passé en un instant d’une simple skybox bleue statique à un cycle jour-nuit complet
  • Vraiment excellent
    Il fut un temps où je me demandais ce que donnerait le rendu d’un ciel sur le web en superposant plusieurs dégradés. J’ai peut-être obtenu des résultats corrects dans une certaine mesure, mais rien de comparable à ce qui a été fait ici. Le résultat est impressionnant et inspirant
    • J’ai déjà implémenté la diffusion de Rayleigh et la diffusion de Mie dans un moteur de jeu que j’avais créé comme hobby
      Rien qu’avec ça, j’avais été surpris d’obtenir un cycle coucher/lever de soleil assez crédible, et si je me souviens bien, le soleil lui-même en émergeait d’une manière assez naturelle. J’utilisais XNA, la plateforme de développement de jeux en C# de Microsoft, en suivant l’excellente série de tutoriels de Riemer, dont on trouve une archive ici : https://github.com/SimonDarksideJ/XNAGameStudio/wiki/Riemers...
      Je n’y vois toutefois rien sur la diffusion, donc j’ai peut-être pris cette partie ailleurs. Je me souviens en tout cas d’avoir lu des articles avec des formules
  • SpaceEngine est aussi réputé pour avoir beaucoup investi ce domaine, donc je le recommande vivement : https://www.youtube.com/watch?v=_4TjdVAbXks
    https://spaceengine.org/
    • J’aime bien les FAQ de ce genre de choses, parce qu’elles donnent une idée de l’échelle et de la variété des questions
      À la question « Combien d’objets y a-t-il dans SpaceEngine ? », la réponse est quelque chose comme : l’intégralité du catalogue d’étoiles Hipparcos, toutes les exoplanètes connues, plus de dix mille galaxies et la plupart des objets du système solaire, soit 130 000 au total, auxquels s’ajoutent plus de galaxies et de systèmes stellaires qu’il n’en existe réellement dans l’univers observable. À « Comment une planète océan peut-elle être chaude ? », la réponse est que l’eau de la haute atmosphère est de la vapeur brûlante, mais qu’en descendant, elle passe en douceur à l’état liquide sous haute pression, puis plus en profondeur à l’état solide appelé ice VII. À « Comment se déplacer ? », la réponse est : avec les touches WASD
    • Avoir Wikipedia dans un onglet et SpaceEngine dans l’autre fait partie de mes expériences de jeu quasi éducatives préférées
      C’est un excellent jeu, et même s’il date déjà un peu, je n’ai toujours rien vu d’aussi réussi
    • C’est un excellent logiciel depuis des années, et pas seulement sur ce sujet : dans bien des domaines, son obsession du détail est remarquable
      Cet article m’a immédiatement fait penser à SpaceEngine
  • La diffusion est depuis longtemps un élément clé pour produire des images de rendu réalistes
    L’un de mes articles préférés : http://www.graphics.stanford.edu/papers/bssrdf/bssrdf.pdf
    Je crois que c’est là que j’ai appris pour la première fois à quel point le rendu du lait est un problème difficile
  • Waouh, quel parcours impressionnant
    Je n’en ai probablement compris qu’environ 5 %, mais j’ai été profondément admiratif
    • Pareil pour moi. Rien que pour les visuels, ça valait la lecture
  • Oh, c’est vraiment un texte magnifique et agréable à lire
    Et si c’est sous licence MIT, alors mon problème de skybox pour mon jeu est pratiquement réglé. La perspective sera fixe, donc il me suffit d’avoir un rendu du soleil traversant le ciel, puis d’étendre cela avec un cycle sinusoïdal pour faire varier l’angle du soleil au fil de l’année