UNPKG

cione-comp-lib

Version:

`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`

310 lines (309 loc) 12.1 kB
import "../../../echarts/lib/echarts.mjs"; import Scene from "../../../claygl/src/Scene.mjs"; import ShadowMapPass from "../../../claygl/src/prePass/ShadowMap.mjs"; import PerspectiveCamera from "../../../claygl/src/camera/Perspective.mjs"; import OrthoCamera from "../../../claygl/src/camera/Orthographic.mjs"; import Matrix4 from "../../../claygl/src/math/Matrix4.mjs"; import Vector3 from "../../../claygl/src/math/Vector3.mjs"; import Vector2 from "../../../claygl/src/math/Vector2.mjs"; import notifier from "../../../claygl/src/core/mixin/notifier.mjs"; import EffectCompositor from "../effect/EffectCompositor.mjs"; import TemporalSuperSampling from "../effect/TemporalSuperSampling.mjs"; import halton from "../effect/halton.mjs"; function ViewGL(projection) { projection = projection || "perspective"; this.layer = null; this.scene = new Scene(); this.rootNode = this.scene; this.viewport = { x: 0, y: 0, width: 0, height: 0 }; this.setProjection(projection); this._compositor = new EffectCompositor(); this._temporalSS = new TemporalSuperSampling(); this._shadowMapPass = new ShadowMapPass(); var pcfKernels = []; var off = 0; for (var i = 0; i < 30; i++) { var pcfKernel = []; for (var k = 0; k < 6; k++) { pcfKernel.push(halton(off, 2) * 4 - 2); pcfKernel.push(halton(off, 3) * 4 - 2); off++; } pcfKernels.push(pcfKernel); } this._pcfKernels = pcfKernels; this.scene.on("beforerender", function(renderer, scene, camera) { if (this.needsTemporalSS()) { this._temporalSS.jitterProjection(renderer, camera); } }, this); } ViewGL.prototype.setProjection = function(projection) { var oldCamera = this.camera; oldCamera && oldCamera.update(); if (projection === "perspective") { if (!(this.camera instanceof PerspectiveCamera)) { this.camera = new PerspectiveCamera(); if (oldCamera) { this.camera.setLocalTransform(oldCamera.localTransform); } } } else { if (!(this.camera instanceof OrthoCamera)) { this.camera = new OrthoCamera(); if (oldCamera) { this.camera.setLocalTransform(oldCamera.localTransform); } } } this.camera.near = 0.1; this.camera.far = 2e3; }; ViewGL.prototype.setViewport = function(x, y, width, height, dpr) { if (this.camera instanceof PerspectiveCamera) { this.camera.aspect = width / height; } dpr = dpr || 1; this.viewport.x = x; this.viewport.y = y; this.viewport.width = width; this.viewport.height = height; this.viewport.devicePixelRatio = dpr; this._compositor.resize(width * dpr, height * dpr); this._temporalSS.resize(width * dpr, height * dpr); }; ViewGL.prototype.containPoint = function(x, y) { var viewport = this.viewport; var height = this.layer.renderer.getHeight(); y = height - y; return x >= viewport.x && y >= viewport.y && x <= viewport.x + viewport.width && y <= viewport.y + viewport.height; }; var ndc = new Vector2(); ViewGL.prototype.castRay = function(x, y, out) { var renderer = this.layer.renderer; var oldViewport = renderer.viewport; renderer.viewport = this.viewport; renderer.screenToNDC(x, y, ndc); this.camera.castRay(ndc, out); renderer.viewport = oldViewport; return out; }; ViewGL.prototype.prepareRender = function() { this.scene.update(); this.camera.update(); this.scene.updateLights(); var renderList = this.scene.updateRenderList(this.camera); this._needsSortProgressively = false; for (var i = 0; i < renderList.transparent.length; i++) { var renderable = renderList.transparent[i]; var geometry = renderable.geometry; if (geometry.needsSortVerticesProgressively && geometry.needsSortVerticesProgressively()) { this._needsSortProgressively = true; } if (geometry.needsSortTrianglesProgressively && geometry.needsSortTrianglesProgressively()) { this._needsSortProgressively = true; } } this._frame = 0; this._temporalSS.resetFrame(); }; ViewGL.prototype.render = function(renderer, accumulating) { this._doRender(renderer, accumulating, this._frame); this._frame++; }; ViewGL.prototype.needsAccumulate = function() { return this.needsTemporalSS() || this._needsSortProgressively; }; ViewGL.prototype.needsTemporalSS = function() { var enableTemporalSS = this._enableTemporalSS; if (enableTemporalSS === "auto") { enableTemporalSS = this._enablePostEffect; } return enableTemporalSS; }; ViewGL.prototype.hasDOF = function() { return this._enableDOF; }; ViewGL.prototype.isAccumulateFinished = function() { return this.needsTemporalSS() ? this._temporalSS.isFinished() : this._frame > 30; }; ViewGL.prototype._doRender = function(renderer, accumulating, accumFrame) { var scene = this.scene; var camera = this.camera; accumFrame = accumFrame || 0; this._updateTransparent(renderer, scene, camera, accumFrame); if (!accumulating) { this._shadowMapPass.kernelPCF = this._pcfKernels[0]; this._shadowMapPass.render(renderer, scene, camera, true); } this._updateShadowPCFKernel(accumFrame); var bgColor = renderer.clearColor; renderer.gl.clearColor(bgColor[0], bgColor[1], bgColor[2], bgColor[3]); if (this._enablePostEffect) { if (this.needsTemporalSS()) { this._temporalSS.jitterProjection(renderer, camera); } this._compositor.updateNormal(renderer, scene, camera, this._temporalSS.getFrame()); } this._updateSSAO(renderer, scene, camera, this._temporalSS.getFrame()); if (this._enablePostEffect) { var frameBuffer = this._compositor.getSourceFrameBuffer(); frameBuffer.bind(renderer); renderer.gl.clear(renderer.gl.DEPTH_BUFFER_BIT | renderer.gl.COLOR_BUFFER_BIT); renderer.render(scene, camera, true, true); frameBuffer.unbind(renderer); if (this.needsTemporalSS() && accumulating) { this._compositor.composite(renderer, scene, camera, this._temporalSS.getSourceFrameBuffer(), this._temporalSS.getFrame()); renderer.setViewport(this.viewport); this._temporalSS.render(renderer); } else { renderer.setViewport(this.viewport); this._compositor.composite(renderer, scene, camera, null, 0); } } else { if (this.needsTemporalSS() && accumulating) { var frameBuffer = this._temporalSS.getSourceFrameBuffer(); frameBuffer.bind(renderer); renderer.saveClear(); renderer.clearBit = renderer.gl.DEPTH_BUFFER_BIT | renderer.gl.COLOR_BUFFER_BIT; renderer.render(scene, camera, true, true); renderer.restoreClear(); frameBuffer.unbind(renderer); renderer.setViewport(this.viewport); this._temporalSS.render(renderer); } else { renderer.setViewport(this.viewport); renderer.render(scene, camera, true, true); } } }; ViewGL.prototype._updateTransparent = function(renderer, scene, camera, frame) { var v3 = new Vector3(); var invWorldTransform = new Matrix4(); var cameraWorldPosition = camera.getWorldPosition(); var transparentList = scene.getRenderList(camera).transparent; for (var i = 0; i < transparentList.length; i++) { var renderable = transparentList[i]; var geometry = renderable.geometry; Matrix4.invert(invWorldTransform, renderable.worldTransform); Vector3.transformMat4(v3, cameraWorldPosition, invWorldTransform); if (geometry.needsSortTriangles && geometry.needsSortTriangles()) { geometry.doSortTriangles(v3, frame); } if (geometry.needsSortVertices && geometry.needsSortVertices()) { geometry.doSortVertices(v3, frame); } } }; ViewGL.prototype._updateSSAO = function(renderer, scene, camera) { var ifEnableSSAO = this._enableSSAO && this._enablePostEffect; if (ifEnableSSAO) { this._compositor.updateSSAO(renderer, scene, camera, this._temporalSS.getFrame()); } var renderList = scene.getRenderList(camera); for (var i = 0; i < renderList.opaque.length; i++) { var renderable = renderList.opaque[i]; if (renderable.renderNormal) { renderable.material[ifEnableSSAO ? "enableTexture" : "disableTexture"]("ssaoMap"); } if (ifEnableSSAO) { renderable.material.set("ssaoMap", this._compositor.getSSAOTexture()); } } }; ViewGL.prototype._updateShadowPCFKernel = function(frame) { var pcfKernel = this._pcfKernels[frame % this._pcfKernels.length]; var renderList = this.scene.getRenderList(this.camera); var opaqueList = renderList.opaque; for (var i = 0; i < opaqueList.length; i++) { if (opaqueList[i].receiveShadow) { opaqueList[i].material.set("pcfKernel", pcfKernel); opaqueList[i].material.define("fragment", "PCF_KERNEL_SIZE", pcfKernel.length / 2); } } }; ViewGL.prototype.dispose = function(renderer) { this._compositor.dispose(renderer.gl); this._temporalSS.dispose(renderer.gl); this._shadowMapPass.dispose(renderer); }; ViewGL.prototype.setPostEffect = function(postEffectModel, api) { var compositor = this._compositor; this._enablePostEffect = postEffectModel.get("enable"); var bloomModel = postEffectModel.getModel("bloom"); var edgeModel = postEffectModel.getModel("edge"); var dofModel = postEffectModel.getModel("DOF", postEffectModel.getModel("depthOfField")); var ssaoModel = postEffectModel.getModel("SSAO", postEffectModel.getModel("screenSpaceAmbientOcclusion")); var ssrModel = postEffectModel.getModel("SSR", postEffectModel.getModel("screenSpaceReflection")); var fxaaModel = postEffectModel.getModel("FXAA"); var colorCorrModel = postEffectModel.getModel("colorCorrection"); bloomModel.get("enable") ? compositor.enableBloom() : compositor.disableBloom(); dofModel.get("enable") ? compositor.enableDOF() : compositor.disableDOF(); ssrModel.get("enable") ? compositor.enableSSR() : compositor.disableSSR(); colorCorrModel.get("enable") ? compositor.enableColorCorrection() : compositor.disableColorCorrection(); edgeModel.get("enable") ? compositor.enableEdge() : compositor.disableEdge(); fxaaModel.get("enable") ? compositor.enableFXAA() : compositor.disableFXAA(); this._enableDOF = dofModel.get("enable"); this._enableSSAO = ssaoModel.get("enable"); this._enableSSAO ? compositor.enableSSAO() : compositor.disableSSAO(); compositor.setBloomIntensity(bloomModel.get("intensity")); compositor.setEdgeColor(edgeModel.get("color")); compositor.setColorLookupTexture(colorCorrModel.get("lookupTexture"), api); compositor.setExposure(colorCorrModel.get("exposure")); ["radius", "quality", "intensity"].forEach(function(name) { compositor.setSSAOParameter(name, ssaoModel.get(name)); }); ["quality", "maxRoughness", "physical"].forEach(function(name) { compositor.setSSRParameter(name, ssrModel.get(name)); }); ["quality", "focalDistance", "focalRange", "blurRadius", "fstop"].forEach(function(name) { compositor.setDOFParameter(name, dofModel.get(name)); }); ["brightness", "contrast", "saturation"].forEach(function(name) { compositor.setColorCorrection(name, colorCorrModel.get(name)); }); }; ViewGL.prototype.setDOFFocusOnPoint = function(depth) { if (this._enablePostEffect) { if (depth > this.camera.far || depth < this.camera.near) { return; } this._compositor.setDOFParameter("focalDistance", depth); return true; } }; ViewGL.prototype.setTemporalSuperSampling = function(temporalSuperSamplingModel) { this._enableTemporalSS = temporalSuperSamplingModel.get("enable"); }; ViewGL.prototype.isLinearSpace = function() { return this._enablePostEffect; }; ViewGL.prototype.setRootNode = function(rootNode) { if (this.rootNode === rootNode) { return; } var children = this.rootNode.children(); for (var i = 0; i < children.length; i++) { rootNode.add(children[i]); } if (rootNode !== this.scene) { this.scene.add(rootNode); } this.rootNode = rootNode; }; ViewGL.prototype.add = function(node3D) { this.rootNode.add(node3D); }; ViewGL.prototype.remove = function(node3D) { this.rootNode.remove(node3D); }; ViewGL.prototype.removeAll = function(node3D) { this.rootNode.removeAll(node3D); }; Object.assign(ViewGL.prototype, notifier); export { ViewGL as default };