SkyBox

It’s nice and easy to upgrade your environment with a SkyBox. Generate a nice 6 sided cubemap. Use a simple centered Box as Geometry. Translate the box to camera position. Apply the ViewProjection. Set pos.z = pos.w to fit allways to farplane. Use the ModelVertexPosition to sample the cubemap.
That’s it…


Some Problems to fix
• you have to change the cullmode, because you are in the box
• you have to set the DepthComparison to LessEqual, because it’s equal


Some Improvements
• draw the box allways as last opaque object
• adjust the Y position
• use a wider field of view for the box
• draw a sun spot for directional light
• draw the sun spot to glow target for BloomEffect
• the sun spot only works if you use averaged model normals


Vertexshader

//SHADER
VS_OUT VShader(float4 pos : POSITION,
               float3 nrm : NORMAL)
{
 VS_OUT Out;

 //VertexPosition
 float3 cpos = CamPosition;
        cpos.y += YAdjustment;
 float4 wpos = float4(cpos, 0) + pos;

 //OutValues
 Out.pos = mul(wpos,SkyCubeViewProjection);
 Out.pos.z = Out.pos.w;
 Out.vpos = pos.xyz;
 Out.nrm = nrm;
 return Out;
}

Pixelshader

//SHADER
PS_OUT PShader(	float4 pos  : SV_POSITION,
                float3 vpos : POSITION,
                float3 nrm  : NORMAL)
{
 PS_OUT Out;

 //normalize
 nrm = normalize(nrm);

 //Sun Dot
 float sunDot = dot(nrm, DirLight.direction);
       sunDot = saturate(pow (sunDot,SunDistance * 2000)) * SunSharpness   * 30;

 //SunColor
 float3 sun = SunColor *sunDot; 

 //Sample RGBA
 float4 RGBA = TextureColor.Sample(Sampler, vpos).rgba; 

 //OutValues
 Out.color.rgb = float4(RGBA.rgb +sun,0);  //Out FinalColor
 Out.glow      = float4(sun,0);
 return Out;
}

SkyBox in Action


Planet Shader TypA

Some changes must be made to the EngineDesign to realize the PlanetShader.

• Multipass Shader implementation
• Deal with transparent Material
• Better and brighter Glow-Pass
• Managing state changes by Material


How the Shader works
The Shader works perfekt on simple SphereGeometry. Here ist the basic idea how to do it.


Pass1
Draw the opaque textured sphere. Calculate a basic-rim, sharpen the rim and discard some rim-pixels. You can use the basic-rim-value to calculate the color of the atmosphere. Add the atmospheric color to rgb-out.

//basic rim-gradient
float rim  = 1-saturate(dot (view,N));
//sharpen rim edges for clipping
float RimOfAtmos = min(1,pow(rim,RimIntensity *30) *10);
//clip some geometry
clip(0.9-RimOfAtmos);

 

 


Pass2
Draw transparent atmospheric glow. Use the same values for rim calculation. Output just the atmospheric rim color and apply a glow pass to the result. Add the glow on top. Because the glow can not lit by the DeferredLightPass, you have to lit it directly in the MaterialShader (NdotL).

PlanetShader atmospheric glow

atmospheric glow


Night Light
The engine supports EmissiveLight. So it was easy, just applied the EmissiveLightMap multiplied by a color and render it to the glow target. Invert and sharpen NdotL to apply the emissive parts only on the dark side.

PlanetShader light and emissive nightlight

light and emissive nightlight


Bright Glow
A simple big graussian blur pass is not enough to get a nice glow or bloom. A better and faster way is to use multiple shorter blur passes and add the results. Now the Glow/Bloom Pass is using four BlurTargets with different sizes, Fullsize/2, Fullsize/4, Fullsize/8, Fullsize/16. Add all results to get the final Glow/Bloom effect. This technique produces nice bright results and reduces flickering.

 

 

Deferred Planar Reflection

Specular highlights are nothing more than reflection of light sources. With planar reflections, reflective surfaces can be rendered even more realistic.


Matrix.Reflection (New Plane (0, 1, 0, 0))

With help of the generated Matrix, the ViewProjection can be mirrored. The Y-Position of the plane depends on the position of the reflective SceneObject.

This has the great advantage that all SceneObjects and Pointlights can be rendered without modifications. The only thing you have to do is using front culling.


Create Reflection Map
Draw all SceneObjects with reflected ViewProjection to all deferred RenderTargets and calculate the lighting.

render the reflected objects

reflected lit objects

Draw normal Scene
Draw all SceneObjects as usual to all deferred RenderTargets. Objects with reflected material are writing a reflection intensitiy value to Alpha-Channel.

normal rendered scene

normal lit scene for visualization

Final Post Processing
The created reflectionmap, the stored reflection intensity and all other informations are used as resource to calculate the final lighting.

use reflection map as input resource

final lit planar-reflected scene


Planar Reflected Material


Deferred Shading

The VBexEngine is built as a Deferred renderer. Objects are rendered in a MultiRenderTarget and all necessary information as Color, Normal and Position is saved separately. In a post-out shader, all collected information is used to create the final frame. The big advantage of this method is that every pixel has only to be calculated once.


Optimizations
To save bandwidth some data is not stored 1:1. The normals are compressed to range 0-1. Only ViewZ is saved. To make the light calculation easier all final normals and positions are in WorldSpace.

Light Update

Ambient, Diffuse, Specular
The PointLights are treated as SceneObjecte and freely positionable. The light consists of ambient, diffuse and specular parts.

Ambient Backside Occlusion
With Ambient Backside Occlusion the normals of the backside are also taken into account.

Texture Occlusion
An occlusion map in the alpha channel of the RGB texture is used to define the areas that darken RGB and Specular. So it is easy to simulate soiling or deep dark areas.

Emissive & Ambient Light

Emissive Glow
In the lighting post-process, the emissive areas are added. This very simple technique creates the illusion of self-luminous objects without complex light calculation. The picture gallery shows up the rendering steps.

Ambient & Backside Occlusion
The ambient light has been optimized. The simple brightness value has been replaced by a color value. This makes it possible to create various ambient moods. Another optimization is backside occlusion. In this case, the backside normals running parallel to the lightdirection are darkest illuminated.


Light in Action