Element/Shader: Difference between revisions

From Multi Theft Auto: Wiki
Jump to navigation Jump to search
No edit summary
Line 46: Line 46:
Here is an Effect File containing a vertex and pixel shader:
Here is an Effect File containing a vertex and pixel shader:
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
//---------------------------------------------------------------------
//-- Variables
//---------------------------------------------------------------------
//-- Declare the textures. These are set using dxSetShaderValue( shader, "Tex0", texture )
//-- Declare the textures. These are set using dxSetShaderValue( shader, "Tex0", texture )
texture Tex0;
texture Tex0;
Line 61: Line 65:




//-- Samplers for the textures are needed for pixel shaders
//---------------------------------------------------------------------
//-- Sampler for the main texture (needed for pixel shaders)
//---------------------------------------------------------------------
sampler Sampler0 = sampler_state
sampler Sampler0 = sampler_state
{
{
     Texture   = (Tex0);
     Texture = (Tex0);
};
};


sampler Sampler1 = sampler_state
 
//---------------------------------------------------------------------
//-- Structure of data sent to the vertex shader
//---------------------------------------------------------------------
struct VSInput
{
{
     Texture  = (Tex1);
     float4 Position : POSITION;
    float4 Diffuse  : COLOR0;
    float2 TexCoord0: TEXCOORD0;
};
};


 
//---------------------------------------------------------------------
//-- Vertex shader output structure for transfer of info from vertex to pixel shader
//-- Structure of data sent to the pixel shader ( from the vertex shader )
struct VS_OUTPUT_Yeah
//---------------------------------------------------------------------
struct PSInput
{
{
    float4 Pos  : POSITION;
  float4 Position : POSITION0;
    float4 Diffuse : COLOR0;
  float4 Diffuse : COLOR0;
    float2 TexCoord0: TEXCOORD0;
  float2 TexCoord : TEXCOORD0;
};
};


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-- Name: VS_Example
//-- VertexShaderExample
//-- Type: Vertex shader
//-- 1. Read from VS structure
//-- Desc: Transform vertices and output
//-- 2. Process
//--  3. Write to PS structure
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
VS_OUTPUT_Yeah VS_Example(
PSInput VertexShaderExample(VSInput VS)
      float3 InPos          : POSITION
    , float4 InDiffuse      : COLOR0
    , float2 InTexCoord0    : TEXCOORD0
    )
{
{
     VS_OUTPUT_Yeah Out = (VS_OUTPUT_Yeah)0;
     PSInput PS = (PSInput)0;
 
    //-- Transform vertex position (You nearly always have to do something like this)
    PS.Position = mul(float4(VS.Position, 1), WorldViewProjection);


     Out.Pos = mul(float4(InPos, 1), WorldViewProjection);
     //-- Copy the color and texture coords so the pixel shader can use them
     Out.Diffuse = InDiffuse;
     PS.Diffuse = VS.Diffuse;
     Out.TexCoord0 = InTexCoord0;
     PS.TexCoord = VS.TexCoord;
     return Out;
 
     return PS;
}
}




//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-- Name: PS_Example
//-- PixelShaderExample
//-- Type: Pixel shader
//-- 1. Read from PS structure
//-- Desc: Calculates the pixel color based on texture lookup and interpolated vertex color
//-- 2. Process
//--  3. Return pixel color
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
float4 PS_Example(
float4 PixelShaderExample(PSInput PS) : COLOR0
    VS_OUTPUT_Yeah In
    ) : COLOR
{
{
     //-- Example of using Time for animation
     //-- Modify the texture coord to make the image look all wobbly
     In.TexCoord0.y += sin(In.TexCoord0.y * 100 + Time * 10)*0.03;
     PS.TexCoord.y += sin(PS.TexCoord.y * 100 + Time * 10) * 0.03;
 
    //-- Grab the pixel from the texture
    float4 finalColor = tex2D(Sampler0, PS.TexCoord);
 
    //-- Apply color tint
    finalColor = finalColor * PS.Diffuse;


     return tex2D(Sampler0, In.TexCoord0) * In.Diffuse;
     return finalColor;
}
}




Line 129: Line 148:
     pass P0
     pass P0
     {
     {
         VertexShader = compile vs_2_0 VS_Example();
         VertexShader = compile vs_2_0 VertexShaderExample();
         PixelShader  = compile ps_2_0 PS_Example();
         PixelShader  = compile ps_2_0 PixelShaderExample();
     }
     }
}
}
Line 154: Line 173:
     }
     }
}
}
</syntaxhighlight>
</syntaxhighlight>



Revision as of 14:07, 20 October 2011

The shader class represents a Microsoft HLSL Effect File(.fx) loaded by the client, which can be used instead of an texture when calling dxDrawImage

The element type of this class is "shader".

How HLSL Effect Files file integrate into MTA:SA

Note: This assumes you know what an Effect File and HLSL is. If not, you had better do some research first.

You can use this shadertest resource to try the examples below. Copy the effect source from the code boxes into shadertest/clientshader.fx and (re)start shadertest to see the output.

After you've done all that, (or maybe before if glancing below is making you panic), visit here to see some more shader resource examples.

Techniques

Effect Files usually contain several techniques, but for simplicity, MTA will only use the first technique that will run correctly on the clients hardware. So, for any given Effect File, put your high end techniques first, and the simplest ones last. That way, players with good hardware get the best technique applied, and players with older hardware get at least something.

Simplest

Here is the contents of an Effect File with one technique which should work on all hardware:

//-- Declare the textures. These are set using dxSetShaderValue( shader, "Tex0", texture )
texture Tex0;
texture Tex1;

//-- Very simple technique
technique simple
{
    pass P0
    {
        //-- Set up texture stage 0
        Texture[0] = Tex0;
        ColorOp[0] = SelectArg1;
        ColorArg1[0] = Texture;
        AlphaOp[0] = SelectArg1;
        AlphaArg1[0] = Texture;
            
        //-- Disable texture stage 1
        ColorOp[1] = Disable;
        AlphaOp[1] = Disable;
    }
}

It doesn't use vertex or pixel shaders, only standard D3D render states. Confusing reference of all the states you can set is here: http://msdn.microsoft.com/en-us/library/bb173347%28v=VS.85%29.aspx

Not so simple

Here is an Effect File containing a vertex and pixel shader:


//---------------------------------------------------------------------
//-- Variables
//---------------------------------------------------------------------
//-- Declare the textures. These are set using dxSetShaderValue( shader, "Tex0", texture )
texture Tex0;
texture Tex1;

//-- Declare a user variable. This can be set using dxSetShaderValue( shader, "PositionOfCheese", 1, 2, 3 )
float3 PositionOfCheese;

//-- These variables are set automatically by MTA
float4x4 World;
float4x4 View;
float4x4 Projection;
float4x4 WorldViewProjection;
float Time;


//---------------------------------------------------------------------
//-- Sampler for the main texture (needed for pixel shaders)
//---------------------------------------------------------------------
sampler Sampler0 = sampler_state
{
    Texture = (Tex0);
};


//---------------------------------------------------------------------
//-- Structure of data sent to the vertex shader
//---------------------------------------------------------------------
struct VSInput
{
    float4 Position : POSITION;
    float4 Diffuse  : COLOR0;
    float2 TexCoord0: TEXCOORD0;
};

//---------------------------------------------------------------------
//-- Structure of data sent to the pixel shader ( from the vertex shader )
//---------------------------------------------------------------------
struct PSInput
{
  float4 Position : POSITION0;
  float4 Diffuse  : COLOR0;
  float2 TexCoord : TEXCOORD0;
};


//-----------------------------------------------------------------------------
//-- VertexShaderExample
//--  1. Read from VS structure
//--  2. Process
//--  3. Write to PS structure
//-----------------------------------------------------------------------------
PSInput VertexShaderExample(VSInput VS)
{
    PSInput PS = (PSInput)0;

    //-- Transform vertex position (You nearly always have to do something like this)
    PS.Position = mul(float4(VS.Position, 1), WorldViewProjection);

    //-- Copy the color and texture coords so the pixel shader can use them
    PS.Diffuse = VS.Diffuse;
    PS.TexCoord = VS.TexCoord;

    return PS;
}


//-----------------------------------------------------------------------------
//-- PixelShaderExample
//--  1. Read from PS structure
//--  2. Process
//--  3. Return pixel color
//-----------------------------------------------------------------------------
float4 PixelShaderExample(PSInput PS) : COLOR0
{
    //-- Modify the texture coord to make the image look all wobbly
    PS.TexCoord.y += sin(PS.TexCoord.y * 100 + Time * 10) * 0.03;

    //-- Grab the pixel from the texture
    float4 finalColor = tex2D(Sampler0, PS.TexCoord);

    //-- Apply color tint
    finalColor = finalColor * PS.Diffuse;

    return finalColor;
}


//-----------------------------------------------------------------------------
//-- Techniques
//-----------------------------------------------------------------------------

//--
//-- MTA will try this technique first:
//--
technique complercated
{
    pass P0
    {
        VertexShader = compile vs_2_0 VertexShaderExample();
        PixelShader  = compile ps_2_0 PixelShaderExample();
    }
}

//--
//-- And if the preceding technique will not validate on
//-- the players computer, MTA will try this one:
//--
technique simple
{
    pass P0
    {
        //-- Set up texture stage 0
        Texture[0] = Tex0;
        ColorOp[0] = SelectArg1;
        ColorArg1[0] = Texture;
        AlphaOp[0] = SelectArg1;
        AlphaArg1[0] = Texture;
            
        //-- Disable texture stage 1
        ColorOp[1] = Disable;
        AlphaOp[1] = Disable;
    }
}

Technique 'complercated' will be used if the computer supports Shader Model 2, otherwise technique 'simple' will be used. Comments in the source explain what MTA does and where.

Misc

Points to remember when switching between editing lua and .fx files:

  • HLSL statements often end with a ; (semi-colon)
  • HLSL indices start from 0 (where as Lua usually starts from 1)
  • HLSL compile errors can be viewed by typing 'debugscript 3' into the client console

Related scripting functions

Client