Game Development Community

dev|Pro Game Development Curriculum

A Basic Shader

by Anthony Rosenbaum · 06/17/2004 (10:05 pm) · 8 comments

I decided to finally test my knowledge of shaders and actually write one, nothing special but something quick and able too see a change, not to mention to get accustomed to the attribute variables used in TSE that can be passed into the Shaders.

Now for anyone who has already read many articles on Shading this will not be so important. However in several months when we have people who do not know the basics of shaders, well they might find this post interesting.

This is a red shader, inspired by The Cg Tutorial first example. BTW I never have read any HLSL books but Cg and HLSL are similar (designed in tandem with each other) so code from that book can be ported easily.

First off there is always 2 shaders Vertex and Pixel ( aka Fragment)

This Vertex shader does nothing but change the vertex coordinates ( received from the game engine, we call these attribute variables) and multiply it my the modelview matrix ( also an attribute variable)

#define IN_HLSL
#include "shdrConsts.h"

//---------------------------------------------------------------
// Constants
//---------------------------------------------------------------
struct Appdata
{
    float4 position        : POSITION;
    float4 texCoord        : TEXCOORD0;

};
struct Conn
{
   float4 HPOS             : POSITION;
   float2 outTexCoord     : TEXCOORD0;

};
//---------------------------------------------------------------
// Main
//---------------------------------------------------------------
Conn main( Appdata In, uniform float4x4 modelview : register(VC_WORLD_PROJ),
			     uniform float4x4 texMat          : register(VC_TEX_TRANS1)

 )
{
   Conn Out;

   //take vert and get coord by transforming by modelviewmatrix
   Out.HPOS = mul(modelview, In.position);
   //set base texture coord
   Out.outTexCoord = mul(texMat, In.texCoord);
   return Out;
}
save that as redShaderV.HLSL
then the Pixel Shader which take the base texture color and add red to it
//--------------------------------------------------------------
//Structures                                                    
//--------------------------------------------------------------
struct ConnectData
{
   float2 texCoord      : TEXCOORD0;

};
struct Fragout
{
   float4 col : COLOR0;
};
//--------------------------------------------------------------
//Main                                                          
//--------------------------------------------------------------
Fragout main(ConnectData IN,  uniform sampler2D baseTex      : register(S0)
)
{
   Fragout OUT;
   //uses the base textures' color to set difuse color
   float4 diffuseColor = tex2D( baseTex, IN.texCoord );
   //use enhance the diffuse with another color, red in this case
   float4 someColor = float4(1.0, 0.0, 0.0, 1.0);
   OUT.col = diffuseColor * someColor;
   return OUT;
}
save that as redShaderP.HLSL

open up shader.cs add this at the bottom
datablock ShaderData( redShader )
{
   DXVertexShaderFile 	= "shaders/redShaderV.hlsl";
   DXPixelShaderFile 	= "shaders/redShaderP.hlsl";
   pixVersion = 1.1;
};

then in material add this at the bottom
datablock CustomMaterial( aRedShader )
{
   texture[0] =  "demo/data/shapes/spaceOrc/orc_ID1_skin";
   shader = redShader;
   version = 1.1;

};
Finally add change the binding of the SpaceOrc

#1
08/18/2004 (2:35 am)
This isnt working for me.
No matter what I do, the orc is black, or flashes between black and his texture.
#2
08/26/2004 (8:03 am)
Did everything compile? Check the console.
#3
01/23/2005 (11:00 am)
Excellent resource! I was trying to figure out how to use this and this resource filled in the missing steps!
#4
03/24/2005 (8:53 pm)
sorry.. seems very fundamental.. what's the meaning of "datablock" keyword you added in shader.cs and material.cs? and what does it do?
#5
10/20/2005 (3:58 am)
A datablock is a chunk of data that can be used as a prototype to create objects, which makes them all come out the same, as well as being easier to edit.
The name or the datablock is in parens.
#6
12/05/2006 (6:18 pm)
"Finally add change the binding of the SpaceOrc"

Huh?
#7
08/05/2007 (7:20 pm)
"Finally add change the binding of the SpaceOrc"

Nice, another potentially useful resource that falls apart because the author couldn't be bothered to elaborate on a crucial step.

*sigh*
#8
08/28/2007 (1:04 am)
Got this to work again.

First change the word datablock to new in the last 2 code boxes. eg. new shaderData( and new CustomMaterial(

In the final code block change the texture to

new CustomMaterial( aRedShader )
{
mapTo = "Orc_Material";
texture[0] = "~/data/shapes/SpaceOrc/Orc_Material";
shader = redShader;
version = 1.1;
};