NgtsContactShadows
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-contact-shadows', template: ` <ngt-canvas [camera]="{ position: [3, 3, 3], fov: 50 }"> <app-soba-wrapper *canvasContent [grid]="false"> <app-scene-graph /> </app-soba-wrapper> </ngt-canvas> `, changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'contact-shadows-demo relative block h-full' }, imports: [NgtCanvas, SobaWrapper, SceneGraph],})export default class ContactShadows { static clientProviders = [provideNgtRenderer()];}import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';import { NgtArgs } from 'angular-three';import { NgtsContactShadows } from 'angular-three-soba/staging';
@Component({ selector: 'app-scene-graph', template: ` <!-- Floating sphere --> <ngt-mesh [position]="[0, 1, 0]"> <ngt-sphere-geometry *args="[0.75, 32, 32]" /> <ngt-mesh-standard-material color="#ff6b6b" /> </ngt-mesh>
<!-- Floating box --> <ngt-mesh [position]="[-1.5, 0.6, 0.5]"> <ngt-box-geometry *args="[0.8, 0.8, 0.8]" /> <ngt-mesh-standard-material color="#4ecdc4" /> </ngt-mesh>
<!-- Floating torus --> <ngt-mesh [position]="[1.5, 0.8, -0.5]" [rotation]="[Math.PI / 4, 0, 0]"> <ngt-torus-geometry *args="[0.4, 0.15, 16, 32]" /> <ngt-mesh-standard-material color="#a29bfe" /> </ngt-mesh>
<!-- Contact shadows - renders shadows on a plane --> <ngts-contact-shadows [options]="{ position: [0, 0, 0], opacity: 0.6, scale: 10, blur: 2.5, far: 4, resolution: 512, color: '#000000', }" />
<!-- Ground plane for reference (slightly below shadows) --> <ngt-mesh [rotation]="[-Math.PI / 2, 0, 0]" [position]="[0, -0.01, 0]"> <ngt-plane-geometry *args="[10, 10]" /> <ngt-mesh-standard-material color="#f5f5f5" /> </ngt-mesh> `, schemas: [CUSTOM_ELEMENTS_SCHEMA], changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgtArgs, NgtsContactShadows],})export class SceneGraph { protected readonly Math = Math;}NgtsContactShadows is a port of Drei’s ContactShadows which creates a contact shadow implementation facing upwards (positive Y) by default.
Contact shadows are ideal for grounding objects in a scene without the complexity of traditional shadow mapping.
Usage
Basic Contact Shadows
<app-model />
<ngts-contact-shadows [options]="{ opacity: 1, scale: 10, blur: 1, far: 10, resolution: 512, color: '#000000' }"/>High-Quality Static Shadows
Since contact shadows can be expensive, you can limit the number of frames for static objects:
<!-- Render only once for static scenes --><ngts-contact-shadows [options]="{ frames: 1 }" />Soft Shadows with Smoothing
<ngts-contact-shadows [options]="{ opacity: 0.8, scale: 15, blur: 2.5, far: 8, resolution: 1024, smooth: true, color: '#1a1a2e' }"/>Non-Square Shadow Plane
<ngts-contact-shadows [options]="{ scale: [20, 10], blur: 1, opacity: 0.6 }"/>Notes
- Contact shadows are Y-up oriented and render from above
- Higher resolution and blur values increase quality but also GPU cost
- For animated scenes, keep
framesat Infinity (default) - For static scenes, set
frames: 1for better performance
Options
options input accepts any properties from THREE.Group in addition to the following:
Properties
| name | type | description |
|---|---|---|
| opacity | number | Opacity of the shadows. Default: 1 |
| width | number | Width of the shadow plane. Default: 1 |
| height | number | Height of the shadow plane. Default: 1 |
| blur | number | Blur radius of the shadows. Default: 1 |
| near | number | Near clipping plane for the shadow camera. Default: 0 |
| far | number | Far distance of the shadow camera. Default: 10 |
| resolution | number | Resolution of the shadow map. Default: 512 |
| smooth | boolean | Whether to apply smoothing to the shadows. Default: true |
| color | THREE.ColorRepresentation | Color of the shadows. Default: '#000000' |
| depthWrite | boolean | Whether the shadows should write to the depth buffer. Default: false |
| frames | number | How many frames it can render, more yields cleaner results. Default: Infinity |
| scale | number | [number, number] | Scale of the shadow plane. Can be a number or [x, y] tuple. Default: 10 |