shader lib

i was working with shaders and i know this can help you as a guide to write correct lighting calculations:

/*********************************************************************NVMH3****
Path:  NVSDK\Common\media\programs
File:  fixed_function.cg

Copyright 2003 by NVIDIA Corporation

TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED
*AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL NVIDIA OR ITS SUPPLIERS
BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES
WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS)
ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF NVIDIA HAS
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.


******************************************************************************/

//======================================================================
//======================================================================
//======================================================================
//
//                  fixed_function.cg
// A cg program demonstrating the fixed function OpenGL pipeline
//
//  This file defines the connectors and functional components
//    that can be combined to produce the same transform, lighting,
//    and texturing available from the fixed function pipeline
//
//======================================================================
//======================================================================
//======================================================================

//======================================================================
//======================================================================
//                       Connectors                                     
//
//  The connectors used in this example are simplified versions of those
//  provided by the Cg Standard Library.
//======================================================================
//======================================================================

//======================================================================
//                                                 Application -> Vertex
// Vertex Programs inputs, 
//
// Define inputs from application
//  although your texture coordinates may only be 2D it is still
//  safe to use 4 vectors here
//======================================================================

struct appin
{
	float4 VPos    : POSITION;       // model space vertex position 
	float4 VWeight : BLENDWEIGHT;    // weights for skinning (u,1-u)
	float4 Norm    : NORMAL;         // model space vertex normal
	float4 PCol    : COLOR0;         // primary color (diffuse)
	float4 SCol    : COLOR1;         // seconary color (specular)
	float4 PSize   : PSIZE0;         // point size
	float4 Tex0    : TEXCOORD0;      // texture coordinate set 0
	float4 Tex1    : TEXCOORD1;      // texture coordinate set 1
	float4 Tex2    : TEXCOORD2;      // texture coordinate set 2
	float4 Tex3    : TEXCOORD3;      // texture coordinate set 3
};

//======================================================================
//                                                    Vertex -> Fragment
// Define outputs from vertex shader
//======================================================================

struct vertout
{
	float4 HPos    : POSITION;      // homogeneous clip space postion
	float4 PCol    : COLOR0;        // primary (diffuse) color
	float4 SCol    : COLOR1;        // secondary (specular) color
	float  Fog     : FOG;           // fog factor
	float  PSize   : PSIZE;         // point size
	float4 Tex0    : TEXCOORD0;     // texture coordinate set 0
	float4 Tex1    : TEXCOORD1;     // texture coordinate set 1
	float4 Tex2    : TEXCOORD2;     // texture coordinate set 2
	float4 Tex3    : TEXCOORD3;     // texture coordinate set 3
};

//======================================================================
//  Uniform GL inputs
//    These map the "standard" gl state for our vertex programs
//======================================================================

// GL Matricies, bound to constant registers for tracking
struct cgglMatrix{
	uniform float4x4 ModelViewProj :C0; //Projection * Modelview matrix
	uniform float4x4 ModelViewIT   :C4; //Modelview inverse transform
	uniform float4x4 ModelView     :C8; //Modelview matrix
};

// GL Material
struct cgglMaterial{
	uniform float4   DiffMat;       //Diffuse material
	uniform float4   SpecMat;       //Specular material
	uniform float4   AmbMat;        //Ambient material
	uniform float4   ShineMat;      //Shininess material, specular power
	uniform float4   EmisMat;       //Emissive material
};

// GL Lights
struct cgglLight{
	uniform float4   LightVec;      //Light direction
	uniform float4   LightPos;      //Light position
	uniform float4   DiffLight;     //Diffuse light
	uniform float4   SpecLight;     //Specular light
	uniform float4   AmbLight;      //Ambient light
	uniform float3   AttenLight;    //the attenuation terms: constant, linear, quadradic
	uniform float2   SpotLight;     //spot light parameters: cos(spot cuttoff angle), spot power
};

// GL Texture transforms
struct cgglTexture{
	uniform float4   TexPlaneX;    //Texture planes for texture 0
	uniform float4   TexPlaneY;
	uniform float4   TexPlaneZ;
	uniform float4   TexPlaneW;
	uniform float4x4 TexMatrix;    //Texture matrix for texture 0
	uniform float4x4 TexIMV;       //Texture inverse modelview for eye-linear texgen mode
};

//======================================================================
//======================================================================
//                       Function defintions:
//
//    While these functions can be called directly, they were designed
//     only to serve as examples, as they may not produce the most
//    optimal vertex programs.
//======================================================================
//======================================================================


//======================================================================
//                        Lighting
//======================================================================

//======================================================================
//   Point light and local viewer shading model
//======================================================================

float4 light_point_view_local(float3 epos,         //the eye space vertex position
							  float3 norm,         //the vertex normal
							  cgglLight    lt,     //the light
							  cgglMaterial mat)    //the material
{
	
	float3 vert2light = lt.LightPos.xyz - epos;  //vector from vertex to the light
	float d = length(vert2light);         //distance between the two, need this for attenuation
	float3 ldir = vert2light/d;           //light direction
	float3 vdir = normalize(-epos);       //view direction, redundent for multiple lights
	float3 halfv = normalize(ldir + vdir); //halfway vector
	
	// Compute the diffuse and specular coefficients
	//  the diffuse cosine is in coeffs.y, the specular is in coeffs.z
	float4 coeffs = lit(dot(norm,ldir), dot(norm,halfv), mat.ShineMat.x);
	
	// Compute the standard shading model
	float4 outCol = 1/(lt.AttenLight.x + d*lt.AttenLight.y + d*d*lt.AttenLight.z) *   //attenuation term
		                 (lt.AmbLight*mat.AmbMat +                       //ambient term
				  lt.DiffLight*mat.DiffMat*coeffs.y +            //diffuse term
				  lt.SpecLight*mat.SpecMat*coeffs.z);            //specular term
	
	return outCol;	
}

//======================================================================
//   Spot light and local viewer shading model
//======================================================================

float4 light_spot_view_local(float3 epos,         //the eye space vertex position
							 float3 norm,         //the vertex normal
							 cgglLight    lt,
							 cgglMaterial mat)
{
	
	float3 vert2light = lt.LightPos.xyz - epos;  //vector from vertex to the light
	float d = length(vert2light);         //distance between the two, need this for attenuation
	float3 ldir = vert2light/d;           //light direction
	float3 vdir = normalize(-epos);       //view direction, redundent for multiple lights
	float3 half = normalize(ldir + vdir); //halfway vector
	
	// Compute the diffuse and specular coefficients
	float4 coeffs = lit(dot(norm,ldir), dot(norm,half), mat.ShineMat.x);
	
	// Compute spotlight effect
	float3 lightDir = normalize(lt.LightVec.xyz);
	float spotDot = dot(ldir, -lightDir);
	float4 spot  = lit(spotDot - lt.SpotLight.x, spotDot, lt.SpotLight.y);
	
	// Compute the standard shading model
	float4 outCol = 1/(lt.AttenLight.x + d*lt.AttenLight.y + d*d*lt.AttenLight.z) *   //attenuation term
		                 (lt.AmbLight*mat.AmbMat +                       //ambient term
				  lt.DiffLight*mat.DiffMat*coeffs.y +            //diffuse term
				  lt.SpecLight*mat.SpecMat*coeffs.z);            //specular term
	
	return outCol;	
}


//======================================================================
//   Directional light and local viewer shading model
//======================================================================

float4 light_directional_view_local(float3 epos,         //the eye space vertex position
									float3 norm,         //the vertex normal
									cgglLight    lt,     //the light
									cgglMaterial mat)    //the material
{
	float3 vdir = normalize(-epos);
	float3 lightDir = normalize(lt.LightVec.xyz);
	float3 half = normalize(vdir - lightDir);
	
	float4 coeffs = lit(dot(norm, - lightDir), dot(norm,half),mat.ShineMat.x);
	
	// Compute the standard shading model
	float4 outCol = lt.AmbLight*mat.AmbMat +               //ambient term
		lt.DiffLight*mat.DiffMat*coeffs.y +            //diffuse term
		lt.SpecLight*mat.SpecMat*coeffs.z;             //specular term
	return outCol;
}

//======================================================================
//   Directional light and infinite viewer shading model
//======================================================================

float4 light_directional_view_inf(float3 norm,         //the vertex normal
								  cgglLight lt,
								  cgglMaterial mat)
{
	float3 lightDir = normalize(lt.LightVec.xyz);
	
	float3 vdir = {0,0,1};
	float3 half = normalize(vdir - lightDir);
	
	float4 coeffs = lit(dot(norm, - lightDir), dot(norm,half),mat.ShineMat.x);
	
	// Compute the standard shading model
	float4 outCol = lt.AmbLight*mat.AmbMat +               //ambient term
		lt.DiffLight*mat.DiffMat*coeffs.y +            //diffuse term
		lt.SpecLight*mat.SpecMat*coeffs.z;             //specular term
	return outCol;
}

//======================================================================
//   A trimed down point light, not part of the standard OGL pipeline
//======================================================================

float4 light_simple_point(float3 epos,
						  float3 norm,
						  float3 lightPos,
						  float4 materialColor,
						  float4 ambientColor,
						  float4 lightColor,
						  float  specPower)
{
	float3 vdir = {0,0,1};
	float3 ldir = normalize(lightPos - epos);
	float3 half = normalize(vdir + ldir);
	float4 coeffs = lit(dot(norm, ldir), dot(norm, half), specPower);
	
	float4 outCol = ambientColor + 
		materialColor*lightColor*coeffs.y +
		lightColor*coeffs.z;
	return outCol;
	
}


//======================================================================
//                       Texture Generation
//======================================================================

//======================================================================
//  Object linear texture generation
//======================================================================

float4 texgen_object(float4   vpos,      //object space vertex position
					 cgglTexture tex)
{
	float4 tcoord;
	
	//create texcoord based on texture planes                   
	tcoord.x = dot(vpos, tex.TexPlaneX);    
	tcoord.y = dot(vpos, tex.TexPlaneY);
	tcoord.z = dot(vpos, tex.TexPlaneZ);
	tcoord.w = dot(vpos, tex.TexPlaneW);
	
	//multiply by texture matrix
	tcoord = mul(tex.TexMatrix, tcoord); 
	
	return tcoord; 
}

//======================================================================
//  Eye linear texture generation
//    Texgen for eye space requires the inverse model view present
//    when glTexGen is invoked.  It may be more efficient to include
//    this matrix in the texture matrix.  
//======================================================================

float4 texgen_eye(float4   epos,      // eye space vertex position
				  cgglTexture tex)
{
	float4 temp;
	float4 tcoord;
	
	//multiply by inverse model view for the texgen 
	temp = mul(tex.TexIMV, epos);
	
	//create texcoord based on texture planes                   
	tcoord.x = dot(temp, tex.TexPlaneX);    
	tcoord.y = dot(temp, tex.TexPlaneY);
	tcoord.z = dot(temp, tex.TexPlaneZ);
	tcoord.w = dot(temp, tex.TexPlaneW);
	
	
	//multiply by texture matrix
	tcoord = mul(tex.TexMatrix, tcoord); 
	
	return tcoord; 
}

//======================================================================
//   Sphere Map texture generation
//======================================================================

float4 texgen_sphere(float4 epos, 
					 float3 norm,
					 cgglTexture tex)
{
	float3 vdir = normalize(epos.xyz);
	
	float3 ref = reflect(vdir, norm);
	
	float3 em = ref + float3(0,0,1);
	em.x = 2 * sqrt(dot(em, em));
	
	float4 tcoord = {0,0,0,1};
	
	tcoord.xy = ref.xy/em.x + .5;
	
	return tcoord;
}

//======================================================================
//======================================================================
//======================================================================
//                   Shaders
//======================================================================
//======================================================================
//======================================================================


//======================================================================
//======================================================================
//======================================================================
//  The "main_point_local" entry point function
//    Shows rendering with a Point light source and a local viewer
//======================================================================
//======================================================================
//======================================================================

vertout main_point_local(appin IN,
						 uniform cgglMatrix mx,
						 uniform cgglMaterial mat,
						 uniform cgglLight lt,
						 uniform cgglTexture tex)
{
	vertout OUT;  // You must create a "vertex2fragment" structure 
	
	//------------------------------------------------------------
	// First, set the homogeneous eye-space position of the vertex
	// and compute the eye-space position for lighting etc..
	//------------------------------------------------------------
	OUT.HPos    = mul(mx.ModelViewProj, IN.VPos);  //The homogeneous vertex position
	float4 EPos = mul(mx.ModelView, IN.VPos);      //The eye-space vertex position
	
	//------------------------------------------------------------
	// Transform the normal from object-space to eye-space
	//    We will do all of our lighting in eye-space
	//------------------------------------------------------------
	float3 normal = normalize( mul( (float3x3)mx.ModelViewIT, IN.Norm.xyz ) );
	
	OUT.Tex0 = IN.Tex0;
	OUT.Tex1 = IN.Tex1;
	OUT.Tex2 = IN.Tex2;
	OUT.Tex3 = IN.Tex3;
	
	// Call the light                      eye      normal light material
	float4 color = light_point_view_local(EPos.xyz, normal, lt,    mat);
	
	OUT.PCol = color + mat.EmisMat;  //be sure to add the emissive color separate from the light
	
	return OUT;
}

//======================================================================
//======================================================================
//======================================================================
//  The "main_spot_local" entry point function
//    Shows rendering with a Spotlight and a local viewer
//======================================================================
//======================================================================
//======================================================================

vertout main_spot_local(appin IN,
						uniform cgglMatrix mx,
						uniform cgglMaterial mat,
						uniform cgglLight lt,
						uniform cgglTexture tex)
{
	vertout OUT;  // You must create a "vertex2fragment" structure 
	
	//------------------------------------------------------------
	// First, set the homogeneous eye-space position of the vertex
	// and compute the eye-space position for lighting etc..
	//------------------------------------------------------------
	OUT.HPos    = mul(mx.ModelViewProj, IN.VPos);  //The homogeneous vertex position
	float4 EPos = mul(mx.ModelView, IN.VPos);      //The eye-space vertex position
	
	//------------------------------------------------------------
	// Transform the normal from object-space to eye-space
	//    We will do all of our lighting in eye-space
	//------------------------------------------------------------
	float3 normal = normalize( mul( (float3x3)mx.ModelViewIT, IN.Norm.xyz ) );
	
	OUT.Tex0 = IN.Tex0;
	OUT.Tex1 = IN.Tex1;
	OUT.Tex2 = IN.Tex2;
	OUT.Tex3 = IN.Tex3;
	
	float4 color = light_spot_view_local(EPos.xyz, normal, lt, mat);    
	
	OUT.PCol = color + mat.EmisMat; //be sure to add the emissive color separate from the light  
	
	return OUT;
}

//======================================================================
//======================================================================
//======================================================================
//  The "main_directional_local" entry point function
//    Shows rendering with a Directional light and a local viewer
//======================================================================
//======================================================================
//======================================================================

vertout main_directional_local(appin IN,
							   uniform cgglMatrix mx,
							   uniform cgglMaterial mat,
							   uniform cgglLight lt,
							   uniform cgglTexture tex)
{
	vertout OUT;  // You must create a "vertex2fragment" structure 
	
	//------------------------------------------------------------
	// First, set the homogeneous eye-space position of the vertex
	// and compute the eye-space position for lighting etc..
	//------------------------------------------------------------
	OUT.HPos    = mul(mx.ModelViewProj, IN.VPos);  //The homogeneous vertex position
	float4 EPos = mul(mx.ModelView, IN.VPos);      //The eye-space vertex position
	
	//------------------------------------------------------------
	// Transform the normal from object-space to eye-space
	//    We will do all of our lighting in eye-space
	//------------------------------------------------------------
	float3 normal = normalize( mul( (float3x3)mx.ModelViewIT, IN.Norm.xyz ) );
	
	OUT.Tex0 = IN.Tex0;
	OUT.Tex1 = IN.Tex1;
	OUT.Tex2 = IN.Tex2;
	OUT.Tex3 = IN.Tex3;
	
	float4 color = light_directional_view_local(EPos.xyz, normal, lt, mat);
	
	OUT.PCol = color + mat.EmisMat;
	
	return OUT;
}

//======================================================================
//======================================================================
//======================================================================
//  The "main_directional_inf" entry point function
//    Shows rendering with a Directional light and a infinite viewer
//======================================================================
//======================================================================
//======================================================================

vertout main_directional_inf(appin IN,
							 uniform cgglMatrix mx,
							 uniform cgglMaterial mat,
							 uniform cgglLight lt,
							 uniform cgglTexture tex)
{
	vertout OUT;  // You must create a "vertex2fragment" structure 

	//------------------------------------------------------------
	// First, set the homogeneous eye-space position of the vertex
	// and compute the eye-space position for lighting etc..
	//------------------------------------------------------------
	OUT.HPos    = mul(mx.ModelViewProj, IN.VPos);  //The homogeneous vertex position
	
	//------------------------------------------------------------
	// Transform the normal from object-space to eye-space
	//    We will do all of our lighting in eye-space
	//------------------------------------------------------------
	float3 normal = normalize( mul( (float3x3)mx.ModelViewIT, IN.Norm.xyz ) );
	
	OUT.Tex0 = IN.Tex0;
	OUT.Tex1 = IN.Tex1;
	OUT.Tex2 = IN.Tex2;
	OUT.Tex3 = IN.Tex3;
	
	float4 color = light_directional_view_inf(normal, lt, mat);
	
	OUT.PCol = color + mat.EmisMat;
	
	return OUT;
}

//======================================================================
//======================================================================
//======================================================================
//  The "main_simple_point" entry point function
//    Shows rendering with a Simplified point light
//======================================================================
//======================================================================
//======================================================================

vertout main_simple_point(appin IN,
						  uniform cgglMatrix mx,
						  uniform cgglMaterial mat,
						  uniform cgglLight lt,
						  uniform cgglTexture tex)
{
	vertout OUT;  // You must create a "vertex2fragment" structure 
	
	//------------------------------------------------------------
	// First, set the homogeneous eye-space position of the vertex
	// and compute the eye-space position for lighting etc..
	//------------------------------------------------------------
	OUT.HPos    = mul(mx.ModelViewProj, IN.VPos);  //The homogeneous vertex position
	float4 EPos = mul(mx.ModelView, IN.VPos);      //The eye-space vertex position
	
	//------------------------------------------------------------
	// Transform the normal from object-space to eye-space
	//    We will do all of our lighting in eye-space
	//------------------------------------------------------------
	float3 normal = normalize( mul( (float3x3)mx.ModelViewIT, IN.Norm.xyz ) );
	
	OUT.Tex0 = IN.Tex0;
	OUT.Tex1 = IN.Tex1;
	OUT.Tex2 = IN.Tex2;
	OUT.Tex3 = IN.Tex3;
	
	OUT.PCol = light_simple_point(EPos.xyz, normal, lt.LightPos.xyz, 
		IN.PCol, mat.AmbMat,  lt.DiffLight, mat.ShineMat.x);    
	
	return OUT;
}

//======================================================================
//======================================================================
//======================================================================
//  The "main_texgen_eye" entry point function
//    Shows rendering with eye-linear
//======================================================================
//======================================================================
//======================================================================

vertout main_texgen_eye(appin IN,
						uniform cgglMatrix mx,
						uniform cgglMaterial mat,
						uniform cgglLight lt,
						uniform cgglTexture tex)
{
	vertout OUT;  // You must create a "vertex2fragment" structure 
	
	//------------------------------------------------------------
	// First, set the homogeneous eye-space position of the vertex
	// and compute the eye-space position for lighting etc..
	//------------------------------------------------------------
	OUT.HPos    = mul(mx.ModelViewProj, IN.VPos);  //The homogeneous vertex position
	float4 EPos = mul(mx.ModelView, IN.VPos);      //The eye-space vertex position
	
	//------------------------------------------------------------
	// Transform the normal from object-space to eye-space
	//    We will do all of our lighting in eye-space
	//------------------------------------------------------------
	float3 normal = normalize( mul( (float3x3)mx.ModelViewIT, IN.Norm.xyz ) );
	
	OUT.Tex0 = texgen_eye(EPos, tex);
	OUT.Tex1 = IN.Tex1;
	OUT.Tex2 = IN.Tex2;
	OUT.Tex3 = IN.Tex3;
	
	OUT.PCol = light_simple_point(EPos.xyz, normal, lt.LightPos.xyz, 
		IN.PCol, mat.AmbMat,  lt.DiffLight, mat.ShineMat.x);    
	
	return OUT;
}

//======================================================================
//======================================================================
//======================================================================
//  The "main_texgen_object" entry point function
//    Shows rendering with object-linear texture generation
//======================================================================
//======================================================================
//======================================================================

vertout main_texgen_object(appin IN,
						   uniform cgglMatrix mx,
						   uniform cgglMaterial mat,
						   uniform cgglLight lt,
						   uniform cgglTexture tex)
{
	vertout OUT;  // You must create a "vertex2fragment" structure 
	
	//------------------------------------------------------------
	// First, set the homogeneous eye-space position of the vertex
	// and compute the eye-space position for lighting etc..
	//------------------------------------------------------------
	OUT.HPos    = mul(mx.ModelViewProj, IN.VPos);  //The homogeneous vertex position
	float4 EPos = mul(mx.ModelView, IN.VPos);      //The eye-space vertex position
	
	//------------------------------------------------------------
	// Transform the normal from object-space to eye-space
	//    We will do all of our lighting in eye-space
	//------------------------------------------------------------
	float3 normal = normalize( mul( (float3x3)mx.ModelViewIT, IN.Norm.xyz ) );
	
	OUT.Tex0 = texgen_object(IN.VPos, tex);
	OUT.Tex1 = IN.Tex1;
	OUT.Tex2 = IN.Tex2;
	OUT.Tex3 = IN.Tex3;
	
	OUT.PCol = light_simple_point(EPos.xyz, normal, lt.LightPos.xyz, 
		IN.PCol, mat.AmbMat,  lt.DiffLight, mat.ShineMat.x);    
	
	return OUT;
}

//======================================================================
//======================================================================
//======================================================================
//  The "main_texgen_sphere" entry point function
//    Shows rendering with object-linear texture generation
//======================================================================
//======================================================================
//======================================================================

vertout main_texgen_sphere(appin IN,
						   uniform cgglMatrix mx,
						   uniform cgglMaterial mat,
						   uniform cgglLight lt,
						   uniform cgglTexture tex)
{
	vertout OUT;  // You must create a "vertex2fragment" structure 
	
	//------------------------------------------------------------
	// First, set the homogeneous eye-space position of the vertex
	// and compute the eye-space position for lighting etc..
	//------------------------------------------------------------
	OUT.HPos    = mul(mx.ModelViewProj, IN.VPos);  //The homogeneous vertex position
	float4 EPos = mul(mx.ModelView, IN.VPos);      //The eye-space vertex position
	
	//------------------------------------------------------------
	// Transform the normal from object-space to eye-space
	//    We will do all of our lighting in eye-space
	//------------------------------------------------------------
	float3 normal = normalize( mul( (float3x3)mx.ModelViewIT, IN.Norm.xyz ) );
	
	OUT.Tex0 = texgen_sphere(IN.VPos, normal, tex);
	OUT.Tex1 = IN.Tex1;
	OUT.Tex2 = IN.Tex2;
	OUT.Tex3 = IN.Tex3;
	
	OUT.PCol = light_simple_point(EPos.xyz, normal, lt.LightPos.xyz, 
		IN.PCol, mat.AmbMat,  lt.DiffLight, mat.ShineMat.x);    
	
	return OUT;
}

Please add any more shader functions that you find useful.

Thanks! I love writing shaders and this will definitely help the process of integrating it into my panda games…thanks for sharing!

Wow. Thanks for sharing, Treeform! :wink: I can sure use this in my shaders, if I may.