UNPKG

lingo3d

Version:

Lingo3D is a React/Vue 3d game development framework that ships with a complete visual editor

200 lines 9.3 kB
import { Effect, Selection } from "postprocessing"; import { Uniform } from "three"; import boxBlur from "./material/shader/boxBlur"; import finalSSRShader from "./material/shader/finalSSRShader"; import helperFunctions from "./material/shader/helperFunctions"; import trCompose from "./material/shader/trCompose"; import { ReflectionsPass } from "./pass/ReflectionsPass"; import { afterRenderSSR, beforeRenderSSR } from "./renderSetup"; import { defaultSSROptions } from "./SSROptions"; import { TemporalResolvePass } from "./temporal-resolve/pass/TemporalResolvePass"; import { generateHalton23Points } from "./utils/generateHalton23Points"; const finalFragmentShader = finalSSRShader .replace("#include <helperFunctions>", helperFunctions) .replace("#include <boxBlur>", boxBlur); export class SSREffect extends Effect { haltonSequence = generateHalton23Points(1024); haltonIndex = 0; selection = new Selection(); lastSize; /** * @param {THREE.Scene} scene The scene of the SSR effect * @param {THREE.Camera} camera The camera with which SSR is being rendered * @param {SSROptions} [options] The optional options for the SSR effect */ constructor(scene, camera, options = defaultSSROptions) { super("SSREffect", finalFragmentShader, { type: "FinalSSRMaterial", uniforms: new Map([ ["reflectionsTexture", new Uniform(null)], ["blur", new Uniform(0)], ["blurSharpness", new Uniform(0)], ["blurKernel", new Uniform(0)] ]), defines: new Map([["RENDER_MODE", "0"]]) }); this._scene = scene; this._camera = camera; const trOptions = { boxBlur: true, dilation: true }; options = { ...defaultSSROptions, ...options, ...trOptions }; // set up passes // temporal resolve pass this.temporalResolvePass = new TemporalResolvePass(scene, camera, trCompose, options); this.uniforms.get("reflectionsTexture").value = this.temporalResolvePass.renderTarget.texture; // reflections pass this.reflectionsPass = new ReflectionsPass(this, options); this.temporalResolvePass.fullscreenMaterial.uniforms.inputTexture.value = this.reflectionsPass.renderTarget.texture; this.lastSize = { width: options.width, height: options.height, resolutionScale: options.resolutionScale, velocityResolutionScale: options.velocityResolutionScale }; this.setSize(options.width, options.height); this.makeOptionsReactive(options); } makeOptionsReactive(options) { let needsUpdate = false; const reflectionPassFullscreenMaterialUniforms = this.reflectionsPass.fullscreenMaterial.uniforms; const reflectionPassFullscreenMaterialUniformsKeys = Object.keys(reflectionPassFullscreenMaterialUniforms); for (const key of Object.keys(options)) { Object.defineProperty(this, key, { get() { return options[key]; }, set(value) { if (options[key] === value && needsUpdate) return; options[key] = value; switch (key) { case "resolutionScale": this.setSize(this.lastSize.width, this.lastSize.height); break; case "velocityResolutionScale": this.temporalResolvePass.velocityResolutionScale = value; this.setSize(this.lastSize.width, this.lastSize.height, true); break; case "blur": this.uniforms.get("blur").value = value; break; case "blurSharpness": this.uniforms.get("blurSharpness").value = value; break; case "blurKernel": this.uniforms.get("blurKernel").value = value; break; // defines case "steps": this.reflectionsPass.fullscreenMaterial.defines.steps = parseInt(value); this.reflectionsPass.fullscreenMaterial.needsUpdate = needsUpdate; break; case "refineSteps": this.reflectionsPass.fullscreenMaterial.defines.refineSteps = parseInt(value); this.reflectionsPass.fullscreenMaterial.needsUpdate = needsUpdate; break; case "missedRays": if (value) { this.reflectionsPass.fullscreenMaterial.defines.missedRays = ""; } else { delete this.reflectionsPass.fullscreenMaterial .defines.missedRays; } this.reflectionsPass.fullscreenMaterial.needsUpdate = needsUpdate; break; case "correctionRadius": this.temporalResolvePass.fullscreenMaterial.defines.correctionRadius = Math.round(value); this.temporalResolvePass.fullscreenMaterial.needsUpdate = needsUpdate; break; case "blend": this.temporalResolvePass.fullscreenMaterial.uniforms.blend.value = value; break; case "correction": this.temporalResolvePass.fullscreenMaterial.uniforms.correction.value = value; break; case "exponent": this.temporalResolvePass.fullscreenMaterial.uniforms.exponent.value = value; break; case "distance": reflectionPassFullscreenMaterialUniforms.rayDistance.value = value; // must be a uniform default: if (reflectionPassFullscreenMaterialUniformsKeys.includes(key)) { reflectionPassFullscreenMaterialUniforms[key].value = value; } } } }); // apply all uniforms and defines this[key] = options[key]; } needsUpdate = true; } setSize(width, height, force = false) { if (!force && width === this.lastSize.width && height === this.lastSize.height && this.resolutionScale === this.lastSize.resolutionScale && this.velocityResolutionScale === this.lastSize.velocityResolutionScale) return; this.temporalResolvePass.setSize(width, height); this.reflectionsPass.setSize(width, height); this.lastSize = { width, height, resolutionScale: this.resolutionScale, velocityResolutionScale: this.velocityResolutionScale }; } setIBLRadiance(iblRadiance, renderer) { this._scene.traverse((c) => { if (c.material) { const uniforms = renderer.properties.get(c.material)?.uniforms; if (uniforms && "disableIBLRadiance" in uniforms) { uniforms.disableIBLRadiance.value = iblRadiance; } } }); } dispose() { super.dispose(); this.reflectionsPass.dispose(); this.temporalResolvePass.dispose(); } update(renderer, inputBuffer) { beforeRenderSSR(); this.haltonIndex = (this.haltonIndex + 1) % this.haltonSequence.length; const [x, y] = this.haltonSequence[this.haltonIndex]; const { width, height } = this.lastSize; this.temporalResolvePass.velocityPass.render(renderer); // jittering the view offset each frame reduces aliasing for the reflection if (this._camera.setViewOffset) this._camera.setViewOffset(width, height, x, y, width, height); // render reflections of current frame this.reflectionsPass.render(renderer, inputBuffer); // compose reflection of last and current frame into one reflection this.temporalResolvePass.render(renderer); this._camera.clearViewOffset(); afterRenderSSR(); } } //# sourceMappingURL=SSREffect.js.map