EDLRendererNew.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. import * as THREE from "../../libs/three.js/build/three.module.js";
  2. import {PointCloudSM} from "../utils/PointCloudSM.js";
  3. import {ExtendEyeDomeLightingMaterial} from "../materials/ExtendEyeDomeLightingMaterial.js";
  4. import {SphereVolume} from "../utils/Volume.js";
  5. import {Utils} from "../utils.js";
  6. import {copyShader} from '../materials/shaders/otherShaders.js'
  7. import {Features} from "../Features.js";
  8. import {easing} from "../custom/utils/transitions.js";
  9. //import DepthTexSampler from "../custom/utils/DepthTexSampler.js";
  10. export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
  11. constructor(viewer){
  12. this.viewer = viewer;
  13. this.edlMaterial = null;
  14. //this.rtRegular;
  15. this.rtEDLs = new Map
  16. this.gl = viewer.renderer.getContext();
  17. //反正也没用到,注释了:
  18. //this.shadowMap = new PointCloudSM(this.viewer.pRenderer);
  19. viewer.addEventListener('resize',this.resize.bind(this))
  20. this.initEDL(viewer)
  21. }
  22. initEDL(viewer){
  23. if (this.edlMaterial != null || !Features.EXT_DEPTH.isSupported()){
  24. return;
  25. }
  26. this.edlMaterial = new ExtendEyeDomeLightingMaterial();
  27. this.edlMaterial.depthTest = true;
  28. this.edlMaterial.depthWrite = true;
  29. this.edlMaterial.transparent = true;
  30. let copyUniforms = THREE.UniformsUtils.clone( copyShader.uniforms );
  31. this.recoverToScreenMat = new THREE.ShaderMaterial({
  32. uniforms: copyUniforms,
  33. vertexShader:copyShader.vertexShader,
  34. fragmentShader: copyShader.fragmentShader,
  35. transparent: true,
  36. defines:{
  37. useDepth: true
  38. }
  39. })
  40. /* let copyUniforms = THREE.UniformsUtils.clone( copyShader.uniforms );
  41. this.copyMaterial = new THREE.ShaderMaterial( {
  42. uniforms: copyUniforms,
  43. vertexShader: copyShader.vertexShader,
  44. fragmentShader: copyShader.fragmentShader,
  45. //premultipliedAlpha: true,
  46. transparent: true,
  47. //blending: THREE.AdditiveBlending,
  48. depthTest: false,
  49. depthWrite: false
  50. }); */
  51. if(Potree.settings.useRTskybox){
  52. viewer.images360.addEventListener('endChangeMode',()=>{
  53. this.resize({viewport:viewer.mainViewport})
  54. })
  55. }
  56. //this.depthTexSampler = new DepthTexSampler(this);
  57. };
  58. resize(e){
  59. if(Features.EXT_DEPTH.isSupported()){
  60. let viewport = e.viewport
  61. let size = Potree.settings.useRTskybox && Potree.settings.displayMode == 'showPanos' ? viewport.resolution2 : viewport.resolution; //若要渲染skybox,需要和设备一样精度的rt
  62. this.getRtEDL(viewport).setSize( size.x, size.y ); //理论上可以是任意尺寸,但会影响精度,且aspect最好和渲染的一致
  63. }
  64. }
  65. clearTargets(params={}){
  66. const viewer = this.viewer;
  67. const {renderer} = viewer;
  68. const oldTarget = renderer.getRenderTarget();
  69. if(params.target){//add
  70. renderer.setRenderTarget( params.target);
  71. renderer.clear()
  72. }
  73. if(Features.EXT_DEPTH.isSupported()){
  74. if(params.rtEDL){
  75. renderer.setRenderTarget( params.rtEDL);
  76. renderer.clear()
  77. }else{
  78. var rtEDL = this.getRtEDL(params.viewport)
  79. if(rtEDL){
  80. renderer.setRenderTarget( rtEDL );
  81. renderer.clear( true, true, true );
  82. }
  83. }
  84. }
  85. //renderer.setRenderTarget( this.rtRegular );
  86. //renderer.clear( true, true, false );
  87. renderer.setRenderTarget(oldTarget);
  88. }
  89. getRtEDL(viewport){//根据不同viewport返回rtEDL的texture
  90. if(!viewport){
  91. console.warn('getRtEDL没传viewport!!!! !!!!!!!!!!')
  92. viewport = viewer.mainViewport
  93. }
  94. var rtEDL = this.rtEDLs.get(viewport)
  95. if(!rtEDL){
  96. if(Features.EXT_DEPTH.isSupported()){
  97. rtEDL = new THREE.WebGLRenderTarget(viewport.resolution.x, viewport.resolution.y, {
  98. minFilter: THREE.NearestFilter,
  99. magFilter: THREE.NearestFilter,
  100. format: THREE.RGBAFormat,
  101. type: THREE.FloatType,
  102. depthTexture: new THREE.DepthTexture(undefined, undefined, THREE.UnsignedIntType)
  103. });
  104. //注: 部分手机在resize时会崩溃,经检验去掉rtEDL的resize可以解决,所以更应该注释掉这个
  105. this.rtEDLs.set(viewport, rtEDL)
  106. }
  107. }
  108. return rtEDL
  109. }
  110. renderShadowMap(visiblePointClouds, camera, lights){
  111. const {viewer} = this;
  112. const doShadows = lights.length > 0 && !(lights[0].disableShadowUpdates);
  113. if(doShadows){
  114. let light = lights[0];
  115. this.shadowMap.setLight(light);
  116. let originalAttributes = new Map();
  117. for(let pointcloud of viewer.scene.pointclouds){
  118. // TODO IMPORTANT !!! check
  119. originalAttributes.set(pointcloud, pointcloud.material.activeAttributeName);
  120. pointcloud.material.disableEvents();
  121. pointcloud.material.activeAttributeName = "depth";
  122. //pointcloud.material.pointColorType = PointColorType.DEPTH;
  123. }
  124. this.shadowMap.render(viewer.scene.scenePointCloud, camera);
  125. for(let pointcloud of visiblePointClouds){
  126. let originalAttribute = originalAttributes.get(pointcloud);
  127. // TODO IMPORTANT !!! check
  128. pointcloud.material.activeAttributeName = originalAttribute;
  129. pointcloud.material.enableEvents();
  130. }
  131. viewer.shadowTestCam.updateMatrixWorld();
  132. viewer.shadowTestCam.matrixWorldInverse.copy(viewer.shadowTestCam.matrixWorld).invert();
  133. viewer.shadowTestCam.updateProjectionMatrix();
  134. }
  135. }
  136. render(params={}){
  137. const viewer = this.viewer;
  138. let camera = params.camera ? params.camera : viewer.scene.getActiveCamera();
  139. const resolution = params.viewport ? params.viewport.resolution : this.viewer.renderer.getSize(new THREE.Vector2());//突然发现mobile用resolution2点云会放大
  140. let rtEDL = Features.EXT_DEPTH.isSupported() && camera.type != "OrthographicCamera" && !params.dontRenderRtEDL && (params.rtEDL || this.getRtEDL(params.viewport)) // 平面相机不用depthTex直接打开depthTest?且不使用edl
  141. let useEDL = viewer.useEDL && rtEDL && Potree.settings.displayMode != 'showPanos'
  142. let target = params.target || null
  143. viewer.renderer.setRenderTarget(target);
  144. //viewer.dispatchEvent({type: "render.pass.begin",viewer: viewer});
  145. let lights = [];
  146. /* viewer.scene.scene.traverse(node => {
  147. if(node.type === "SpotLight"){
  148. lights.push(node);
  149. }
  150. }); */
  151. //skybox 全景图
  152. if(!params.magnifier){
  153. Potree.Utils.setCameraLayers(camera, ['skybox'])
  154. let useDepthTex
  155. if(Potree.settings.displayMode == 'showPanos' && viewer.images360.currentPano.pointcloud.hasDepthTex && rtEDL){//渲染深度图
  156. useDepthTex = true
  157. viewer.renderer.setRenderTarget(rtEDL) //将带有深度图的skybox画在rtEDL一下,这样就不需要绘制后边的点云了
  158. viewer.renderer.render(viewer.scene.scene, camera);
  159. viewer.renderer.setRenderTarget(target);
  160. if(Potree.settings.useRTskybox){//直接使用rtEDL,但是会失去抗锯齿,不知在skybox上需要抗锯齿吗
  161. this.recoverToScreenMat.uniforms.depthTex.value = rtEDL.depthTexture
  162. this.recoverToScreenMat.uniforms.tDiffuse.value = rtEDL.texture
  163. Utils.screenPass.render(viewer.renderer, this.recoverToScreenMat, target);
  164. }else{
  165. viewer.renderer.render(viewer.scene.scene, camera);
  166. }
  167. }else{
  168. viewer.renderer.render(viewer.scene.scene, camera);
  169. }
  170. if(useDepthTex)return
  171. }
  172. const visiblePointClouds2 = viewer.scene.pointclouds.filter(pc => Potree.Utils.getObjVisiByReason(pc,'datasetSelection') ); //需要绘制到rtEDL的
  173. const showPointClouds = params.magnifier ? visiblePointClouds2.length>0 : viewer.scene.pointclouds.some(e=>e.visible) //是否有需要绘制到屏幕的
  174. visiblePointClouds2.forEach(e=>{//为了绘制到depthTexture,先显示(展示全景图时隐藏了点云,所以需要显示下。且放大镜需要绘制点云)
  175. e.oldVisi = e.visible
  176. e.visible = true;
  177. })
  178. Potree.Utils.setCameraLayers(camera, ['pointcloud'])
  179. camera.layers.set(Potree.config.renderLayers.pointcloud);
  180. //TODO adapt to multiple lights
  181. //this.renderShadowMap(visiblePointClouds2, camera, lights); //???????
  182. {
  183. for (let pointcloud of visiblePointClouds2) {
  184. let material = pointcloud.material;
  185. let octreeSize = pointcloud.pcoGeometry.boundingBox.getSize(new THREE.Vector3()).x;
  186. material.fov = THREE.Math.degToRad(camera.fov)
  187. material.resolution = resolution
  188. material.spacing = pointcloud.pcoGeometry.spacing; // * Math.max(this.scale.x, this.scale.y, this.scale.z);
  189. material.near = camera.near;
  190. material.far = camera.far;
  191. material.uniforms.octreeSize.value = octreeSize
  192. if(useEDL ){
  193. material.useEDL = true;
  194. //material.fakeEDL = false; //add
  195. }else{
  196. material.useEDL = false;
  197. //material.fakeEDL = true; //add 使也输出深度
  198. }
  199. }
  200. if(rtEDL/* Features.EXT_DEPTH.isSupported() && !params.dontRenderRtEDL */){ //借用rtEDL存储深度信息
  201. viewer.renderer.setRenderTarget( rtEDL );
  202. if(visiblePointClouds2.length>0){ //渲染scenePointCloud到rtEDL
  203. viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, rtEDL, {
  204. shadowMaps: lights.length > 0 ? [this.shadowMap] : null,
  205. clipSpheres: viewer.scene.volumes.filter(v => (v instanceof SphereVolume)),
  206. transparent: false,
  207. });
  208. }
  209. if(Potree.settings.intersectOnObjs){// model也要渲染到rtEDL
  210. camera.layers.set(Potree.config.renderLayers.model);
  211. viewer.objs.traverse(e=>{if(e.material)e._OlddepthWrite = e.material.depthWrite, e.material.depthWrite = true}) //否则半透明的mesh无法遮住测量线
  212. viewer.renderer.render(viewer.scene.scene, camera);
  213. viewer.objs.traverse(e=>{if(e.material)e.material.depthWrite = e._OlddepthWrite})
  214. //缺点:半透明的model 就算完全透明, 也会遮住测量线
  215. }
  216. }
  217. }
  218. //渲染到rtEDL完毕
  219. viewer.dispatchEvent({type: "render.pass.scene", viewer: viewer });
  220. viewer.renderer.setRenderTarget( target );
  221. if(!params.magnifier)visiblePointClouds2.forEach(e=>{//放大镜显示点云
  222. e.visible = e.oldVisi
  223. })
  224. if(showPointClouds){ //绘制点云到画布
  225. if(useEDL) { //设置edlMaterial //Features.EXT_DEPTH不支持的话不会到这一块
  226. const uniforms = this.edlMaterial.uniforms;
  227. uniforms.resolution.value.copy(resolution)
  228. uniforms.edlStrength.value = viewer.edlStrength;
  229. uniforms.radius.value = viewer.edlRadius;
  230. uniforms.useEDL.value = 1;//add
  231. let proj = camera.projectionMatrix;
  232. let projArray = new Float32Array(16);
  233. projArray.set(proj.elements);
  234. uniforms.uProj.value = projArray;
  235. uniforms.uEDLColor.value = rtEDL.texture;
  236. uniforms.opacity.value = viewer.edlOpacity; // HACK
  237. Utils.screenPass.render(viewer.renderer, this.edlMaterial, target); //相当于一个描边后期特效。 缺点: 因为target上的没有抗锯齿,所以点云在晃动镜头时会不稳定地闪烁1px位置。优点:比不打开edl少绘制一次点云,更流畅了?!
  238. }else{
  239. //渲染点云 (直接用rtEDL上的会失去抗锯齿, 导致频闪、密集时出现条纹, 自己写抗锯齿也要渲染好几次。另外透明度也要处理下)
  240. let prop = {
  241. shadowMaps: lights.length > 0 ? [this.shadowMap] : null,
  242. clipSpheres: viewer.scene.volumes.filter(v => (v instanceof SphereVolume)) ,
  243. notAdditiveBlending: Potree.settings.notAdditiveBlending//add 否则透明的点云会挡住后面的模型。 加上这句后竟然透明不会叠加了!
  244. }
  245. viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, null , prop);
  246. }
  247. }
  248. visiblePointClouds2.forEach(e=>{
  249. e.visible = e.oldVisi
  250. })
  251. //viewer.dispatchEvent({type: "render.pass.end",viewer: viewer});
  252. }
  253. /*
  254. 渲染顺序:
  255. 底层:背景 -> skybox(也可中间)
  256. 中间层(含有深度信息):1 点云、marker等mesh,
  257. 2 测量线(现在被做成借用depthTex
  258. 顶层:maginifier
  259. magnifier的贴图渲染不需要顶层、中间层只需要点云。
  260. */
  261. }