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
Add Effect Folder and import our Effect file in the same path of Game.cs.And
change its properties as seen below:
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:
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,