PerPixel Lighting         A simple, everytime accurate per-pixel cg shader for Ogre, right out of box

For now, just quick and dirty :-)



Because I know how hard it was for me to get into this shader topic, I decided to post some here. First of all, the basics. The following lines will give you a simple, everytime accurate per-pixel cg shader for Ogre, right out of box.
Efficiency is traded for quality this time. If you want more FPS, things get more complicate. See links at the bottom of this page.

EDIT: I have added support for textures with this simple perpixel method. The same code can be used with the more advanced perpixel lighting from this tutorial, perpixel lighting part II.


Screen of tank model with Simple_Perpixel as shader and material

Shader: file

//The simplest (EXACT, see remarks) perpixel lighting I could do is:
 //(though it still supports ambient and specular terms, so it could still be simpler :)
 //Note: lighting is done in object-space, in the frag shader
 void Simple_Perpixel_Vert(
                        //ADDED BY EUGEN - support for texture with the per pixel lighting
                        float2 uv : TEXCOORD0,
                         float4 position : POSITION, 
                         float3 normal   : NORMAL,
                 //vert shader input
                         uniform float4 lightPosition,
             uniform float3 eyePosition,
                 //both in object space
                         uniform float4x4 worldviewproj, 
                         out float4 oClipPos    : POSITION,
                 //pass to clipping
             out float4 oPos    : TEXCOORD0,
             out float3 oNorm    : TEXCOORD1,
                         out float4 oLightPos    : TEXCOORD2,            
             out float3 oEyePos    : TEXCOORD3,
                        //ADDED BY EUGEN - support for texture with the per pixel lighting
                        out float2 oUv       : TEXCOORD4
                 //pass to frag shader
     oClipPos = mul(worldviewproj, position); 
     oPos = position;
     oNorm     = normal; 
     oLightPos = lightPosition;
     oEyePos = eyePosition;
        //ADDED BY EUGEN - support for texture with the per pixel lighting
        oUv = uv;
         //since we want exact calculations in every case,
         //calculate light and eye directions in frag shader,
         //don't let the rasterizer interpolate them from here
         //more costy than doing directions here, per-vertex, but
         //produces accurate lighting in VERY low tessellation cases,
         //light close to surface (for.ex. closer than poly size)
 void Simple_PerPixel_Frag(
                  float4 pos         : TEXCOORD0,
             float3 normal        : TEXCOORD1, 
              float4 lightpos        : TEXCOORD2,
             float3 eyepos        : TEXCOORD3,
                        //ADDED BY EUGEN - support for texture with the per pixel lighting
                        float2 uv        : TEXCOORD4,
             uniform float4 lightDiffuse,
             uniform float4 lightSpecular,
             uniform float exponent,
             uniform float4 ambient,
             uniform sampler2D texture,
                         out float4 oColor : COLOR 
     float3 N = normalize(normal);
         //we could do this normalize() in vert shader, or skip it
         //see some info at lighthouse3d GLSL explanations    
     float3 EyeDir = normalize(eyepos -;
     float3 LightDir = normalize( -  (pos * lightpos.w));
     float3 HalfAngle = normalize(LightDir + EyeDir);
     float NdotL = dot(LightDir, N);
     float NdotH = dot(HalfAngle, N);
     float4 Lit = lit(NdotL,NdotH,exponent);
     //cg docs say using their lit function is the fastest
        //ADDED BY EUGEN - support for texture with the per pixel lighting
        float3 textColour = expand(tex2D(texture, uv).xyz);
        //ADDED BY EUGEN - support for texture with the per pixel lighting
        oColor = lightDiffuse * Lit.y + lightSpecular * Lit.z + ambient + float4(textColour, 1);

Material: file ARNOLD.material

vertex_program Simple_Perpixel_Vert cg 
                  param_named_auto lightPosition light_position_object_space 0
         param_named_auto eyePosition camera_position_object_space
                  param_named_auto worldviewproj worldviewproj_matrix
       entry_point Simple_Perpixel_Vert 
       profiles vs_1_1 arbvp1 
 fragment_program Simple_PerPixel_Frag cg 
                  param_named_auto lightDiffuse light_diffuse_colour 0
         param_named_auto lightSpecular light_specular_colour 0
         param_named exponent float 127
             //VERY high value, to produce large highlights
         param_named ambient float4 0.0 0.0 0.0 1.0
             //faint environment lighting
       entry_point Simple_PerPixel_Frag
       profiles ps_2_0 arbfp1
 material Simple_Perpixel 
         // Base ambient pass, needing to avoid transparent artifacts
         // at for.ex. knot mesh
 //        pass
 //        {    
 //            vertex_program_ref Ambient
 //            {
 //            }
 //        }
             // do this for each light
 //            iteration once_per_light
 //            scene_blend add
                     vertex_program_ref Simple_Perpixel_Vert
                     fragment_program_ref Simple_PerPixel_Frag
                        //EUGEN - support for textures with the perpixel lighting
                                //use your own texture here, this is just an example
 //(uncomment lines to add multipass multilight support: plus you need Ambient vert shader  
 // from below, plus take out the ”+ambient” part of final color line in Simple_PerPixel_Frag)
 // And perhaps the file parser will complain if perpixel material is listed before ambient stuff
 // so you might list ambient things in the start of this file.
 void Ambient_vp(
         float4 position : POSITION,
           out float4 oPosition : POSITION,
           out float4 colour    : COLOR,
           uniform float4x4 worldViewProj,
           uniform float4 ambient)
     oPosition = mul(worldViewProj, position);
     colour = ambient;
 vertex_program Ambient cg
         param_named_auto worldViewProj worldviewproj_matrix
         param_named ambient float4 0.2 0.2 0.2 1.0
     entry_point Ambient_vp
     profiles vs_1_1 arbvp1


Don't ask why ARNOLD :-)
Forum username is: guilderstein
Contact: Send message in Ogre forums or mailto: forgamedev at AND insert "OGRE" in subject

PerPixel Lighting II - More adv. per-pixel method, lotsa theory
PerPixel Lighting With Offset(Parallax) Mapping - For nice bumps, with specular
The Monster - All-in-one deity, working with oFusion

Alias: PerPixel_Lighting