UNPKG

bytev-charts

Version:

基于echarts和JavaScript及ES6封装的一个可以直接调用的图表组件库,内置主题设计,简单快捷,且支持用户自定义配置; npm 安装方式: npm install bytev-charts 若启动提示还需额外install插件,则运行 npm install @babel/runtime-corejs2 即可;

188 lines (155 loc) 8.19 kB
import _Object$create from "@babel/runtime-corejs2/core-js/object/create"; import "core-js/modules/es.math.sign.js"; import "core-js/modules/es.array.join.js"; import { Color, LinearFilter, MathUtils, Matrix4, Mesh, PerspectiveCamera, Plane, Quaternion, RGBFormat, ShaderMaterial, UniformsUtils, Vector3, Vector4, WebGLRenderTarget } from "../../../build/three.module.js"; var Refractor = function Refractor(geometry, options) { Mesh.call(this, geometry); this.type = 'Refractor'; var scope = this; options = options || {}; var color = options.color !== undefined ? new Color(options.color) : new Color(0x7F7F7F); var textureWidth = options.textureWidth || 512; var textureHeight = options.textureHeight || 512; var clipBias = options.clipBias || 0; var shader = options.shader || Refractor.RefractorShader; // var virtualCamera = new PerspectiveCamera(); virtualCamera.matrixAutoUpdate = false; virtualCamera.userData.refractor = true; // var refractorPlane = new Plane(); var textureMatrix = new Matrix4(); // render target var parameters = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBFormat, stencilBuffer: false }; var renderTarget = new WebGLRenderTarget(textureWidth, textureHeight, parameters); if (!MathUtils.isPowerOfTwo(textureWidth) || !MathUtils.isPowerOfTwo(textureHeight)) { renderTarget.texture.generateMipmaps = false; } // material this.material = new ShaderMaterial({ uniforms: UniformsUtils.clone(shader.uniforms), vertexShader: shader.vertexShader, fragmentShader: shader.fragmentShader, transparent: true // ensures, refractors are drawn from farthest to closest }); this.material.uniforms["color"].value = color; this.material.uniforms["tDiffuse"].value = renderTarget.texture; this.material.uniforms["textureMatrix"].value = textureMatrix; // functions var visible = function () { var refractorWorldPosition = new Vector3(); var cameraWorldPosition = new Vector3(); var rotationMatrix = new Matrix4(); var view = new Vector3(); var normal = new Vector3(); return function visible(camera) { refractorWorldPosition.setFromMatrixPosition(scope.matrixWorld); cameraWorldPosition.setFromMatrixPosition(camera.matrixWorld); view.subVectors(refractorWorldPosition, cameraWorldPosition); rotationMatrix.extractRotation(scope.matrixWorld); normal.set(0, 0, 1); normal.applyMatrix4(rotationMatrix); return view.dot(normal) < 0; }; }(); var updateRefractorPlane = function () { var normal = new Vector3(); var position = new Vector3(); var quaternion = new Quaternion(); var scale = new Vector3(); return function updateRefractorPlane() { scope.matrixWorld.decompose(position, quaternion, scale); normal.set(0, 0, 1).applyQuaternion(quaternion).normalize(); // flip the normal because we want to cull everything above the plane normal.negate(); refractorPlane.setFromNormalAndCoplanarPoint(normal, position); }; }(); var updateVirtualCamera = function () { var clipPlane = new Plane(); var clipVector = new Vector4(); var q = new Vector4(); return function updateVirtualCamera(camera) { virtualCamera.matrixWorld.copy(camera.matrixWorld); virtualCamera.matrixWorldInverse.getInverse(virtualCamera.matrixWorld); virtualCamera.projectionMatrix.copy(camera.projectionMatrix); virtualCamera.far = camera.far; // used in WebGLBackground // The following code creates an oblique view frustum for clipping. // see: Lengyel, Eric. “Oblique View Frustum Depth Projection and Clipping”. // Journal of Game Development, Vol. 1, No. 2 (2005), Charles River Media, pp. 5–16 clipPlane.copy(refractorPlane); clipPlane.applyMatrix4(virtualCamera.matrixWorldInverse); clipVector.set(clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.constant); // calculate the clip-space corner point opposite the clipping plane and // transform it into camera space by multiplying it by the inverse of the projection matrix var projectionMatrix = virtualCamera.projectionMatrix; q.x = (Math.sign(clipVector.x) + projectionMatrix.elements[8]) / projectionMatrix.elements[0]; q.y = (Math.sign(clipVector.y) + projectionMatrix.elements[9]) / projectionMatrix.elements[5]; q.z = -1.0; q.w = (1.0 + projectionMatrix.elements[10]) / projectionMatrix.elements[14]; // calculate the scaled plane vector clipVector.multiplyScalar(2.0 / clipVector.dot(q)); // replacing the third row of the projection matrix projectionMatrix.elements[2] = clipVector.x; projectionMatrix.elements[6] = clipVector.y; projectionMatrix.elements[10] = clipVector.z + 1.0 - clipBias; projectionMatrix.elements[14] = clipVector.w; }; }(); // This will update the texture matrix that is used for projective texture mapping in the shader. // see: http://developer.download.nvidia.com/assets/gamedev/docs/projective_texture_mapping.pdf function updateTextureMatrix(camera) { // this matrix does range mapping to [ 0, 1 ] textureMatrix.set(0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0); // we use "Object Linear Texgen", so we need to multiply the texture matrix T // (matrix above) with the projection and view matrix of the virtual camera // and the model matrix of the refractor textureMatrix.multiply(camera.projectionMatrix); textureMatrix.multiply(camera.matrixWorldInverse); textureMatrix.multiply(scope.matrixWorld); } // function render(renderer, scene, camera) { scope.visible = false; var currentRenderTarget = renderer.getRenderTarget(); var currentXrEnabled = renderer.xr.enabled; var currentShadowAutoUpdate = renderer.shadowMap.autoUpdate; renderer.xr.enabled = false; // avoid camera modification renderer.shadowMap.autoUpdate = false; // avoid re-computing shadows renderer.setRenderTarget(renderTarget); if (renderer.autoClear === false) renderer.clear(); renderer.render(scene, virtualCamera); renderer.xr.enabled = currentXrEnabled; renderer.shadowMap.autoUpdate = currentShadowAutoUpdate; renderer.setRenderTarget(currentRenderTarget); // restore viewport var viewport = camera.viewport; if (viewport !== undefined) { renderer.state.viewport(viewport); } scope.visible = true; } // this.onBeforeRender = function (renderer, scene, camera) { // Render renderTarget.texture.encoding = renderer.outputEncoding; // ensure refractors are rendered only once per frame if (camera.userData.refractor === true) return; // avoid rendering when the refractor is viewed from behind if (!visible(camera) === true) return; // update updateRefractorPlane(); updateTextureMatrix(camera); updateVirtualCamera(camera); render(renderer, scene, camera); }; this.getRenderTarget = function () { return renderTarget; }; }; Refractor.prototype = _Object$create(Mesh.prototype); Refractor.prototype.constructor = Refractor; Refractor.RefractorShader = { uniforms: { 'color': { value: null }, 'tDiffuse': { value: null }, 'textureMatrix': { value: null } }, vertexShader: ['uniform mat4 textureMatrix;', 'varying vec4 vUv;', 'void main() {', ' vUv = textureMatrix * vec4( position, 1.0 );', ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', '}'].join('\n'), fragmentShader: ['uniform vec3 color;', 'uniform sampler2D tDiffuse;', 'varying vec4 vUv;', 'float blendOverlay( float base, float blend ) {', ' return( base < 0.5 ? ( 2.0 * base * blend ) : ( 1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) );', '}', 'vec3 blendOverlay( vec3 base, vec3 blend ) {', ' return vec3( blendOverlay( base.r, blend.r ), blendOverlay( base.g, blend.g ), blendOverlay( base.b, blend.b ) );', '}', 'void main() {', ' vec4 base = texture2DProj( tDiffuse, vUv );', ' gl_FragColor = vec4( blendOverlay( base.rgb, color ), 1.0 );', '}'].join('\n') }; export { Refractor };