XNA for C#
DirectX 9 for C#
DirectX 9 for C++
DirectX 9 for VB
Forum
   
My XNA Book
      
       Go to section on this site

Additional info


Latest Forum posts

 Easter Day Deals
  Posted by: Applefly
  When: 19/04/2014 at 22:18:14

 40% OFF Pavtube DVD Ripper for Mac
  Posted by: VIKIVannessa
  When: 19/04/2014 at 02:02:54

 DVD Ripper with 40% off
  Posted by: VIKIVannessa
  When: 19/04/2014 at 02:02:22

 Get DVD Ripper Wind/Mac + $14 Coupon
  Posted by: VIKIVannessa
  When: 19/04/2014 at 02:02:03

 Backup DVD Escape Plan
  Posted by: Applefly
  When: 17/04/2014 at 06:00:12

 Disney DVDs to MP4
  Posted by: Applefly
  When: 17/04/2014 at 05:56:07

 DVD movies through media streamer
  Posted by: VIKIVannessa
  When: 16/04/2014 at 02:25:09

 DVD movies to play on Galaxy Tab 3 10.1
  Posted by: VIKIVannessa
  When: 16/04/2014 at 02:20:51

 Blu-ray to Apple ProRes
  Posted by: Applefly
  When: 12/04/2014 at 00:47:46

 HD H.264 MP4 format
  Posted by: Applefly
  When: 12/04/2014 at 00:43:23


Ads

Adding shadows to our colored scene

Now we can sample the correct position in our Shadow map for each pixel in our scene, we have all the ingredients we need to create our shadows. We will be drawing our scene with real colors and lighting like we did before, so our vertex shader will need to pass the texture coordinates, the normal and the 3D position of every vertex to the interpolator and pixel shader. This chapter, we’ll also test the real distance between the pixel and the light against the value found in the Shadow Map, so we’ll also need this real distance. Thus we can add these 4 variables to our SSceneVertexToPixel struct:

float4 RealDistance        : TEXCOORD1;
float2 TexCoords            : TEXCOORD2;
float3 Normal            : TEXCOORD3;
float3 Position3D            : TEXCOORD4;

We’ve already seen how to fill the last 3 variables. We can find the real distance between a vertex and the light by transforming the vertex into the camera space of the light and taking the Z component. To be conform with the values stored in the Shadow map, we need to divide this value by xMaxDepth. Remember we need again all info sent to us in the vertex stream:

SSceneVertexToPixel ShadowedSceneVertexShader( float4 inPos : POSITION, float2 inTexCoords : TEXCOORD0, float3 inNormal : NORMAL)
{
    SSceneVertexToPixel Output = (SSceneVertexToPixel)0;
    
    Output.Position = mul(inPos, xWorldViewProjection);
    Output.ShadowMapSamplingPos = mul(inPos, xLightWorldViewProjection);
    Output.RealDistance = Output.ShadowMapSamplingPos.z/xMaxDepth;
    Output.TexCoords = inTexCoords;
    Output.Normal = mul(inNormal, xRot);
    Output.Position3D = inPos;
    
    return Output;    
}

This already starts to look like a real vertex shader. Before moving on to the pixel shader, make sure you re-include our DotProduct method we created in one of the previous chapters:

float DotProduct(float4 LightPos, float3 Pos3D, float3 Normal)
{
    float3 LightDir = normalize(LightPos - Pos3D);
    return dot(LightDir, Normal);
}

This chapter, we’ll only draw the pixels that are being lit by the headlights. This means we first have to check if the pixels are in view of the headlights. In other words: if the projected x and y coordinates are within the [0, 1] range. For this, we can use the HLSL ‘saturate’ method, which clips any value to this range. So if the value after clipping is not the same as the value before clipping, we know the value wasn’t in the [0, 1] range, and thus isn’t in the view of our headlights. In HLSL code:

if ((saturate(ProjectedTexCoords.x) == ProjectedTexCoords.x) && (saturate(ProjectedTexCoords.y) == ProjectedTexCoords.y))
{
}

So if the pixel successfully enters this if-block, it can be lit by the light. Next, we will check whether the pixel isn’t shadowed by another object. For this, we first retrieve the distance between pixel and light, as stored in the Shadow Map:

float StoredDepthInShadowMap = tex2D(ShadowMapSampler, ProjectedTexCoords).x;

Now we check if the real distance isn’t bigger than this stored value:

if ((PSIn.RealDistance.x - 1.0f/100.0f) <= StoredDepthInShadowMap)
{
}

You see we subtracted a little bias of 1/100. Let me show you why. We store depth information as a color in our Shadow Map. One color component of this map is stored in only 8 bits, so the smallest difference is 1/256. Now say the maximal distance in our scene is 40.0f, so the smallest difference is 40/256 = 0.156f. This means that in even the best case, all points with distances 0.156f to 0.234f will be stored as 0.156f.

Take for example a point at real distance 2.0f (which is stored as 0.156f in our shadow map!). You would like to check whether the real and stored distances are the same: if (2.0f == 0.156f) so this would FAIL, and you would think the point is in the shadow of another object. For this, we need to subtract a small value of our real distance while comparing.

OK, with that out of the way, we can actually draw our scene, exactly like we did a few chapters ago: by sampling the texture and multiplying that color by the dot-product-factor and the power of the light. So we get as pixel shader:

SScenePixelToFrame ShadowedScenePixelShader(SSceneVertexToPixel PSIn)
{
    SScenePixelToFrame Output = (SScenePixelToFrame)0;

    float2 ProjectedTexCoords;
    ProjectedTexCoords[0] = PSIn.ShadowMapSamplingPos.x/PSIn.ShadowMapSamplingPos.w/2.0f +0.5f;
    ProjectedTexCoords[1] = -PSIn.ShadowMapSamplingPos.y/PSIn.ShadowMapSamplingPos.w/2.0f +0.5f;

    if ((saturate(ProjectedTexCoords.x) == ProjectedTexCoords.x) && (saturate(ProjectedTexCoords.y) == ProjectedTexCoords.y))
    {    
        float StoredDepthInShadowMap = tex2D(ShadowMapSampler, ProjectedTexCoords).x;    
        if ((PSIn.RealDistance.x - 1.0f/100.0f) <= StoredDepthInShadowMap)    
        {
            float DiffuseLightingFactor = DotProduct(xLightPos, PSIn.Position3D, PSIn.Normal);
            float4 ColorComponent = tex2D(ColoredTextureSampler, PSIn.TexCoords);
            Output.Color = ColorComponent*DiffuseLightingFactor*xLightPower;
        }
    }    

    return Output;
}

Now we’ve had the HLSL part for this chapter, let’s move on to the DirectX code. First we should reset the xColoredTextured value, as we deleted it a few chapters ago. I’ve put this line immediately after the line that loads the texture file:

 effect.SetValue("xColoredTextured", StreetTexture);

Because we’re currently only working with one light, let’s make it a bit more powerful:

 float LightPower = 2f;

Running this code should give you something like this:




DirectX Tutorial 14 - The first shadow

If you appreciate the amount of time I spend creating and updating
these pages, feel free to donate -- any amount is welcome !



Click here to go to the forum on this chapter!

Or click on one of the topics on this chapter to go there:
  • Only shadow map renders
          I used the code straigt from the tutorial , but it...
  • 2-way lightning
          Hi, First of all, I like this tutorial, it work...
  • Greater Accuracy
          In the littel game I'm creating I require the lig...


    Finally, we see the first shadows! The car casts a nice shadow, and you can also find the shadow of our lampposts. Note that only the pixels in the view of the headlights are colored, the others are black (this is obtained by the if ((saturate(ProjectedTexCoords.x) ==…. Check in the pixel shader).

    Although we’ve got shadows, our light itself hasn’t got a nice shape: you can see the corners of its view frustrum. Next chapter we’re going to solve this.

    Our updated HLSL code:

    struct SMapVertexToPixel
    {
        float4 Position     : POSITION;    
        float3 Position2D    : TEXCOORD0;
    };

    struct SMapPixelToFrame
    {
        float4 Color : COLOR0;
    };

    struct SSceneVertexToPixel
    {
        float4 Position             : POSITION;
        float4 ShadowMapSamplingPos : TEXCOORD0;    

         float4 RealDistance            : TEXCOORD1;
         float2 TexCoords            : TEXCOORD2;
         float3 Normal                : TEXCOORD3;
         float3 Position3D            : TEXCOORD4;

    };

    struct SScenePixelToFrame
    {
        float4 Color : COLOR0;
    };

    //------- Constants --------

    float4x4 xWorldViewProjection;
    float4x4 xLightWorldViewProjection;
    float4x4 xRot;
    float4 xLightPos;
    float xLightPower;
    float xMaxDepth;

    //------- Texture Samplers --------


     Texture xColoredTexture;

    sampler ColoredTextureSampler = sampler_state { texture = <xColoredTexture> ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = mirror; AddressV = mirror;};

    Texture xShadowMap;

    sampler ShadowMapSampler = sampler_state { texture = <xShadowMap> ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = clamp; AddressV = clamp;};
    //------- Vertex Shaders --------

    SMapVertexToPixel ShadowMapVertexShader( float4 inPos : POSITION)
    {
        SMapVertexToPixel Output = (SMapVertexToPixel)0;
        
        Output.Position = mul(inPos, xLightWorldViewProjection);
        Output.Position2D = Output.Position;
        
        return Output;    
    }


     SSceneVertexToPixel ShadowedSceneVertexShader( float4 inPos : POSITION, float2 inTexCoords : TEXCOORD0, float3 inNormal : NORMAL)

    {
        SSceneVertexToPixel Output = (SSceneVertexToPixel)0;
        
        Output.Position = mul(inPos, xWorldViewProjection);
        Output.ShadowMapSamplingPos = mul(inPos, xLightWorldViewProjection);

         Output.RealDistance = Output.ShadowMapSamplingPos.z/xMaxDepth;
         Output.TexCoords = inTexCoords;
         Output.Normal = mul(inNormal, xRot);
         Output.Position3D = inPos;

        
        return Output;    
    }

    //------- Pixel Shaders --------


     float DotProduct(float4 LightPos, float3 Pos3D, float3 Normal)
     {
         float3 LightDir = normalize(LightPos - Pos3D);
         return dot(LightDir, Normal);
     }
     

    SMapPixelToFrame ShadowMapPixelShader(SMapVertexToPixel PSIn)
    {
        SMapPixelToFrame Output = (SMapPixelToFrame)0;

        Output.Color = PSIn.Position2D.z/xMaxDepth;

        return Output;
    }

    SScenePixelToFrame ShadowedScenePixelShader(SSceneVertexToPixel PSIn)
    {
        SScenePixelToFrame Output = (SScenePixelToFrame)0;

        float2 ProjectedTexCoords;
        ProjectedTexCoords[0] = PSIn.ShadowMapSamplingPos.x/PSIn.ShadowMapSamplingPos.w/2.0f +0.5f;
        ProjectedTexCoords[1] = -PSIn.ShadowMapSamplingPos.y/PSIn.ShadowMapSamplingPos.w/2.0f +0.5f;


         if ((saturate(ProjectedTexCoords.x) == ProjectedTexCoords.x) && (saturate(ProjectedTexCoords.y) == ProjectedTexCoords.y))
         {    
             float StoredDepthInShadowMap = tex2D(ShadowMapSampler, ProjectedTexCoords).x;    
             if ((PSIn.RealDistance.x - 1.0f/100.0f) <= StoredDepthInShadowMap)    
             {
                 float DiffuseLightingFactor = DotProduct(xLightPos, PSIn.Position3D, PSIn.Normal);
                 float4 ColorComponent = tex2D(ColoredTextureSampler, PSIn.TexCoords);
                 Output.Color = ColorComponent*DiffuseLightingFactor*xLightPower;
             }
         }    


        return Output;
    }

    //------- Techniques --------

    technique ShadowMap
    {
        pass Pass0
        {
            VertexShader = compile vs_2_0 ShadowMapVertexShader();
            PixelShader = compile ps_2_0 ShadowMapPixelShader();
        }
    }

    technique ShadowedScene
    {
        pass Pass0
        {
            VertexShader = compile vs_2_0 ShadowedSceneVertexShader();
            PixelShader = compile ps_2_0 ShadowedScenePixelShader();
        }
    }

    There were only a few minor cosmetical changes to our DirectX code, but here it is:

     using System;
     using System.Drawing;
     using System.Collections;
     using System.ComponentModel;
     using System.Windows.Forms;
     using System.Data;
     using Microsoft.DirectX;
     using Microsoft.DirectX.Direct3D;
     using D3D = Microsoft.DirectX.Direct3D;
     
     namespace DirectX_Tutorial
     {
         struct myownvertexformat
         {
             public Vector3 Pos;
             public Vector3 Normal;
             public Vector2 TexCoord;
     
             public myownvertexformat(Vector3 _Pos, Vector3 _Normal, float texx, float texy)
             {
                 Pos = _Pos;
                 Normal = _Normal;
                 TexCoord.X = texx;
                 TexCoord.Y = texy;
             }
         }
     
         public class WinForm : System.Windows.Forms.Form
         {        
             private System.ComponentModel.Container components = null;
             private D3D.Device device;        
             private VertexBuffer vb;
             private Vector3 CameraPos;
             private VertexDeclaration vd;
             private Effect effect;
     
             private Texture StreetTexture;
             private Mesh Lamppost;
             private Material[] LamppostMaterials;
             private Texture[] LamppostTextures;
             private Mesh Car;
             private Material[] CarMaterials;
             private Texture[] CarTextures;
     
             private Matrix matView;
             private Matrix matProjection;
             private Matrix LightViewProjection;
     
             private int LastTickCount = 1;
             private int Frames = 0;
             private float LastFrameRate = 0;
             private D3D.Font text;
     
             private RenderToSurface RtsHelper;
             private Texture RenderTexture;
             private Surface RenderSurface;
             private int RenderSurfaceSize = 512;
     
             public WinForm()
             {
                 InitializeComponent();
                 this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
             }
     
             public void InitializeDevice()
             {
                 PresentParameters presentParams = new PresentParameters();
                 presentParams.Windowed = true;
                 presentParams.SwapEffect = SwapEffect.Discard;
                 presentParams.AutoDepthStencilFormat = DepthFormat.D16;
                 presentParams.EnableAutoDepthStencil = true;
     
                 Caps DevCaps = D3D.Manager.GetDeviceCaps(0, D3D.DeviceType.Hardware);
                 D3D.DeviceType DevType = D3D.DeviceType.Reference;
                 CreateFlags DevFlags = CreateFlags.SoftwareVertexProcessing;
                 if ((DevCaps.VertexShaderVersion >= new Version(2, 0)) && (DevCaps.PixelShaderVersion >= new Version(2, 0)))
                 {
                     DevType = D3D.DeviceType.Hardware;                
                     if (DevCaps.DeviceCaps.SupportsHardwareTransformAndLight)
                     {
                         DevFlags = CreateFlags.HardwareVertexProcessing;
                         if (DevCaps.DeviceCaps.SupportsPureDevice)
                         {
                             DevFlags |= CreateFlags.PureDevice;
                         }
                     }                
                 }
     
                 device = new D3D.Device(0, DevType, this, DevFlags, presentParams);
                 device.DeviceReset += new EventHandler(this.HandleDeviceReset);            
             }
     
             private void HandleDeviceReset(object sender, EventArgs e)
             {
                 FillResources();        
             }
     
             private void AllocateResources()
             {
                 vb = new VertexBuffer(typeof(myownvertexformat), 18, device, Usage.WriteOnly, VertexFormats.Position | VertexFormats.Normal | VertexFormats.Texture0, Pool.Managed);                        
                 InitializeFont();
                 effect = D3D.Effect.FromFile(device, @"../../OurHLSLFile.fx", null, null, ShaderFlags.None, null);
             }
     
             private void FillResources()
             {
                 myownvertexformat[] vertices = new myownvertexformat[18];
     
                 vertices[0] = new myownvertexformat(new Vector3(20, -10, 0), new Vector3(0, 0, 1), -0.25f, 25.0f);
                 vertices[1] = new myownvertexformat(new Vector3(20, 100, 0), new Vector3(0, 0, 1), -0.25f, 0.0f);
                 vertices[2] = new myownvertexformat(new Vector3(-2, -10, 0), new Vector3(0, 0, 1), 0.25f, 25.0f);                        
                 vertices[3] = new myownvertexformat(new Vector3(-2, 100, 0), new Vector3(0, 0, 1), 0.25f, 0.0f);
                 vertices[4] = new myownvertexformat(new Vector3(-2, -10, 0), new Vector3(1, 0, 0), 0.25f, 25.0f);                        
                 vertices[5] = new myownvertexformat(new Vector3(-2, 100, 0), new Vector3(1, 0, 0), 0.25f, 0.0f);
                 vertices[6] = new myownvertexformat(new Vector3(-2, -10, 1), new Vector3(1, 0, 0), 0.375f, 25.0f);
                 vertices[7] = new myownvertexformat(new Vector3(-2, 100, 1), new Vector3(1, 0, 0), 0.375f, 0.0f);
                 vertices[8] = new myownvertexformat(new Vector3(-2, -10, 1), new Vector3(0, 0, 1), 0.375f, 25.0f);
                 vertices[9] = new myownvertexformat(new Vector3(-2, 100, 1), new Vector3(0, 0, 1), 0.375f, 0.0f);
                 vertices[10] = new myownvertexformat(new Vector3(-3, -10, 1), new Vector3(0, 0, 1), 0.5f, 25.0f);
                 vertices[11] = new myownvertexformat(new Vector3(-3, 100, 1), new Vector3(0, 0, 1), 0.5f, 0.0f);
                 vertices[12] = new myownvertexformat(new Vector3(-13, -10, 1), new Vector3(0, 0, 1), 0.75f, 25.0f);
                 vertices[13] = new myownvertexformat(new Vector3(-13, 100, 1), new Vector3(0, 0, 1), 0.75f, 0.0f);
                 vertices[14] = new myownvertexformat(new Vector3(-13, -10, 1), new Vector3(1, 0, 0), 0.75f, 25.0f);
                 vertices[15] = new myownvertexformat(new Vector3(-13, 100, 1), new Vector3(1, 0, 0), 0.75f, 0.0f);
                 vertices[16] = new myownvertexformat(new Vector3(-13, -10, 21), new Vector3(1, 0, 0), 1.25f, 25.0f);
                 vertices[17] = new myownvertexformat(new Vector3(-13, 100, 21), new Vector3(1, 0, 0), 1.25f, 0.0f);
                 
                 vb.SetData(vertices, 0, LockFlags.None);
     
                 SetUpCamera();
     
                 VertexElement[] velements = new VertexElement[]
                 {
                     new VertexElement(0, 0, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Position, 0),
                     new VertexElement(0, 12, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Normal, 0),
                     new VertexElement(0, 24, DeclarationType.Float2, DeclarationMethod.Default, DeclarationUsage.TextureCoordinate, 0),
                     VertexElement.VertexDeclarationEnd
                 };
                 vd = new VertexDeclaration(device, velements);
     
                 StreetTexture = TextureLoader.FromFile(device, "streettexture.jpg");
                 effect.SetValue("xColoredTexture", StreetTexture);
     
                 LoadMesh("lamppost.x", ref Lamppost, ref LamppostMaterials, ref LamppostTextures);
                 LoadMesh("car.x", ref Car, ref CarMaterials, ref CarTextures);            
     
                 RtsHelper = new RenderToSurface(device, RenderSurfaceSize, RenderSurfaceSize, Format.X8R8G8B8, true, DepthFormat.D16);
                 RenderTexture = new Texture(device, RenderSurfaceSize, RenderSurfaceSize, 1, Usage.RenderTarget, Format.X8R8G8B8, Pool.Default);
                 RenderSurface = RenderTexture.GetSurfaceLevel(0);
             }
     
             private void InitializeFont()
             {
                 System.Drawing.Font systemfont = new System.Drawing.Font("Arial", 12f, FontStyle.Regular);
                 text = new D3D.Font(device, systemfont);
             }
     
             private void DrawMesh(Mesh mesh, Material[] meshmaterials, Texture[] meshtextures)
             {
                 for (int i = 0; i < meshmaterials.Length; i++)
                 {
                     if (meshtextures.Length > 3) effect.SetValue("xColoredTexture", meshtextures[i]);
                     effect.CommitChanges();
                     mesh.DrawSubset(i);
                 }
             }
     
             protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
             {
                 UpdateLightData();
                 GenerateShadowMap();
     
                 device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0);
                 device.BeginScene();
     
                 RenderShadowedScene();
                 using (Sprite spriteobject = new Sprite(device))
                 {
                     spriteobject.Begin(SpriteFlags.DoNotSaveState);
                     spriteobject.Transform = Matrix.Scaling(0.25f, 0.25f, 0.25f);
                     spriteobject.Draw(RenderTexture, new Rectangle(0, 0, RenderSurfaceSize, RenderSurfaceSize), new Vector3(0, 0, 0), new Vector3(0, 0, 0), Color.White);
                     spriteobject.End();
                 }
                 UpdateFramerate();
     
                 device.EndScene();
                 device.Present();
                 this.Invalidate();    
             }
     
             private void GenerateShadowMap()
             {
                 RtsHelper.BeginScene(RenderSurface);            
                 device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0);            
     
                 effect.Technique = "ShadowMap";
                 effect.SetValue("xMaxDepth", 60);
                 int numpasses = effect.Begin(0);
                 for (int i = 0; i < numpasses; i++)
                 {
                     effect.BeginPass(i);
                     DrawScene();
                     effect.EndPass();
                 }
                 effect.End();
     
                 RtsHelper.EndScene(Filter.None);
             }
     
             private void RenderShadowedScene()
             {
                 effect.Technique = "ShadowedScene";
                 effect.SetValue("xShadowMap", RenderTexture);
                 int numpasses = effect.Begin(0);
                 for (int i = 0; i < numpasses; i++)
                 {
                     effect.BeginPass(i);
                     DrawScene();
                     effect.EndPass();
                 }
                 effect.End();
             }
     
             private void UpdateLightData()
             {
                 Vector3 LightPos = new Vector3(18, 2, 5);
                 float LightPower = 2f;
     
                 LightViewProjection = Matrix.LookAtLH(LightPos, new Vector3(2, 10, -3), new Vector3(0, 0, 1)) * Matrix.PerspectiveFovLH((float)Math.PI / 2, this.Width / this.Height, 1f, 100f);
                 effect.SetValue("xLightPos", new Vector4(LightPos.X, LightPos.Y, LightPos.Z, 1));
                 effect.SetValue("xLightPower", LightPower);
             }
     
             private void DrawScene()
             {
                 effect.SetValue("xWorldViewProjection", Matrix.Identity * matView * matProjection);
                 effect.SetValue("xLightWorldViewProjection", Matrix.Identity * LightViewProjection);
                 effect.SetValue("xRot", Matrix.Identity);
                 effect.SetValue("xColoredTexture", StreetTexture);
                 effect.CommitChanges();
                 device.SetStreamSource(0, vb, 0);
                 device.VertexDeclaration = vd;
                 device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 16);
     
                 Matrix LamppostWorld = Matrix.Scaling(0.05f, 0.05f, 0.05f) * Matrix.RotationX((float)Math.PI / 2) * Matrix.Translation(-4.0f, 5, 1);
                 effect.SetValue("xWorldViewProjection", LamppostWorld * matView * matProjection);
                 effect.SetValue("xLightWorldViewProjection", LamppostWorld * LightViewProjection);
                 effect.SetValue("xRot", Matrix.RotationX((float)Math.PI / 2));
                 effect.CommitChanges();
                 DrawMesh(Lamppost, LamppostMaterials, LamppostTextures);
     
                 LamppostWorld = Matrix.Scaling(0.05f, 0.05f, 0.05f) * Matrix.RotationX((float)Math.PI / 2) * Matrix.Translation(-4.0f, 35, 1);
                 effect.SetValue("xWorldViewProjection", LamppostWorld * matView * matProjection);
                 effect.SetValue("xLightWorldViewProjection", LamppostWorld * LightViewProjection);
                 effect.SetValue("xRot", Matrix.RotationX((float)Math.PI / 2));
                 effect.CommitChanges();
                 DrawMesh(Lamppost, LamppostMaterials, LamppostTextures);
     
                 Matrix CarWorld = Matrix.Scaling(4f, 4f, 4f) * Matrix.RotationYawPitchRoll((float)Math.PI / 2, (float)Math.PI / 2, (float)Math.PI / 2) * Matrix.Translation(3, 15, 0f);
                 effect.SetValue("xWorldViewProjection", CarWorld * matView * matProjection);
                 effect.SetValue("xLightWorldViewProjection", CarWorld * LightViewProjection);
                 effect.SetValue("xRot", Matrix.RotationYawPitchRoll((float)Math.PI / 2, (float)Math.PI / 2, (float)Math.PI / 2) * Matrix.Translation(3, 15, 0f));
                 DrawMesh(Car, CarMaterials, CarTextures);
     
                 CarWorld = Matrix.Scaling(4f, 4f, 4f) * Matrix.RotationYawPitchRoll((float)Math.PI / 2, (float)Math.PI / 8, (float)Math.PI / 2) * Matrix.Translation(28, -1.9f, 0f);
                 effect.SetValue("xWorldViewProjection", CarWorld * matView * matProjection);
                 effect.SetValue("xLightWorldViewProjection", CarWorld * LightViewProjection);
                 effect.SetValue("xRot", Matrix.RotationYawPitchRoll((float)Math.PI / 2, (float)Math.PI / 2, (float)Math.PI / 2) * Matrix.Translation(3, 15, 0f));
                 DrawMesh(Car, CarMaterials, CarTextures);
             }
     
             private void UpdateFramerate()
             {
                 Frames++;
                 if (Math.Abs(Environment.TickCount - LastTickCount) > 1000)
                 {
                     LastFrameRate = (float)Frames * 1000 / Math.Abs(Environment.TickCount - LastTickCount);
                     LastTickCount = Environment.TickCount;
                     Frames = 0;
                 }
                 text.DrawText(null, string.Format("Framerate : {0:0.00} fps", LastFrameRate), new Point(10, 430), Color.Red);
             }
     
             private void SetUpCamera()
             {
                 CameraPos = new Vector3(25, -18, 13);
                 matProjection = Matrix.PerspectiveFovLH((float)Math.PI / 4, this.Width / this.Height, 0.3f, 200f);
                 matView = Matrix.LookAtLH(CameraPos, new Vector3(0, 12, 2), new Vector3(0, 0, 1));
             }
     
             private void LoadMesh(string filename, ref Mesh mesh, ref Material[] meshmaterials, ref Texture[] meshtextures)
             {
                 ExtendedMaterial[] materialarray;
                 GraphicsStream adj = null;
     
                 mesh = Mesh.FromFile(filename, MeshFlags.Managed, device, out adj, out materialarray);
     
                 if ((materialarray != null) && (materialarray.Length > 0))
                 {
                     meshmaterials = new Material[materialarray.Length];
                     meshtextures = new Texture[materialarray.Length];
     
                     for (int i = 0; i < materialarray.Length; i++)
                     {
                         meshmaterials[i] = materialarray[i].Material3D;
                         meshmaterials[i].Ambient = meshmaterials[i].Diffuse;
     
                         if ((materialarray[i].TextureFilename != null) && (materialarray[i].TextureFilename != string.Empty))
                         {
                             meshtextures[i] = TextureLoader.FromFile(device, materialarray[i].TextureFilename);
                         }
                     }                
                 }
     
                 mesh = mesh.Clone(mesh.Options.Value, CustomVertex.PositionNormalTextured.Format, device);
                 mesh.ComputeNormals();
             }
     
             protected override void Dispose(bool disposing)
             {
                 if (disposing)
                 {
                     if (components != null)
                     {
                         components.Dispose();
                     }
                 }
                 base.Dispose(disposing);
             }
     
             private void InitializeComponent()
             {
                 this.components = new System.ComponentModel.Container();
                 this.Size = new System.Drawing.Size(500, 500);
                 this.Text = "Riemer's DirectX & HLSL Tutorial using C# -- Season 3";
             }
     
             static void Main()
             {
                 using (WinForm our_directx_form = new WinForm())
                 {
                     our_directx_form.InitializeDevice();                
                     our_directx_form.AllocateResources();
                     our_directx_form.FillResources();
                     Application.Run(our_directx_form);
                 }
             }
         }
     }


    Google
     
    Webwww.riemers.net


    If you appreciate the amount of time I spend creating and updating
    these pages, feel free to donate -- any amount is welcome !



    - Website design & XNA + DirectX code : Riemer Grootjans -
    ©2003 - 2011 Riemer Grootjans
  • Translations

    This site in English
    This site in Korean
    This site in Czech

    Microsoft MVP Award



    2007 - 2011 MVP Award
    DirectX - XNA

    Contents

    News
    Home
    Forum
    XNA 2.0 Recipes Book (8)
    XNA 3.0 Recipes Book (8)
    Downloads
    Extra Reading (3)
    Matrices: geometrical
    Matrix Mathematics
    Homogenous matrices
    Community Projects (1)
    Tutorials (160)
    XNA 4.0 using C# (89)
    DirectX using C# (54)
    Series 1:Terrain (14)
    Series 2: Flightsim (19)
    Series 3: HLSL (19)
    Starting point
    HLSL Introduction
    Vertex Shader
    Shaded triangle
    Pixel Shader
    Textured Triangle
    Triangle Strip
    World transform
    Adding normals
    The first light
    Shadow mapping
    Render To Texture
    Projective texturing
    The first shadow
    Shaping the light
    Preshaders
    Multiple lights
    Adjusting Z values
    Finishing touch
    Short Tuts (2)
    DirectX using C++ (15)
    DirectX using VB (2)
    -- Expand all --


    Thank you!

    Support this site --
    any amount is welcome !

    Stay up-to-date

    I don't have the time to keep a News section, so stay informed about the updates by clicking on this RSS file!