PhongShader.cpp

In this article

Overview of the Phong shader source

The listing below is the complete source for PhongShader.cpp, a Sh shader class that builds a vertex program and a fragment program for per-fragment lighting. The vertex program prepares interpolated normals, a half-vector, texture coordinates, and irradiance; the fragment program combines them into a texture-mapped Blinn-Phong shading result.

Vertex program

#include "Globals.hpp"
#include "PhongShader.hpp"
using namespace SH;
PhongShader::PhongShader()
{
}
PhongShader::~PhongShader()
{
}
void PhongShader::init()
{
  vsh = SH_BEGIN_VERTEX_PROGRAM {
    // declare input vertex parameters
    // unpacked in order given
    ShInputTexCoord2f ui;       // texture coords
    ShInputNormal3f normal;     // normal vectors (MCS)
    ShInputPosition4f pm;          // poisition (MCS)
    // declare output vertex parameters
    // packed in order given
    ShOutputVector3f hv;        // half-vector (VCS)
    ShOutputTexCoord2f uo = ui; // texture coords
    ShOutputNormal3f nv;        // normal (VCS)
    ShOutputColor3f ec;         // irradiance
    ShOutputPosition4f pd;         // position (HDCS)
    // compute VCS position
    ShPoint3f pv = (Globals::mv | pm)(0,1,2);
    // compute DCS position
    pd = Globals::mvp | pm;
    // compute normalized VCS normal
    ShNormal3f nvt = normalize(Globals::mv | normal)(0,1,2);
    nv = nvt;
    // compute normalized VCS light vector
    ShVector3f lvv = Globals::lightPos - pv;
    ShAttrib1f rsq = ShConstant1f(1.0)/(lvv|lvv);
    lvv *= sqrt(rsq);
    // compute irradiance
    ShAttrib1f ct = (nvt | lvv);
    ct *= ct > ShAttrib1f(0.0);
    ec = ShColor3f(1.0, 1.0, 1.0) * ct;
    // compute normalized VCS view vector
    ShVector3f vvv = -normalize(pv);
    // compute normalized VCS half vector
    hv = normalize(lvv + vvv);
  } SH_END_PROGRAM;
  fsh = SH_BEGIN_FRAGMENT_PROGRAM {
    // declare input fragment parameters
    // unpacked in order given
    ShInputVector3f hv;   // half-vector (VCS)
    ShInputTexCoord2f u;  // texture coordinates
    ShInputNormal3f nv;   // normal (VCS)
    ShInputColor3f ec;    // irradiance
    ShInputPosition3f pdxy; // fragment position (DCS)
    // Declare output fragment parameters
    // packed in order given
    ShOutputColor3f fc;            // fragment color
    // compute texture-mapped Blinn-Phong model
    fc = (Globals::color
          + ShAttrib3f(1.0, 1.0, 1.0) * (dot(normalize(hv), normalize(nv)) ^ Globals::exponent)) * ec;
  } SH_END_PROGRAM;
}

Fragment program and shader application

void PhongShader::apply(void) { shBindShader(vsh); shBindShader(fsh); } void PhongShader::vertex(const SH::ShPoint4f& n, // normal const SH::ShPoint4f& t, // tangent const SH::ShPoint4f& tex, // texture // coordinates const SH::ShPoint4f& t2, // secondary tangent const SH::ShPoint4f& v // vertex ) { pushSmAttrib(tex); pushSmAttrib(n); pushSmVertex(v); } // Instantiate the shader PhongShader phongShader;

Frequently Asked Questions

What lighting model does this Phong shader implement?

The fragment program computes a texture-mapped Blinn-Phong model, combining an ambient color term with a specular term based on the dot product of the normalized half-vector and normal raised to the configured exponent, multiplied by the interpolated irradiance.

What does the vertex program compute?

It transforms the position into view and device coordinate spaces, normalizes the view-space normal, computes the light vector and its squared distance, derives irradiance from the clamped normal-light dot product, and produces the normalized half-vector of the light and view directions.

Which inputs does the shader accept?

The vertex entry point accepts a normal, tangent, texture coordinates, a secondary tangent, and a vertex position; the shader pushes texture coordinates, the normal, and the vertex into the pipeline.

How is the shader bound and instantiated?

The apply method binds the vertex and fragment programs with shBindShader, and a global PhongShader phongShader; instance is created at the end of the file.

Where do the lighting parameters come from?

Color, exponent, light position, and the model-view and model-view-projection matrices are read from the shared Globals structure referenced by the shader.