Docstoc

High Level Shader Language HLSL

Document Sample
High Level Shader Language HLSL Powered By Docstoc
					High Level Shader Language
         (HLSL)
         Chapter 11




                             1
              What is HLSL?
The previous vertex and pixel shader programming is to
use assembly language to write instructions, which can de
directly executed by GPU Graphical Processing Unit.
HLSL, which refers to High Level Shader Language, is a C
style programming language in GPU. However, in order to
make HLSL working, the GPU of video card must have
ability to compile HLSL into assembly instructions. The
minimal requirement for GPU is to fit the shader version 2.
Some tested GPU chips are:
       ATI Radeon Xpress 200 or high.
       nVIDIA GeForce 5200 or high
       Intel GMA 945 is failed to execute IndexBuffer
                                                          2
Check video card shader Version
Caps DevCaps = Manager.GetDeviceCaps(0, DeviceType.Hardware);
DeviceType DevType = D3D.DeviceType.Reference;
CreateFlags DevFlags = CreateFlags.SoftwareVertexProcessing;
if ((DevCaps.VertexShaderVersion >= new Version(2, 0)) &&
    (DevCaps.PixelShaderVersion >= new Version(2, 0)))
 {
    DevType =DeviceType.Hardware;
    if (DevCaps.DeviceCaps.SupportsHardwareTransformAndLight)
    {
         DevFlags = CreateFlags.HardwareVertexProcessing;
         if (DevCaps.DeviceCaps.SupportsPureDevice)
         {
                 DevFlags |= CreateFlags.PureDevice;
         }
    }
}
                                                                3
                 Class Effect
HLSL code is written in text file with extension *.fx.
First we need to load is to an Effect object .

 public static Effect FromFile(
   Device               device,
   string               fileName,
   Include              includeFile,   // use null
   ShaderFlags          flags,
   EffectPool           pool           // use null
 )

Example
 Effect effect = Effect.FromFile(device, "rotation.fx",
 null, ShaderFlags.None, null);
                                                          4
        Structure of HLSL code
HLSL code has four parts:
   1. Variables that get values from application
   2. Input and Output structure (optional)
   3. Functions
   4. Techniques and passes.
One HLSL file could have more techniques. One technique
can have multiple passes. Lets see the following example
   struct VS_OUPUT
   {
      float4 pos        : POSITION;
      float4 color      : COLOR0;
   };

   float4x4 WorldViewProj : WORLDVIEWPROJECTION;
                                                           5
VS_OUTPUT Rotation(in float4 position : POSITION ,
                     in float4 color: COLOR0)
{
  VS_OUTPUT Out = (VS_OUTPUT)0;
  Out.pos = mul(position, WorldViewProj); // Set position
  Out.color = color;                       // Set color
  return Out;
}

technique Transformation
{
   pass Pass0
   {
       VertexShader = compile vs_1_1 Rotation();
       PixelShader = NULL;
   }
}

                                                       6
         VertexDeclaration in HLSL
VertexDeclaration decl;
VertexElement[] velements = new VertexElement[]
 {
    new VertexElement(0, 0, DeclarationType.Float3,
DeclarationMethod.Default, DeclarationUsage.Position, 0),
   new VertexElement(0, 12, DeclarationType.Color,
DeclarationMethod.Default, DeclarationUsage.Color, 0),
    VertexElement.VertexDeclarationEnd
};
decl = new VertexDeclaration(device, velements)



 This is same as ASM shader definition

                                                            7
             Send Value to Shader
We need to send some values from application to GPU,
besides the Vertices information. One data must be sent is
the matrix that is the product of an object WorldMatrix,
ViewMatrix and ProjectionMatrix. If we have more than one
objects, then we need send more such matrix. If we want set
light in Shader, then we need to send the light direction
vector and the inverse matrix of object WorldMatrix. If we
want to do animation, then some dynamic data are also to be
sent. The basic usage is
effect.SetValue(object_name_in_HLSL, object_in_application)

 For example:
effect.SetValue("WorldViewProj", MatrixWorldViewProj)
                                                              8
         Some control code
CullMode = None;       // can be control in application
CullMode = ccw;
FillMode = WireFrame; // can be control in application
FillMode = solid;
Zenable = true;
ZWriteEnable = true;
ZFunc = less;
StencilEnable = false;
AlphaBlendEnable = false;
AlphaTestEnable = false;
ColorWriteEnable = red | green | blue;
Srcblend = One;
Destblend = One;

                                                          9
              Set Matrix Value
private void SetViewProjectPosition()
{
    Matrix matView = Matrix.LookAtLH(
       new Vector3( 0.0f, 2f, -5.0f ),
       new Vector3( 0.0f, 0.0f, 0.0f ),
       new Vector3( 0.0f, 1.0f, 0.0f )       );
    Matrix matProj = Matrix.PerspectiveFovLH(
       (float)Math.PI / 4.0f,
       (float)this.Width /(float)this.Height,
               1.0f,          1000.0f );
    float t = (float)Environment.TickCount/500f *Math.PI;
    Matrix matRot= Matrix.RotationY(t);
    Matrix worldViewProj = matRot * matView* matProj ;
    effect.SetValue("WorldViewProj", worldViewProj);
}
                                                        10
               One Pass Render
private void Render()
{      . . .. . . . .
    device.BeginScene();
    device.RenderState.CullMode = Cull.None ;
    effect.Technique = "Transformation";
    device.VertexDeclaration = decl;
    device.SetStreamSource(0, VB,0);
    effect.Begin(0);
    effect.BeginPass(0);
    device.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
    effect.EndPass();
    effect.End();
    device.EndScene();
    Device.Present();
}
                                                           11
         Multiple Passes Render
private void Render()
{
    ..........
    int numPasses = effect.Begin(0);
    for (int i = 0; i < numPasses; i++)
    {
       effect.BeginPass(i);
       device.DrawPrimitives( . . . . . . . . );
       effect.EndPass();
    }
    effect.End();
    .........
}

                                                   12
Output




         13
             HLSL with Texture
If we set texture data by code
  device.SetTexture(0, texture0);

Then in HLSL we can use
  sampler TextureSampler;

to get the image data. The pixel color will be

  color = tex2D(TextureSampler, textureCoords);


However, we must use a pixel operation function to get the
color. We won’t get Texture color in Vertex operation
function                                                     14
                     Example
sampler TextureSampler;    // input texture
float4x4 WorldViewProj : WORLDVIEWPROJECTION;
void Rotation( in float4 inputPosition : POSITION,
               in float2 inputTexCoord : TEXCOORD0,
               out float4 outputPosition : POSITION,
               out float2 outputTexCoord : TEXCOORD0)
{
       // Get position
    outputPosition = mul(inputPosition, WorldViewProj);
     outputTexCoord = inputTexCoord;
}

This function only gets the position of the vertex. Also it
output the texture coordinates outputTexCoord.
Any output could be used as the input of the next function.
                                                              15
textureCoords is the out put of the last function

void TextureColor( in float2 textureCoords : TEXCOORD0,
                     out float4 diffuseColor : COLOR0)
{
        // Get the texture color
   diffuseColor = tex2D(TextureSampler, textureCoords);
};

The pass will call two functions
technique TransformTexture
{
   pass P0
   {
       VertexShader = compile vs_1_1 Rotation();
       PixelShader = compile ps_1_1 TextureColor();
   }
}
                                                      16
Output




         17
   HLSL with Multiple Textures
It is easy to send multiple textures to HLSL by SetValue(…)
 Texture t1, t2, t3;

After loading them, use code
 effect.SetValue("Texture1", t1);
 effect.SetValue("Texture2", t2);
 effect.SetValue("Texture3", t3);
In HLSL, we set this way
Texture Texture1;
Texture Texture2;
Texture Texture3;
sampler samp1 = sampler_state
{       texture = <Texture1>; }
sampler samp2 = sampler_state
{       texture = <Texture2>; }
 sampler samp3 = sampler_state
{       texture = <Texture3>; }                               18
Texture Texture1;
Texture Texture2;
Texture Texture3;
sampler samp1 = sampler_state
{
    texture = <Texture1>;
    minfilter = LINEAR; mipfilter = LINEAR; magfilter = LINEAR;
};
sampler samp2 = sampler_state
{
    texture = <Texture2>;
    minfilter = LINEAR; mipfilter = LINEAR; magfilter = LINEAR;
};
 sampler samp3 = sampler_state
{
    texture = <Texture3>;
    minfilter = LINEAR; mipfilter = LINEAR; magfilter = LINEAR;
};
float4x4 WorldViewProj : WORLDVIEWPROJECTION;
float4 Alpha;
                                                            19
void Rotation( in float4 inputPosition    : POSITION,
                in float2 inputTexCoord : TEXCOORD0,
                out float4 outputPosition : POSITION,
                out float2 outputTexCoord : TEXCOORD0 )
{
     outputPosition = mul(inputPosition, WorldViewProj);
     outputTexCoord = inputTexCoord;
}
void TextureColor1( in float2 textureCoords : TEXCOORD0,
                     out float4 diffuseColor : COLOR0)
{
     diffuseColor = tex2D(samp1, textureCoords);
};




                                                           20
void TextureColor2(   in float2 textureCoords : TEXCOORD0,
                       out float4 diffuseColor : COLOR0)
{
     diffuseColor = tex2D(samp2, textureCoords);
};


void TextureColor3(   in float2 textureCoords : TEXCOORD0,
                       out float4 diffuseColor : COLOR0)
{
     diffuseColor = tex2D(samp3, textureCoords);
};




                                                             21
void TextureColor4(    in float2 textureCoords : TEXCOORD0,
                        out float4 diffuseColor : COLOR0)
{
     vector color1 = tex2D(samp1, textureCoords);
     vector color2 = tex2D(samp2, textureCoords);
     diffuseColor = color1*color2 ; // must ps_2_0 version
};
void TextureColor5(    in float2 textureCoords : TEXCOORD0,
                        out float4 diffuseColor : COLOR0)
{
     vector color1 = tex2D(samp1, textureCoords);
     diffuseColor = 1-color1;
};




                                                              22
void TextureColor6(     in float2 textureCoords : TEXCOORD0,
                         out float4 diffuseColor : COLOR0){
     vector color1 = tex2D(samp1, textureCoords);
     vector color2 = tex2D(samp2, textureCoords);
     diffuseColor = 0.9-(1-color1)*color2 ;
};
void TextureColor7(     in float2 textureCoords : TEXCOORD0,
                         out float4 diffuseColor : COLOR0){
     float4 a = float4(0.33f, 0.33f, 0.33f, 0.0f);
     vector color1 = tex2D(samp1, textureCoords);
     diffuseColor.xyz = dot(a, color1);
     diffuseColor.w=1.0;
};




                                                               23
void TextureColor8(     in float2 textureCoords : TEXCOORD0,
                         out float4 diffuseColor : COLOR0) {
     diffuseColor.x = textureCoords.x;
     diffuseColor.y = textureCoords.y;
     diffuseColor.z =0;
     diffuseColor.w = 1.0;
};
void TextureColor9(     in float2 textureCoords : TEXCOORD0,
                         out float4 diffuseColor : COLOR0) {
     vector color1 = tex2D(samp1, textureCoords);
     vector color2 = tex2D(samp2, textureCoords);
     diffuseColor = color1*Alpha + color2*(1-Alpha) ;
};




                                                               24
technique TransformTexture1{
   pass P0
   {
     VertexShader = compile vs_1_1 Rotation();
     PixelShader = compile ps_1_1 TextureColor1();
   }
}
technique TransformTexture2{
   pass P0
   {
     VertexShader = compile vs_1_1 Rotation();
     PixelShader = compile ps_1_1 TextureColor2();
   }
}
technique TransformTexture3{
   pass P0
   {
     VertexShader = compile vs_1_1 Rotation();
     PixelShader = compile ps_1_1 TextureColor3();
   }
}                                                    25
technique TransformTexture4{
   pass P0
   {
     VertexShader = compile vs_1_1 Rotation();
     PixelShader = compile ps_2_0 TextureColor4();
   }
}
technique TransformTexture5{
   pass P0
   {
     VertexShader = compile vs_1_1 Rotation();
     PixelShader = compile ps_1_1 TextureColor5();
   }
}
technique TransformTexture6{
   pass P0
   {
     VertexShader = compile vs_1_1 Rotation();
     PixelShader = compile ps_2_0 TextureColor6();
   }
}
                                                     26
technique TransformTexture7{
   pass P0
   {
     VertexShader = compile vs_1_1 Rotation();
     PixelShader = compile ps_1_1 TextureColor7();
   }
}
technique TransformTexture8{
   pass P0
   {
     VertexShader = compile vs_1_1 Rotation();
     PixelShader = compile ps_1_1 TextureColor8();
   }
}
technique TransformTexture9{
   pass P0
   {
     VertexShader = compile vs_1_1 Rotation();
     PixelShader = compile ps_2_0 TextureColor9();
   }
}
                                                     27
    Control code in application
protected override void OnKeyDown(KeyEventArgs e)
{
    if(e.KeyCode ==Keys.Up) flag--;
    if(e.KeyCode ==Keys.Down) flag++;
    if(flag==6) flag=1;
    if(flag==0) flag =5;
    if (flag==1)effect.Technique = "TransformTexture1";
    if(flag==2)effect.Technique = "TransformTexture2";
    if(flag==3)effect.Technique = "TransformTexture3";
    if(flag==4)effect.Technique = "TransformTexture4";
    if(flag==5)effect.Technique = "TransformTexture5";
    if(flag==6)effect.Technique = "TransformTexture6";
    if(flag==7)effect.Technique = "TransformTexture7";
    if(flag==8)effect.Technique = "TransformTexture8";
    if(flag==9)effect.Technique = "TransformTexture9";
}
                                                          28
              HLSL with Lights
All lights are applied to the last position of the 3D object.
However, in HLSL the object is in its original position.
Therefore we can either multiply the inverse of the world
matrix of the object to the lights direction or multiply world
matrix to the normal direction of the 3D object in HLSL.

The formula of the color is:

Color = lightColor*saturate(dot(lightDirection, objectNormal))

LastColor = Color *(1-ambient) +ambient)

Two directions lightDirection and objectNormal must be
normalized and in the same world coordinate system
                                                                 29
              HLSL Animation
 HLSL animation is exactly same as ASM shader animation.




    Mesh0          Mesh3            Mesh2                Mesh1
                    smile      right eyebrow down   left eyebrow down

   The animation formula is

mesh0+ a*(mesh1-mesh0)+ b*(mesh2-mesh0)+ g*(mesh3-mesh0)

  Here a, b and g are floating numbers between 0 and 1
                                                              30
   Declare Vertex Element for HLSL
VertexElement[] TweenElements = new VertexElement[]
{
 new VertexElement(0, 0, DeclarationType.Float3,
    DeclarationMethod.Default, DeclarationUsage.Position, 0),
 new VertexElement(0, 12, DeclarationType.Float3,
    DeclarationMethod.Default, DeclarationUsage.Normal, 0),
 new VertexElement(0, 24, DeclarationType.Float2,
  DeclarationMethod.Default, DeclarationUsage.TextureCoordinate, 0),
 new VertexElement(1, 0, DeclarationType.Float3,
    DeclarationMethod.Default, DeclarationUsage.Position, 1),
 new VertexElement(1, 12, DeclarationType.Float3,
   DeclarationMethod.Default, DeclarationUsage.Normal, 1),
 new VertexElement(1, 24, DeclarationType.Float2,
   DeclarationMethod.Default, DeclarationUsage.TextureCoordinate, 1)

                                                                       31
new VertexElement(2, 0, DeclarationType.Float3,
   DeclarationMethod.Default, DeclarationUsage.Position, 2),
new VertexElement(2, 12, DeclarationType.Float3,
    DeclarationMethod.Default, DeclarationUsage.Normal, 2),
new VertexElement(2, 24, DeclarationType.Float2,
    DeclarationMethod.Default, DeclarationUsage.TextureCoordinate, 2),
new VertexElement(3, 0, DeclarationType.Float3,
   DeclarationMethod.Default, DeclarationUsage.Position, 3),
new VertexElement(3, 12, DeclarationType.Float3,
    DeclarationMethod.Default, DeclarationUsage.Normal, 3),
new VertexElement(3, 24, DeclarationType.Float2,
    DeclarationMethod.Default, DeclarationUsage.TextureCoordinate, 3),
VertexElement.VertexDeclarationEnd
};
VertexDeclaration declaration ;
                                                                    32
                   Define Vertex Format
public struct Vertex   // preparing for shader
{
        public Vector3 p;
        public Vector3 n;
        public float tu, tv;
        public static readonly VertexFormats Format =
                VertexFormats.Position | VertexFormats.Normal |
                VertexFormats.Texture1;
}




                                                              33
    Create VertexBuffer that has vertex Format
private VertexBuffer CreateVertexBufferWithFormat(Mesh mesh)
{
     int total = mesh.NumberVertices ;
     Vertex[] src = (Vertex[])mesh.LockVertexBuffer(typeof(Vertex),
                  LockFlags.None, total);
     VertexBuffer VB = new VertexBuffer(typeof(Vertex), total ,
          device, Usage.WriteOnly, 0, Pool.Managed);
      Vertex[] dst = (Vertex[])VB.Lock(0, typeof(Vertex), 0, total);
      for(int k=0; k<total; k++) {        dst[k] = src[k]; }
      VB.Unlock();
      mesh.UnlockVertexBuffer();
      return VB;
}
                                                                   34
private void SetMesh()
 {
   ExtendedMaterial[] emtrl;
   Mesh0 = Mesh.FromFile("base.x", MeshFlags.Managed,
              device, out emtrl );
   materials = new Material[ emtrl.Length ];
   textures = new Texture[ emtrl.Length ];
   for(int i = 0; i < emtrl.Length; i++)
   {
   if (emtrl[i].TextureFilename != null)
   {
        textures[i] = TextureLoader.FromFile( device,
                 emtrl[i].TextureFilename);
   }
  mesh1 = Mesh.FromFile( "smile.x", MeshFlags.Managed, device);
  mesh2 = Mesh.FromFile( "l-ebrow-down.x", MeshFlags.Managed,
                    device);
  mesh3 = Mesh.FromFile( "l-ebrow-down.x", MeshFlags.Managed,
                   device);                                35
    VB0 = CreateVertexBufferWithFormat(mesh0);
    VB1 = CreateVertexBufferWithFormat(mesh1);
    VB2 = CreateVertexBufferWithFormat(mesh2);
    VB3 = CreateVertexBufferWithFormat(mesh3);
    GraphicsStream stream = VB0.Lock(0, mesh0.NumberVertices,
                                     LockFlags.None) ;
    radius =Geometry.ComputeBoundingSphere( stream,
                      mesh0.NumberVertices,
                      Vertex.Format,
                      out vCenter);
    Matrix S = Matrix.Scaling(4/radius, 4/radius, 4/radius);
    Matrx T = Matrix.Translation (-vCenter);
    worldMatrix = T*S;
    effect = Effect.FromFile(device, "HardwareHLSL.fx", null, null,
                            ShaderFlags.NotCloneable, null );
}                                                                     36
private void SetViewAndProjection()
{
    viewMatrix = Matrix.LookAtLH( new Vector3(0, 0, -8),
              new Vector3(0, 0, 0), new Vector3(0,1,0));
    projectionMatrix = Matrix.PerspectiveFovLH(
               (float)Math.PI / 4f,
               (float)this.Width / (float)this.Height,
               0.1f, 10000f );
    worldMatrix = T*S*rotationMatrix;
    Matrix mat = worldMatrix*viewMatrix * projectionMatrix;
    effect.SetValue( "WorldViewProjection", mat);
    effect.SetValue( "World", rotationMatrix );
}
                                                           37
protected override void OnMouseDown(MouseEventArgs e)
{
       if(e.Button ==MouseButtons.Right ) return;
       down = true;        lastX = e.X ; lastY = e.Y ;
}
protected override void OnMouseUp(MouseEventArgs e)
{      down = false;       }
protected override void OnMouseMove(MouseEventArgs e)
{
       if(!down) return;
       float dx = (float)(lastX - e.X) ;
       float dy = (float)(lastY - e.Y) ;
       lastX = e.X ; lastY = e.Y ;
      Matrix mat = Matrix.RotationYawPitchRoll(dx/80f,
                           dy/80f, 0.0f);
      rotationMatrix = mat*rotationMatrix;
}
                                                         38
public void SetWeight()
{
    float t1 = 1f;
    float t2 = 1.25f;
    float t3 = 1.5f;
    float time = (float) Environment.TickCount /400;
    Wight1 = (float)Math.Pow( Math.Sin( t1 * time), 2);
    Wight2 = (float)Math.Pow( Math.Sin( t2 * time), 2);
    Wight3 = (float)Math.Pow( Math.Sin( t3 * time), 2);
    effect.SetValue( "Weight1", Wight1 );
    effect.SetValue( "Weight2", Wight2 );
    effect.SetValue( "Weight3", Wight3 );
}
                                                          39
private void Render()
{
    device.Clear(ClearFlags.ZBuffer | ClearFlags.Target,
                0x000000ff, 1.0f, 0);
    AttributeRange[] attributes = mesh0.GetAttributeTable();
    device.BeginScene();
    SetWeight();
    SetViewAndProjection();
    device.SetStreamSource(0, VB0,0 );
    device.SetStreamSource(1, VB1,0 );
    device.SetStreamSource(2, VB2,0 );
    device.SetStreamSource(3, VB3, 0 );
    device.VertexDeclaration = declaration;
    effect.Technique = "Tween";
    device.Indices = mesh0.IndexBuffer;
    int numPasses = effect.Begin( FX.None );
                                                               40
    for (int pass = 0; pass < numPasses; pass++)
    {
         effect.BeginPass(pass);
         for( int i = 0; i < attributes.Length; i++)
         {
            effect.SetValue("Tex0", textures[i]);
            effect.SetValue("UseTexture", textures[i] != null );
            effect.SetValue("MaterialDiffuse",
                           ColorToVector4( materials[i].Diffuse ));
            effect.CommitChanges();
            device.DrawIndexedPrimitives( PrimitiveType.TriangleList,
                  0, attributes[i].VertexStart, attributes[i].VertexCount,
                 attributes[i].FaceStart * 3, attributes[i].FaceCount );
         }
         effect.EndPass();
    }
    effect.End();
    device.EndScene();
    device.Present();
                                                                       41
}
                       HLSL code
float4x4 WorldViewProjection; // World * View * Projection
float4x4 World;                  // World matrix
float3 LightDirection = { 0, 0.5f, -1 };
float4 MaterialDiffuse;
float Weight1;
float Weight2;
float Weight3;
bool UseTexture = false;
texture Tex0;
sampler Tex0Sampler = sampler_state
{
     Texture = <Tex0>;
     MinFilter = Linear;
     MagFilter = Linear;
     MipFilter = Linear;
};
                                                             42
struct VS_INPUT
{
   float4 position0     : POSITION0;
   float3 normal0       : NORMAL0;
   float2 tex0          : TEXCOORD0;
     float4 position1   : POSITION1;
     float3 normal1     : NORMAL1;
     float4 position2   : POSITION2;
     float3 normal2     : NORMAL2;
     float4 position3   : POSITION3;
     float3 normal3     : NORMAL3;
};
void ps( in float2 tex0          : TEXCOORD0 ,
         in float3 normal        : TEXCOORD1,
         out float4 color        : COLOR0 )
{
    if (UseTexture) { color = tex2D( Tex0Sampler, tex0 );}
   else               { color = MaterialDiffuse;  }
   color *= saturate(dot(LightDirection, normal));
};                                                           43
void vsTween( in VS_INPUT input,
                out float4 position : POSITION0,
                out float2 tex1       : TEXCOORD0,
                out float3 normal     : TEXCOORD1)
{
        float4 pos = input.position0;
        pos += (input.position1 - input.position0) * Weight1;
        pos += (input.position2 - input.position0) * Weight2;
        pos += (input.position3 - input.position0) * Weight3;
        position = mul(pos, WorldViewProjection);
       float3 nor = input.normal0;
       nor += (input.normal1 - input.normal0) * Weight1;
       nor += (input.normal2 - input.normal0) * Weight2;
       nor += (input.normal3 - input.normal0) * Weight3;
       normal = mul( nor, World );
       tex1 = input.tex0;
};


                                                                44
technique Tween
{
   pass P0
   {
      VertexShader = compile vs_2_0 vsTween();
      PixelShader = compile ps_2_0 ps();
    }
}




                                                 45

				
DOCUMENT INFO
Shared By:
Categories:
Tags:
Stats:
views:41
posted:9/2/2011
language:English
pages:45