Coder Social home page Coder Social logo

barthpaleologue / volumetric-atmospheric-scattering Goto Github PK

View Code? Open in Web Editor NEW
21.0 2.0 6.0 25.39 MB

A simple implementation of volumetric atmospheric scattering using babylonjs.

Home Page: https://barthpaleologue.github.io/volumetric-atmospheric-scattering/dist

License: Apache License 2.0

HTML 5.87% JavaScript 6.85% TypeScript 49.58% GLSL 33.88% SCSS 3.82%
atmospheric-scattering shaders earth webgl glsl babylonjs volumetric webgpu wgpu

volumetric-atmospheric-scattering's Introduction

Volumetric Atmospheric Scattering

NodeJS with Webpack ESLint pages-build-deployment CodeQL License

A simple WebGPU and WebGL implementation of volumetric atmospheric scattering using BabylonJS. All you need are two files and two lines of code!

Pictures

photo1 photo2 photo3 photo4

Online demo

You can find a demo at https://barthpaleologue.github.io/volumetric-atmospheric-scattering/dist/

You can know the current backend by looking at the bottom left corner of the screen, the logo will either be that of WebGL or WebGPU.

How to use

You need to include the ./src/ts/atmosphericScattering.ts in your project using ES6 imports.

import { AtmosphericScatteringPostProcess } from "./atmosphericScattering";

Then you can use it in your BabylonJS simply by writing:

const atmosphere = new AtmosphericScatteringPostProcess("atmospherePostProcess", planet: Mesh, planetRadius: number, atmosphereRadius: number, sun: Light | Mesh, camera: Camera, depthRenderer: DepthRenderer, scene: Scene);

Note that you can easily set up a depth renderer in your scene in BabylonJS with this syntax:

const depthRenderer = scene.enableDepthRenderer(camera, false, true);

The third parameter is set to true to increase the precision of the depth buffer, it is useful when working at planetary scales.

The atmosphere can be tweaked using various settings grouped in the interface AtmosphericScatteringPostProcess.settings:

interface AtmosphereSettings {
    planetRadius: number, // changes the value used as the minimum height of the atmosphere
    atmosphereRadius: number, // changes the value used as the maximum height of the atmosphere
    falloffFactor: number, // changes the pace at whitch the density of the atmosphere decreases
    intensity: number, // changes the intensity of the colors scattered
    scatteringStrength: number, // changes the dispersion of the three wavelengths
    densityModifier: number, // changes the overall density of the atmosphere
    redWaveLength: number, // changes the value used as the red wavelength in nanometers
    greenWaveLength: number, // same but green
    blueWaveLength: number, // same but blue
}

You can take a look at the simplest implementation in ./src/ts/starter.ts

volumetric-atmospheric-scattering's People

Contributors

ajamesphillips avatar barthpaleologue avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

volumetric-atmospheric-scattering's Issues

Multiple issues

First, let me congratulate and at the same time thank you for your work - being relatively simple (compared to other scary shaders) and done in BabylonJS, it was pretty much the only example I could use to port it to the similar ThreeJS. I hope it's ok, and I'll make sure the proper credits and license (still not sure if more is needed) will be present in the final work, when and if it will be completed. For the record, my use case is including it in an Earth skin I made for the free Rainmeter software, where I can use web technology via a WebView2 capable plugin (though the code will be able to run in a local server webpage as well).

That being said, here are the issues I noticed with your shader:

  1. This has been already mentioned elsewhere, but the random noise here, while creating a reasonable effect for thicker atmospheres, is making it all grainy / pixelated when the atmosphere is thinner (around 0.02 of Earth's radius like in reality, i.e. 51 to 50 radiuses) - as usual, the squared artefacts are solved by increasing the sphere segments number in ThreeJS too, so I multiplied the noise value by 0.0 in effect removing it and it's just fine:
    Atmosphere - Grain
  2. Apparently, if you set the BabylonJS loop to run just once, simulating a single frame or a stopped animation, by commenting line 117 and 123 from here, stuff gets messed up (more on that later on). Not an expert in BabylonJS by any means, so it may be a setting or something that I'm not aware of, but again, it doesn't happen in my nearly identical ThreeJS implementation:
    Atmosphere - Frame
  3. The most important thing, for which I hope there is a reasonable solution or even a hint on how to correct, is the fact that when choosing a bit more extreme values of camera far and near (and, of course, adjusting the radiuses, camera position and so on accordingly), something similar to the image above or downright an invisible or circularly truncated atmosphere happens. Now I realize that BabylonJS probably sets these values automatically, but in case the user wants to modify them, or, like me, has to set them to realistic values, e.g. planetRadius = 6371, atmosphereRadius = planetRadius * 1.02, lookFrom = 42164, cameraFOV = 17, cameraNear = 0.000001, cameraFar = 720000 * planetRadius, corresponding to a real sized Earth in km, geosynchronous orbit, planet occupying full view, minimal near plane and a frustum able to fully include a back-faced celestial sphere, the unwanted surpise of not having a visible atmosphere happens. My guess is that this is related to either the depth or the world coordinate calculation and usage in the other functions, but I've not been able to identify exactly where - somewhere along the line nonunitar values of the camera near (and consequently, different camera distance from the Earth) affect the result, and you can notice this even when zooming out far enough. These can be tested even without modifying the camera near, by using the following in the shader here, instead of this:
// compute the world position of a pixel from its uv coordinates and depth
vec3 worldFromUVDepth(vec2 pos, float posdepth)
{
  vec4 wpos = inverse(view) * inverse(projection) * (vec4(pos, posdepth, 1.0) * 2.0 - 1.0);
  return wpos.xyz / wpos.w;
}

The function, while it may not be exactly what is needed in this case, is replicating the "stages" that the atmosphere is going through, based on the camera distance and the near value. I feel the solution is within reach, some proportionality (or lack of) to the (cameraposition - near) thing, but maybe you know better.

P.S. If you ever think of doing a ThreeJS version of this, the way to solve a logarithmic depth buffer (not sure if it exists in BabylonJS) is like this. Or, I can directly share a fiddle with my simple port to it, if you like. Cheers!

Segment pixilation at large distances from origin.

Hi BarthPaleologue, I've been testing out your shader in babylonJs to see if has any use with my Project. For the most part its amazing and quite customizable.
However my planet system is quite large and it seems that the shader is unable to correctly display the atmosphere scattering effect when the distances in question are above 10,000 units in the engine.
It seems that its the distance from origin thats the issue as rotating the arc camera causes the effect to jitter about the place. Its almost like missing float precision
chrome_2022-06-18_16-53-21
.

Visual glitches

Hey, amazing post process, great work. Exactly what I was looking for. The problem is when I combine this post process with my LOD planet, I get these visual glitches everytime the terrain updates. (video) Any idea what the problem/fix could be? (I'm speculating that the problem might have something to do with the depth buffer).

planet.mp4

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.