Alright reserved to Cubecg studio 2008

Render a complex lensflare effect with a single spriteBatch

THE PROJECT FILE TO DOWNLOAD

 

Long name and shot story.Let's get started.

this story is also goody for newbes on XNA or experenced users.

First of all the prepareration:

1.Dubble click the VC# and start a new XNA game project.debug it ,you got a blue screen .you got the first point of the render.

2.Load assets to the content,rightclick the content to load the three pictures used for lens render which you can download it at the TOP of this story.

3.Create a FX effect by rightclick the content to make a new effect file name it"flares".

Prepareration is done .simple?Yes.

 

step 2:(make the light visable )

1.I use a null(cross) to represent the light.How to ? Right click the project to add a exist thing  which named "Drawnull" .and now you will find a new Drawnull.cs file insight.

2.Adding a camera. just I as mentioned above load a Camera.cs file to you project.

(the cs file is in my project folder unzip it out...done not forget the "namespace")

3.mix them together.In the main cs window fingers type this:

 

  public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        SpriteFont font;
        Texture2D[] lenmap = new Texture2D[3];
        Effect effect;
    
        SampleGrid grid;
        Drawnull Null;
        Camera camera;
    

    public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            grid = new SampleGrid();
            Null = new Drawnull();
            camera = new Camera(this);
            this.Components.Add(camera);
            
            IsMouseVisible = true;   
        }

 

(what is the Samplegrid? just add the samplegrid.cs as I said before)

 

 4.To make the things work :add them to the assets manager of XNA.just type in this:

   protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
             lenmap[0]=Content.Load<Texture2D>("flare");
             lenmap[1] = Content.Load<Texture2D>("flaredot1");
             lenmap[2] = Content.Load<Texture2D>("flaredot");
             effect = Content.Load<Effect>("flares");
        }

5.How can I see them on the screen? you need to draw them with your fingers

type there words:

 

 protected override void Draw(GameTime gameTime)
        {
            graphics.GraphicsDevice.Clear(Color.Gray);

           Vector3 lightpos = new Vector3(10,20,100);

 

grid.DrawGrid(camera.View, camera.Projection,GraphicsDevice);
            Null.DrawNull(Matrix.CreateTranslation(lightpos), camera.View, camera.Projection, 1, GraphicsDevice);
            Null.DrawNull(Matrix.Identity, Matrix.Identity, Matrix.Identity, 1, GraphicsDevice);

      base.Draw(gameTime);
        }       

 And debug->

use your right mouse button to turn around.Now you got a gird as gound plan and a Null cross as a light.

 

The final part.make the null shining and take the flares out to us!

   protected override void Draw(GameTime gameTime)
        {
            graphics.GraphicsDevice.Clear(Color.Gray);

            Vector3 lightpos = new Vector3(10,20,100);
         
            Vector3 pp =GraphicsDevice.Viewport.Project            (lightpos,camera.Projection,camera.View, Matrix.Identity);
            Vector2 lightproject=Vector2.One/2- new Vector2(pp.X/800 ,pp.Y/600);
          
            float disapear=0;
            if (0.5f-lightproject.X < 1 && 0.5f-lightproject.Y < 1)
            { disapear = MathHelper.Min(0.5f - lightproject.X, 0.5f - lightproject.Y); }
            else if (0.5f-lightproject.X > 1 ||0.5f- lightproject.Y > 1)
            { disapear = 1 - MathHelper.Max(0.5f - lightproject.X, 0.5f - lightproject.Y); }
           
            float sunsize = 3;
            float circlesize =5;
            float circledistance =1.25f;
            float intens = 0.8f+MathHelper.Clamp(disapear*4,-0.8f,0);
           
            effect.CurrentTechnique = effect.Techniques["lens"];
            effect.Parameters["A"].SetValue(lenmap[0]);
            effect.Parameters["A1"].SetValue(lenmap[1]);
            effect.Parameters["A2"].SetValue(lenmap[2]);
            effect.Parameters["lightpos"].SetValue(lightproject);
            effect.Parameters["n"].SetValue(sunsize);
            effect.Parameters["T"].SetValue(circlesize);
            effect.Parameters["o"].SetValue(circledistance);
            effect.Parameters["intensy"].SetValue(intens);

            spriteBatch.Begin(SpriteBlendMode.None, SpriteSortMode.Immediate, SaveStateMode.None);
            effect.Begin();
            effect.CurrentTechnique.Passes[0].Begin();
            spriteBatch.Draw(lenmap[0], new Rectangle(0, 0, 800, 600), Color.White);
            spriteBatch.End();
            effect.CurrentTechnique.Passes[0].End();
            effect.End();

            grid.DrawGrid(camera.View, camera.Projection,GraphicsDevice);
            Null.DrawNull(Matrix.CreateTranslation(lightpos), camera.View, camera.Projection, 1, GraphicsDevice);
            Null.DrawNull(Matrix.Identity, Matrix.Identity, Matrix.Identity, 1, GraphicsDevice);
                   base.Draw(gameTime);
        }       

 

Here you go ,you got the flare effects and some control options to tweak with ,discover them by yourself smarters.just change the lightpos to see what will happen.

Good luck.

 

Copy and past the words below to your "flares.fx" file under the content folder.

 

texture A ;
 sampler2D ASampler = sampler_state
{
 Texture = <A>;
  MagFilter = Linear;  MinFilter = Linear;  MipFilter = Linear;
  AddressU = Border;  AddressV = Border;  BorderColor = 0x00000000;
};
texture A1;
 sampler2D ASampler1 = sampler_state
{
 Texture = <A1>;
  MagFilter = Linear;  MinFilter = Linear;  MipFilter = Linear;
  AddressU = Border;  AddressV = Border;  BorderColor = 0x00000000;
};
texture A2;
 sampler2D ASampler2 = sampler_state
{
 Texture = <A2>;
  MagFilter = Linear;  MinFilter = Linear;  MipFilter = Linear;
  AddressU = Border;  AddressV = Border;  BorderColor = 0x00000000;
};
float count[8] =
{  5,2.5,1.8,0.5,-0.5,-1.25,-2.5,-3.5,};
float4 Samples[8] =
                {
     float4(2.355512,   1.709318,  1.102371,  -0.5 ),
     float4(1.234186,    0.71511,  0.115167,  0.415167 ),
     float4(0.87866,    1.8657139,  1.115167, 0.709318 ),
     float4(1.2040679,   2.475516,  2.0639818,  1.102371),
     float4(4.1796121,  0.858842,  0.677075,   0.858842),
     float4(1.2759516, 1.801676,  0.483625,  1.177075),
     float4(2.12493,    2.4223423, 1.483625,  0.383625),
     float4(0.5720074,  1.243395,  1.967251,  0.243395 ),
                   };
float2 lightpos;
float intensy,n,T, o;

float4 af(float2  texCoord : TEXCOORD0) : COLOR
{
 float2 c=float2(1.3,1);

float2 lp=(lightpos.xy)*c;
float2 UV =(texCoord-0.5)*n*c+0.5;

float4 A = tex2D(ASampler,UV+lp*n);
float4 sum=0;
float4 sum1=0;
for(int i = 0; i < 8; i++)
   {
   float2 nUV=(texCoord-0.5)*Samples[i].x*T*c+0.5;
   sum+=tex2D(ASampler1,nUV+lp*(count[i]*o)*Samples[i].x)*Samples[i];
   sum1+=tex2D(ASampler2,nUV+lp*(count[i]*o)*Samples[i].w*2.5)*Samples[i]*2;}

return (sum/12+sum1/8+A*A.a)*intensy;
}

technique lens
{
    pass Pass1
    {
  AlphaBlendEnable = true;
 SrcBlend =one;
 DestBlend = one;
 PixelShader = compile ps_2_a af();
    }
}