Gordon Freeman is back! Half-Life 2 picks up some time after the original Half-Life left off, with Gordon Freeman working for the G-Man. Along with scientist Eli Vance and his daughter Alyx, your mission is to... well, that would be telling.

Report this article Source Shaders Tutorial

This short tutorial contains simple information on building shaders within the Source Engine for Half Life 2 mods.

Posted by justinms66 on Nov 6th, 2007 digg this super bookmark
Basic Client Side Coding.


I have been wanting to learn about shaders for source for a while now, but the content that was available to me (including the other shader tutorials here on moddb) was very confusing, so i decided to share what i found out.

Also this tutorial is about teaching, not giving out code, so please don't ask for it.


For the shader compile to work, you need to have Perl installed, so get ActivePerl and install it from here.

You will also need the DirectX SDK if you do not already, which you can get here
Add the include, bin, and library paths to your Visual Studio.
If you do not know how to do that:
go to Tools -> Options:
Tutorial Image
then go to Projects and Solutions -> VC++ Directories
Tutorial Image
and add your directX directories.
You can change from executables to includes or libraries by going here:
Tutorial Image

Navigate to:
~MOD_SOURCE~\materialsystem\stdshaders
and double click on
"stdshader_dx9-2005.sln"

now since the shaders were updated and the code was not, we first have to fix some things. We need to change the names of alot of the shader names to put an SDK in front of it.
the easiest way to do this is press "ctrl+F" (find)
enter in this for the "Find What" box
DEFINE_FALLBACK_SHADER|BEGIN_VS_SHADER\( [^S][^D][^K]
And set the rest of the params to look like this:
Tutorial Image
now keep pressing "Find Next", and with everything it finds, before the shader name, add "SDK_" (no quotes)
so for example:
BEGIN_VS_SHADER( Refract_DX90, "Help for Refract" )
would become
BEGIN_VS_SHADER( SDK_Refract_DX90, "Help for Refract" )



The very basics of what a shader is:

Shaders almost always have two parts:
Pixel Shaders - Modifies each rendered pixel
Vertex Shaders - Modifies each rendered vertex

Shaders can be programmed with several languages. The common ones are:
GLSL - OpenGL Shading Language (OpenGL)
HLSL - High Level Shader Language (DirectX)
now since we are using DirectX for the source engine, we will be programming in HLSL.

There are several types of shaders.
Post Process - shaders that simply affect the entire screen
Per Object - shaders that are applied to objects.

The basic shader structure is within 3 files:
TestShader_ps20.fxc - "ps" being "pixel shader", 20 being the shader version.
TestShader_vs20.fxc - "vs" being "vertex shader", 20 being the shader version.
TestShader.cpp - the shader configuration file.

TestShader.cpp is the only file that will be compiled with the stdshader solution that you should still have open. the .fxc files are separate and will take another technique to compile. However all of these files go in the same directory, the one you should still be in:
~MOD_SOURCE~\materialsystem\stdshaders



Some things to keep in mind while coding in HLSL

when using float2,float3...etc, that simply defines how many variables are held inside of it.
for example:

  1. code:
  1. float2 pos = {value_1, value_2};

now if i had 3 values in float2:

  1. code:
  1. float2 pos = {value_1, value_2, value_3};

it would return an error during compile, i would need to use

  1. code:
  1. float3 pos = {value_1, value_2, value_3};

now when getting values FROM a variable, you would use something like this:
say you wanted to get value_2 from a float3. there are multiple ways, all can work:

  1. code:
  1. float val = pos[0];
  2. float val = pos.x;

or i could EVEN get two of the 3 parameters

  1. code:
  1. float2 val = pos.xy;

that now holds:

  1. code:
  1. {value_1, value_2};

Now you can use tex2D or tex3D.... etc for sampling texture data. here are the major ones:
tex1D(s, t) - 1D texture lookup. s is a sampler. t is a scalar.
tex2D(s, t) 2D - texture lookup. s is a sampler. t is a 2D texture coordinate.
tex3D(s, t) 3D - volume texture lookup. s is a sampler. t is a 3D texture coordinate.
texCUBE(s, t) - Cubemap lookup. s is a sampler. t is a 3D texture coordinate.

[page=Shader Structure - Vertex Shader]
i am now editing "TestShader_vs20.fxc"

The main purpose of this file is sending the variables that you want to send, to the pixel shader.

the 1st line that you want in your vertex shader is

  1. code:
  1. #include "common_vs_fxc.h"

this adds the pre-designed shader functions and headers for ease of use.

now this part is easier to understand if you are familiar with structures of classes, no matter what language.

if we were coding in C++ this part would be in the ".h" file (just to give you some reference)
it is simply defining the variables, except with HLSL you don't define the functions as well. only the variables.

  1. code:
  1. struct VS_OUTPUT
  2. {
  3. float4 Pos : POSITION;
  4. float2 Tex : TEXCOORD0;
  5. };

pos is going to be the position of the vertex
tex is going to be the texture coordinate.

now we set the "Main()" function.

  1. code:
  1. VS_OUTPUT main(
  2. in float4 inPos : POSITION,
  3. in float3 inTex: TEXCOORD0
  4. )
  5. {  
  6. VS_OUTPUT Out = (VS_OUTPUT) 0;
  7. Out.Pos = inPos;
  8. Out.Tex = inTex;
  9. return Out;
  10. }

in the parenthesis of the function we set the variables we want. but we put a "in " before it.
then we define an output, set the variables of it, and return it (that goes to the pixel shader)



I am now editing "TestShader_ps20.fxc"

The main purpose of this file is to actually modify the screen however you wish.

the 1st line that you want in your pixel shader is

  1. code:
  1. #include "common_ps_fxc.h"

that IS a different file than the one we used for the vertex shader!!!
now right away we need to declare the sampler.

  1. code:
  1. sampler BaseTextureSampler: register( s0 );

you can use and manipulate more than 1 sampler, but for now i am just going to use 1.
now since i am going to be using the variable "Color" later on, i am going to define it up here

  1. code:
  1. float4 Color;

again, for this next part we are just going to declare the variable names:

  1. code:
  1. struct PS_INPUT
  2. {
  3. float2 Tex: TEXCOORD0;
  4. float4 Pos : POSITION;
  5. };

now lets get to the fun part

  1. code:
  1. float4 main( in float4 Pos : POSITION, in float3 Tex: TEXCOORD0) : COLOR
  2. {
  3. // your modification code will go here.
  4. }

inside the main() function parenthesis i again define the variables we are getting. put "in " before them again also.

and that is the basic structure, go on to the next part, which is making some effects!

[page=Shader Effects Examples]

Ok i will be workin only in the pixel shader, and only adding to the middle of the main() function, where i have:
// your modification code will go here.

BLUR

  1. code:
  1. Color = tex2D( BaseTextureSampler, Tex.xy);
  2. Color += tex2D(BaseTextureSampler, Tex.xy+0.001);
  3. Color += tex2D( BaseTextureSampler, Tex.xy+0.002);
  4. Color += tex2D( BaseTextureSampler, Tex.xy+0.003);
  5. Color = Color / 4;

what i have done here is added the coordinants of slightly off the current position to the current color and divided it by how many there are so that it averages out the brightness, creating a blur effect.

SEPIA

  1. code:
  1. float4 vWeightsBW=float4(0.3,0.59,0.11,0);
  2. float4 vWeightsSepia=float4(0.9,0.7,0.3,1);
  3. float4 cColor=tex2D(BaseTextureSampler,iTexCoord);
  4. float4 cTempColor=dot(cColor,vWeightsBW);
  5. return dot(cTempColor,vWeightsSepia);

RIPPLE / UNDERWATER EFFECT

  1. code:
  1. Tex.y = Texy + (sin(Tex.x*200)*0.01);
  2. float4 color = tex2D(BaseTextureSampler,Tex);
  3. return color;

I will be adding to this alot so hang tight!
also if i made an error or you want to add something, please do!!!

Comments
justinms66
justinms66 Dec 17 2007, 5:39pm says:

Yar

+1 vote     reply to comment
zalak
zalak Jun 2 2008, 2:18pm says:

yarb

+1 vote     reply to comment
Post a Comment

Only registered members can share their thoughts. So come on! Join the Mod DB community today (totally free) and do things you never thought possible.

Icon
Half-Life 2
Platforms
PC, X360, PS3, XBOX
Developer & Publisher
Valve
Engine
Source
Contact
Send Message
Official Page
Valvesoftware.com
Release Date
Released Nov 10, 2004
Game Watch
Track this game
Bookmark
Digg Super bookmark
Tutorial
Browse
Tutorials
Views
3,294 (11 today)
Report Abuse
Report this article
Bookmark
Digg Super bookmark
Related Games
Half-Life 2
Half-Life 2
Single & Multiplayer First Person Shooter
Related Engines
Source
Source
Commercial Released Nov 1, 2004
Related Groups
Valve
Valve
Development & Publishing company