GlowBalloon CG Shader        

So one day I was looking for shaders to use in my game involving cells when I came across this shader. Unfortunately it was a CGFX shader and ogre does not support .cgfx shaders. So I had to convert it to .cg.

It's not really that hard, actually, and this is coming from someone with next to zero shader knowledge. Just keep the manual pages close to hand :P


The original shader. Note that I've removed the "#ifndef" stuff since it doesn't apply and everything between <angled brackets> because those are just stuff from the WYSIWYG editor (since it came with FX Composer).
I suggest you remove these too since they help clean up the code a lot :P

You can download the original shader here.

Original Shader
// transform object vertices to world-space:
// world_matrix
float4x4 gWorldXf : World;
// transform object normals, tangents, & binormals to world-space:
// inverse_transpose_world_matrix
float4x4 gWorldITXf : WorldInverseTranspose;
// transform object vertices to view space and project them in perspective:
// worldviewproj_matrix
float4x4 gWvpXf : WorldViewProjection;
// provide tranform from "view" or "eye" coords back to world-space:
// inverse_view_matrix
float4x4 gViewIXf : ViewInverse;

// color and depth used for full-screen clears

float4 gClearColor = {0,0,0,0};

float gClearDepth = 1.0;

/************* TWEAKABLES **************/

float gInflate = 0.06;

float3 gGlowColor = {1.0f, 0.9f, 0.3f};

float gGlowExpon = 1.3;


/* data from application vertex buffer */
struct appdata {
    float3 Position	: POSITION;
    float4 UV		: TEXCOORD0;
    float4 Normal	: NORMAL;
    float4 Tangent	: TANGENT0;
    float4 Binormal	: BINORMAL0;

/* data passed from vertex shader to pixel shader */
struct gloVertOut {
    float4 HPosition	: POSITION;
    float3 WorldNormal	: TEXCOORD0;
    float3 WorldView	: TEXCOORD1;

/*********** vertex shader ******/

gloVertOut gloBalloon_VS(appdata IN,
    uniform float Inflate,
    uniform float4x4 WorldITXf, // our four standard "untweakable" xforms
	uniform float4x4 WorldXf,
	uniform float4x4 ViewIXf,
	uniform float4x4 WvpXf
) {
    gloVertOut OUT = (gloVertOut)0;
    OUT.WorldNormal = mul(WorldITXf,IN.Normal).xyz;
    float4 Po = float4(,1);
    Po += (Inflate*normalize(float4(,0))); // the balloon effect
    float4 Pw = mul(WorldXf,Po);
    OUT.WorldView = normalize(float3(ViewIXf[0].w,ViewIXf[1].w,ViewIXf[2].w) -;
    OUT.HPosition = mul(WvpXf,Po);
    return OUT;

/********* pixel shaders ********/

float4 gloBalloon_PS(gloVertOut IN,
    uniform float3 GlowColor,
    uniform float GlowExpon
) : COLOR {
    float3 Nn = normalize(IN.WorldNormal);
    float3 Vn = normalize(IN.WorldView);
    float edge = 1.0 - dot(Nn,Vn);
    edge = pow(edge,GlowExpon);
    float3 result = edge * GlowColor.rgb;
    return float4(result,edge);

/// TECHNIQUES ////////////////////////

technique Main {
    pass GlowPass {
        VertexProgram = compile vp40 gloBalloon_VS(gInflate,gWorldITXf,gWorldXf,
		DepthTestEnable = true;
		DepthMask = true;
		BlendEnable = true;
		BlendFunc = int2(SrcAlpha,OneMinusSrcAlpha);
		CullFaceEnable = true;
		DepthFunc = LEqual;
        FragmentProgram = compile fp40 gloBalloon_PS(gGlowColor,gGlowExpon);

Then I made three files,,, and glowBalloon.material. We need to split up this cgfx file into those three.

Also because I don't know how to use structs I just removed them and replaced the structs with the arguments the shader needed.
void main(float3 Position : POSITION,
		    float4 Normal : NORMAL,
			uniform float Inflate,
			uniform float4x4 WorldITXf, // our four standard "untweakable" xforms
			uniform float4x4 WorldXf,
			uniform float4x4 ViewIXf,
			uniform float4x4 WvpXf,
			out float4 HPosition : POSITION,
			out float3 WorldNormal : TEXCOORD0,
			out float3 WorldView : TEXCOORD1
) {
    WorldNormal = mul(WorldITXf, Normal).xyz;
    float4 Po = float4(, 1);
    Po += (Inflate * normalize(float4(, 0))) * Normal; // the balloon effect
    float4 Pw = mul(WorldXf, Po);
    WorldView = normalize(float3(ViewIXf[0].w, ViewIXf[1].w, ViewIXf[2].w) -;
    HPosition = mul(WvpXf, Po);
float4 main(float3 WorldNormal : TEXCOORD0,
			float3 WorldView : TEXCOORD1,
			uniform float3 GlowColor,
			uniform float GlowExpon
			) : COLOR
    float3 Nn = normalize(WorldNormal);
    float3 Vn = normalize(WorldView);
    float edge = 1.0 - dot(Nn, Vn);
    edge = pow(edge, GlowExpon);
    float3 result = edge * GlowColor.rgb;
    return float4(result, edge);

There, that wasn't too hard! So now just comes the material.

We need to specify the fragment/vertex programs and tell ogre they exist, along with giving them their arguments.
This is where the manual comes in handy ;D
Then we just have to write the material, reference the shaders, and try to make our material match the one at the bottom of the original shader.

vertex_program glowBalloon_vs cg {
	entry_point main
	profiles vs_2_0 arbvp1 vs_2_x vs_3_0 vp40
	default_params {
		param_named 	 Inflate   float 0.06
		param_named_auto WorldITXf inverse_transpose_world_matrix
		param_named_auto WorldXf   world_matrix
		param_named_auto ViewIXf   inverse_view_matrix
		param_named_auto WvpXf     worldviewproj_matrix

fragment_program glowBalloon_ps cg {
	entry_point main
	profiles ps_2_0 arbfp1 ps_2_x ps_3_0 ps_3_x fp40
	default_params {
		param_named GlowColor float3 1.0 1.0 1.0
		param_named GlowExpon float  1.3

material cg/balloon_glow {
	technique {
		pass {
			scene_blend src_alpha one_minus_src_alpha
			depth_check on
			depth_func less_equal
			lighting off
			vertex_program_ref glowBalloon_vs {
				param_named Inflate float 0.1
			fragment_program_ref glowBalloon_ps {
				param_named GlowColor float3 0.0 1.0 0.0
				param_named GlowExpon float  1.3


- Pyritie

Alias: GlowBalloon_CG_Shader