NgtsMeshRefractionMaterial
import { ChangeDetectionStrategy, Component } from '@angular/core';import { SobaWrapper } from '@soba/wrapper.ts';import { NgtCanvas, provideNgtRenderer } from 'angular-three/dom';import { SceneGraph } from './scene-graph';
@Component({ selector: 'app-mesh-refraction-material', template: ` <ngt-canvas [camera]="{ position: [0, 0, 4], fov: 50 }"> <app-soba-wrapper *canvasContent [grid]="false" [lights]="false"> <app-scene-graph /> </app-soba-wrapper> </ngt-canvas> `, changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'mesh-refraction-material-demo relative block h-full' }, imports: [NgtCanvas, SobaWrapper, SceneGraph],})export default class MeshRefractionMaterial { static clientProviders = [provideNgtRenderer()];}import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, ElementRef, viewChild } from '@angular/core';import { beforeRender, NgtArgs } from 'angular-three';import { NgtsCameraContent, NgtsCubeCamera } from 'angular-three-soba/cameras';import { NgtsMeshRefractionMaterial } from 'angular-three-soba/materials';import { NgtsEnvironment } from 'angular-three-soba/staging';import { Mesh } from 'three';
@Component({ selector: 'app-scene-graph', template: ` <!-- HDRI Environment - this is what gets refracted through the crystal --> <ngts-environment [options]="{ preset: 'sunset', background: true, backgroundBlurriness: 0.3 }" />
<!-- CubeCamera captures the surrounding environment for refraction calculations --> <ngts-cube-camera [options]="{ frames: Infinity, resolution: 256 }"> <ng-template cameraContent let-texture> <!-- Crystal/Diamond mesh - the refraction material makes it appear as a transparent gem that bends light with chromatic aberration (rainbow color splitting like a real diamond/prism) --> <ngt-mesh #crystal [scale]="1.2"> <!-- Icosahedron with subdivision creates diamond-like facets --> <ngt-icosahedron-geometry *args="[1, 0]" /> <ngts-mesh-refraction-material [envMap]="texture" [options]="{ bounces: 4, ior: 2.4, fresnel: 1, aberrationStrength: 0.04, fastChroma: true, toneMapped: false, color: 'red', }" /> </ngt-mesh> </ng-template> </ngts-cube-camera>
<!-- Small colored lights to show how they refract through the crystal --> <ngt-point-light [position]="[-3, 2, 2]" color="#ff6b6b" [intensity]="50" /> <ngt-point-light [position]="[3, 2, 2]" color="#4ecdc4" [intensity]="50" /> <ngt-point-light [position]="[0, -2, 3]" color="#ffe66d" [intensity]="50" />
<ngt-ambient-light [intensity]="0.2" /> `, schemas: [CUSTOM_ELEMENTS_SCHEMA], changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgtArgs, NgtsMeshRefractionMaterial, NgtsCubeCamera, NgtsCameraContent, NgtsEnvironment],})export class SceneGraph { private crystalRef = viewChild<ElementRef<Mesh>>('crystal');
constructor() { beforeRender(({ delta }) => { const crystal = this.crystalRef()?.nativeElement; if (crystal) { crystal.rotation.y += delta * 0.2; crystal.rotation.x += delta * 0.1; } }); }}NgtsMeshRefractionMaterial is a port of Drei’s MeshRefractionMaterial that simulates realistic light refraction through transparent objects. It uses ray tracing with BVH acceleration for accurate light bending effects, making it ideal for diamonds, crystals, glass, and other transparent materials.
Peer Dependencies
Requires three-mesh-bvh:
npm install three-mesh-bvhUsage
import { NgtsMeshRefractionMaterial } from 'angular-three-soba/materials';If you want the material to reflect other objects in the scene, pair it with NgtsCubeCamera:
<ngts-cube-camera> <ngt-mesh *cameraContent="let texture"> <ngt-dodecahedron-geometry /> <ngts-mesh-refraction-material [envMap]="texture()" /> </ngt-mesh></ngts-cube-camera>Otherwise, just pass an environment map directly:
<!-- texture = loaderResource(() => RGBELoader, () => 'path/to/texture.hdr') --><ngt-mesh> <ngt-dodecahedron-geometry /> <ngts-mesh-refraction-material [envMap]="texture()" /></ngt-mesh>Diamond Example
@Component({ template: ` <ngts-cube-camera [options]="{ resolution: 256, frames: 1 }"> <ngt-mesh *cameraContent="let texture"> <ngt-dodecahedron-geometry /> <ngts-mesh-refraction-material [envMap]="texture()" [options]="{ bounces: 3, ior: 2.4, fresnel: 1, aberrationStrength: 0.02, color: 'white' }" /> </ngt-mesh> </ngts-cube-camera> `})export class Diamond {}Common IOR Values
| Material | IOR |
|---|---|
| Air | 1.0 |
| Water | 1.33 |
| Glass | 1.5 |
| Crystal | 2.0 |
| Diamond | 2.4 |
Higher bounces values produce more accurate refractions but require more computation. For most cases, 2-3 bounces provide a good balance between quality and performance.
Inputs
| name | type | description | required |
|---|---|---|---|
| envMap | THREE.CubeTexture | THREE.Texture | The environment map used for refraction. Required for the material to work. | yes |
| attach | string | How to attach the material to its parent object. | no |
Options
Properties
| name | type | description |
|---|---|---|
| bounces | number | The number of ray-cast bounces for light simulation. |
| ior | number | The refraction index. Diamond is 2.4, glass is 1.5, water is 1.33. |
| fresnel | number | The Fresnel effect intensity (strip light reflections). |
| aberrationStrength | number | The RGB chromatic aberration shift intensity. |
| color | THREE.ColorRepresentation | The color of the material. |
| fastChroma | boolean | Whether to use fewer ray casts for the RGB shift, sacrificing physical accuracy for performance. |