Skip to content

Custom Shaders (Advanced)

BoHHavoc edited this page Feb 3, 2013 · 7 revisions

General

Basic syntax of a custom shader:
Properties
Custom Vertex-/Pixelshader In-/Outputs
#include <scHeaderObject>
custom code
#include <scObject>

Example:
#define SKIN_ABLEDO <skin1.xyz>
#define SKIN_NORMAL <skin2.xyz>
#define NORMALMAPPING

#include <scHeaderObject>

#define CUSTOM_VS_POSITION
#ifndef MATWORLD
#define MATWORLD
float4x4 matWorld;
#endif
#ifndef MATWORLDVIEWPROJ
#define MATWORLDVIEWPROJ
float4x4 matWorldViewProj;
#endif
#ifndef VECTIME
#define VECTIME
float4 vecTime;
#endif
#ifndef VECSKILL1
#define VECSKILL1
float4 vecSkill1;
#endif
float4 Custom_VS_Position(vsIn In)
{
float3 P = mul(In.Pos, matWorld);
float force_x = vecSkill1.x;
float force_y = vecSkill1.y;
float speed = sin((vecTime.w+0.2*(P.x+P.y+P.z)) * vecSkill1.z);

if (In.Pos.y > 0 ) // move only upper part of tree
{
In.Pos.x += speed * force_x * In.Pos.y;
In.Pos.z += speed * force_y * In.Pos.y;
In.Pos.y -= 0.1*abs(speed*(force_x+force_y)) * In.Pos.y;
}

return mul(In.Pos,matWorldViewProj);
}

#include <scObject>

When writing your own code, ALWAYS USE
#ifndef X
#define X
put your variable here
#endif
everytime you introduce a global variable. The Ubershader already contains a bunch of generic variables like float3x3 matTangent and float4x4 matWorldView etc. . To make sure you don't double define a variable, or are suddenly missing a variable when a Shade-C Update removes a variable from it's ubershader, use the above mentioned defines.

Naming convention is to just write the variable you want to introduce in CAPITAL letters when checking the defines.

Example:
#ifndef MATTANGENT
#define MATTANGENT
float3x3 matTangent;
#endif

This might seem like more work at first, but will save you A LOT of trouble later on!

Properties

General

TARGET_VS target

Set the vertexshader target. Default is vs_2_0.
Note: Some Ati/Amd cards don't support different pixel- and vertexshadertargets. You should therefor always set pixel and vertexshader to the same target.

Example:
#define TARGET_VS vs_2_0


TARGET_PS target

Set the pixelshader target. Default is ps_2_a.
Note: Some Ati/Amd cards don't support different pixel- and vertexshadertargets. You should therefor always set pixel and vertexshader to the same target.

Example:
#define TARGET_PS ps_2_a


ZPREPASS

Renders a Z-PrePass for the Object, which MIGHT speed up the rendering. This makes sense for heavy shaders like parallax occlusion mapping and the likes. On the other hand, it MIGHT slow down rendering if you actiavte this for fast/small shaders. If you are unsure, just give it a try and see if performance gets better or worse ;)

Example:
#define ZPREPASS


Skins

SKIN1 name

Set the skin that skin1 is mapped to. Default is #define SKIN1 entSkin1

Example:
#define SKIN1 entSkin1 //use entity skin1
#define SKIN1 mtlSkin1 //use material skin1
#define SKIN1 entSkin3 //use entity skin3, very uncommon, but possible


SKIN2 name

Set the skin that skin2 is mapped to. Default is #define SKIN2 entSkin2

Example:
#define SKIN2 entSkin2 //use entity skin2, common
#define SKIN2 mtlSkin2 //use material skin2, uncommmon
#define SKIN2 entSkin3 //use entity skin3, very uncommon, but possible


SKIN3 name

Set the skin that skin3 is mapped to. Default is #define SKIN3 entSkin3

Example:
#define SKIN3 entSkin3 //use entity skin3, common
#define SKIN3 mtlSkin3 //use material skin3, uncommmon
#define SKIN3 entSkin1 //use entity skin1, very uncommon, but possible


SKIN4 name

Set the skin that skin4 is mapped to. Default is #define SKIN4 entSkin4

Example:
#define SKIN4 entSkin4 //use entity skin4, common
#define SKIN4 mtlSkin4 //use material skin4, uncommmon
#define SKIN4 entSkin3 //use entity skin3, very uncommon, but possible


NO_SKIN1

If set, skin1 won't be accesible in the shader.
Use this to speed up the shader a bit if you don't need skin1 access.


NO_SKIN2

If set, skin2 won't be accesible in the shader.
Use this to speed up the shader a bit if you don't need skin2 access.


NO_SKIN3

If set, skin3 won't be accesible in the shader.
Use this to speed up the shader a bit if you don't need skin3 access.


NO_SKIN4

If set, skin4 won't be accesible in the shader.
Use this to speed up the shader a bit if you don't need skin4 access.


Hook-Ups

In-/Output Structs

struct vsIn
{
float4 Pos : POSITION;
half2 Tex : TEXCOORD0;
half2 TexShadow : TEXCOORD1;
half3 Normal : NORMAL;
#ifdef NORMALMAPPING
half4 Tangent: TEXCOORD2;
#endif
#ifdef BONES
int4 BoneIndices: BLENDINDICES;
float4 BoneWeights: BLENDWEIGHT;
#endif
#ifdef CUSTOM_VS_INPUT_EXTEND
CUSTOM_VS_INPUT_EXTEND
#endif
};

struct vsOut
{
float4 Pos : POSITION;
float Pos2D : TEXCOORD0;
float4 Tex : TEXCOORD1;
float3 Normal : TEXCOORD2;
#ifdef NORMALMAPPING
float3 Tangent : TEXCOORD3;
float3 Binormal : TEXCOORD4;
#endif
#ifdef CUSTOM_VS_OUTPUT_EXTEND
CUSTOM_VS_OUTPUT_EXTEND
#endif
};

struct psOut
{
float4 NormalsAndDepth : COLOR0;
half4 AlbedoAndEmissiveMask : COLOR1;
float4 MaterialData : COLOR2;
//float4 lightmapAnd : COLOR3;

#ifdef CUSTOM_PS_OUTPUT_EXTEND
CUSTOM_PS_OUTPUT_EXTEND
#endif
};

If you want to extend the In-/Outputs, define CUSTOM_VS_INPUT_EXTEND (addition) , CUSTOM_VS_OUTPUT_EXTEND (addition) or CUSTOM_PS_OUTPUT_EXTEND (addition). You should always use the highest available texcoord (which is TEXCOORD7) for your extension, as future Shade-C updates might introduce more used TEXCOORDs.

Examples:
//Correct
#define CUSTOM_VS_OUTPUT_EXTEND (
float4 myCustomOutput1 : TEXCOORD7;
float4 myCustomOutput2 : TEXCOORD6;
)

//Incorrect
#define CUSTOM_VS_OUTPUT_EXTEND (
float4 myCustomOutput1 : TEXCOORD5;
float4 myCustomOutput2 : TEXCOORD6;
)

Also, You have to define your custom In-/Outputs BEFORE including scHeaderObject!

Example:
#define CUSTOM_VS_OUTPUT_EXTEND (
float4 myCustomOutput1 : TEXCOORD7;
float4 myCustomOutput2 : TEXCOORD6;
)
#include <scHeaderObject>
custom code goes here
#include <scObject>

VertexShader:

#define CUSTOM_VS_POSITION

float4 Custom_VS_Position(vsIn In)


#define CUSTOM_VS_TEX

float2 Custom_VS_Tex(vsIn In)


#define CUSTOM_VS_TEXSHADOW

float Custom_VS_TexShadow(vsIn In)


#define CUSTOM_VS_NORMAL

float3 Custom_VS_Normal(vsIn In) //return in View Space! ( return mul(output, matWorldView) )


#define CUSTOM_VS_TANGENT

float3 Custom_VS_Tangent(vsIn In) //return in View Space! ( return mul(output, matWorldView) )


#define CUSTOM_VS_BINORMAL

float3 Custom_VS_Binormal(In) //return in View Space! ( return mul(output, matWorldView) )


#define CUSTOM_VS_EXTEND

Extends the VertexShader. Out will hold all data which has been processed so far.
vsOut Custom_VS_Extend(vsIn In, vsOut Out)


PixelShader:

#define CUSTOM_PS_TEX

float4 Custom_PS_Tex(vsOut In)
Custom Texcoords. XY is used to fetch the model's skins. ZW is used to fetch the static shadowmap (not implemented yet).


#define CUSTOM_PS_SKIN1

half4 Custom_PS_Skin1(vsOut In)


#define CUSTOM_PS_SKIN2

half4 Custom_PS_Skin2(vsOut In)


#define CUSTOM_PS_SKIN3

half4 Custom_PS_Skin3(vsOut In)


#define CUSTOM_PS_SKIN4

half4 Custom_PS_Skin4(vsOut In)


#define CUSTOM_PS_ALPHA

half Custom_PS_Alpha(vsOut In, half skinAlpha)


#define CUSTOM_PS_NORMALMAPPING

half3 Custom_PS_Normalmapping(vsOut In, half3 skinNormals); //Note: skinNormals are in range 0..1!


#define CUSTOM_PS_DEPTH

float Custom_PS_Depth(vsOut In) //Depth should be linear


#define CUSTOM_PS_DIFFUSE

half3 Custom_PS_Diffuse(vsOut In, half3 skinAlbedo)


#define CUSTOM_PS_COLOR

half3 Custom_PS_Color(vsOut In, half3 skinColor)


#define CUSTOM_PS_EMISSIVEMASK

half3 Custom_PS_EmissiveMask(vsOut In, half skinEmissiveMask)


#define CUSTOM_PS_MATERIALID

float Custom_PS_MaterialID(vsOut In) //range 0..1


#define CUSTOM_PS_SPECULARPOWER

float Custom_PS_SpecularPower(vsOut In) //range 0..1


#define CUSTOM_PS_GLOSS

half Custom_PS_Gloss(vsOut In, half skinGloss)


#define CUSTOM_PS_EXTEND

Extends the PixelShader. Out will hold all data which has been processed so far.
psOut Custom_PS_Extend(vsOut In, psOut Out)