src/materials/SSAOMaterial.js
import { Matrix4, PerspectiveCamera, ShaderMaterial, Uniform, Vector2 } from "three";
import fragmentShader from "./glsl/ssao/shader.frag";
import vertexShader from "./glsl/ssao/shader.vert";
/**
* A Screen Space Ambient Occlusion (SSAO) shader material.
*/
export class SSAOMaterial extends ShaderMaterial {
/**
* Constructs a new SSAO material.
*
* @param {Camera} camera - A camera.
*/
constructor(camera) {
super({
type: "SSAOMaterial",
defines: {
SAMPLES_INT: "0",
SAMPLES_FLOAT: "0.0",
SPIRAL_TURNS: "0.0",
RADIUS: "1.0",
RADIUS_SQ: "1.0",
DISTANCE_SCALING: "1",
DEPTH_PACKING: "0"
},
uniforms: {
normalBuffer: new Uniform(null),
normalDepthBuffer: new Uniform(null),
noiseTexture: new Uniform(null),
inverseProjectionMatrix: new Uniform(new Matrix4()),
projectionMatrix: new Uniform(new Matrix4()),
texelSize: new Uniform(new Vector2()),
cameraNear: new Uniform(0.0),
cameraFar: new Uniform(0.0),
distanceCutoff: new Uniform(new Vector2()),
proximityCutoff: new Uniform(new Vector2()),
noiseScale: new Uniform(new Vector2()),
minRadiusScale: new Uniform(0.33),
intensity: new Uniform(1.0),
fade: new Uniform(0.01),
bias: new Uniform(0.0)
},
fragmentShader,
vertexShader,
depthWrite: false,
depthTest: false
});
/** @ignore */
this.toneMapped = false;
this.adoptCameraSettings(camera);
}
/**
* The depth packing of the source depth buffer.
*
* @type {Number}
*/
get depthPacking() {
return Number(this.defines.DEPTH_PACKING);
}
/**
* Sets the depth packing.
*
* @type {Number}
*/
set depthPacking(value) {
this.defines.DEPTH_PACKING = value.toFixed(0);
this.needsUpdate = true;
}
/**
* Sets the texel size.
*
* @param {Number} x - The texel width.
* @param {Number} y - The texel height.
*/
setTexelSize(x, y) {
this.uniforms.texelSize.value.set(x, y);
}
/**
* Adopts the settings of the given camera.
*
* @param {Camera} [camera=null] - A camera.
*/
adoptCameraSettings(camera = null) {
if(camera !== null) {
const uniforms = this.uniforms;
uniforms.cameraNear.value = camera.near;
uniforms.cameraFar.value = camera.far;
if(camera instanceof PerspectiveCamera) {
this.defines.PERSPECTIVE_CAMERA = "1";
} else {
delete this.defines.PERSPECTIVE_CAMERA;
}
this.needsUpdate = true;
}
}
}