How you can load HLSL effects on your XNA project

So Whats HLSL?

The High Level Shader Language or High Level Shading Language (HLSL) is a proprietary shading language developed by Microsoft for use with the Microsoft Direct3D API. It is analogous to the GLSL shading language used with the OpenGL standard. It is the same as the NVIDIA Cg shading language, as it was developed alongside it.

HLSL programs come in three forms, vertex shaders, geometry shaders, and pixel (or fragment) shaders. A vertex shader is executed for each vertex that is submitted by the application, and is primarily responsible for transforming the vertex from object space to view space, generating texture coordinates, and calculating lighting coefficients such as the vertex's tangent, binormal and normal vectors. When a group of vertices (normally 3, to form a triangle) come through the vertex shader, their output position is interpolated to form pixels within its area; this process is known as rasterisation. Each of these pixels comes through the pixel shader, whereby the resultant screen colour is calculated.

HLSL can be directly imported in XNA because of the built-in content importer written for HLSL.

Now lets create a project and show you how to load HLSL and use it

Image1.gif

Add Effect Folder and import our Effect file in the same path of Game.cs.And change its properties as seen below:

Image2.gif

This way we will be reading it from Debug folder.

The effect file is looking like this:

struct VertextoPixel
{
float4 Position : POSITION;
float4 Color : COLOR0;
float LightingFactor: TEXCOORD0;
float2 TextureCoords: TEXCOORD1;
};

struct PixeltoScene
{
float4 Color : COLOR0;
};

float4x4 xView;
float4x4 xProjection;
float4x4 xWorld;
float3 xLightDirection;
float xAmbient;
bool xEnableLighting;
bool xShowNormals;

VertexToPixel TransformVS( float4 inPos : POSITION, float4 inColor: COLOR)
{
VertexToPixel Output = (VertexToPixel)0;
Output.Position = inPos;
Output.Color = inColor;
return Output;
}

PixelToScene TransformPS(VertexToPixel PSIn)
{
PixelToScene Output = (PixelToScene)0;
Output.Color = PSIn.Color;
return Output;
}

technique Transform
{
pass Pass0
{
VertexShader = compile vs_2_0 TransformVS();
PixelShader = compile ps_2_0 TransformPS();
}
}

Now as we added the effect file in XNA lets see how we can use it

Add these variables:

SpriteBatch spriteBatch;
GraphicsDeviceManager graphics;      
GraphicsDevice device;
Effect effect;
VertexPositionColor[] vertices;

We will be using XNA as a device in this sample.And we are creating Effect class to work with the effect file we imported.

Update your Initialize function as seen below:

protected override void Initialize(
{
  base.Initialize();
  XNA_Set_Device();
  Set_Vertices();
}

Update your XNA_Set_Device function as seen below:

private void XNA_Set_Device()
        {
            device = graphics.GraphicsDevice;

            graphics.PreferredBackBufferWidth = 500;
            graphics.PreferredBackBufferHeight = 500;
            graphics.IsFullScreen = false;
            graphics.ApplyChanges();
            Window.Title = "HLSL Sample";
 
            CompiledEffect compiledEffect = Effect.CompileEffectFromFile("effects.fx", null, null, CompilerOptions.None, TargetPlatform.Windows);
            effect = new Effect(graphics.GraphicsDevice, compiledEffect.GetEffectCode(), CompilerOptions.None, null);
        }

We are using CompiledEffect.As you well know Visual Studio have the ability to compile Effect files(.fx only)

Update your Set_Vertices function as seen below:

private void Set_Vertices()
{
  vertices = new VertexPositionColor[3];
  vertices[0].Position = new Vector3(-0.5f, -0.5f, 0f);
  vertices[0].Color = Color.Red;
  vertices[1].Position = new Vector3(0, 0.5f, 0f);
  vertices[1].Color = Color.Green;
  vertices[2].Position = new Vector3(0.5f, -0.5f, 0f);
  vertices[2].Color = Color.Yellow;
}

We are setting each Vertice of the triangle.

Update your "Update" and Draw functions as seen below:

protected override void Update(GameTime gameTime)
{
   base.Update(gameTime);
   KeyboardState state = Keyboard.GetState();

   if (state.IsKeyDown(Keys.Escape))
   {
     this.Exit();
   }    
}

protected
override void Draw(GameTime gameTime)
{
   GraphicsDevice.Clear(Color.CornflowerBlue);
   device.Clear(Color.DarkSlateBlue);
   effect.CurrentTechnique = effect.Techniques["Transform"];
   effect.Begin();

   foreach (EffectPass pass in effect.CurrentTechnique.Passes)
   {
     pass.Begin();
     device.VertexDeclaration = new VertexDeclaration(device, VertexPositionColor.VertexElements);
     device.DrawUserPrimitives(PrimitiveType.TriangleList, vertices, 0, 1);
     pass.End();
   }
     effect.End();
     base.Draw(gameTime);
}

Ok we have set everything up.and its time to explain: In this article as i told you before we will be using a triangle which each vertice cleared with different color using HLSL.Transform function we call from HLSL is:

technique Transform
{
pass Pass0
{
VertexShader = compile vs_2_0 TransformVS();
PixelShader = compile ps_2_0 TransformPS();
}
}

Function in HLSL==Technique.By thinking this way you can understand the meaning of HLSL s much more better.

Every technique works like a function.Thats the thing you should know about XNA-HLSL integration.

EffectPass whats that?

Well while getting datas -which are pixel and vertex datas- from HLSL Effect file.We tell it to do this:

send -> process it -> and then return it as a data.

And after that,the returned data is presented on your display device as a result processing Vertex and Pixel Shaders.

So you pass datas between these Shaders.

Ok. Now lets run our application and see what happens:

Image3.gif

This is the result of Passing datas between Shaders and sending datas to our display device.

HLSL works in this way.

I hope this article have helped you understand the true meanings of HLSL using in XNA.And dont worry i will be talking more about HLSL and Effects in the following articles.

If you have a question please ask, I will help you as I can ;)

Cheers,
 


Similar Articles