EDLRenderer.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. import * as THREE from "../../libs/three.js/build/three.module.js";
  2. import {PointCloudSM} from "../utils/PointCloudSM.js";
  3. import {EyeDomeLightingMaterial} from "../materials/EyeDomeLightingMaterial.js";
  4. import {SphereVolume} from "../objects/tool/Volume.js";
  5. import {Utils} from "../utils.js";
  6. import {copyShader} from '../materials/shaders/otherShaders'
  7. import {Features} from "../Features.js";
  8. export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
  9. constructor(viewer){
  10. this.viewer = viewer;
  11. this.edlMaterial = null;
  12. //this.rtRegular;
  13. this.rtEDLs = new Map
  14. this.gl = viewer.renderer.getContext();
  15. //反正也没用到,注释了:
  16. //this.shadowMap = new PointCloudSM(this.viewer.pRenderer);
  17. viewer.addEventListener('resize',this.resize.bind(this))
  18. this.initEDL(viewer)
  19. }
  20. initEDL(viewer){
  21. if (this.edlMaterial != null) {
  22. return;
  23. }
  24. this.edlMaterial = new EyeDomeLightingMaterial();
  25. this.edlMaterial.depthTest = true;
  26. this.edlMaterial.depthWrite = true;
  27. this.edlMaterial.transparent = true;
  28. /* this.rtRegular = new THREE.WebGLRenderTarget(viewer.mainViewport.resolution2.x, viewer.mainViewport.resolution2.y, {
  29. minFilter: THREE.NearestFilter,
  30. magFilter: THREE.NearestFilter,
  31. format: THREE.RGBAFormat,
  32. depthTexture: new THREE.DepthTexture(undefined, undefined, THREE.UnsignedIntType)
  33. });
  34. */
  35. /* let copyUniforms = THREE.UniformsUtils.clone( copyShader.uniforms );
  36. this.copyMaterial = new THREE.ShaderMaterial( {
  37. uniforms: copyUniforms,
  38. vertexShader: copyShader.vertexShader,
  39. fragmentShader: copyShader.fragmentShader,
  40. //premultipliedAlpha: true,
  41. transparent: true,
  42. //blending: THREE.AdditiveBlending,
  43. depthTest: false,
  44. depthWrite: false
  45. }); */
  46. };
  47. resize(e ){
  48. if(Features.EXT_DEPTH.isSupported()){
  49. let viewport = e.viewport
  50. this.getRtEDL(viewport).setSize(viewport.resolution2.x, viewport.resolution2.y);
  51. }
  52. }
  53. clearTargets(params={}){
  54. const viewer = this.viewer;
  55. const {renderer} = viewer;
  56. const oldTarget = renderer.getRenderTarget();
  57. if(params.target){//add
  58. renderer.setRenderTarget( params.target);
  59. renderer.clear()
  60. }
  61. if(Features.EXT_DEPTH.isSupported()){
  62. if(params.rtEDL){
  63. renderer.setRenderTarget( params.rtEDL);
  64. renderer.clear()
  65. }else{
  66. var rtEDL = this.getRtEDL(params.viewport)
  67. if(rtEDL){
  68. renderer.setRenderTarget( rtEDL );
  69. renderer.clear( true, true, true );
  70. }
  71. }
  72. }
  73. //renderer.setRenderTarget( this.rtRegular );
  74. //renderer.clear( true, true, false );
  75. renderer.setRenderTarget(oldTarget);
  76. }
  77. getRtEDL(viewport){//根据不同viewport返回rtEDL的texture
  78. if(!viewport){
  79. console.warn('getRtEDL没传viewport!!!! !!!!!!!!!!')
  80. viewport = viewer.mainViewport
  81. }
  82. var rtEDL = this.rtEDLs.get(viewport)
  83. if(!rtEDL){
  84. if(Features.EXT_DEPTH.isSupported()){
  85. rtEDL = new THREE.WebGLRenderTarget(viewport.resolution2.x, viewport.resolution2.y, {
  86. minFilter: THREE.NearestFilter,
  87. magFilter: THREE.NearestFilter,
  88. format: THREE.RGBAFormat,
  89. type: THREE.FloatType,
  90. depthTexture: new THREE.DepthTexture(undefined, undefined, THREE.UnsignedIntType)
  91. });
  92. //注: 部分手机在resize时会崩溃,经检验去掉rtEDL的resize可以解决,所以更应该注释掉这个
  93. this.rtEDLs.set(viewport, rtEDL)
  94. }
  95. }
  96. return rtEDL
  97. }
  98. renderShadowMap(visiblePointClouds, camera, lights){
  99. const {viewer} = this;
  100. const doShadows = lights.length > 0 && !(lights[0].disableShadowUpdates);
  101. if(doShadows){
  102. let light = lights[0];
  103. this.shadowMap.setLight(light);
  104. let originalAttributes = new Map();
  105. for(let pointcloud of viewer.scene.pointclouds){
  106. // TODO IMPORTANT !!! check
  107. originalAttributes.set(pointcloud, pointcloud.material.activeAttributeName);
  108. pointcloud.material.disableEvents();
  109. pointcloud.material.activeAttributeName = "depth";
  110. //pointcloud.material.pointColorType = PointColorType.DEPTH;
  111. }
  112. this.shadowMap.render(viewer.scene.scenePointCloud, camera);
  113. for(let pointcloud of visiblePointClouds){
  114. let originalAttribute = originalAttributes.get(pointcloud);
  115. // TODO IMPORTANT !!! check
  116. pointcloud.material.activeAttributeName = originalAttribute;
  117. pointcloud.material.enableEvents();
  118. }
  119. viewer.shadowTestCam.updateMatrixWorld();
  120. viewer.shadowTestCam.matrixWorldInverse.copy(viewer.shadowTestCam.matrixWorld).invert();
  121. viewer.shadowTestCam.updateProjectionMatrix();
  122. }
  123. }
  124. render(params={}){
  125. /*
  126. 渲染顺序:
  127. 底层:背景 -> skybox(也可中间)
  128. 中间层(含有深度信息):1 点云、marker等mesh,
  129. 2 测量线(现在被做成借用depthTex
  130. 顶层:maginifier
  131. magnifier的贴图渲染不需要顶层、中间层只需要点云。
  132. */
  133. const viewer = this.viewer;
  134. let camera = params.camera ? params.camera : viewer.scene.getActiveCamera();
  135. const resolution = params.viewport ? params.viewport.resolution2 : this.viewer.renderer.getSize(new THREE.Vector2());
  136. //viewer.dispatchEvent({type: "render.pass.begin",viewer: viewer});
  137. let lights = [];
  138. /* viewer.scene.scene.traverse(node => {
  139. if(node.type === "SpotLight"){
  140. lights.push(node);
  141. }
  142. }); */
  143. viewer.renderer.setRenderTarget(params.target || null);
  144. let background = params.background || viewer.background;
  145. let backgroundOpacity = params.backgroundOpacity == void 0 ? viewer.backgroundOpacity : params.backgroundOpacity//如果想完全透明,只需要backgroundOpacity为0
  146. if(backgroundOpacity != 0){//绘制背景
  147. if(background === "skybox"){
  148. viewer.skybox.camera.rotation.copy(viewer.scene.cameraP.rotation);
  149. viewer.skybox.camera.fov = viewer.scene.cameraP.fov;
  150. viewer.skybox.camera.aspect = viewer.scene.cameraP.aspect;
  151. viewer.skybox.parent.rotation.x = 0;
  152. viewer.skybox.parent.updateMatrixWorld();
  153. viewer.skybox.camera.updateProjectionMatrix();
  154. viewer.renderer.render(viewer.skybox.scene, viewer.skybox.camera);
  155. }else if(background === 'gradient'){
  156. viewer.scene.cameraBG.layers.set(Potree.config.renderLayers.bg);
  157. viewer.renderer.render(viewer.scene.scene, viewer.scene.cameraBG);
  158. }else if(background === 'overlayColor'){//在不clear的前提下加一层背景色
  159. viewer.scene.bg2.material.color.copy(params.backgroundColor)
  160. viewer.scene.bg2.material.opacity = params.backgroundOpacity
  161. viewer.scene.cameraBG.layers.set(Potree.config.renderLayers.bg2);
  162. viewer.renderer.render(viewer.scene.scene, viewer.scene.cameraBG);
  163. }
  164. }
  165. //skybox 全景图
  166. if(!params.magnifier){
  167. viewer.setCameraLayers(camera, ['skybox'])
  168. if(Potree.settings.hasDepthTex && Potree.settings.displayMode == 'showPanos' && Features.EXT_DEPTH.isSupported()){//渲染深度图
  169. viewer.renderer.setRenderTarget(params.rtEDL || this.getRtEDL(params.viewport))
  170. viewer.renderer.render(viewer.scene.scene, camera);
  171. viewer.renderer.setRenderTarget(params.target || null);
  172. }
  173. viewer.renderer.render(viewer.scene.scene, camera);
  174. if(Potree.settings.hasDepthTex && Potree.settings.displayMode == 'showPanos' )return
  175. }
  176. //const visiblePointClouds = viewer.scene.pointclouds.filter(pc => pc.visible );
  177. const visiblePointClouds2 = viewer.scene.pointclouds.filter(pc => viewer.getObjVisiByReason(pc,'datasetSelection') );
  178. const showPointClouds = viewer.scene.pointclouds.some(e=>e.visible)
  179. viewer.scene.pointclouds.forEach(e=>{//为了绘制到depthTexture,先显示(展示全景图时隐藏了点云,所以需要显示下。且放大镜需要绘制点云)
  180. e.oldVisi = e.visible
  181. if(viewer.getObjVisiByReason(e, 'datasetSelection') ) e.visible = true;
  182. })
  183. //pointcloud
  184. viewer.setCameraLayers(camera, ['pointcloud'])
  185. camera.layers.set(Potree.config.renderLayers.pointcloud);
  186. //TODO adapt to multiple lights
  187. //this.renderShadowMap(visiblePointClouds2, camera, lights); //???????
  188. { //scenePointCloud COLOR & DEPTH PASS
  189. for (let pointcloud of visiblePointClouds2) {
  190. let material = pointcloud.material;
  191. let octreeSize = pointcloud.pcoGeometry.boundingBox.getSize(new THREE.Vector3()).x;
  192. material.fov = THREE.Math.degToRad(camera.fov)
  193. /* material.screenWidth = width;
  194. material.screenHeight = height; */
  195. material.resolution = resolution
  196. material.spacing = pointcloud.pcoGeometry.spacing; // * Math.max(this.scale.x, this.scale.y, this.scale.z);
  197. material.near = camera.near;
  198. material.far = camera.far;
  199. material.uniforms.octreeSize.value = octreeSize
  200. if(viewer.useEDL && Potree.settings.displayMode != 'showPanos'){
  201. /* material.weighted = false;
  202. material.useLogarithmicDepthBuffer = false; */
  203. material.useEDL = true;
  204. //material.fakeEDL = false; //add
  205. }else{
  206. material.useEDL = false;
  207. //material.fakeEDL = true; //add 使也输出深度
  208. }
  209. }
  210. if(Features.EXT_DEPTH.isSupported()){
  211. //借用rtEDL存储深度信息
  212. viewer.renderer.setRenderTarget(params.rtEDL || this.getRtEDL(params.viewport)/* this.rtEDL */);
  213. //pointDensity已经使用的是panorama模式,在画面边缘点云会稀疏,遮挡效果差
  214. /* if(Potree.settings.displayMode == "showPanos"){ //还原成点云模式的材质,且可能要更大些,因点云变稀疏
  215. var matBefore = {
  216. pointSizeType : new Map(),
  217. size : new Map(),
  218. usePanoMap : new Map(),
  219. }
  220. for (let pointcloud of visiblePointClouds2) {
  221. matBefore.usePanoMap.set(pointcloud, pointcloud.material.usePanoMap)
  222. //matBefore.pointSizeType.set(pointcloud, pointcloud.material.pointSizeType)
  223. matBefore.size.set(pointcloud, pointcloud.temp.pointSize)
  224. //pointcloud.material.pointSizeType = Potree.config.material.pointSizeType //不能修改这项,因为是define,会卡。
  225. //pointcloud.changePointSize(pointcloud.temp.pointSize * (1+Potree.config.material.sizeAddAtPanoRtEDL))
  226. //pointcloud.changePointSize(Potree.config.material.sizeAtPanoRtEDL, true)
  227. pointcloud.material.usePanoMap = false //禁止使用absolutePanoramaSize大小
  228. }
  229. } */
  230. //渲染scenePointCloud到rtEDL
  231. viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, params.rtEDL || this.getRtEDL(params.viewport), {
  232. shadowMaps: lights.length > 0 ? [this.shadowMap] : null,
  233. clipSpheres: viewer.scene.volumes.filter(v => (v instanceof SphereVolume)),
  234. transparent: false,
  235. });
  236. /* if(Potree.settings.displayMode == "showPanos"){
  237. for (let pointcloud of visiblePointClouds2) {
  238. //pointcloud.material.pointSizeType = matBefore.pointSizeType.get(pointcloud)
  239. pointcloud.material.usePanoMap = matBefore.usePanoMap.get(pointcloud)
  240. //pointcloud.changePointSize(matBefore.size.get(pointcloud))
  241. }
  242. } */
  243. }
  244. }
  245. //渲染到rtEDL完毕
  246. viewer.dispatchEvent({type: "render.pass.scene", viewer: viewer/* , renderTarget: this.rtRegular */});
  247. viewer.renderer.setRenderTarget(params.target || null);
  248. if(!params.magnifier)viewer.scene.pointclouds.forEach(e=>{//放大镜显示点云
  249. e.visible = e.oldVisi
  250. })
  251. //设置edlMaterial
  252. if(viewer.useEDL && showPointClouds /* || params.magnifier */) {
  253. //Features.EXT_DEPTH不支持的话不会到这一块
  254. const uniforms = this.edlMaterial.uniforms;
  255. //if(viewer.useEDL){
  256. /* uniforms.screenWidth.value = width;
  257. uniforms.screenHeight.value = height; */
  258. uniforms.resolution.value.copy(resolution)
  259. uniforms.edlStrength.value = viewer.edlStrength;
  260. uniforms.radius.value = viewer.edlRadius;
  261. uniforms.useEDL.value = 1;//add
  262. /* }else{
  263. uniforms.useEDL.value = 0;//add
  264. } */
  265. let proj = camera.projectionMatrix;
  266. let projArray = new Float32Array(16);
  267. projArray.set(proj.elements);
  268. uniforms.uProj.value = projArray;
  269. uniforms.uEDLColor.value = (params.rtEDL || this.getRtEDL(params.viewport)).texture;
  270. //uniforms.uEDLDepth.value = (params.rtEDL || this.getRtEDL(params.viewport)).depthTexture; //其实没用到
  271. uniforms.opacity.value = viewer.edlOpacity; // HACK
  272. Utils.screenPass.render(viewer.renderer, this.edlMaterial, params.target);
  273. }else{
  274. //渲染点云 (直接用rtEDL上的会失去抗锯齿)
  275. viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, null , {
  276. shadowMaps: lights.length > 0 ? [this.shadowMap] : null,
  277. clipSpheres: viewer.scene.volumes.filter(v => (v instanceof SphereVolume))
  278. });
  279. }
  280. //viewer.dispatchEvent({type: "render.pass.end",viewer: viewer});
  281. viewer.scene.pointclouds.forEach(e=>{
  282. e.visible = e.oldVisi
  283. })
  284. }
  285. }