123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388 |
- import * as THREE from "../../libs/three.js/build/three.module.js";
- import {PointCloudSM} from "../utils/PointCloudSM.js";
- import {EyeDomeLightingMaterial} from "../materials/EyeDomeLightingMaterial.js";
- import {SphereVolume} from "../objects/tool/Volume.js";
- import {Utils} from "../utils.js";
- import {copyShader} from '../materials/shaders/otherShaders.js'
- import {Features} from "../Features.js";
- export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
- constructor(viewer){
- this.viewer = viewer;
- this.edlMaterial = null;
- //this.rtRegular;
- this.rtEDLs = new Map
- this.gl = viewer.renderer.getContext();
- //反正也没用到,注释了:
- //this.shadowMap = new PointCloudSM(this.viewer.pRenderer);
-
- viewer.addEventListener('resize',this.resize.bind(this))
- this.initEDL(viewer)
- }
- initEDL(viewer){
- if (this.edlMaterial != null) {
- return;
- }
- this.edlMaterial = new EyeDomeLightingMaterial();
- this.edlMaterial.depthTest = true;
- this.edlMaterial.depthWrite = true;
- this.edlMaterial.transparent = true;
-
-
- /* this.rtRegular = new THREE.WebGLRenderTarget(viewer.mainViewport.resolution2.x, viewer.mainViewport.resolution2.y, {
- minFilter: THREE.NearestFilter,
- magFilter: THREE.NearestFilter,
- format: THREE.RGBAFormat,
- depthTexture: new THREE.DepthTexture(undefined, undefined, THREE.UnsignedIntType)
- });
- */
-
-
-
-
- /* let copyUniforms = THREE.UniformsUtils.clone( copyShader.uniforms );
-
- this.copyMaterial = new THREE.ShaderMaterial( {
- uniforms: copyUniforms,
- vertexShader: copyShader.vertexShader,
- fragmentShader: copyShader.fragmentShader,
- //premultipliedAlpha: true,
- transparent: true,
- //blending: THREE.AdditiveBlending,
- depthTest: false,
- depthWrite: false
- }); */
-
- };
- resize(e ){
- if(Features.EXT_DEPTH.isSupported()){
- let viewport = e.viewport
-
- this.getRtEDL(viewport).setSize(viewport.resolution2.x, viewport.resolution2.y);
- }
- }
-
- clearTargets(params={}){
- const viewer = this.viewer;
- const {renderer} = viewer;
- const oldTarget = renderer.getRenderTarget();
-
- if(params.target){//add
- renderer.setRenderTarget( params.target);
- renderer.clear()
- }
-
-
-
- if(Features.EXT_DEPTH.isSupported()){
- if(params.rtEDL){
- renderer.setRenderTarget( params.rtEDL);
- renderer.clear()
- }else{
- var rtEDL = this.getRtEDL(params.viewport)
- if(rtEDL){
- renderer.setRenderTarget( rtEDL );
- renderer.clear( true, true, true );
- }
-
- }
- }
-
-
-
- //renderer.setRenderTarget( this.rtRegular );
- //renderer.clear( true, true, false );
- renderer.setRenderTarget(oldTarget);
- }
-
-
- getRtEDL(viewport){//根据不同viewport返回rtEDL的texture
- if(!viewport){
- console.warn('getRtEDL没传viewport!!!! !!!!!!!!!!')
- viewport = viewer.mainViewport
- }
- var rtEDL = this.rtEDLs.get(viewport)
- if(!rtEDL){
- if(Features.EXT_DEPTH.isSupported()){
- rtEDL = new THREE.WebGLRenderTarget(viewport.resolution2.x, viewport.resolution2.y, {
- minFilter: THREE.NearestFilter,
- magFilter: THREE.NearestFilter,
- format: THREE.RGBAFormat,
- type: THREE.FloatType,
- depthTexture: new THREE.DepthTexture(undefined, undefined, THREE.UnsignedIntType)
- });
- //注: 部分手机在resize时会崩溃,经检验去掉rtEDL的resize可以解决,所以更应该注释掉这个
-
-
- this.rtEDLs.set(viewport, rtEDL)
- }
- }
-
- return rtEDL
- }
-
- renderShadowMap(visiblePointClouds, camera, lights){
- const {viewer} = this;
- const doShadows = lights.length > 0 && !(lights[0].disableShadowUpdates);
- if(doShadows){
- let light = lights[0];
-
- this.shadowMap.setLight(light);
- let originalAttributes = new Map();
- for(let pointcloud of viewer.scene.pointclouds){
- // TODO IMPORTANT !!! check
- originalAttributes.set(pointcloud, pointcloud.material.activeAttributeName);
- pointcloud.material.disableEvents();
- pointcloud.material.activeAttributeName = "depth";
- //pointcloud.material.pointColorType = PointColorType.DEPTH;
- }
- this.shadowMap.render(viewer.scene.scenePointCloud, camera);
- for(let pointcloud of visiblePointClouds){
- let originalAttribute = originalAttributes.get(pointcloud);
- // TODO IMPORTANT !!! check
- pointcloud.material.activeAttributeName = originalAttribute;
- pointcloud.material.enableEvents();
- }
- viewer.shadowTestCam.updateMatrixWorld();
- viewer.shadowTestCam.matrixWorldInverse.copy(viewer.shadowTestCam.matrixWorld).invert();
- viewer.shadowTestCam.updateProjectionMatrix();
- }
- }
- render(params={}){
-
-
- /*
- 渲染顺序:
- 底层:背景 -> skybox(也可中间)
- 中间层(含有深度信息):1 点云、marker等mesh,
- 2 测量线(现在被做成借用depthTex
- 顶层:maginifier
- magnifier的贴图渲染不需要顶层、中间层只需要点云。
- */
-
- const viewer = this.viewer;
- let camera = params.camera ? params.camera : viewer.scene.getActiveCamera();
- const resolution = params.viewport ? params.viewport.resolution2 : this.viewer.renderer.getSize(new THREE.Vector2());
-
-
- //viewer.dispatchEvent({type: "render.pass.begin",viewer: viewer});
-
-
- let lights = [];
- /* viewer.scene.scene.traverse(node => {
- if(node.type === "SpotLight"){
- lights.push(node);
- }
- }); */
- viewer.renderer.setRenderTarget(params.target || null);
- let background = params.background || viewer.background;
- let backgroundOpacity = params.backgroundOpacity == void 0 ? viewer.backgroundOpacity : params.backgroundOpacity//如果想完全透明,只需要backgroundOpacity为0
- if(backgroundOpacity != 0){//绘制背景
- if(background === "skybox"){
- viewer.skybox.camera.rotation.copy(viewer.scene.cameraP.rotation);
- viewer.skybox.camera.fov = viewer.scene.cameraP.fov;
- viewer.skybox.camera.aspect = viewer.scene.cameraP.aspect;
- viewer.skybox.parent.rotation.x = 0;
- viewer.skybox.parent.updateMatrixWorld();
- viewer.skybox.camera.updateProjectionMatrix();
-
- viewer.renderer.render(viewer.skybox.scene, viewer.skybox.camera);
- }else if(background === 'gradient'){
- viewer.scene.cameraBG.layers.set(Potree.config.renderLayers.bg);
- viewer.renderer.render(viewer.scene.scene, viewer.scene.cameraBG);
- }else if(background === 'overlayColor'){//在不clear的前提下加一层背景色
- viewer.scene.bg2.material.color.copy(params.backgroundColor)
- viewer.scene.bg2.material.opacity = params.backgroundOpacity
- viewer.scene.cameraBG.layers.set(Potree.config.renderLayers.bg2);
- viewer.renderer.render(viewer.scene.scene, viewer.scene.cameraBG);
- }
-
- }
-
- //skybox 全景图
- if(!params.magnifier){
- viewer.setCameraLayers(camera, ['skybox'])
- let useDepthTex
- if(Potree.settings.displayMode == 'showPanos' && viewer.images360.currentPano.pointcloud.hasDepthTex && Features.EXT_DEPTH.isSupported()){//渲染深度图
- useDepthTex = true
- viewer.renderer.setRenderTarget(params.rtEDL || this.getRtEDL(params.viewport)) //将带有深度图的skybox画在rtEDL一下,这样就不需要绘制后边的点云了
- viewer.renderer.render(viewer.scene.scene, camera);
- viewer.renderer.setRenderTarget(params.target || null);
- }
- viewer.renderer.render(viewer.scene.scene, camera);
- if(useDepthTex)return
- }
-
-
- const visiblePointClouds2 = viewer.scene.pointclouds.filter(pc => viewer.getObjVisiByReason(pc,'datasetSelection') ); //需要绘制到rtEDL的
- const showPointClouds = params.magnifier ? visiblePointClouds2.length>0 : viewer.scene.pointclouds.some(e=>e.visible) //是否有需要绘制到屏幕的
-
- visiblePointClouds2.forEach(e=>{//为了绘制到depthTexture,先显示(展示全景图时隐藏了点云,所以需要显示下。且放大镜需要绘制点云)
- e.oldVisi = e.visible
- e.visible = true;
- })
-
-
- viewer.setCameraLayers(camera, ['pointcloud'])
- camera.layers.set(Potree.config.renderLayers.pointcloud);
-
- //TODO adapt to multiple lights
- //this.renderShadowMap(visiblePointClouds2, camera, lights); //???????
- {
- for (let pointcloud of visiblePointClouds2) {
-
- let material = pointcloud.material;
- let octreeSize = pointcloud.pcoGeometry.boundingBox.getSize(new THREE.Vector3()).x;
- material.fov = THREE.Math.degToRad(camera.fov)
- /* material.screenWidth = width;
- material.screenHeight = height; */
- material.resolution = resolution
-
-
-
- material.spacing = pointcloud.pcoGeometry.spacing; // * Math.max(this.scale.x, this.scale.y, this.scale.z);
- material.near = camera.near;
- material.far = camera.far;
- material.uniforms.octreeSize.value = octreeSize
-
- if(viewer.useEDL && Potree.settings.displayMode != 'showPanos'){
- /* material.weighted = false;
- material.useLogarithmicDepthBuffer = false; */
- material.useEDL = true;
- //material.fakeEDL = false; //add
- }else{
- material.useEDL = false;
- //material.fakeEDL = true; //add 使也输出深度
- }
-
- }
-
-
- if(Features.EXT_DEPTH.isSupported() && !params.dontRenderRtEDL){
- //借用rtEDL存储深度信息
- viewer.renderer.setRenderTarget(params.rtEDL || this.getRtEDL(params.viewport)/* this.rtEDL */);
-
-
- if(visiblePointClouds2.length>0){
- //渲染scenePointCloud到rtEDL
- viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, params.rtEDL || this.getRtEDL(params.viewport), {
- shadowMaps: lights.length > 0 ? [this.shadowMap] : null,
- clipSpheres: viewer.scene.volumes.filter(v => (v instanceof SphereVolume)),
- transparent: false,
- });
- }
- if(Potree.settings.intersectOnObjs){// model也要渲染到rtEDL
- camera.layers.set(Potree.config.renderLayers.model);
- viewer.objs.traverse(e=>{if(e.material)e._OlddepthWrite = e.material.depthWrite, e.material.depthWrite = true}) //否则半透明的mesh无法遮住测量线
- viewer.renderer.render(viewer.scene.scene, camera);
- viewer.objs.traverse(e=>{if(e.material)e.material.depthWrite = e._OlddepthWrite})
- //缺点:半透明的model 就算完全透明, 也会遮住测量线
- }
- //test
- /* {
- viewer.objs.traverse((obj)=>{
- if(obj.material){
- obj.material = obj.depthMat
- }
- })
- viewer.setCameraLayers(camera, ['sceneObjects'])
- viewer.renderer.render(viewer.scene.scene, camera)
- viewer.objs.traverse((obj)=>{
- if(obj.material){
- obj.material = obj.standardMat
- }
- })
- } */
- }
- }
-
-
-
-
- //渲染到rtEDL完毕
- viewer.dispatchEvent({type: "render.pass.scene", viewer: viewer/* , renderTarget: this.rtRegular */});
- viewer.renderer.setRenderTarget(params.target || null);
-
- if(!params.magnifier)visiblePointClouds2.forEach(e=>{//放大镜显示点云
- e.visible = e.oldVisi
- })
-
-
-
- if(showPointClouds){ //绘制点云到画布
- if(viewer.useEDL) { //设置edlMaterial
- //Features.EXT_DEPTH不支持的话不会到这一块
-
- const uniforms = this.edlMaterial.uniforms;
- //if(viewer.useEDL){
- /* uniforms.screenWidth.value = width;
- uniforms.screenHeight.value = height; */
- uniforms.resolution.value.copy(resolution)
-
- uniforms.edlStrength.value = viewer.edlStrength;
- uniforms.radius.value = viewer.edlRadius;
- uniforms.useEDL.value = 1;//add
- /* }else{
- uniforms.useEDL.value = 0;//add
- } */
-
- let proj = camera.projectionMatrix;
- let projArray = new Float32Array(16);
- projArray.set(proj.elements);
- uniforms.uProj.value = projArray;
-
- uniforms.uEDLColor.value = (params.rtEDL || this.getRtEDL(params.viewport)).texture;
- //uniforms.uEDLDepth.value = (params.rtEDL || this.getRtEDL(params.viewport)).depthTexture; //其实没用到
-
- uniforms.opacity.value = viewer.edlOpacity; // HACK
-
-
- Utils.screenPass.render(viewer.renderer, this.edlMaterial, params.target);
- }else{
- //渲染点云 (直接用rtEDL上的会失去抗锯齿)
-
- let prop = {
- shadowMaps: lights.length > 0 ? [this.shadowMap] : null,
- clipSpheres: viewer.scene.volumes.filter(v => (v instanceof SphereVolume)) ,
- notAdditiveBlending: Potree.settings.notAdditiveBlending//add 否则透明的点云会挡住后面的模型。 加上这句后竟然透明不会叠加了!
- }
-
- viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, null , prop);
- }
- }
-
- //viewer.dispatchEvent({type: "render.pass.end",viewer: viewer});
- visiblePointClouds2.forEach(e=>{
- e.visible = e.oldVisi
- })
-
- }
- }
|