PhongShader.cpp
In this article
- What the Phong shader source implements
- Vertex program: normals, light vector, and irradiance
- Fragment program: the Blinn-Phong lighting model
- Applying and instantiating the shader
- Frequently asked questions
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.
