Skip to main content

Reflections

RayTracer Studio implements recursive reflections with a Fresnel-like effect for realistic mirror surfaces.

How Reflections Workโ€‹

When a ray hits a reflective surface:

  1. Calculate the reflection direction
  2. Spawn a new ray in that direction
  3. Recursively trace the reflected ray
  4. Blend the reflected color with the surface color
Vec3 traceRay(Ray ray, int depth) {
if (depth >= maxDepth) return backgroundColor;

HitRecord hit = trace(ray);
if (!hit.hit) return backgroundColor;

Vec3 localColor = calculateLighting(ray, hit);

if (hit.material.reflectivity > 0) {
Vec3 reflectDir = ray.direction.reflect(hit.normal);
Ray reflectRay(hit.point + offset, reflectDir);

Vec3 reflectedColor = traceRay(reflectRay, depth + 1);

localColor = blend(localColor, reflectedColor, reflectivity);
}

return localColor;
}

Reflection Formulaโ€‹

The reflection of vector V around normal N:

R = V - 2(V ยท N)N
Vec3 Vec3::reflect(const Vec3& normal) const {
return *this - normal * (2.0f * this->dot(normal));
}
        N (normal)
โ†‘
โ”‚
V โ•ฒ โ”‚ โ•ฑ R (reflection)
โ•ฒโ”‚โ•ฑ
โ”€โ”€โ”€โ”€โ—โ”€โ”€โ”€โ”€ Surface

Fresnel Effectโ€‹

Real materials are more reflective at grazing angles (when you look at them from the side):

float cosTheta = abs(normal.dot(viewDir * -1.0f));
float fresnelFactor = reflectivity +
(1.0f - reflectivity) * pow(1.0f - cosTheta, 3.0f);

This creates a more realistic effect where:

  • Center of sphere: Less reflective
  • Edges of sphere: More reflective
     Low reflection
โ†“
โ•ญโ”€โ”€โ”€โ•ฎ
โ•ฑ โ•ฒ โ† High reflection
โ”‚ โ”‚
โ”‚ โ— โ”‚ (viewing angle)
โ”‚ โ”‚
โ•ฒ โ•ฑ โ† High reflection
โ•ฐโ”€โ”€โ”€โ•ฏ
โ†‘
Low reflection

Recursion Depthโ€‹

Reflections are recursive - a mirror can reflect another mirror infinitely. We limit this with maxReflectionDepth:

if (depth >= maxReflectionDepth) {
return getBackgroundColor(ray);
}
DepthEffect
1Single reflection
3Mirror-in-mirror visible
5Default, good quality
8Maximum, for complex scenes

Material Reflectivityโ€‹

The reflectivity property controls how mirror-like a surface is:

ValueAppearance
0.0No reflection (matte)
0.3Subtle reflection (glossy plastic)
0.7Strong reflection (polished metal)
0.95Near-perfect mirror

Color Blendingโ€‹

The final color is a blend of local color and reflected color:

finalColor = localColor * (1 - fresnel) + reflectedColor * fresnel;

For a perfect mirror (reflectivity = 1.0), the surface takes on entirely the reflected color.

Ground Plane Reflectionsโ€‹

The ground plane can also be reflective, creating a polished floor effect:

groundPlane.material.reflectivity = 0.15f;  // Subtle floor reflection

This allows spheres to be partially visible in the ground.

Self-Intersection Preventionโ€‹

When spawning reflection rays, we offset the origin slightly to avoid hitting the same surface:

Vec3 reflectOrigin = hit.point + hit.normal * 0.001f;
Ray reflectRay(reflectOrigin, reflectDir);

Without this offset, floating-point errors could cause the ray to immediately hit the surface it just reflected off of.

Performance Impactโ€‹

Each reflection level multiplies the number of rays:

BouncesRays per Pixel (worst case)
12
38
532
8256

Reduce maxBounces in the View tab for better performance.

Scene Presetsโ€‹

Different presets showcase reflections:

  • Mirror Spheres: Chrome and metallic balls with high reflectivity
  • Three Spheres: Various reflectivity levels to compare