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

 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

 DVD collection to computer
  Posted by: VIKIVannessa
  When: 04/04/2014 at 07:13:33

 DVD movies to play on Galaxy Tab 3 10.1
  Posted by: VIKIVannessa
  When: 04/04/2014 at 07:11:27

 DVD movies to play on Galaxy Tab 3 10.1
  Posted by: VIKIVannessa
  When: 04/04/2014 at 07:11:27

 DVD Ripper to populate
  Posted by: Applefly
  When: 04/04/2014 at 05:01:35

 kids and family watch DVD
  Posted by: Applefly
  When: 04/04/2014 at 04:59:21

 Blu-ray movie for your lovely kids
  Posted by: VIKIVannessa
  When: 02/04/2014 at 05:47:49


Ads

Explanation of the Shadow Mapping algorithm

Now we know some HLSL basics and have defined our first light, it’s time for something more complex. Now you’ve added the light to your scene, you should have noted that the cars and lampposts don’t cast any shadows on the wall or pavement.

Let’s see how we can add real shadowing to our scene. We want this shadowing algorithm to be completely dynamic: we want to define the position and direction of our light only one time, and every object within its range should automatically cast a shadow.

Let’s start with the car at the bottom left corner of our screen. Its headlights are shining light towards the right side of our scene. So the light hits the lampposts and the other car, which have to cast shadows on the wall. The question: how do we know which pixels on the wall are lit, and which are shadowed?

While I explain the Depth Mapping algorithm, you can have a look at the image below, where the 2 major steps are illustrated. The first step would be to draw the scene, as seen by the headlights. This means we have to move our camera to the position of the headlights. Using this point of view, the only thing we are interested in is the distance of every pixel to the headlights. For example, the first lamppost would be 4 meters away of the headlights. Very important: the pixels of the wall behind this first lamppost are not seen by the headlights. At the location of these pixels on the wall, 4 meters was stored as distance to the headlights. We store this distance information of the whole scene in what is called a shadow map or depth map.

During the second phase, we draw the scene the usual way; that is, from our camera’s point of view. Only this time, for each pixel we first calculate the distance to the headlights, and compare this depth to the depth stored in the depth map. For most objects, both distances will be the same. Our lamppost, for example, will still be 4 meters away from the headlights.

However, when we calculate the distance for the pixels of the wall behind the light, we find that the distance to the headlights is 5 meters. This is not the same as the distance of 4 meters that was stored for these pixels. This way, we know these pixels can not be seen by the headlights, and should therefore not be lit.



This will all be better illustrated as we move on to the first step: drawing the depth map. We’ll be defining a new technique for this in our HLSL code, ShadowMap, that renders the depth of the scene to the screen. You can already add the technique definition to the very end of our HLSL file:

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

Our vertex shader will be very simple, as this is the only output it needs to generate. Add this immediately above the technique definition:

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

As always, we need to supply the interpolator and pixel shader with the 2D screen coordinates. Only this time, since this screen coordinate also contains the distance between the object and the camera, we need this information also in our pixel shader, so we need to pass it using one of the TEXCOORDn semantics. We’ve already covered the biggest part of this, so this is our new vertex shader:

SMapVertexToPixel ShadowMapVertexShader( float4 inPos : POSITION)
{
    SMapVertexToPixel Output = (SMapVertexToPixel)0;

    Output.Position = mul(inPos, xLightsWorldViewProjection);
    Output.Position2D = Output.Position;

    return Output;
}

Something very important to notice here: we’re using xLightsWorldViewProjection here instead of xWorldViewProjection, because this time we need to look at the scene as seen by the headlights, instead of as by our camera.

The WorldViewProjection matrix is the combination of 3 matrices (World, View and Projection matrix). Although its name might confuse you, the LightsWorldViewProjection matrix is a combination of also 3 matrices: the same World matrix, but a View and Projection matrix specific to the light. These View and Projection matrices are different from those of the camera.

This is a new matrix, so we need to initialize it at the top of our HLSL code:

float4x4 xLightsWorldViewProjection;

Which we’ll fill from within our XNA app later on in this chapter. Next, we’ll code our pixel shader, which again only has to calculate the color:

struct SMapPixelToFrame
{
    float4 Color : COLOR0;
};

And this will be our pixel shader:

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

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

    return Output;
}

The X and Y coordinates of the PSIn.Position contain the X and Y values of the screen coordinate of the current pixel, but the Z coordinate is also very useful as it contains the distance between the camera and the pixel.

However, this vector is the result of a multiplication of a vector and a 4x4 matrix, which happened in the vertex shader. the result of such a multiplication has 4 components: X,Y,Z and W. We cannot use any of the X,Y or Z components immediately, we first need to divide them by the W component. The W component is called the “homogeneous” component, you can find more explanation on this in the “Extra Reading” section of my site.

After dividing the Z component by the homogeneous component, the result will be between 0 and 1, where 0 corresponds to pixels at the near clipping plane and 1 to pixels at the far clipping plane, as defined in the creation of the Projection matrix.

So far for the HLSL part. Let’s go to our XNA code, where we need to pass all variables to our effect. Let’s start with the xLightsWorldViewProjection variable. Because this depends on the position of the light, we’ll update it in the UpdateLightData method, and we need to add this variable to our code:

 Matrix lightsViewProjectionMatrix;

Now we’ll change the contents of our UpdateLightData method. We change the position of our light to the front of the car, change its intensity and the 3rd line is new:

 private void UpdateLightData()
 {
     ambientPower = 0.2f;
 
     lightPos = new Vector3(-18, 5, -2);
     lightPower = 1.0f;
 
     Matrix lightsView = Matrix.CreateLookAt(lightPos, new Vector3(-2, 3, -10), new Vector3(0, 1, 0));
     Matrix lightsProjection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver2, 1f, 5f, 100f);
 
     lightsViewProjectionMatrix = lightsView* lightsProjection;
 }

In order to draw the shadow map, we need to draw the scene as seen by the headlights, we need to create a corresponding ViewProjection matrix. This is almost identical to setting up these matrices for the camera. 2 notes:

  • The aspectratio of the projection matrix only needs to equal the apsectratio of your screen in case you are setting up your camera. In this case, I defined 1f as apectration, so our light will see a square.
  • The distance of the near and far clipping planes will correspond to black and white in our distance map.

    We need to pass this matrix to our graphics card before drawing our trianglestrip, and before drawing our models. So add this line to our Draw method:

     effect.Parameters["xLightsWorldViewProjection"].SetValue(Matrix.Identity * lightsViewProjectionMatrix);

    Note that the ViewProjection matrix is multiplied with the World matrix (the Identity matrix in the case of the street) to obtain the WorldViewProjection matrix.

    Add this line to the DrawModel method:

     currenteffect.Parameters["xLightsWorldViewProjection"].SetValue(worldMatrix * lightsViewProjectionMatrix);

    Now we still need to select the proper technique to render our scene. As we’ll need to render our scene a second time with a later technique later on, now would be a nice time to put the whole contents of our Draw method in another method, DrawScene:

     private void DrawScene(string technique)
     {
         effect.CurrentTechnique = effect.Techniques[technique];
         effect.Parameters["xWorldViewProjection"].SetValue(Matrix.Identity * viewMatrix * projectionMatrix);
         effect.Parameters["xTexture"].SetValue(streetTexture);
         effect.Parameters["xWorld"].SetValue(Matrix.Identity);
         effect.Parameters["xLightPos"].SetValue(lightPos);
         effect.Parameters["xLightPower"].SetValue(lightPower);
         effect.Parameters["xAmbient"].SetValue(ambientPower);
         effect.Parameters["xLightsWorldViewProjection"].SetValue(Matrix.Identity * lightsViewProjectionMatrix);
     
         foreach (EffectPass pass in effect.CurrentTechnique.Passes)
         {
             pass.Apply();
     
             device.SetVertexBuffer(vertexBuffer);
             device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 16);
         }
     
         Matrix car1Matrix = Matrix.CreateScale(4f) * Matrix.CreateRotationY(MathHelper.Pi) * Matrix.CreateTranslation(-3, 0, -15);
         DrawModel(carModel, carTextures, car1Matrix, technique);
     
         Matrix car2Matrix = Matrix.CreateScale(4f) * Matrix.CreateRotationY(MathHelper.Pi * 5.0f / 8.0f) * Matrix.CreateTranslation(-28, 0, -1.9f);
         DrawModel(carModel, carTextures, car2Matrix, technique);
     }

    This method will render our street, and 2 cars using the technique specified in the argument. Call this method from your Draw method like this:

     protected override void Draw(GameTime gameTime)
     {
         device.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1.0f, 0);
     
         DrawScene("ShadowMap");
     
         base.Draw(gameTime);
     }

    Now when you run this code, you should see the image below. It might look pretty strange at first sight, but it’s perfect: it is the depth map of the scene as seen by the headlights of the car. The more white the pixel, the farther away it is from the headlights.




    DirectX Tutorial 12 - Shadow map

    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:
  • Shadow Map not working fully to scale
          I have followed the tutorials and for some reason ...
  • 2.5D Engine Using Shaders
          Good day, I only just began learning XNA and shad...
  • Scene almost completely black
          Hi, I have been following the tutorial to the let...
  • Playing Around with .X
          Okay hi guys: this is my first post on here, so fi...
  • Light View Matrix
          Forgive me if this is like a stupid question, but....
  • Mixing series 3 and 4
          Hi Riemer i love your tutorials they helped me a l...
  • Shadows all white
          For some reason all the objects are coming through...
  • Directional lights?
          Hi Riemer and community! I've followed the series...
  • Shadows
          Hello there Riemer, and other people. I have ha...
  • LightPos as Vector4?
          Hey can someone explain to me why we use a vector4...
  • odd result
          hey reimer, i suppose i have the same problem a...
  • Weird Result - HELP!
          I've followed this chapter exactly. However, I ge...
  • Projecting and the z coordinate
          I always thought about a projection as a sort of f...


    Our HLSL file:

    float4x4 xWorldViewProjection;
    float4x4 xLightsWorldViewProjection;
    float4x4 xWorld;
    float3 xLightPos;
    float xLightPower;
    float xAmbient;

    Texture xTexture;

    sampler TextureSampler = sampler_state { texture = <xTexture> ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = mirror; AddressV = mirror;};
    struct VertexToPixel
    {
        float4 Position     : POSITION;    
        float2 TexCoords    : TEXCOORD0;
        float3 Normal        : TEXCOORD1;
        float3 Position3D    : TEXCOORD2;
    };

    struct PixelToFrame
    {
        float4 Color        : COLOR0;
    };

    float DotProduct(float3 lightPos, float3 pos3D, float3 normal)
    {
        float3 lightDir = normalize(pos3D - lightPos);
        return dot(-lightDir, normal);    
    }

    VertexToPixel SimplestVertexShader( float4 inPos : POSITION0, float3 inNormal: NORMAL0, float2 inTexCoords : TEXCOORD0)
    {
        VertexToPixel Output = (VertexToPixel)0;
        
        Output.Position =mul(inPos, xWorldViewProjection);
        Output.TexCoords = inTexCoords;
        Output.Normal = normalize(mul(inNormal, (float3x3)xWorld));    
        Output.Position3D = mul(inPos, xWorld);

        return Output;
    }

    PixelToFrame OurFirstPixelShader(VertexToPixel PSIn)
    {
        PixelToFrame Output = (PixelToFrame)0;    

        float diffuseLightingFactor = DotProduct(xLightPos, PSIn.Position3D, PSIn.Normal);
        diffuseLightingFactor = saturate(diffuseLightingFactor);
        diffuseLightingFactor *= xLightPower;

        PSIn.TexCoords.y--;
        float4 baseColor = tex2D(TextureSampler, PSIn.TexCoords);
        Output.Color = baseColor*(diffuseLightingFactor + xAmbient);

        return Output;
    }

    technique Simplest
    {
        pass Pass0
        {
            VertexShader = compile vs_2_0 SimplestVertexShader();
            PixelShader = compile ps_2_0 OurFirstPixelShader();
        }
    }


     struct SMapVertexToPixel
     {
         float4 Position     : POSITION;
         float4 Position2D    : TEXCOORD0;
     };
     
     struct SMapPixelToFrame
     {
         float4 Color : COLOR0;
     };
     
     
     SMapVertexToPixel ShadowMapVertexShader( float4 inPos : POSITION)
     {
         SMapVertexToPixel Output = (SMapVertexToPixel)0;
     
         Output.Position = mul(inPos, xLightsWorldViewProjection);
         Output.Position2D = Output.Position;
     
         return Output;
     }
     
     SMapPixelToFrame ShadowMapPixelShader(SMapVertexToPixel PSIn)
     {
         SMapPixelToFrame Output = (SMapPixelToFrame)0;            
     
         Output.Color = PSIn.Position2D.z/PSIn.Position2D.w;
     
         return Output;
     }
     
     
     technique ShadowMap
     {
         pass Pass0
         {
             VertexShader = compile vs_2_0 ShadowMapVertexShader();
             PixelShader = compile ps_2_0 ShadowMapPixelShader();
         }
     }

    The XNA code:

     using System;
     using System.Collections.Generic;
     using Microsoft.Xna.Framework;
     using Microsoft.Xna.Framework.Audio;
     using Microsoft.Xna.Framework.Content;
     using Microsoft.Xna.Framework.GamerServices;
     using Microsoft.Xna.Framework.Graphics;
     using Microsoft.Xna.Framework.Input;
     using Microsoft.Xna.Framework.Net;
     using Microsoft.Xna.Framework.Storage;
     
     namespace XNAseries3
     {
         public struct MyOwnVertexFormat
         {
             public Vector3 position;
             private Vector2 texCoord;
             private Vector3 normal;
     
             public MyOwnVertexFormat(Vector3 position, Vector2 texCoord, Vector3 normal)
             {
                 this.position = position;
                 this.texCoord = texCoord;
                 this.normal = normal;
             }
     
             public readonly static VertexDeclaration VertexDeclaration = new VertexDeclaration
                  (
                      new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0),
                      new VertexElement(sizeof(float) * 3, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0),
                      new VertexElement(sizeof(float) * (3+2), VertexElementFormat.Vector3, VertexElementUsage.Normal, 0)
                  );
         }
     
         public class Game1 : Microsoft.Xna.Framework.Game
         {
             GraphicsDeviceManager graphics;
             GraphicsDevice device;
     
             Effect effect;
             Matrix viewMatrix;
             Matrix projectionMatrix;
             VertexBuffer vertexBuffer;
             Vector3 cameraPos;
             Texture2D streetTexture;
             Model lamppostModel;
             Texture2D[] lamppostTextures;
             Model carModel;
             Texture2D[] carTextures;
             Vector3 lightPos;
             float lightPower;
             float ambientPower;
             Matrix lightsViewProjectionMatrix;
     
             public Game1()
             {
                 graphics = new GraphicsDeviceManager(this);
                 Content.RootDirectory = "Content";
             }
     
             protected override void Initialize()
             {
                 graphics.PreferredBackBufferWidth = 500;
                 graphics.PreferredBackBufferHeight = 500;
                 graphics.IsFullScreen = false;
                 graphics.ApplyChanges();
                 Window.Title = "Riemer's XNA Tutorials -- Series 3";
     
                 base.Initialize();
             }
     
             protected override void LoadContent()
             {
                 device = GraphicsDevice;
     

                effect = Content.Load<Effect> ("OurHLSLfile");            SetUpVertices();
                SetUpCamera();


                streetTexture = Content.Load<Texture2D> ("streettexture");            carModel = LoadModel("car", out carTextures);
                lamppostModel = LoadModel("lamppost", out lamppostTextures);
                lamppostTextures[0] = streetTexture;
            }

            private Model LoadModel(string assetName, out Texture2D[] textures)
            {

                Model newModel = Content.Load<Model> (assetName);
                textures = new Texture2D[7];
                int i = 0;
                foreach (ModelMesh mesh in newModel.Meshes)
                    foreach (BasicEffect currentEffect in mesh.Effects)
                        textures[i++] = currentEffect.Texture;

                foreach (ModelMesh mesh in newModel.Meshes)
                    foreach (ModelMeshPart meshPart in mesh.MeshParts)
                        meshPart.Effect = effect.Clone();

                return newModel;
            }

            private void SetUpVertices()
            {
                MyOwnVertexFormat[] vertices = new MyOwnVertexFormat[18];

                vertices[0] = new MyOwnVertexFormat(new Vector3(-20, 0, 10), new Vector2(-0.25f, 25.0f), new Vector3(0, 1, 0));
                vertices[1] = new MyOwnVertexFormat(new Vector3(-20, 0, -100), new Vector2(-0.25f, 0.0f), new Vector3(0, 1, 0));
                vertices[2] = new MyOwnVertexFormat(new Vector3(2, 0, 10), new Vector2(0.25f, 25.0f), new Vector3(0, 1, 0));
                vertices[3] = new MyOwnVertexFormat(new Vector3(2, 0, -100), new Vector2(0.25f, 0.0f), new Vector3(0, 1, 0));
                vertices[4] = new MyOwnVertexFormat(new Vector3(2, 0, 10), new Vector2(0.25f, 25.0f), new Vector3(-1, 0, 0));
                vertices[5] = new MyOwnVertexFormat(new Vector3(2, 0, -100), new Vector2(0.25f, 0.0f), new Vector3(-1, 0, 0));
                vertices[6] = new MyOwnVertexFormat(new Vector3(2, 1, 10), new Vector2(0.375f, 25.0f), new Vector3(-1, 0, 0));
                vertices[7] = new MyOwnVertexFormat(new Vector3(2, 1, -100), new Vector2(0.375f, 0.0f), new Vector3(-1, 0, 0));
                vertices[8] = new MyOwnVertexFormat(new Vector3(2, 1, 10), new Vector2(0.375f, 25.0f), new Vector3(0, 1, 0));
                vertices[9] = new MyOwnVertexFormat(new Vector3(2, 1, -100), new Vector2(0.375f, 0.0f), new Vector3(0, 1, 0));
                vertices[10] = new MyOwnVertexFormat(new Vector3(3, 1, 10), new Vector2(0.5f, 25.0f), new Vector3(0, 1, 0));
                vertices[11] = new MyOwnVertexFormat(new Vector3(3, 1, -100), new Vector2(0.5f, 0.0f), new Vector3(0, 1, 0));
                vertices[12] = new MyOwnVertexFormat(new Vector3(13, 1, 10), new Vector2(0.75f, 25.0f), new Vector3(0, 1, 0));
                vertices[13] = new MyOwnVertexFormat(new Vector3(13, 1, -100), new Vector2(0.75f, 0.0f), new Vector3(0, 1, 0));
                vertices[14] = new MyOwnVertexFormat(new Vector3(13, 1, 10), new Vector2(0.75f, 25.0f), new Vector3(-1, 0, 0));
                vertices[15] = new MyOwnVertexFormat(new Vector3(13, 1, -100), new Vector2(0.75f, 0.0f), new Vector3(-1, 0, 0));
                vertices[16] = new MyOwnVertexFormat(new Vector3(13, 21, 10), new Vector2(1.25f, 25.0f), new Vector3(-1, 0, 0));
                vertices[17] = new MyOwnVertexFormat(new Vector3(13, 21, -100), new Vector2(1.25f, 0.0f), new Vector3(-1, 0, 0));

                vertexBuffer = new VertexBuffer(device, MyOwnVertexFormat.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
                vertexBuffer.SetData(vertices);
            }

            private void SetUpCamera()
            {
                cameraPos = new Vector3(-25, 13, 18);
                viewMatrix = Matrix.CreateLookAt(cameraPos, new Vector3(0, 2, -12), new Vector3(0, 1, 0));
                projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, device.Viewport.AspectRatio, 1.0f, 200.0f);
            }

            protected override void UnloadContent()
            {
            }

            protected override void Update(GameTime gameTime)
            {
                if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                    this.Exit();

                UpdateLightData();

                base.Update(gameTime);
            }


             private void UpdateLightData()
             {
                 ambientPower = 0.2f;
     
                 lightPos = new Vector3(-18, 5, -2);
                 lightPower = 1.0f;
     
                 Matrix lightsView = Matrix.CreateLookAt(lightPos, new Vector3(-2, 3, -10), new Vector3(0, 1, 0));
                 Matrix lightsProjection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver2, 1f, 5f, 100f);
     
                 lightsViewProjectionMatrix = lightsView * lightsProjection;
             }
     
             protected override void Draw(GameTime gameTime)
             {
                 device.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1.0f, 0);
     
                 DrawScene("ShadowMap");
     
                 base.Draw(gameTime);
             }
     
             private void DrawScene(string technique)
             {
                 effect.CurrentTechnique = effect.Techniques[technique];
                 effect.Parameters["xWorldViewProjection"].SetValue(Matrix.Identity * viewMatrix * projectionMatrix);
                 effect.Parameters["xTexture"].SetValue(streetTexture);
                 effect.Parameters["xWorld"].SetValue(Matrix.Identity);
                 effect.Parameters["xLightPos"].SetValue(lightPos);
                 effect.Parameters["xLightPower"].SetValue(lightPower);
                 effect.Parameters["xAmbient"].SetValue(ambientPower);
                 effect.Parameters["xLightsWorldViewProjection"].SetValue(Matrix.Identity * lightsViewProjectionMatrix);
     
                 foreach (EffectPass pass in effect.CurrentTechnique.Passes)
                 {
                     pass.Apply();
     
                     device.SetVertexBuffer(vertexBuffer);
                     device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 16);
                 }
     
                 Matrix car1Matrix = Matrix.CreateScale(4f) * Matrix.CreateRotationY(MathHelper.Pi) * Matrix.CreateTranslation(-3, 0, -15);
                 DrawModel(carModel, carTextures, car1Matrix, technique);
     
                 Matrix car2Matrix = Matrix.CreateScale(4f) * Matrix.CreateRotationY(MathHelper.Pi * 5.0f / 8.0f) * Matrix.CreateTranslation(-28, 0, -1.9f);
                 DrawModel(carModel, carTextures, car2Matrix, technique);
             }
     
             private void DrawModel(Model model, Texture2D[] textures, Matrix wMatrix, string technique)
             {
                 Matrix[] modelTransforms = new Matrix[model.Bones.Count];
                 model.CopyAbsoluteBoneTransformsTo(modelTransforms);
                 int i = 0;
                 foreach (ModelMesh mesh in model.Meshes)
                 {
                     foreach (Effect currentEffect in mesh.Effects)
                     {
                         Matrix worldMatrix = modelTransforms[mesh.ParentBone.Index] * wMatrix;
                         currentEffect.CurrentTechnique = currentEffect.Techniques[technique];
                         currentEffect.Parameters["xWorldViewProjection"].SetValue(worldMatrix * viewMatrix * projectionMatrix);
                         currentEffect.Parameters["xTexture"].SetValue(textures[i++]);
                         currentEffect.Parameters["xWorld"].SetValue(worldMatrix);
                         currentEffect.Parameters["xLightPos"].SetValue(lightPos);
                         currentEffect.Parameters["xLightPower"].SetValue(lightPower);
                         currentEffect.Parameters["xAmbient"].SetValue(ambientPower);
                         currentEffect.Parameters["xLightsWorldViewProjection"].SetValue(worldMatrix * lightsViewProjectionMatrix);
                     }
                     mesh.Draw();
                 }
             }
     
         }
     }
     


    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)
    2D Series: Shooters (22)
    3D Series 1: Terrain (13)
    3D Series 2: Flightsim (14)
    3D Series 3: HLSL (18)
    Starting point
    HLSL introduction
    Vertex format
    Vertex shader
    Pixel shader
    Per-pixel colors
    Textured triangle
    Triangle strip
    World transform
    World normals
    Per-pixel lighting
    Shadow map
    Render to texture
    Projective texturing
    Real shadow
    Shaping the light
    Preshaders
    3D Series 4: Adv. terrain (19)
    Short Tuts (3)
    DirectX using C# (54)
    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!