Skip to main content

Glass Material

glassMaterial is an experimental cross-backend shader module for refractive translucent surfaces. It combines captured scene-color transmission, Schlick Fresnel reflection, chromatic dispersion, Beer-Lambert absorption, and roughness-dependent highlights.

import {
glassMaterial,
glassMaterialPlugin,
glassTransmission,
glassTransmissionPlugin,
opticalLighting,
type GlassMaterialBindings,
type GlassMaterialProps,
type GlassMaterialUniforms
} from '@luma.gl/experimental';

Properties

PropertyTypeDefaultDescription
viewportSize[number, number][1, 1]Scene-color texture dimensions in physical pixels.
sceneColorTextureTextureRequired for rendering.Opaque scene color captured before translucent geometry.
indexOfRefractionnumber1.48Optical refraction index; ordinary glass is approximately 1.5.
roughnessnumber0.14Surface roughness between zero and one.
dispersionnumber0.022Separation of red, green, and blue transmission samples.
thicknessnumber1.05Approximate optical distance used for transmission and absorption.
refractionStrengthnumber1Camera-aligned background lens displacement.
reflectionStrengthnumber1Multiplier for environment reflection and highlights.
fresnelStrengthnumber1Grazing-angle reflection multiplier.
clearcoatStrengthnumber0.7Secondary polished surface highlight.
iridescenceStrengthnumber0.1Thin-film spectral edge variation.
internalReflectionStrengthnumber0.42Internal environment-bounce multiplier.
transmissionStrengthnumber1Amount of transmitted scene color.

Shader Helper

fn glassMaterial_getColor(
normal: vec3<f32>,
worldPosition: vec3<f32>,
baseColor: vec4<f32>,
cameraPosition: vec3<f32>,
fragmentPosition: vec4<f32>
) -> vec4<f32>

GLSL exposes the equivalent vec4 glassMaterial_getColor(...) function. Add glassMaterialPlugin to the model so the helper and its shared opticalLighting dependency are installed before compilation.

For surfaces illuminated by nearby moving lights, install opticalPointLightsPlugin alongside glassMaterialPlugin and call glassMaterial_getIlluminatedColor(...) with the same arguments. Bind opticalPointLights through ShaderInputs with up to MAX_OPTICAL_POINT_LIGHTS world-space light positions, colors, radii, and intensities. The original glassMaterial_getColor(...) remains available for scenes without dynamic local lights.

Rasterized Volume Extension

Install glassTransmissionPlugin to add depth-aware, two-surface transmission without changing existing glassMaterial_getColor(...) consumers.

PropertyTypeDefaultDescription
viewportSize[number, number][1, 1]Dimensions shared by the scene and backface textures.
depthRange[number, number][0.1, 100]Near and far perspective clip planes.
sceneDepthTextureTextureRequired for rendering.Sampleable opaque-scene depth attachment.
backfaceTextureTextureRequired for rendering.Encoded world-space backface normals and depth.
environmentTextureTextureRequired for rendering.Equirectangular studio or HDR environment.
environmentIntensitynumber1Environment reflection multiplier.
environmentMipLevelsnumber1Number of initialized environment-probe mip levels available for roughness-selected reflection.
environmentPrefilterStrengthnumber0Opt-in roughness-to-mip multiplier; zero preserves legacy bounded environment filtering.
thicknessStrengthnumber1Measured optical-path multiplier.
roughTransmissionStrengthnumber0Thickness-aware rough transmission and filtered environment reflection strength.
spectralAbsorptionStrengthnumber0Wavelength-dependent Beer-Lambert extinction inside the measured glass volume.
thinFilmThicknessnumber0Surface coating thickness in nanometers; zero disables coating interference.
thinFilmStrengthnumber0Intensity of angle-dependent red, green, and blue coating interference.
volumeScatteringStrengthnumber0Strength of restrained in-volume scattering and nearby point-light coupling.
contactShadowStrengthnumber0Depth-aware optical contact shadows around adjacent opaque network hardware.
depthBiasnumber0.00008Foreground depth-comparison tolerance.
dynamicReflectionStrengthnumber0Captured-scene reflection strength for nearby moving objects.
secondaryBounceStrengthnumber0Additional reflected environment bounce inside the glass shell.
faultDistortionStrengthnumber0Animated lens distortion and internal filaments on warm fault-tinted glass.
timenumber0Animation clock for optional fault-driven surface effects.

Use glassTransmission_getColor(...), or add opticalPointLightsPlugin and use glassTransmission_getIlluminatedColor(...) for localized illumination. Both are available in matching WGSL and GLSL forms.

The optional volume controls preserve existing output when left at their zero defaults. Rough transmission adds bounded scene-color and environment samples; a prefiltered environment texture can replace repeated neighborhood sampling with explicit roughness-selected mip levels; spectral absorption uses the backface-measured optical path; thin-film interference evaluates representative red, green, and blue wavelengths from the coating thickness; volume scattering couples nearby optical point lights into the glass interior; and optional contact shadows use the opaque depth already captured for foreground rejection. No mode requires per-pixel ray tracing.

opticalCausticsPlugin separately adds a bounded array of focused glass lenses for nearby reflective receiver surfaces. Call opticalCaustics_getColor(normal, worldPosition, cameraPosition) and add its RGB result to the receiver's existing material color. At most MAX_OPTICAL_CAUSTIC_LENSES entries are uploaded, and each entry specifies a world-space position, radius, color, and optional intensity.

Usage

import {Model, ShaderInputs} from '@luma.gl/engine';
import {glassMaterial, glassMaterialPlugin} from '@luma.gl/experimental';

const shaderInputs = new ShaderInputs({glassMaterial});

shaderInputs.setProps({
glassMaterial: {
viewportSize: [width, height],
sceneColorTexture,
indexOfRefraction: 1.5,
thickness: 1
}
});

const model = new Model(device, {
source: glassShader,
plugins: [glassMaterialPlugin],
shaderInputs,
geometry
});

Capture scene color into a separate texture before drawing glass. Sampling the active render attachment creates an invalid feedback loop on WebGPU.

For OIT composition and quality limitations, see Transparency and Glass Effects.