Instancing, Animation & Skinning

23.1 Instanced rendering

Draw thousands of copies with one call:

Alternatively, index an SSBO/texture with gl_InstanceID (or gl_InstanceIndex in Vulkan) for unlimited per-instance data.

layout (location = 0) in vec3 aPos;
layout (location = 4) in mat4 aInstanceModel;   // per-instance attribute (occupies locations 4–7)
layout (location = 8) in vec3 aInstanceColor;
out vec3 vColor;
void main() {
    vColor = aInstanceColor;
    gl_Position = uViewProj * aInstanceModel * vec4(aPos, 1.0);
}
glVertexAttribDivisor(4, 1);   // advance once per instance (repeat for locations 5, 6, 7, 8)
glDrawElementsInstanced(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, 0, instanceCount);

23.2 Skeletal animation (linear blend skinning)

Improvements: dual quaternion skinning (avoids "candy-wrapper" artifacts), bone matrices in SSBOs/textures for large skeletons or instanced crowds, compute-shader pre-skinning.

layout (location = 5) in ivec4 aBoneIDs;       // integer attribute: glVertexAttribIPointer!
layout (location = 6) in vec4 aBoneWeights;    // weights sum to 1
const int MAX_BONES = 128;
uniform mat4 uBones[MAX_BONES];                // final bone matrices (inverse bind × animated global)

void main() {
    mat4 skin = aBoneWeights.x * uBones[aBoneIDs.x]
              + aBoneWeights.y * uBones[aBoneIDs.y]
              + aBoneWeights.z * uBones[aBoneIDs.z]
              + aBoneWeights.w * uBones[aBoneIDs.w];
    vec4 skinnedPos = skin * vec4(aPos, 1.0);
    vec3 skinnedNormal = mat3(skin) * aNormal;
    gl_Position = uViewProj * uModel * skinnedPos;
    vNormal = mat3(uModel) * skinnedNormal;
}

23.3 Morph targets (blend shapes)

layout (location = 7) in vec3 aMorphDelta0;
layout (location = 8) in vec3 aMorphDelta1;
uniform vec2 uMorphWeights;
vec3 p = aPos + uMorphWeights.x * aMorphDelta0 + uMorphWeights.y * aMorphDelta1;

🧪 Part II Exercises

Render a rotating textured cube with MVP matrices passed as uniforms (and as a UBO).

Implement Blinn–Phong lighting with one directional light, two point lights, and a spotlight; add a toggle for Phong vs Blinn–Phong.

Add normal mapping with a TBN matrix; visualize world-space normals as colors for debugging.

Implement a skybox and a reflective/refractive sphere with Fresnel blending.

On Shadertoy, draw a smiley face using only 2-D SDFs and boolean operations, with anti-aliased edges.

Create animated clouds or marble using fBm and domain warping.

Build a post-processing chain: scene → bloom (bright pass + blur) → ACES tone mapping → gamma correction → vignette.

Implement shadow mapping with PCF for a directional light; tune bias to remove acne and peter-panning.

Render 10,000 instanced cubes with per-instance colors and transforms; compare with 10,000 individual draw calls.

Implement toon shading with outlines (inverted hull or Sobel on normals/depth).