Atmospheric Scattering

Hi there



i tried to implement Sean Oneils Atmospheric Scattering from GPUGems 2 by porting the c-code to JME / Java Code.

It works suboptimal, there are different problems.



I think the biggest problem is that there are some uniforms not found in the shaders:


SCHWERWIEGEND: Shader uniform [fInnerRadius2] could not be located in shader
24.07.2008 19:44:46 com.jme.scene.state.lwjgl.shader.LWJGLShaderUtil updateUniformLocation
SCHWERWIEGEND: Shader uniform [fCameraHeight] could not be located in shader



But these vars are defined in the shaders.
Also the shaders create heavy artefacts. Dont know where they come from. ONeil wrote in a gamasutra that his shaders are for HDR Rendering, he renders in his source to a texture of a cameraaligned quad and does some HDR-Magic in another shader. But i dont think that this solves such artifacts....

Also there are artifacts resulting from the geometries.

If you run the provided code, press "8" to set all uniforms - then the rendering "works". Without hitting 8 only the uniforms which can be found are send to the shaders - but then they arent working.

Some Links:
http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter16.html
http://sponeil.net/index.htm
http://www.gamedev.net/reference/articles/article2093.asp

The Code:
http://snareoj.byteholder.de/atmoscattering/AtmosphericScattering.zip

Perhaps someone has already done this and can provide correct code examples, or somebody can give me a hind what i am doing wrong.

So long,
snareoj

Some Pics:


maybe this thread can help you http://www.jmonkeyengine.com/jmeforum/index.php?topic=6410.0

are you using those uniforms in the shader? if not, they will be optimized away by the shader compiler and you would get that logging info.



he probably outputs to a 64 or 128 bpp texture and then uses tonemapping in another shader to bring it down to 8 bpp for display on screen…

Yes, the uniforms are used in the shader.



Im wondering, because if i dont set the uniforms which can not be found the shader doesnt work, but if the uniforms are set it works…



For Example in the fragmentshader, where "g" can not be found:



@Core: Yes i looked into this, perhaps not too deep enough…



uniform vec3 v3LightPos;
uniform float g;
uniform float g2;

uniform float fExposure;

varying vec3 v3Direction;


void main (void)
{
   float fCos = dot(v3LightPos, v3Direction) / length(v3Direction);
   // here should be the texture lookup for opticalDepthBuffer ? - snareoj
   float fRayleighPhase = 0.75 * (1.0 + fCos*fCos);
   float fMiePhase = 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos*fCos) / pow(1.0 + g2 - 2.0*g*fCos, 1.5);
   gl_FragColor = fRayleighPhase * gl_Color + fMiePhase * gl_SecondaryColor;
   //gl_FragColor.a = gl_FragColor.b;
   
   // simple "HDR" clamping
   gl_FragColor = (1 - exp(-fExposure * gl_FragColor));
}



He uses following shaders after rendering the planet:
(Posting here because dont know if it does what mr coder said)
HDRFrag.glsl


//
// Atmospheric scattering fragment shader
//
// Author: Sean O'Neil
//
// Copyright (c) 2004 Sean O'Neil
//

uniform sampler2DRect s2Test;   // RECTANGLE textures supported in GLSL?
uniform float fExposure;


void main (void)
{
   vec4 f4Color = texture2DRect(s2Test, gl_TexCoord[0].st * 1024.0);
   gl_FragColor = 1.0 - exp(f4Color * -fExposure);
}



HDRVertglsl


//
// Atmospheric scattering vertex shader
//
// Author: Sean O'Neil
//
// Copyright (c) 2004 Sean O'Neil
//


void main(void)
{
   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
   gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
}



Thanks for your answers anyway.

Have a nice day
snare
Core-Dump said:

http://www.jmonkeyengine.com/jmeforum/index.php?topic=6410.0


These two shaders are quite different. For one, the above mentioned doesn't look nearly as good as the one in this thread (except for the artefacts  ;)) and it can render the atmosphere from the inside too  :D. Unfortunately, I'm not that familiar with shaders and cant help you here, but be assured that i will come back and take the finished shader and use the hell out of it.  :evil:

EDIT: I did have quite the same artefacts with the other shader (link above) at first because i forgot the CullStates (front and backside were rendered into each other and resulted in those ugly lines). so that may be it.

so long,

Thanks for the tip, now a part of the artefacts are gone.

Inserted an CullState.setFace(Face.Back); at line 321 at above code.



Now it looks better:

Old:



New:





But the artefacts inside the atmosphere are the same. ONeil mentioned that Nvidia Cards produce more artefacts than ATI cards because of accuracy…



I’ll try to implement his HDR shader, perhaps this will help.



The biggest negative point of these shaders is, that the radius of the ground and the atmosphere have to be 1:1.025 because of the functions are optimized for this in the shaders.



Thanks,

snare

Hi there, i finally managed it.



The reason why there were the artefacts is my nvidida card.

In the atmopshere vertex shader, the colors of the vertices arent calculated in range of [0-1]. And Nvidia cards clamp the gl_FrontColor, which is later used in the fragmentshader, to [0-1] so there is an information loss. Now i am passing the new colors through my own vectors to the fragmentshader.



I have no clue, if this is bad, e.g. for performance or compatibility for older cards or ATI… but the artefacts are gone.



Source code is here: Sourcecode with shaders



Image:



yeah i lost my version back in the jadestone days. seems like you really did it though! cool

Hi There



i implemented ONeils HDR Shader.  It works like a blend in a camera, if exposure is high there will be more light and vise verca.



The artefacts arent gone.



But the effect is nice:







Extreme Artefact





deleted crap

I hope my english isnt to bad and that i dont bore anyone…



Yours,

snare

Seems that i didn’t search the forums completely.

Mr Coders SkyScattering



This is exactly what my code tries to do.



I read the mentioned pages in the thread already before i found the thread, searched the internet for hours for shader implementations. Didn’t find anything, so tried to implement Oneal’s shaders. But these shaders are a mess. Variables in the source which aren’t used in the shaders, different implementations from gpu gems and his hompage…



@Mr Coder: Did you write the shaders yourself? Are u thinking about sharing your code?



Regards



snare

I already talked to mr. coder back then. he implemented the shaders himself but the code got lost.  :expressionless:

Oh thats sad.



I'll try it on my own and if i am successfull i'll post them here.



Thanks for answer.



Have a nice day

snare

I tried to get this running but I am having problems. It builds everything fine, no errors, but when I start it up I get shader errors logged:



29.07.2008 21:24:07 com.jme.scene.state.lwjgl.shader.LWJGLShaderUtil updateUniformLocation

SEVERE: Shader uniform [fSamples] could not be located in shader

29.07.2008 21:24:07 com.jme.scene.state.lwjgl.shader.LWJGLShaderUtil updateUniformLocation

SEVERE: Shader uniform [nSamples] could not be located in shader

29.07.2008 21:24:07 com.jme.scene.state.lwjgl.shader.LWJGLShaderUtil updateUniformLocation

SEVERE: Shader uniform [fScaleOverScaleDepth] could not be located in shader

29.07.2008 21:24:07 com.jme.scene.state.lwjgl.shader.LWJGLShaderUtil updateUniformLocation

SEVERE: Shader uniform [fScaleDepth] could not be located in shader

29.07.2008 21:24:07 com.jme.scene.state.lwjgl.shader.LWJGLShaderUtil updateUniformLocation

SEVERE: Shader uniform [fScale] could not be located in shader



etc. finishing off with:



SEVERE: Exception in game loop

org.lwjgl.opengl.OpenGLException: Invalid operation (1282)

at org.lwjgl.opengl.Util.checkGLError(Util.java:54)

at org.lwjgl.opengl.Display.swapBuffers(Display.java:626)

at org.lwjgl.opengl.Display.update(Display.java:645)

at com.jme.renderer.lwjgl.LWJGLRenderer.displayBackBuffer(LWJGLRenderer.java:506)

at com.jme.app.BaseGame.start(BaseGame.java:87)

at ONeilPlanetGame.main(ONeilPlanetGame.java:121)





Have I neglected to something out of my ignorance or is this a graphics card problem? It is logged as:

INFO: Running on: ati2dvag

Driver version: 6.14.10.6806

ATI Technologies Inc. - ATI Radeon 9600 / X1050 Series - 2.1.7537 Release



Looks great by the way :slight_smile:

hm currently i have no idea why this happens.

Maybe he could not locate the shaders. They are loaded by class.getClassLoader().getResource(string), the shaders have to be located (if you dont change the source) in the same directory like the ONeilPlanetgame class in a subfolder called “homepage”, like “homepage/Shader.name”.

My structure is:

| - bin / OneilPlanetGame.class

|  bin / homepage / GroundFromAtmosphereFrag.glsl

|  bin / homepage / The.Other.Shaders…

|  bin / earth.jpg

|

| - src / OneilPlanetGame.class

|  src / homepage / GroundFromAtmosphereFrag.glsl

|  src / homepage / The.Other.Shaders…

|  src / earth.jpg



I made a package where you can click run.bat for windows and a run.sh for linux (linux not tested)



Zip File



Mfg

snare


thats very cool, works nicely on nv 7600 and ati X1400

Got it to run on my other comp which has an NVidia card.



However I did notice some ripping across the top part of the screen when in full screen mode… It did not happen when I was running at native resolution… when I set the resolution lower, then it happened occasionally. No ripping was noticed in windowed mode… I guess its a driver problem as I could not  resize the image correctly?



In general it run very smoothly, there were only some artifacts when I mouse-looked around… it could not render the planet fast enough I guess… as I could see squares out of alignment with the rest of the planet… (could not screenshot it… looked fine on the images) Nothing like this when moving though.



All in all really really cool :slight_smile:

not that when you have performance problems with that kind of shader, you can always try to create the geometry that the shader is applied to with less details. in this case that means that the performance greatly increases when you create the planet sphere with less samples.

Yes, currently i am searching through LOD Systems for pregenerated planetary terrain.



For the atmosphere, there could be easyly an DescreteLodNode or an AreaClodMesh integrated.



Cu

snare

TestDiscreteLOD (for LOD of a sphere)

and http://earthobservatory.nasa.gov/Newsroom/BlueMarble/ (for free textures)



EDIT: http://earthobservatory.nasa.gov/Newsroom/BlueMarble/BlueMarble_monthlies.html

i just tried it and it looks great on my nvidia geforce go 7900 gs (despite the artifacts around the sun when seen from space).



however, there are two things that make it useless the way it is now:


  1. the atmosphere is drawn over everything else in the scene, even the black parts. so when i add a moon, for instance, it is not visible when seen through the atmosphere.


  2. the shaders seem to depend on the translation, scale and rotation of the planet and its atmosphere, so when i change any of these, it looks ugly.



    any ideas how these issues could be dealt with?