XNA for C#
DirectX 9 for C#
DirectX 9 for C++
DirectX 9 for VB
Forum
   August 27: 2D-7: Writing text
My Book: Out Now!
      
       Go to section on this site

Additional info


Latest Forum posts

 DX vs XNA vs OGL
  Posted by: Rich_Zap
  When: 28/08/2008 at 10:54:39

 understanding of SetUpIndices
  Posted by: YoYoFreakCJ
  When: 28/08/2008 at 05:51:04

 billboard does not rotate after scaling
  Posted by: kigunda
  When: 28/08/2008 at 04:55:29

 exception error
  Posted by: Rich_Zap
  When: 28/08/2008 at 03:34:29

 exception error
  Posted by: besi
  When: 28/08/2008 at 00:14:11

 Having trouble with effect file
  Posted by: Anonymous
  When: 27/08/2008 at 22:15:15

 Polygon Clipping for Octree
  Posted by: lbmurali
  When: 27/08/2008 at 18:13:55

 understanding of SetUpIndices
  Posted by: vToMy
  When: 27/08/2008 at 18:05:45

 A Typo with loading the Font
  Posted by: riemer
  When: 27/08/2008 at 15:26:43

 mistake found
  Posted by: riemer
  When: 27/08/2008 at 15:22:31


Ads

Processing in 2D screen coordinates

In this chapter we will add the glow around the light bulbs. First, let me things clear that you in most cases you should do this using billboards (see Recipes 3-11 and 3-12). But since we haven’t done any 2D screen processing in our HLSL tutorial yet, let’s add the glows using HLSL.

The approach we are going to follow is quite simple. We will start by calculating the 2D screen position of the light. Then we calculate the distance between this 2D screen pos of the light, and the 2D screen pos of the current pixel. If this distance is smaller than a certain amount, we add some white to the final color value for that pixel.

Before we can start, we will need 3 more XNA-to-HLSL variables:

float4x4 xViewProjection;
float3 xCameraPos;
float3 xLamppostPos[2];

The xViewProjection matrix will be required to transform some 3D positions to 2D screen coordinates. We’ll need the position of the camera to determine the radius of the glow. Obviously, we also need the 3D positions of both lampposts. Note that this is the first time we’re using an array as XNA-to-HLSL variable.

In the pixel shader, we will first calculate the 2D screen pos of the current pixel. We have done this many times before: by multiplying the 3D position with the WorldViewProjection matrix of the camera. Up till now, we’ve done this in the vertex shader, but you can also do matrix multiplications in the pixel shader. Add these lines to the end of our pixel shader:

float4 screenPos = mul(PSIn.Position3D, xViewProjection);
screenPos /= screenPos.w;

The first line transforms the 3D position to 2D screen position. After dividing the result by its homogeneous coordinate, the X and Y coordinate will be in the [-1,1] region.

It’s quite important to note that we are multiplying with the ViewProjection matrix instead of the WorldViewProjection matrix. This is simply because PSIn.Position3D was created in the vertex shader by multiplying the 3D position in the vertices by the World matrix. So the resulting screenPos value is the original 3D position, transformed by the World matrix, and then by the ViewProjection matrix.

Next, we will find the screen positions of our 2 lights. Since we haven’t done this before, we’ll use a for loop for this:

for (int CurrentLight=0; CurrentLight<2; CurrentLight++)
{
}

For each light, we will calculate its 2D screen coordinate exacly the same way:

float4 lightScreenPos = mul(float4(xLamppostPos[CurrentLight],1),xViewProjection);
lightScreenPos /= lightScreenPos.w;

Here, we again transform with only the ViewProjection matrix. However, the reason is totally different. In this case, the position of the lamppost has NOT yet been transformed by the World matrix in the vertex shader, is it is provided immediately by our XNA code. But when we will set these positions in our XNA code, we will provide them immediately in World coordinates. Therefore, we do not have to transform them with the World matrix as the coordinates are already in World space.

Now we know both the screen coordinate of the current pixel and of the lamppost (both in the [-1,1] region, it’s easy to calculate the distance between them:

float dist = distance(screenPos.xy, lightScreenPos.xy);

All that remain is define a maximum radius for the glow. This should get smaller as the distance between the camera and lamppost gets larger:

 float radius = 7.0f/distance(xCameraPos, xLamppostPos[CurrentLight]);

Adjust the 7 to make the glow larger/smaller. With the radius defined, let’s check if the current pixel is within this distance to lamppost:

if (dist < radius)
{
}

If it is, add some white to the pixel color. The closer to the lamppost, the more white should be added:

Output.Color.rgb += (radius-dist)*4.0f;

That’s it for the HLSL part! Let’s not forget to set the extra 3 XNA-to-HLSL variables. Go to our XNA code, and add this variable to our class:

 Vector3[] lamppostPositions = new Vector3[2];

And set them in our UpdateLightData method:

 lamppostPositions[0] = new Vector3(3f, 11.5f, -35f);
 lamppostPositions[1] = new Vector3(3f, 11.5f, -5f);

With this data ready, it’s easy to set the 3 XNA-to-HLSL parameters in our DrawScene method:

 effect.Parameters["xCameraPos"].SetValue(cameraPos);            effect.Parameters["xViewProjection"].SetValue(viewMatrix*projectionMatrix);
 effect.Parameters["xLamppostPos"].SetValue(lamppostPositions);

And in our DrawModel method:

 currentEffect.Parameters["xCameraPos"].SetValue(cameraPos);
 currentEffect.Parameters["xViewProjection"].SetValue(viewMatrix * projectionMatrix);
 currentEffect.Parameters["xLamppostPos"].SetValue(lamppostPositions);

You see how easy it is to pass in an array to our HLSL code.

Now when you run your code you should see the same image as below:




DirectX Tutorial 17 - 2D screen processing

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:
  • Shader problem
          When I tried to compile my HLSL code, it throwed a...
  • Missing Shadow??
          Has anyone run into a situation where the shadow f...


    However, if we take a look at the calculations done by the last pixel shader, we notice a lot of constant calculations are being done, such as the 2D position of our lights, the dist and the radius values. These are being calculated for every pixel, while they will always remain the same!

    Not completely true. We’ll see what kind of optimizations the HLSL compilers can perform for us, in the next chapter.

    Our final 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 class Game1 : Microsoft.Xna.Framework.Game
         {
             struct MyOwnVertexFormat
             {
                 private 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 static VertexElement[] VertexElements =
                 {
                     new VertexElement(0, 0, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Position, 0),
                     new VertexElement(0, sizeof(float)*3, VertexElementFormat.Vector2, VertexElementMethod.Default, VertexElementUsage.TextureCoordinate, 0),
                     new VertexElement(0, sizeof(float)*5, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Normal, 0),
                 };
     
                 public static int SizeInBytes = sizeof(float) * (3 + 2 + 3);
             }
     
             GraphicsDeviceManager graphics;
             GraphicsDevice device;
             
             Effect effect;
             Matrix viewMatrix;
             Matrix projectionMatrix;
             VertexBuffer vertexBuffer;
             VertexDeclaration vertexDeclaration;
             Vector3 cameraPos;
     
             Texture2D streetTexture;
             Model lamppostModel;
             Texture2D[] lamppostTextures;
             Model carModel;
             Texture2D[] carTextures;
             Texture2D carLight;
     
             Vector3 lightPos;
             float lightPower;
             float ambientPower;
     
             Matrix lightsViewProjectionMatrix;
     
             RenderTarget2D renderTarget;
             Texture2D shadowMap;
     
             Vector3[] lamppostPositions = new Vector3[2];
     
             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");
                streetTexture = Content.Load<Texture2D> ("streettexture");
                carLight = Content.Load<Texture2D> ("carlight");
                carModel = LoadModel("racer", out carTextures);
                lamppostModel = LoadModel("lamppost", out lamppostTextures);

                SetUpVertices();
                SetUpCamera();

                PresentationParameters pp = device.PresentationParameters;
                renderTarget = new RenderTarget2D(device, pp.BackBufferWidth, pp.BackBufferHeight, 1, SurfaceFormat.Single);
            }

            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(device);

                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, vertices.Length * MyOwnVertexFormat.SizeInBytes, BufferUsage.WriteOnly);
                vertexBuffer.SetData(vertices);

                vertexDeclaration = new VertexDeclaration(device, MyOwnVertexFormat.VertexElements);
            }

            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, 5.0f, 100.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.5f;

                lightPos = new Vector3(-18, 5, -2);
                lightPower = 2.0f;

                Matrix lightsView = Matrix.CreateLookAt(lightPos, new Vector3(-2, -3, -10), new Vector3(0, 1, 0));
                Matrix lightsProjection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver2, 1f, 1f, 100f);
                lightsViewProjectionMatrix = lightsView* lightsProjection;


                 lamppostPositions[0] = new Vector3(3f, 11.5f, -35f);
                 lamppostPositions[1] = new Vector3(3f, 11.5f, -5f);
             }
     
             protected override void Draw(GameTime gameTime)
             {
                 device.SetRenderTarget(0, renderTarget);
     
                 device.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1.0f, 0);
                 DrawScene("ShadowMap");
     
                 device.SetRenderTarget(0, null);
                 shadowMap = renderTarget.GetTexture();
     
                 device.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1.0f, 0);
                 DrawScene("ShadowedScene");
     
                 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);
                 effect.Parameters["xShadowMap"].SetValue(shadowMap);
                 effect.Parameters["xCarLightTexture"].SetValue(carLight);
                 effect.Parameters["xCameraPos"].SetValue(cameraPos);
                 effect.Parameters["xViewProjection"].SetValue(viewMatrix*projectionMatrix);
                 effect.Parameters["xLamppostPos"].SetValue(lamppostPositions);
                 effect.Begin();
                 foreach (EffectPass pass in effect.CurrentTechnique.Passes)
                 {
                     pass.Begin();
                     device.VertexDeclaration = vertexDeclaration;
                     device.Vertices[0].SetSource(vertexBuffer, 0, MyOwnVertexFormat.SizeInBytes);
                     device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 18);
                     pass.End();
                 }
                 effect.End();
     
                 Matrix car1Matrix = Matrix.CreateScale(4f) * Matrix.CreateRotationY(MathHelper.Pi) * Matrix.CreateTranslation(-3, 0, -15);
                 DrawModel(carModel, carTextures, car1Matrix, technique, false);
     
                 Matrix car2Matrix = Matrix.CreateScale(4f) * Matrix.CreateRotationY(MathHelper.Pi * 5.0f / 8.0f) * Matrix.CreateTranslation(-28, 0, -1.9f);
                 DrawModel(carModel, carTextures, car2Matrix, technique, false);
     
                 Matrix lamp1Matrix = Matrix.CreateScale(0.05f) * Matrix.CreateTranslation(4.0f, 1, -35);
                 DrawModel(lamppostModel, lamppostTextures, lamp1Matrix, technique, true);
     
                 Matrix lamp2Matrix = Matrix.CreateScale(0.05f) * Matrix.CreateTranslation(4.0f, 1, -5);
                 DrawModel(lamppostModel, lamppostTextures, lamp2Matrix, technique, true);            
             }
     
             private void DrawModel(Model model, Texture2D[] textures, Matrix wMatrix, string technique, bool solidBrown)
             {
                 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["xSolidBrown"].SetValue(solidBrown);
                         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);
                         currentEffect.Parameters["xShadowMap"].SetValue(shadowMap);
                         currentEffect.Parameters["xCarLightTexture"].SetValue(carLight);
                         currentEffect.Parameters["xCameraPos"].SetValue(cameraPos);
                         currentEffect.Parameters["xViewProjection"].SetValue(viewMatrix * projectionMatrix);
                         currentEffect.Parameters["xLamppostPos"].SetValue(lamppostPositions);
                     }
                     mesh.Draw();
                 }
             }
     
         }
     }

    And the HLSL code:

    float4x4 xLightsWorldViewProjection;
    float4x4 xWorldViewProjection;
    float4x4 xWorld;

     float4x4 xViewProjection;

    bool xSolidBrown;
    float3 xLightPos;
    float xLightPower;
    float xAmbient;

     float3 xCameraPos;
     float3 xLamppostPos[2];


    Texture xTexture;

    sampler TextureSampler = sampler_state { texture = <xTexture> ; 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;};
    Texture xCarLightTexture;

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

    struct PixelToFrame
    {
        float4 Color        : COLOR0;
    };

    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;
    }

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

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

        float diffuseLightingFactor = DotProduct(xLightPos, PSIn.Position3D, PSIn.Normal);
        diffuseLightingFactor = saturate(diffuseLightingFactor);
        diffuseLightingFactor *= xLightPower;
        
        float4 baseColor = tex2D(TextureSampler, PSIn.TexCoords);
        if (xSolidBrown == true)
            baseColor = float4(0.25f, 0.21f, 0.20f, 1);
        
        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();
        }
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////

    struct SSceneVertexToPixel
    {
        float4 Position             : POSITION;
        float4 Pos2DAsSeenByLight    : TEXCOORD0;
        float2 TexCoords            : TEXCOORD1;
        float3 Normal                : TEXCOORD2;
        float4 Position3D            : TEXCOORD3;
    };

    struct SScenePixelToFrame
    {
        float4 Color : COLOR0;
    };

    SSceneVertexToPixel ShadowedSceneVertexShader( float4 inPos : POSITION, float2 inTexCoords : TEXCOORD0, float3 inNormal : NORMAL)
    {
        SSceneVertexToPixel Output = (SSceneVertexToPixel)0;

        Output.Position = mul(inPos, xWorldViewProjection);    
        Output.Pos2DAsSeenByLight = mul(inPos, xLightsWorldViewProjection);    
        Output.Normal = normalize(mul(inNormal, (float3x3)xWorld));    
        Output.Position3D = mul(inPos, xWorld);
        Output.TexCoords = inTexCoords;    

        return Output;
    }

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

        float2 ProjectedTexCoords;
        ProjectedTexCoords[0] = PSIn.Pos2DAsSeenByLight.x/PSIn.Pos2DAsSeenByLight.w/2.0f +0.5f;
        ProjectedTexCoords[1] = -PSIn.Pos2DAsSeenByLight.y/PSIn.Pos2DAsSeenByLight.w/2.0f +0.5f;
        
        float diffuseLightingFactor = 0;
        if ((saturate(ProjectedTexCoords).x == ProjectedTexCoords.x) && (saturate(ProjectedTexCoords).y == ProjectedTexCoords.y))
        {
            float depthStoredInShadowMap = tex2D(ShadowMapSampler, ProjectedTexCoords).r;
            float realDistance = PSIn.Pos2DAsSeenByLight.z/PSIn.Pos2DAsSeenByLight.w;
            if ((realDistance - 1.0f/100.0f) <= depthStoredInShadowMap)
            {    
                diffuseLightingFactor = DotProduct(xLightPos, PSIn.Position3D, PSIn.Normal);
                diffuseLightingFactor = saturate(diffuseLightingFactor);
                diffuseLightingFactor *= xLightPower;            
                
                float lightTextureFactor = tex2D(CarLightSampler, ProjectedTexCoords).r;
                diffuseLightingFactor *= lightTextureFactor;
            }
        }    
        
        float4 baseColor = tex2D(TextureSampler, PSIn.TexCoords);
                if (xSolidBrown == true)
                    baseColor = float4(0.25f, 0.21f, 0.20f, 1);
                    
        Output.Color = baseColor*(diffuseLightingFactor + xAmbient);
        

         float4 screenPos = mul(PSIn.Position3D, xViewProjection);
         screenPos /= screenPos.w;
         
         for (int CurrentLight=0; CurrentLight<2; CurrentLight++)
         {
             float4 lightScreenPos = mul(float4(xLamppostPos[CurrentLight],1),xViewProjection);
             lightScreenPos /= lightScreenPos.w;
             
             float dist = distance(screenPos.xy, lightScreenPos.xy);
             float radius = 7.0f/distance(xCameraPos, xLamppostPos[CurrentLight]);
             if (dist < radius)
             {
                 Output.Color.rgb += (radius-dist)*4.0f;

            }
        }

        return Output;
    }

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


    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 - 2008 Riemer Grootjans
  • Translations

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

    Microsoft MVP Award



    2007 - 2008 MVP Award
    DirectX - XNA

    Contents

    News
    Home
    Forum
    XNA 2.0 Recipes Book (8)
    Downloads
    Extra Reading (3)
    Matrices: geometrical
    Matrix Mathematics
    Homogenous matrices
    Tutorials (145)
    XNA 2.0 using C# (74)
    2D Series: Shooters! (7)
    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
    2D screen processing
    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!