UNPKG

polygonjs-engine

Version:

node-based webgl 3D engine https://polygonjs.com

129 lines (128 loc) 5.89 kB
import {WebGLRenderTarget as WebGLRenderTarget2} from "three/src/renderers/WebGLRenderTarget"; import {UniformsUtils as UniformsUtils2} from "three/src/renderers/shaders/UniformsUtils"; import {ShaderMaterial as ShaderMaterial2} from "three/src/materials/ShaderMaterial"; import {Scene as Scene2} from "three/src/scenes/Scene"; import {RGBFormat} from "three/src/constants"; import {PlaneBufferGeometry as PlaneBufferGeometry2} from "three/src/geometries/PlaneBufferGeometry"; import {OrthographicCamera as OrthographicCamera2} from "three/src/cameras/OrthographicCamera"; import {Mesh as Mesh2} from "three/src/objects/Mesh"; import {LinearFilter} from "three/src/constants"; import {BokehShader, BokehDepthShader} from "../../three/examples/jsm/shaders/BokehShader2"; import {CoreScene} from "../../../core/geometry/Scene"; import DepthInstanceVertex from "./gl/DepthInstance.vert.glsl"; import {Color as Color2} from "three/src/math/Color"; import {DepthOfFieldPostNode} from "../../../engine/nodes/post/DepthOfField"; export class BokehPass2 { constructor(_depth_of_field_node, _scene, _camera, _resolution) { this._depth_of_field_node = _depth_of_field_node; this._scene = _scene; this._camera = _camera; this._resolution = _resolution; this._camera_uniforms = {mNear: {value: 0}, mFar: {value: 0}}; this.enabled = true; this.needsSwap = true; this.clear = true; this.renderToScreen = true; this._processing_scene = new Scene2(); this.clear_color = new Color2(1, 1, 1); this._prev_clear_color = new Color2(); this._core_scene = new CoreScene(this._scene); const shaderSettings = { rings: 3, samples: 4 }; this._processing_camera = new OrthographicCamera2(this._resolution.x / -2, this._resolution.x / 2, this._resolution.y / 2, this._resolution.y / -2, -1e4, 1e4); this._processing_camera.position.z = 100; this._processing_scene.add(this._processing_camera); var pars = {minFilter: LinearFilter, magFilter: LinearFilter, format: RGBFormat}; this._rtTextureDepth = new WebGLRenderTarget2(this._resolution.x, this._resolution.y, pars); this._rtTextureColor = new WebGLRenderTarget2(this._resolution.x, this._resolution.y, pars); var bokeh_shader = BokehShader; if (!bokeh_shader) { console.error("BokehPass relies on BokehShader"); } this.bokeh_uniforms = UniformsUtils2.clone(bokeh_shader.uniforms); this.bokeh_uniforms["tColor"].value = this._rtTextureColor.texture; this.bokeh_uniforms["tDepth"].value = this._rtTextureDepth.texture; this.bokeh_uniforms["textureWidth"].value = this._resolution.x; this.bokeh_uniforms["textureHeight"].value = this._resolution.y; this.bokeh_material = new ShaderMaterial2({ uniforms: this.bokeh_uniforms, vertexShader: bokeh_shader.vertexShader, fragmentShader: bokeh_shader.fragmentShader, defines: { RINGS: shaderSettings.rings, SAMPLES: shaderSettings.samples } }); this._quad = new Mesh2(new PlaneBufferGeometry2(this._resolution.x, this._resolution.y), this.bokeh_material); this._quad.position.z = -500; this._processing_scene.add(this._quad); var depthShader = BokehDepthShader; if (!depthShader) { console.error("BokehPass relies on BokehDepthShader"); } this.materialDepth = new ShaderMaterial2({ uniforms: depthShader.uniforms, vertexShader: depthShader.vertexShader, fragmentShader: depthShader.fragmentShader }); this.materialDepthInstance = new ShaderMaterial2({ uniforms: depthShader.uniforms, vertexShader: DepthInstanceVertex, fragmentShader: depthShader.fragmentShader }); this.update_camera_uniforms_with_node(this._depth_of_field_node, this._camera); } setSize(width, height) { this._rtTextureDepth.setSize(width, height); this._rtTextureColor.setSize(width, height); this.bokeh_uniforms["textureWidth"].value = width; this.bokeh_uniforms["textureHeight"].value = height; } dispose() { this._rtTextureDepth.dispose(); this._rtTextureColor.dispose(); } render(renderer, writeBuffer, readBuffer) { const debug_display_depth = false; renderer.getClearColor(this._prev_clear_color); renderer.setClearColor(this.clear_color); renderer.clear(); renderer.setRenderTarget(this._rtTextureColor); renderer.clear(); renderer.render(this._scene, this._camera); renderer.setClearColor(0); this._core_scene.with_overriden_material(this.materialDepth, this.materialDepthInstance, this._camera_uniforms, () => { if (debug_display_depth) { renderer.setRenderTarget(null); } else { renderer.setRenderTarget(this._rtTextureDepth); } renderer.clear(); renderer.render(this._scene, this._camera); }); if (!debug_display_depth) { renderer.setRenderTarget(null); renderer.clear(); renderer.render(this._processing_scene, this._processing_camera); } renderer.setClearColor(this._prev_clear_color); } update_camera_uniforms_with_node(node, camera) { this.bokeh_uniforms["focalLength"].value = camera.getFocalLength(); this.bokeh_uniforms["znear"].value = camera.near; this.bokeh_uniforms["zfar"].value = camera.far; var sdistance = DepthOfFieldPostNode.smoothstep(camera.near, camera.far, node.pv.focalDepth); var ldistance = DepthOfFieldPostNode.linearize(1 - sdistance, camera.near, camera.far); this.bokeh_uniforms["focalDepth"].value = ldistance; this._camera_uniforms = { mNear: {value: camera.near}, mFar: {value: camera.far} }; for (let material of [this.materialDepth, this.materialDepthInstance]) { material.uniforms["mNear"].value = this._camera_uniforms["mNear"].value; material.uniforms["mFar"].value = this._camera_uniforms["mFar"].value; } } }