Point Light

14 / 17
Learn core lighting terms (diffuse/specular/rim) on a simple sphere.

This tutorial extends directional lighting with two new ideas: the light has a position, and it gets weaker with distance. The key lines are:

Let's break each part down.


Directional light vs. point light

A directional light has only a direction — every pixel on the canvas receives light from the exact same angle, like sunlight.

A point light has a position. Each pixel computes a different direction toward the light source, and pixels farther away receive less light — like a candle that's bright up close and fades into darkness.


Light direction per pixel

normalize shrinks the vector to length 1, keeping only its direction. Every pixel gets a different l — that's the fundamental difference from a directional light.


Distance attenuation

The farther the pixel is from the light, the dimmer it should appear:

dot(v, v) gives the squared length of a vector without a costly sqrt. The formula 1 / (1 + 3d²) starts at 1 when distance is 0 (100% bright) and drops toward 0 as distance grows. The coefficient 3.0 controls how quickly the light fades — larger means faster falloff.


Combining diffuse and attenuation

0.1 is the ambient floor — it keeps the back of the sphere from going completely black. diff * 2.0 amplifies the diffuse contribution.


Try changing it

ChangeEffect
Move lightPos x/y to -0.3, 0.2Light shifts left, lit face changes
Change the 3.0 coefficient to 10.0Faster falloff, darker overall
Change the 3.0 coefficient to 0.5Slower falloff, wider bright area
Change 0.1 to 0.4Stronger ambient, back face brightens

Exercise

The exercise code already computes the light direction l, but attenuation is missing. Fill in the att calculation and multiply it into diff to make the sphere darken with distance from the light.

Answer Breakdown

The starting code has diff = max(dot(n, l), 0.0) with no attenuation — the light acts as if it has infinite reach, so brightness depends only on the surface angle, not the distance.

Adding att brings in falloff: pixels close to the light source get an att near 1 (nearly full brightness), while distant pixels get an att near 0 (almost no contribution). The sphere gains a natural gradient from bright center to dark edges.

Using dot(lightPos-pos, lightPos-pos) instead of length() avoids a square root, which is faster on the GPU.

Try changing the light's z from 0.6 to 0.1 to bring it closer to the sphere surface and watch how the falloff shape changes.

GLSL Code Editor

Correct Code Preview

Current Code Preview