import * as THREE from "../../libs/three.js/build/three.module.js"; import { EventDispatcher } from "../EventDispatcher.js"; export class ViewerBase extends EventDispatcher{ constructor(domElement, args = {}){ super() this.renderArea = domElement this.oldResolution = new THREE.Vector2() this.screenSizeInfo = { W:0, H:0, pixelRatio:1 } this.initContext(args); this.addEventListener('content_changed', ()=>{//画面改变,需要渲染 this.needRender = true }) } initContext(args){ //console.log(`initializing three.js ${THREE.REVISION}`); let width = this.renderArea.clientWidth; let height = this.renderArea.clientHeight; let contextAttributes = { alpha: true, depth: true, stencil: false, antialias: true, //premultipliedAlpha: _premultipliedAlpha, preserveDrawingBuffer: true, powerPreference: "high-performance", }; // let contextAttributes = { // alpha: false, // preserveDrawingBuffer: true, // }; // let contextAttributes = { // alpha: false, // preserveDrawingBuffer: true, // }; let canvas = document.createElement("canvas"); let context = canvas.getContext('webgl', contextAttributes ); this.renderer = new THREE.WebGLRenderer({ alpha: true, //支持透明 premultipliedAlpha: false, canvas: canvas, context: context, }); this.renderer.sortObjects = true; //原先false 打开了renderOrder才奏效 //this.renderer.setSize(width, height); this.renderer.autoClear = args.autoClear; args.clearColor && this.renderer.setClearColor(args.clearColor) this.renderArea.appendChild(this.renderer.domElement); this.renderer.domElement.tabIndex = '2222'; this.renderer.domElement.style.position = 'absolute'; this.renderer.domElement.addEventListener('mousedown', () => { this.renderer.domElement.focus(); }); //this.renderer.domElement.focus(); // NOTE: If extension errors occur, pass the string into this.renderer.extensions.get(x) before enabling // enable frag_depth extension for the interpolation shader, if available let gl = this.renderer.getContext(); gl.getExtension('EXT_frag_depth'); gl.getExtension('WEBGL_depth_texture'); gl.getExtension('WEBGL_color_buffer_float'); // Enable explicitly for more portability, EXT_color_buffer_float is the proper name in WebGL 2 if(gl.createVertexArray == null){ let extVAO = gl.getExtension('OES_vertex_array_object'); if(!extVAO){ throw new Error("OES_vertex_array_object extension not supported"); } gl.createVertexArray = extVAO.createVertexArrayOES.bind(extVAO); gl.bindVertexArray = extVAO.bindVertexArrayOES.bind(extVAO); } } updateScreenSize(o={}) { //有可能需要让viewport来判断,当窗口大小不变但viewport大小变时 var render = false, ratio, w, h; //记录应当render的大小 if (o.width != void 0 && o.height != void 0) { w = o.width h = o.height render = true ratio = 1 }else { w = this.renderArea.clientWidth; h = this.renderArea.clientHeight if(w !== this.screenSizeInfo.W || h !== this.screenSizeInfo.H || o.forceUpdateSize || this.screenSizeInfo.pixelRatio != window.devicePixelRatio){ this.screenSizeInfo.W = w this.screenSizeInfo.H = h render = true this.screenSizeInfo.pixelRatio = window.devicePixelRatio //如果player放在小窗口了,也要监测devicePixelRatio,因为缩放时client宽高不会改变 //config.isMobile ? (ratio = Math.min(window.devicePixelRatio, 2)) : (ratio = window.devicePixelRatio) ratio = window.devicePixelRatio } } if (render) { this.setSize(w, h, ratio); } } setSize(width, height, devicePixelRatio){ this.renderer.setSize(width, height, null, devicePixelRatio); // resize之后会自动clear(似乎因为setScissor ),所以一定要立刻绘制,所以setSize要在cameraChanged、update之前 //this.composer.setSize(width, height); if(this.viewports){ this.viewports.forEach((view,i)=>{ if(!view.active)return var width_ = width * view.width var height_ = height * view.height view.setResolution(Math.floor(width_), Math.floor(height_), width, height ) let aspect = width_ / height_; //camera的参数精确些,不用视口的归整的resolution像素值,否则hasChange无法为true, 导致canvasResize了但map没update从而闪烁 view.camera.aspect = aspect; if(view.camera.type == "OrthographicCamera"){ /* //不改宽度 同4dkk var heightHalf = view.camera.right / aspect view.camera.top = heightHalf view.camera.bottom = -heightHalf */ //高宽都改 使大小不随视口大小改变 navvis (直接和视口大小一致即可,通过zoom来定大小) view.camera.left = -width_/2 view.camera.right = width_/2 view.camera.bottom = -height_/2; view.camera.top = height_/2 }else{ } view.camera.updateProjectionMatrix(); }) } this.emitResizeMsg({viewport:this.viewports[0]}) //this.emitResizeMsg({resolution:this.viewports[0].resolution2, left:this.viewports[0].left, bottom:this.viewports[0].bottom}) //如果多个的话,render时会一直发送的 } emitResizeMsg(e){//切换viewport渲染时就发送一次, 通知一些材质更新resolution。 if(!e.viewport.resolution.equals(this.oldResolution)){ this.dispatchEvent({viewport:e.viewport, type:'resize'}) } this.oldResolution.copy(e.viewport.resolution) } cameraChanged() {//判断相机是否改变 var changed = false; /* if(this.needRender){ this.needRender = false return true } */ for(let i=0,j=this.viewports.length;i