Atmospheric light scattering shader... 4 use with ATMOsphere

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Grz-
Posts: 62
Joined: Wed Dec 26, 2007 1:06 pm

Post by Grz- »

I though so, sorry for all the mails haha... well, i think the only problem i have right now is that i can't get a correct horizon alignment of the hemi-sphere, i did a work around by editing this line in the lookup.frag, but it seem everything is a bit stretched, without this fix, the scattering is applied on the whole sphere.

Code: Select all

float rY = acos(norm.y+1.0)/1.570796;
devsh
Competition winner
Posts: 2049
Joined: Tue Dec 09, 2008 6:00 pm
Location: UK
Contact:

Post by devsh »

Hmm I do not seem to have a problem sir...

Image

the only thing I done to the shader is just adding a multiplier to the 1.0-exp(f(x)) part, because I wanted HDR
Grz-
Posts: 62
Joined: Wed Dec 26, 2007 1:06 pm

Post by Grz- »

Using the shader without any fix i got this result:

Image

Everything seem inverted.

I use this code to setup everything:

Code: Select all

                s32 matScattering = loadShaders("data/shaders/std.vert", "data/shaders/scatter.frag");
                s32 matLookUp = loadShaders("data/shaders/std.vert", "data/shaders/lookup.frag");

                screenQuad = new CScreenQuad(smgr->getRootSceneNode(),smgr,10);
                screenQuad->getMaterial(0).MaterialType = (video::E_MATERIAL_TYPE)matScattering ;

                rt = driver->addRenderTargetTexture(core::dimension2d<u32>(512,512), "RTT1", video::ECF_A8R8G8B8);

                skyDome = smgr->addSkyDomeSceneNode(rt,32,32,1.0f,2.0f, 20000.0f);
                skyDome->setMaterialFlag ( video::EMF_LIGHTING , false );
                skyDome->setMaterialFlag(video::EMF_TRILINEAR_FILTER, true);
                skyDome->setMaterialFlag(video::EMF_ANISOTROPIC_FILTER, true);
                skyDome->setMaterialTexture(0, rt);
                skyDome->setMaterialTexture(1, driver->getTexture("data/stars.jpg"));
                skyDome->setMaterialType ( (video::E_MATERIAL_TYPE)matLookUp );
Shader parameters:

Code: Select all

            irr::f32 TexVar = -0.921f;
            services->setPixelShaderConstant("g", &TexVar, 1);

            TexVar = 0.946f;
            services->setPixelShaderConstant("gSQ", &TexVar, 1);

            TexVar = 10.0f;
            services->setPixelShaderConstant("altitudeMetres", &TexVar, 1);

            TexVar = 120.0f;
            services->setPixelShaderConstant("atmoAltInKm", &TexVar, 1);

            TexVar = 150.0f;
            services->setPixelShaderConstant("sunIntensity", &TexVar, 1);

            TexVar = 1.6f;
            services->setPixelShaderConstant("Exposure", &TexVar, 1);

            irr::u32 TexVar2 = 9;
            services->setPixelShaderConstant("nSamples", (irr::f32*)(&TexVar2), 1);
core::vector3df pos = core::vector3df(0.640,0.560,0.455);

services->setPixelShaderConstant ( "WaveLen" , reinterpret_cast<f32*>( &pos ) , 3 );

core::vector3df np = smgr->getActiveCamera()->getAbsolutePosition();
services->setPixelShaderConstant ( "sun" , reinterpret_cast<f32*>( &np ) , 3 );


			irr::u32 TexVar3 = 1;
			services->setPixelShaderConstant("tex1", (irr::f32*)(&TexVar3), 1);
            TexVar3 = 0;
			services->setPixelShaderConstant("tex0", (irr::f32*)(&TexVar3), 1);
Then i render using this:

Code: Select all

                driver->beginScene(true, true, video::SColor(255, 50, 50, 200));
                driver->setRenderTarget(rt, true, true, video::SColor(255,255,255,255));
                screenQuad->render();
                driver->setRenderTarget(0, true, true, 0);
                smgr->drawAll();
                env->drawAll();
                driver->endScene();
devsh
Competition winner
Posts: 2049
Joined: Tue Dec 09, 2008 6:00 pm
Location: UK
Contact:

Post by devsh »

why is the terrain in the RTT ??
Grz-
Posts: 62
Joined: Wed Dec 26, 2007 1:06 pm

Post by Grz- »

The terrain is not in the RTT.

Also when i look down, it look like this:

Image
devsh
Competition winner
Posts: 2049
Joined: Tue Dec 09, 2008 6:00 pm
Location: UK
Contact:

Post by devsh »

its a well known thing in the engine, please flip the UV y coordinate. either in the atmosphere shader or in your skydome.
Grz-
Posts: 62
Joined: Wed Dec 26, 2007 1:06 pm

Post by Grz- »

Thank, i forgot that somehow, it work well now.

Do you know what is causing this 'line' tho?

Image
devsh
Competition winner
Posts: 2049
Joined: Tue Dec 09, 2008 6:00 pm
Location: UK
Contact:

Post by devsh »

you are rendering to a texture? and updating it every N-th frame?

if yes then its most probably some kind of filtering issue, check the shaders, if they feature a clamp(some texcoord modification,0.001,0.999) function try making the variables closer to 0.0000001 and 0.999999 by adding a digit each time

it could be an issue with your bilinear filtering, try all modes, bilinear, trilinear and anisotropic. Also it can be an issue with your UV coords on the skydome.
Grz-
Posts: 62
Joined: Wed Dec 26, 2007 1:06 pm

Post by Grz- »

Do you know how ground 'scattering' could be added? I know that i can fake it with fog but it is not as good looking.

PS: The line was caused by filtering issue.
devsh
Competition winner
Posts: 2049
Joined: Tue Dec 09, 2008 6:00 pm
Location: UK
Contact:

Post by devsh »

yeh it's a per vertex shader, a bit different though... I could write it for you quickly if you set up standard basic shaders to use by terrain which do what you want them to do (splat or summink) but I'd need your project files/source so I could recompile

Here is a SkyX shader from OGRE, try to make sense of it and use my variables :) then ground will match sky (translate to GLSL)

Code: Select all

/*

--------------------------------------------------------------------------------

This source file is part of SkyX.

Visit ---



Copyright (C) 2009 Xavier Verguín González <xavierverguin@hotmail.com>

                                           <xavyiy@gmail.com>



This program is free software; you can redistribute it and/or modify it under

the terms of the GNU Lesser General Public License as published by the Free Software

Foundation; either version 2 of the License, or (at your option) any later

version.



This program is distributed in the hope that it will be useful, but WITHOUT

ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS

FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.



You should have received a copy of the GNU Lesser General Public License along with

this program; if not, write to the Free Software Foundation, Inc., 59 Temple

Place - Suite 330, Boston, MA 02111-1307, USA, or go to

http://www.gnu.org/copyleft/lesser.txt.

--------------------------------------------------------------------------------

*/



// --------------------- SkyX ground material ------------------------



float scale(float cos, float uScaleDepth)

{

	float x = 1.0 - cos;

	return uScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));

}



void main_vp(

    // IN

	float4 iPosition	        : POSITION,

	// OUT

	out float4 oPosition		: POSITION,

	out float3 oRayleighColor   : TEXCOORD0,

	// UNIFORM

	uniform float4x4 uWorldViewProj,

    uniform float4x4 uWorld,

	// Global information

	uniform float3 uLightDir,

	// Position information

	uniform float3 uCameraPos,

	uniform float3 uCameraPos_,

	uniform float3 uInvWaveLength,

	uniform float  uInnerRadius,

	// Scattering parameters

	uniform float  uKrESun, // Kr * ESun

	uniform float  uKr4PI,  // Kr * 4 * PI

	uniform float  uKm4PI,  // Km * 4 * PI

	// Atmosphere properties

	uniform float uScale,               // 1 / (outerRadius - innerRadius)

	uniform float uScaleDepth,          // Where the average atmosphere density is found

	uniform float uScaleOverScaleDepth, // Scale / ScaleDepth

	uniform float uSkydomeRadius,

	// Number of samples

	uniform int   uNumberOfSamples,

	uniform float uSamples)

{

    // Clip space position

	oPosition = mul(uWorldViewProj, iPosition);

	

	// Calculate vertex world position

	float3 vertexWorldPos = mul(uWorld, iPosition);

	

	// Get the ray from the camera to the vertex, and its length (which is the far point of the ray passing through the atmosphere)

	float3 v3Pos;

	v3Pos.xz = (vertexWorldPos.xz-uCameraPos_.xz) / uSkydomeRadius;

	v3Pos.y = uCameraPos.y + vertexWorldPos.y / uSkydomeRadius;

	

	float3 v3Ray = v3Pos - uCameraPos;

	float fFar = length(v3Ray);

	v3Ray /= fFar;

	

	// Calculate the ray's starting position, then calculate its scattering offset

	float3 v3Start = uCameraPos; // Creo k ai k ajustar la posicion y del pixel

	float fDepth = exp((uInnerRadius - uCameraPos.y) / uScaleDepth);

	float fCameraAngle = dot(v3Ray, uCameraPos) / length(v3Pos);

	float fLightAngle = dot(normalize(uLightDir), v3Pos) / length(v3Pos);

	float fCameraScale = scale(fCameraAngle, uScaleDepth);

	float fLightScale = scale(fLightAngle, uScaleDepth);

	float fCameraOffset = fDepth*fCameraScale;

	float fTemp = (fLightScale + fCameraScale);

	

    // Init loop variables

	float fSampleLength = fFar / uSamples;

	float fScaledLength = fSampleLength * uScale;

	float3 v3SampleRay = v3Ray * fSampleLength;

	float3 v3SamplePoint = v3Start + v3SampleRay * 0.5f;

	

	// Loop the ray

	float3 color = float3(0,0,0);

	for (int i = 0; i < uNumberOfSamples; i++)

	{

    	float fHeight = length(v3SamplePoint);

		float fDepth = exp(uScaleOverScaleDepth * (uInnerRadius-fHeight));

		float fScatter = fDepth*fTemp - fCameraOffset;

		float3 v3Attenuate = exp(-fScatter * (uInvWaveLength * uKr4PI + uKm4PI)); // <<< TODO

		

		color += v3Attenuate * (fDepth * fScaledLength);

		v3SamplePoint += v3SampleRay;

	}



    // Outputs

    oRayleighColor = color * (uInvWaveLength * uKrESun); // TODO <--- parameter

}



void main_fp(

    // IN

	float3 iRayleighColor   : TEXCOORD0,

	// OUT 

	out float4 oColor		: COLOR

	// UNIFORM

#ifdef LDR

	,uniform float  uExposure

#endif // LDR

	)

{	

	oColor = float4(iRayleighColor,1);

	

#ifdef LDR

	oColor.xyz = 1 - exp(-uExposure * oColor);

#endif // LDR

}
Post Reply