void Application_Idle( object sender, EventArgs e ) {
if ( m_Device == null )
return;
// Setup global data
m_CB_Main.m.iResolution = new float3( panelOutput.Width, panelOutput.Height, 0 );
if ( checkBoxAnimate.Checked )
m_CB_Main.m.iGlobalTime = GetGameTime() - m_StartTime;
m_CB_Main.UpdateData();
// Setup area light buffer
float LighOffsetX = 1.2f;
float SizeX = floatTrackbarControlLightScaleX.Value;
float SizeY = 1.0f;
float RollAngle = (float) (Math.PI * floatTrackbarControlLightRoll.Value / 180.0);
float3 LightPosition = new float3( LighOffsetX + floatTrackbarControlLightPosX.Value, 1.0f + floatTrackbarControlLightPosY.Value, -1.0f + floatTrackbarControlLightPosZ.Value );
float3 LightTarget = new float3( LightPosition.x + floatTrackbarControlLightTargetX.Value, LightPosition.y + floatTrackbarControlLightTargetY.Value, LightPosition.z + 2.0f + floatTrackbarControlLightTargetZ.Value );
float3 LightUp = new float3( (float) Math.Sin( -RollAngle ), (float) Math.Cos( RollAngle ), 0.0f );
float4x4 AreaLight2World = new float4x4();
AreaLight2World.BuildRotRightHanded( LightPosition, LightTarget, LightUp );
float4x4 World2AreaLight = AreaLight2World.Inverse;
double Phi = Math.PI * floatTrackbarControlProjectionPhi.Value / 180.0;
double Theta = Math.PI * floatTrackbarControlProjectionTheta.Value / 180.0;
float3 Direction = new float3( (float) (Math.Sin(Theta) * Math.Sin(Phi)), (float) (Math.Sin(Theta) * Math.Cos(Phi)), (float) Math.Cos( Theta ) );
const float DiffusionMin = 1e-2f;
const float DiffusionMax = 1000.0f;
// float Diffusion_Diffuse = DiffusionMin / (DiffusionMin / DiffusionMax + floatTrackbarControlProjectionDiffusion.Value);
float Diffusion_Diffuse = DiffusionMax + (DiffusionMin - DiffusionMax) * (float) Math.Pow( floatTrackbarControlProjectionDiffusion.Value, 0.01f );
// float3 LocalDirection_Diffuse = (float3) (new float4( Diffusion_Diffuse * Direction, 0 ) * World2AreaLight);
float3 LocalDirection_Diffuse = Diffusion_Diffuse * Direction;
m_CB_Light.m._AreaLightX = (float3) AreaLight2World[0];
m_CB_Light.m._AreaLightY = (float3) AreaLight2World[1];
m_CB_Light.m._AreaLightZ = (float3) AreaLight2World[2];
m_CB_Light.m._AreaLightT = (float3) AreaLight2World[3];
m_CB_Light.m._AreaLightScaleX = SizeX;
m_CB_Light.m._AreaLightScaleY = SizeY;
m_CB_Light.m._AreaLightDiffusion = floatTrackbarControlProjectionDiffusion.Value;
m_CB_Light.m._AreaLightIntensity = floatTrackbarControlLightIntensity.Value;
m_CB_Light.m._AreaLightTexDimensions = new float4( m_Tex_AreaLightSAT.Width, m_Tex_AreaLightSAT.Height, 1.0f / m_Tex_AreaLightSAT.Width, 1.0f / m_Tex_AreaLightSAT.Height );
m_CB_Light.m._ProjectionDirectionDiff = LocalDirection_Diffuse;
m_CB_Light.UpdateData();
// =========== Render shadow map ===========
// float KernelSize = 16.0f * floatTrackbarControlProjectionDiffusion.Value;
float KernelSize = floatTrackbarControlKernelSize.Value;
// float ShadowZFar = (float) Math.Sqrt( 2.0 ) * m_Camera.Far;
float ShadowZFar = 10.0f;
m_CB_ShadowMap.m._ShadowOffsetXY = (float2) Direction;
m_CB_ShadowMap.m._ShadowZFar = new float2( ShadowZFar, 1.0f / ShadowZFar );
m_CB_ShadowMap.m._KernelSize = KernelSize;
m_CB_ShadowMap.m._InvShadowMapSize = 1.0f / m_Tex_ShadowMap.Width;
m_CB_ShadowMap.m._HardeningFactor = new float2( floatTrackbarControlHardeningFactor.Value, floatTrackbarControlHardeningFactor2.Value );
m_CB_ShadowMap.UpdateData();
if ( m_Shader_RenderShadowMap != null && m_Shader_RenderShadowMap.Use() ) {
m_Tex_ShadowMap.RemoveFromLastAssignedSlots();
m_Device.SetRenderTargets( m_Tex_ShadowMap.Width, m_Tex_ShadowMap.Height, new View2D[0], m_Tex_ShadowMap );
#if FILTER_EXP_SHADOW_MAP
// m_Device.ClearDepthStencil( m_Tex_ShadowMap, 0.0f, 0, true, false );
// m_Device.SetRenderStates( RASTERIZER_STATE.CULL_NONE, DEPTHSTENCIL_STATE.READ_WRITE_DEPTH_GREATER, BLEND_STATE.DISABLED ); // For exp shadow map, the Z order is reversed
m_Device.ClearDepthStencil( m_Tex_ShadowMap, 1.0f, 0, true, false );
m_Device.SetRenderStates( checkBoxCullFront.Checked ? RASTERIZER_STATE.CULL_BACK : RASTERIZER_STATE.CULL_NONE, DEPTHSTENCIL_STATE.READ_WRITE_DEPTH_LESS, BLEND_STATE.DISABLED ); // For exp shadow map, the Z order is reversed
#else
m_Device.ClearDepthStencil( m_Tex_ShadowMap, 1.0f, 0, true, false );
m_Device.SetRenderStates( RASTERIZER_STATE.CULL_NONE, DEPTHSTENCIL_STATE.READ_WRITE_DEPTH_LESS, BLEND_STATE.DISABLED );
#endif
RenderScene( m_Shader_RenderShadowMap );
m_Device.RemoveRenderTargets();
m_Tex_ShadowMap.SetPS( 2 );
}
#if FILTER_EXP_SHADOW_MAP
if ( m_Shader_FilterShadowMapH != null ) {
// m_Tex_ShadowMapFiltered[1].RemoveFromLastAssignedSlots();
m_Device.SetRenderStates( RASTERIZER_STATE.CULL_NONE, DEPTHSTENCIL_STATE.DISABLED, BLEND_STATE.DISABLED );
// Filter horizontally
m_Device.SetRenderTarget( m_Tex_ShadowMapFiltered[0], null );
m_Shader_FilterShadowMapH.Use();
m_Prim_Quad.Render( m_Shader_FilterShadowMapH );
// Filter vertically
m_Device.SetRenderTarget( m_Tex_ShadowMapFiltered[1], null );
m_Tex_ShadowMapFiltered[0].SetPS( 2 );
m_Shader_FilterShadowMapV.Use();
m_Prim_Quad.Render( m_Shader_FilterShadowMapV );
m_Device.RemoveRenderTargets();
m_Tex_ShadowMapFiltered[1].SetPS( 2 );
}
#else
if ( m_Shader_BuildSmoothie != null && m_Shader_BuildSmoothie.Use() ) {
m_Tex_ShadowSmoothie.RemoveFromLastAssignedSlots();
m_Device.SetRenderStates( RASTERIZER_STATE.CULL_NONE, DEPTHSTENCIL_STATE.DISABLED, BLEND_STATE.DISABLED );
// Render the (silhouette + Z) RG16 buffer
m_Device.SetRenderTarget( m_Tex_ShadowSmoothie, null );
m_Prim_Quad.Render( m_Shader_BuildSmoothie );
m_Device.RemoveRenderTargets();
m_Tex_ShadowSmoothie.SetPS( 3 );
// Build distance field
m_Device.SetRenderTarget( m_Tex_ShadowSmoothiePou[0], null );
m_Shader_BuildSmoothieDistanceFieldH.Use();
m_Prim_Quad.Render( m_Shader_BuildSmoothieDistanceFieldH );
// m_Device.RemoveRenderTargets();
// m_Tex_ShadowSmoothiePou[0].SetPS( 3 );
m_Device.SetRenderTarget( m_Tex_ShadowSmoothiePou[1], null );
m_Tex_ShadowSmoothiePou[0].SetPS( 0 );
m_Shader_BuildSmoothieDistanceFieldV.Use();
m_Prim_Quad.Render( m_Shader_BuildSmoothieDistanceFieldV );
m_Device.RemoveRenderTargets();
m_Tex_ShadowSmoothiePou[1].SetPS( 3 );
}
#endif
// =========== Render scene ===========
m_Device.SetRenderTarget( m_Device.DefaultTarget, m_Device.DefaultDepthStencil );
m_Device.Clear( m_Device.DefaultTarget, float4.Zero );
m_Device.ClearDepthStencil( m_Device.DefaultDepthStencil, 1.0f, 0, true, false );
m_Tex_AreaLightSAT.SetPS( 0 );
// m_Tex_AreaLight3D.SetPS( 0 );
m_Tex_AreaLightSATFade.SetPS( 1 );
m_Tex_AreaLight.SetPS( 4 );
m_Tex_FalseColors.SetPS( 6 );
// m_Tex_GlossMap.SetPS( 7 );
// m_Tex_Normal.SetPS( 8 );
// Render the area light itself
m_Device.SetRenderStates( RASTERIZER_STATE.CULL_NONE, DEPTHSTENCIL_STATE.READ_WRITE_DEPTH_LESS, BLEND_STATE.DISABLED );
if ( m_Shader_RenderAreaLight != null && m_Shader_RenderAreaLight.Use() ) {
m_CB_Object.m._Local2World = AreaLight2World;
m_CB_Object.m._Local2World.Scale( new float3( SizeX, SizeY, 1.0f ) );
m_CB_Object.m._World2Local = m_CB_Object.m._Local2World.Inverse;
m_CB_Object.m._UseTexture = checkBoxUseTexture.Checked ? 1U : 0U;
m_CB_Object.m._FalseColors = checkBoxFalseColors.Checked ? 1U : 0U;
m_CB_Object.m._FalseColorsMaxRange = floatTrackbarControlFalseColorsRange.Value;
m_CB_Object.UpdateData();
m_Prim_Rectangle.Render( m_Shader_RenderAreaLight );
} else {
m_Device.Clear( new float4( 1, 0, 0, 0 ) );
}
// Render the scene
m_Device.SetRenderStates( RASTERIZER_STATE.CULL_BACK, DEPTHSTENCIL_STATE.NOCHANGE, BLEND_STATE.NOCHANGE );
if ( m_Shader_RenderScene != null && m_Shader_RenderScene.Use() ) {
RenderScene( m_Shader_RenderScene );
} else {
m_Device.Clear( new float4( 1, 1, 0, 0 ) );
}
// Show!
m_Device.Present( false );
// Update window text
// Text = "Zombizous Prototype - " + m_Game.m_CurrentGameTime.ToString( "G5" ) + "s";
}