OGRE Wiki
Support and community documentation for Ogre3D
Ogre Forums
ogre3d.org
Log in
Username:
Password:
CapsLock is on.
Remember me (for 1 year)
Log in
Home
Tutorials
Tutorials Home
Basic Tutorials
Intermediate Tutorials
Mad Marx Tutorials
In Depth Tutorials
Older Tutorials
External Tutorials
Cookbook
Cookbook Home
CodeBank
Snippets
Experiences
Ogre Articles
Libraries
Libraries Home
Alternative Languages
Assembling A Toolset
Development Tools
OGRE Libraries
List of Libraries
Tools
Tools Home
DCC Tools
DCC Tutorials
DCC Articles
DCC Resources
Assembling a production pipeline
Development
Development Home
Roadmap
Building Ogre
Installing the Ogre SDK
Setting Up An Application
Ogre Wiki Tutorial Framework
Frequently Asked Questions
Google Summer Of Code
Help Requested
Ogre Core Articles
Community
Community Home
Projects Using Ogre
Recommended Reading
Contractors
Wiki
Immediate Wiki Tasklist
Wiki Ideas
Wiki Guidelines
Article Writing Guidelines
Wiki Styles
Wiki Page Tracker
Ogre Wiki Help
Ogre Wiki Help Overview
Help - Basic Syntax
Help - Images
Help - Pages and Structures
Help - Wiki Plugins
Toolbox
Freetags
Categories
List Pages
Structures
Trackers
Statistics
Rankings
List Galleries
Ogre Lexicon
Comments
History: Atmosphere Shader
View page
Source of version: 2
(current)
{maketoc} !!Description This shader is used to create atmospheric rings around a planet as depicted in the picture below: {IMG(src="dl2110&display")}{IMG} !!Usage You will need to assign this material to a sphere that is a little bigger then your planet. Also you will need to give this shader the radius of your planet and the radius of the sphere you use as the atmosphere. You can do that with this line of code {CODE(wrap="1", colors="c++")} //Create our entity AtmosphereEntity = sm->createEntity(PlanetName + "_atm_Ent",PlanetName + "_atm"); //assign it our material AtmosphereEntity->setMaterialName ("Atmosphere"); //also this will make the atmosphere to be rendered behind the planet AtmosphereEntity->setRenderQueueGroup (Ogre::RENDER_QUEUE_BACKGROUND); //here you will replace PlanetRadius and AtmosphereRadius with your values AtmosphereEntity->getSubEntity (0)->setCustomParameter (0, Ogre::Vector4(PlanetRadius,AtmosphereRadius,0,0));{CODE} And here is the gradient you need as a texture (just right click / save image as and save it into your media folder) {IMG(src="dl2111&display")}{IMG} ~~#F00:WARNING : It is extremely important that you do not rotate the atmosphere holding sphere, as this will screw up the shader!!!~~ !!Atmosphere.material {CODE(wrap="1", colors="c++")} vertex_program AtmosphereVertexProgram hlsl { source Atmosphere.hlsl entry_point main2VS target vs_2_0 default_params { param_named_auto lightPos light_position_object_space 0 param_named_auto WorldXf world_matrix param_named_auto ViewIXf camera_position_object_space param_named_auto WorldViewProj worldviewproj_matrix } } fragment_program AtmosphereFragmentProgram hlsl { source Atmosphere.hlsl entry_point mainBPS target ps_2_0 } material Atmosphere { technique { pass { depth_check off depth_write off scene_blend one one_minus_src_alpha vertex_program_ref AtmosphereVertexProgram { param_named_auto SurfaceAtmosphereRadius4 custom 0 } fragment_program_ref AtmosphereFragmentProgram { } texture_unit { texture AtmosphereGradient.jpg tex_address_mode clamp clamp filtering linear linear linear } } } } {CODE} !!Atmosphere.hlsl {CODE(wrap="1", colors="c++")} void main2VS( float3 pos : POSITION, uniform float4 lightPos, uniform float4x4 WorldXf, uniform float4 ViewIXf, uniform float4x4 WorldViewProj, uniform float4 SurfaceAtmosphereRadius4, out float4 oPosition: POSITION, out float2 oUV: TEXCOORD0, out float oAlpha: TEXCOORD1, out float3 oCamToPos: TEXCOORD2, out float3 oLightDir :TEXCOORD3 ) { float SurfaceRadius = SurfaceAtmosphereRadius4.x; float AtmosphereRadius = SurfaceAtmosphereRadius4.y; float StretchAmt = 0.5f; float4 Po = float4(pos.xyz,1); float4 Pw = mul(WorldXf, pos); float3 position = Pw.xyz; float4 camPos = ViewIXf; oPosition = mul(WorldViewProj, Po); float radius = length(position); float radius2 = radius * radius; float camHeight = length(camPos.xyz); float3 camToPos = position - camPos.xyz; float farDist = length(camToPos); float3 lightDir = normalize(lightPos.xyz); float3 normal = normalize(position); float3 rayDir = camToPos / farDist; float camHeight2 = camHeight * camHeight; // Calculate the closest intersection of the ray with the outer atmosphere float B = 2.0 * dot(camPos.xyz, rayDir); float C = camHeight2 - radius2; float det = max(0.0, B*B - 4.0 * C); float nearDist = 0.5 * (-B - sqrt(det)); float3 nearPos = camPos.xyz + (rayDir * nearDist); float3 nearNormal = normalize(nearPos); // get dot products we need float lc = dot(lightDir, camPos / camHeight); float ln = dot(lightDir, normal); float lnn = dot(lightDir, nearNormal); // get distance to surface horizon float altitude = camHeight - SurfaceRadius; float horizonDist = sqrt((altitude*altitude) + (2.0 * SurfaceRadius * altitude)); float maxDot = horizonDist / camHeight; // get distance to atmosphere horizon - use max(0,...) because we can go into the atmosphere altitude = max(0,camHeight - AtmosphereRadius); horizonDist = sqrt((altitude*altitude) + (2.0 * AtmosphereRadius * altitude)); // without this, the shift between inside and outside atmosphere is jarring float tweakAmount = 0.1; float minDot = max(tweakAmount,horizonDist / camHeight); // scale minDot from 0 to -1 as we enter the atmosphere float minDot2 = ((camHeight - SurfaceRadius) * (1.0 / (AtmosphereRadius - SurfaceRadius))) - (1.0 - tweakAmount); minDot = min(minDot, minDot2); // get dot product of the vertex we're looking out float posDot = dot(camToPos / farDist,-camPos.xyz / camHeight) - minDot; // calculate the height from surface in range 0..1 float height = posDot * (1.0 / (maxDot - minDot)); // push the horizon back based on artistic taste ln = max(0,ln + StretchAmt); lnn = max(0,lnn + StretchAmt); // the front color is the sum of the near and far normals float brightness = saturate(ln + (lnn * lc)); // use "saturate(lc + 1.0 + StretchAmt)" to make more of the sunset side color be used when behind the planet oUV.x = brightness * saturate(lc + 1.0 + StretchAmt); oUV.y = height; // as the camera gets lower in the atmosphere artificially increase the height // so that the alpha value gets raised and multiply the increase amount // by the dot product of the light and the vertex normal so that // vertices closer to the sun are less transparent than vertices far from the sun. height -= min(0.0,minDot2 + (ln * minDot2)); oAlpha = height * brightness; // normalised camera to position ray oCamToPos = -rayDir; oLightDir = normalize(lightPos.xyz - position.xyz); } float4 mainBPS( float2 uv : TEXCOORD0, float alpha : TEXCOORD1, float3 camToPos : TEXCOORD2, float3 lightDir :TEXCOORD3, uniform sampler2D TexSampler ) : COLOR { float Atmosphere_G = -0.95f; const float fExposure = 1.5; float g = Atmosphere_G; float g2 = g * g; // atmosphere color float4 diffuse = tex2D(TexSampler,uv); // sun outer color - might could use atmosphere color float4 diffuse2 = tex2D(TexSampler,float2(min(0.5,uv.x),1)); // this is equivilant but faster than fCos = dot(normalize(lightDir.xyz),normalize(camToPos)); float fCos = dot(lightDir.xyz,camToPos) * rsqrt( dot(lightDir.xyz,lightDir.xyz) * dot(camToPos,camToPos)); float fCos2 = fCos * fCos; // apply alpha to atmosphere float4 diffuseColor = diffuse * alpha; // sun glow color float fMiePhase = 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos2) /(1.0 + g2 - 2.0*g*fCos); float4 mieColor = diffuse2 * fMiePhase * alpha; // use exponential falloff because mie color is in high dynamic range // boost diffuse color near horizon because it gets desaturated by falloff return 1.0 - exp((diffuseColor * (1.0 + uv.y) + mieColor) * -fExposure); } {CODE} !!Credits Full credits go to Alex Peterson over at his [http://petrocket.blogspot.com/2010/04/atmosphere-shader-update-and-treegrass.html|blog]. I only converted the .fx he posted over there to ogre material.
Search by Tags
Search Wiki by Freetags
Latest Changes
One Function Ogre
IDE Eclipse
FMOD SoundManager
HDRlib
Building Ogre V2 with CMake
Ogre 2.1 FAQ
Minimal Ogre Collision
Artifex Terra
OpenMB
Advanced Mogre Framework
...more
Search
Find
Advanced
Search Help
Online Users
170 online users