cione-comp-lib
Version:
`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`
310 lines (309 loc) • 12.1 kB
JavaScript
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 };