LensDirt gives a realistic camera posteffect and is a nice and easy improvement to your scene.

How to…

  • calculate dot between Lightdirection and Viewdirection
  • saturate and sharpen the dot
  • sample the DirtTexture
  • use the dot as DirtIntensity
  • add result additive to fullscreen

Some Improvements

  • use a one-channel DirtTexture
  • use the suncolor to colorize the dirt
  • simulate chromatic aberration by shiftig the texcoords
  • reduce intensity on occluder by LinearDepth



float LensDirtIntensity;
float3 LensDirtColor;
float2 ofsG = float2(0,0.002);
float2 ofsB = float2(0.002,0);

LensDirtColor.r = TextureDirt.Sample(Sampler, tex) * DirLight.SunColor.r;
LensDirtColor.g = TextureDirt.Sample(Sampler, tex + ofsG) * DirLight.SunColor.g;
LensDirtColor.b = TextureDirt.Sample(Sampler, tex + ofsB) * DirLight.SunColor.b;

LensDirtIntensity = saturate(dot(WViewDirection,-DirLight.direction) * max(GBuffer.LDepth, 0.8));
LensDirtIntensity = pow(LensDirtIntensity, 20) * 2;

LensDirtColor *= LensDirtIntensity;





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



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

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

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


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

 nrm = normalize(nrm);

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

 float3 sun = SunColor *sunDot; 

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

 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.

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



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


Merry 3D Christmas

Here is a small test of the engine with several objects and lights, creating a nice Christmas Scene.
Have fun watching the video …

3D Christmas


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.

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.