SSRPassProxy.js

import Check from "@lijuhong1981/jscheck/src/Check.js";
import PassNodeProxy from "./PassNodeProxy.js";
import SSRNode, { ssr } from 'three/addons/tsl/display/SSRNode.js';
import { Camera, Node, TextureNode } from "three/webgpu";

/**
 * SSRPassProxy是PassNodeProxy的一个子类,用于代理SSR(Screen Space Reflections)后处理特效的Pass节点。
 * @class
 * @extends PassNodeProxy<SSRNode>
*/
class SSRPassProxy extends PassNodeProxy {
    constructor(library) {
        super(library);
        this._values = {
            resolutionScale: 1,
            maxDistance: 1,
            thickness: 0.03,
            opacity: 1,
            quality: 0.5,
            blurQuality: 1,
        };
    }
    /**
     * The resolution scale. Valid values are in the range
     * `[0,1]`. `1` means best quality but also results in
     * more computational overhead. Setting to `0.5` means
     * the effect is computed in half-resolution.
     *
     * @type {number}
     * @default 1
     */
    set resolutionScale(value) {
        Check.typeOf.number('resolutionScale', value);
        this._values.resolutionScale = value;
        this.node && (this.node.resolutionScale = value);
    }
    get resolutionScale() {
        return this._values.resolutionScale;
    }
    /**
     * Controls how far a fragment can reflect. Increasing this value result in more
     * computational overhead but also increases the reflection distance.
     *
     * @type {number}
     * @default 1
     */
    set maxDistance(value) {
        Check.typeOf.number('maxDistance', value);
        this._values.maxDistance = value;
        this.node && (this.node.maxDistance.value = value);
    }
    get maxDistance() {
        return this._values.maxDistance;
    }
    /**
     * Controls the cutoff between what counts as a possible reflection hit and what does not.
     *
     * @type {number}
     * @default 0.03
     */
    set thickness(value) {
        Check.typeOf.number('thickness', value);
        this._values.thickness = value;
        this.node && (this.node.thickness.value = value);
    }
    get thickness() {
        return this._values.thickness;
    }
    /**
     * Controls how the SSR reflections are blended with the beauty pass.
     *
     * @type {number}
     * @default 1
     */
    set opacity(value) {
        Check.typeOf.number('opacity', value);
        this._values.opacity = value;
        this.node && (this.node.opacity.value = value);
    }
    get opacity() {
        return this._values.opacity;
    }
    /**
     * This parameter controls how detailed the raymarching process works.
     * The value ranges is `[0,1]` where `1` means best quality (the maximum number
     * of raymarching iterations/samples) and `0` means no samples at all.
     *
     * A quality of `0.5` is usually sufficient for most use cases. Try to keep
     * this parameter as low as possible. Larger values result in noticeable more
     * overhead.
     *
     * @type {number}
     * @default 0.5
     */
    set quality(value) {
        Check.typeOf.number('quality', value);
        this._values.quality = value;
        this.node && (this.node.quality.value = value);
    }
    get quality() {
        return this._values.quality;
    }
    /**
     * The quality of the blur. Must be an integer in the range `[1,3]`.
     *
     * @type {number}
     * @default 1
     */
    set blurQuality(value) {
        Check.typeOf.number('blurQuality', value);
        this._values.blurQuality = value;
        this.node && (this.node.blurQuality.value = value);
    }
    get blurQuality() {
        return this._values.blurQuality;
    }
    /**
     * 构建SSR Pass节点。
     * @param {TextureNode} colorNode - 颜色节点对象 
     * @param {TextureNode} depthNode - 深度节点对象
     * @param {TextureNode} normalNode - 法线节点对象
     * @param {Node} metalnessNode - 金属度节点对象
     * @param {Node} roughnessNode - 粗糙度节点对象
     * @param {Camera} camera - 相机对象
     * @param {TextureNode} outputNode - 输出节点对象
     * @returns {TextureNode} 处理后的节点对象
     * @override
    */
    build(colorNode, depthNode, normalNode, metalnessNode, roughnessNode, camera, outputNode) {
        const ssrPass = this.node = ssr(colorNode, depthNode, normalNode, metalnessNode, roughnessNode, camera).toInspector('SSR');
        this.setValues(this._values);
        return outputNode.add(ssrPass.rgb);
    }
};

export default SSRPassProxy;
export { SSRPassProxy };