Graphics glossary 22 terms mentioned in this lesson
Select any term for a clear definition. The return button brings you back to the exact term link you used.
Transparent objects are often demonstrated by lowering opacity. That makes the background visible, but it does not model a ray crossing a boundary. Glass bends directions according to the two media, may reflect some contribution at the same boundary and can prevent transmission entirely at sufficiently shallow exit angles. A convincing alpha blend can hide all three missing mechanisms.
We shall model an ideal dielectric boundary using an index of refraction, Snell's law and the Schlick approximation for Fresnel reflectance. Absorption, dispersion, roughness and nested medium tracking are outside this compact material. The omissions are stated because a recognisable glass sphere is not evidence that every glass behaviour has been implemented.
What you should be able to account for
- Choose the refractive-index ratio from the front-face state.
- Calculate a transmitted direction or identify total internal reflection.
- Use an angle-dependent Fresnel approximation to combine reflection and transmission.
The boundary has two sides
Air is approximated with index 1.0. Typical teaching glass may use 1.5. When a front-face hit enters glass, the ratio used by the vector form is 1.0 / 1.5. When a ray leaves, it is 1.5 / 1.0. The face flag retained in Lesson 6 tells us which case applies.
const eta = hit.frontFace
? 1.0 / material.indexOfRefraction
: material.indexOfRefraction / 1.0;
This assumes the outside medium is air and the inside medium is the material. It fails for glass inside water or overlapping dielectrics because the current medium cannot be inferred from one boolean. A fuller renderer carries medium state along the path or resolves a boundary stack. The simple case is appropriate here only because the scene is deliberately constrained.
Separate perpendicular and parallel components
Let D be the unit incoming direction and N the oriented normal. The cosine of the incident angle is:
cosθ = min(−D · N, 1)
The sine follows from sin²θ + cos²θ = 1. If eta × sinθ > 1, no real transmitted direction exists. This is total internal reflection.
const cosTheta = Math.min(dot(scale(D, -1), N), 1);
const sinTheta = Math.sqrt(1 - cosTheta * cosTheta);
const cannotRefract = eta * sinTheta > 1;
When transmission is possible, construct its components:
function refract(D, N, eta) {
const cosTheta = Math.min(dot(scale(D, -1), N), 1);
const perpendicular = scale(
add(D, scale(N, cosTheta)),
eta
);
const parallel = scale(
N,
-Math.sqrt(Math.abs(1 - dot(perpendicular, perpendicular)))
);
return add(perpendicular, parallel);
}
The absolute value protects the square root from a tiny negative value produced by rounding near the critical angle. It should not be used to pretend that a materially negative value is valid. The separate cannotRefract test establishes the geometric case first.
Fresnel response prevents a fixed split
A dielectric reflects more contribution at grazing angles than when viewed close to the normal. Schlick's approximation gives a compact unpolarised reflectance estimate:
R₀ = ((1 − η) / (1 + η))²
R(θ) = R₀ + (1 − R₀)(1 − cosθ)⁵
function schlick(cosine, eta) {
let r0 = (1 - eta) / (1 + eta);
r0 *= r0;
return r0 + (1 - r0) * Math.pow(1 - cosine, 5);
}
At normal incidence, common glass reflects only a modest fraction. Near a grazing angle, the estimate approaches one. A fixed 50:50 blend would be easy to implement and would produce something transparent, but it would discard the angle-dependent boundary behaviour we are trying to understand.
Glass-boundary laboratory
Bend One Ray at an Air-to-Glass Boundary
Keep a 45-degree incident direction fixed, change the glass index and calculate the transmitted angle and Fresnel reflection weight.
Change this, then watch this: Change the glass index. The incident direction and normal stay fixed while the transmitted direction and Fresnel percentage change.
- Material index η₂
- Transmitted angle
- Fresnel reflection
- Traced branches
sin θ₂ = (η₁ ÷ η₂) sin θ₁
What this establishes:
Trace both possible routes
At a glass hit with remaining depth, always calculate the reflected direction. If total internal reflection occurs, trace only that route. Otherwise trace reflected and transmitted rays, then combine their colours using the Fresnel estimate.
const reflected = trace(reflectedRay, remaining - 1);
if (cannotRefract) {
return reflected;
}
const transmitted = trace(transmittedRay, remaining - 1);
const reflectance = schlick(cosTheta, eta);
return add(
scale(reflected, reflectance),
scale(transmitted, 1 - reflectance)
);
The transmitted origin is offset to the opposite side of the oriented normal; the reflected origin is offset along it. The directions themselves also determine the side on which the next ray should travel. A single positive-normal offset for both rays would push one route back across its intended boundary.
Normal incidence into glass
For air to glass at index 1.5, eta = 2/3. At normal incidence cosθ = 1, so the transmitted ray does not bend away from the original line. Schlick's base value is approximately ((1 - 2/3) / (1 + 2/3))² = 0.04. Roughly four per cent of this idealised contribution reflects and the remainder transmits before later boundaries are considered.
A visible sphere still does not prove nested media
The laboratory sphere has two boundaries. An entering ray refracts, meets the back of the sphere and refracts again. The oriented normal and face flag make those two ratios differ. Change the index and observe the distortion and ray counters.
The present shadow query also treats every blocking primitive as opaque, including the glass sphere. Transmitting light through a dielectric towards another surface requires a transport calculation along the light route, not the Boolean any-hit result introduced for opaque shadows. The glass seen by a camera ray therefore does not prove that transparent shadows have been implemented. They have not.
Now consider placing one glass sphere inside another with a different index. The boolean face state says whether the current surface is being entered, but not which medium the ray is leaving. The displayed simple sphere cannot validate that harder case. This is the point at which a renderer needs explicit medium tracking rather than another conditional guessed from appearance.
Identify total internal reflection
A ray is leaving glass of index 1.5 for air. The sine of the incident angle is 0.8. Does a transmitted direction exist under the test used above?
Reveal the test
The ratio is eta = 1.5 / 1.0 = 1.5. Multiplying by sinθ = 0.8 gives 1.2, which is greater than one. No real transmitted direction exists, so the considered contribution is reflected.
Trace entry and exit
Select one pixel through the glass sphere. Record the front-face flag, eta, incident cosine, Fresnel estimate and transmitted direction at entry. Follow the ray to the exit surface and record them again. Explain why the eta ratio reverses. Then choose a grazing internal route and locate the first total-internal-reflection decision.
Keep this model for Vulkan
A Vulkan closest-hit shader can carry origin, direction, throughput, depth and medium information in a ray payload, or a compute loop can store the same state explicitly. Hardware traversal does not provide a physically meaningful Fresnel split or maintain a material stack automatically. Those remain shader responsibilities grounded in the boundary model constructed here.
Reflection and transmission can now create multiple routes from one sample. Lesson 13 returns to the image plane and asks whether one route through the centre of each pixel is an adequate estimate of the image.