EDLRenderer.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  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 "../utils/Volume.js";
  5. import {Utils} from "../utils.js";
  6. import {copyShader} from '../materials/shaders/otherShaders'
  7. export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
  8. constructor(viewer){
  9. this.viewer = viewer;
  10. this.edlMaterial = null;
  11. this.rtRegular;
  12. this.rtEDL;
  13. this.gl = viewer.renderer.getContext();
  14. this.shadowMap = new PointCloudSM(this.viewer.pRenderer);
  15. viewer.addEventListener('resize',this.resize.bind(this))
  16. this.initEDL()
  17. }
  18. initEDL(){
  19. if (this.edlMaterial != null) {
  20. return;
  21. }
  22. this.edlMaterial = new EyeDomeLightingMaterial();
  23. this.edlMaterial.depthTest = true;
  24. this.edlMaterial.depthWrite = true;
  25. this.edlMaterial.transparent = true;
  26. this.rtEDL = new THREE.WebGLRenderTarget(1024, 1024, {
  27. minFilter: THREE.NearestFilter,
  28. magFilter: THREE.NearestFilter,
  29. format: THREE.RGBAFormat,
  30. type: THREE.FloatType,
  31. depthTexture: new THREE.DepthTexture(undefined, undefined, THREE.UnsignedIntType)
  32. });
  33. this.rtRegular = new THREE.WebGLRenderTarget(1024, 1024, {
  34. minFilter: THREE.NearestFilter,
  35. magFilter: THREE.NearestFilter,
  36. format: THREE.RGBAFormat,
  37. depthTexture: new THREE.DepthTexture(undefined, undefined, THREE.UnsignedIntType)
  38. });
  39. let copyUniforms = THREE.UniformsUtils.clone( copyShader.uniforms );
  40. this.copyMaterial = new THREE.ShaderMaterial( {
  41. uniforms: copyUniforms,
  42. vertexShader: copyShader.vertexShader,
  43. fragmentShader: copyShader.fragmentShader,
  44. //premultipliedAlpha: true,
  45. transparent: true,
  46. //blending: THREE.AdditiveBlending,
  47. depthTest: false,
  48. depthWrite: false
  49. });
  50. };
  51. resize(e){
  52. //width, height
  53. /* if(this.screenshot){
  54. width = this.screenshot.target.width;
  55. height = this.screenshot.target.height;
  56. } */
  57. let resolution = e.viewport.resolution2
  58. this.rtEDL.setSize(resolution.x, resolution.y);
  59. this.rtRegular.setSize(resolution.x, resolution.y);
  60. }
  61. clearTargets(params){
  62. const viewer = this.viewer;
  63. const {renderer} = viewer;
  64. const oldTarget = renderer.getRenderTarget();
  65. if(params.target){//add
  66. renderer.setRenderTarget( params.target);
  67. renderer.clear()
  68. }
  69. if(params.rtEDL){
  70. renderer.setRenderTarget( params.rtEDL);
  71. renderer.clear()
  72. }else{
  73. renderer.setRenderTarget( this.rtEDL );
  74. renderer.clear( true, true, true );
  75. }
  76. renderer.setRenderTarget( this.rtRegular );
  77. renderer.clear( true, true, false );
  78. renderer.setRenderTarget(oldTarget);
  79. }
  80. clear(params={}){
  81. //this.initEDL();
  82. const viewer = this.viewer;
  83. const {renderer, background} = viewer;
  84. if(background === "skybox"){
  85. renderer.setClearColor(0x000000, 0);
  86. } else if (background === 'gradient') {
  87. renderer.setClearColor(0x000000, 0);
  88. } else if (background === 'black') {
  89. renderer.setClearColor(0x000000, 1);
  90. } else if (background === 'white') {
  91. renderer.setClearColor(0xFFFFFF, 1);
  92. } else {
  93. renderer.setClearColor(0x000000, 0);
  94. }
  95. params.target || renderer.clear();
  96. this.clearTargets(params);
  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 {width, height} = params.width ? params : this.viewer.renderer.getSize(new THREE.Vector2());
  136. //viewer.dispatchEvent({type: "render.pass.begin",viewer: viewer});
  137. const visiblePointClouds = viewer.scene.pointclouds.filter(pc => pc.visible );
  138. const visiblePointClouds2 = viewer.scene.pointclouds.filter(pc => pc.isVisible );
  139. const showPointClouds = viewer.scene.pointclouds.some(e=>e.visible)
  140. viewer.scene.pointclouds.forEach(e=>{//为了绘制到depthTexture,先显示(展示全景图时隐藏了点云,所以需要显示下。且放大镜需要绘制点云)
  141. e.oldVisi = e.visible
  142. if(e.isVisible)e.visible = true;
  143. })
  144. let lights = [];
  145. viewer.scene.scene.traverse(node => {
  146. if(node.type === "SpotLight"){
  147. lights.push(node);
  148. }
  149. });
  150. viewer.renderer.setRenderTarget(params.target || null);
  151. {//绘制背景
  152. if(viewer.background === "skybox"){
  153. viewer.skybox.camera.rotation.copy(viewer.scene.cameraP.rotation);
  154. viewer.skybox.camera.fov = viewer.scene.cameraP.fov;
  155. viewer.skybox.camera.aspect = viewer.scene.cameraP.aspect;
  156. viewer.skybox.parent.rotation.x = 0;
  157. viewer.skybox.parent.updateMatrixWorld();
  158. viewer.skybox.camera.updateProjectionMatrix();
  159. }else if (viewer.background === 'gradient') {
  160. }
  161. viewer.renderer.render(viewer.scene.scene, viewer.scene.cameraBG);
  162. }
  163. //skybox
  164. viewer.setCameraLayers(camera, ['skybox'])
  165. viewer.renderer.render(viewer.scene.scene, camera);
  166. //pointcloud
  167. viewer.setCameraLayers(camera, ['pointcloud'])
  168. camera.layers.set(Potree.config.renderLayers.pointcloud);
  169. //TODO adapt to multiple lights
  170. this.renderShadowMap(visiblePointClouds2, camera, lights); //???????
  171. { //scenePointCloud COLOR & DEPTH PASS
  172. for (let pointcloud of visiblePointClouds2) {
  173. let material = pointcloud.material;
  174. let octreeSize = pointcloud.pcoGeometry.boundingBox.getSize(new THREE.Vector3()).x;
  175. material.fov = THREE.Math.degToRad(camera.fov)
  176. material.screenWidth = width;
  177. material.screenHeight = height;
  178. material.spacing = pointcloud.pcoGeometry.spacing; // * Math.max(this.scale.x, this.scale.y, this.scale.z);
  179. material.near = camera.near;
  180. material.far = camera.far;
  181. material.uniforms.octreeSize.value = octreeSize
  182. if(viewer.useEDL){
  183. /* material.weighted = false;
  184. material.useLogarithmicDepthBuffer = false; */
  185. material.useEDL = true;
  186. //material.fakeEDL = false; //add
  187. }else{
  188. material.useEDL = false;
  189. //material.fakeEDL = true; //add 使也输出深度
  190. }
  191. }
  192. //借用rtEDL存储深度信息
  193. viewer.renderer.setRenderTarget(params.rtEDL || this.rtEDL);
  194. //渲染scenePointCloud到rtEDL
  195. viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, params.rtEDL || this.rtEDL, {
  196. shadowMaps: lights.length > 0 ? [this.shadowMap] : null,
  197. clipSpheres: viewer.scene.volumes.filter(v => (v instanceof SphereVolume)),
  198. transparent: false,
  199. });
  200. }
  201. //渲染到rtEDL完毕
  202. viewer.dispatchEvent({type: "render.pass.scene", viewer: viewer, renderTarget: this.rtRegular});
  203. viewer.renderer.setRenderTarget(params.target || null);
  204. viewer.scene.pointclouds.forEach(e=>{
  205. e.visible = e.oldVisi
  206. })
  207. //设置edlMaterial
  208. if(viewer.useEDL && showPointClouds /* || params.magnifier */) {
  209. // EDL PASS
  210. const uniforms = this.edlMaterial.uniforms;
  211. //if(viewer.useEDL){
  212. uniforms.screenWidth.value = width;
  213. uniforms.screenHeight.value = height;
  214. uniforms.edlStrength.value = viewer.edlStrength;
  215. uniforms.radius.value = viewer.edlRadius;
  216. uniforms.useEDL.value = 1;//add
  217. /* }else{
  218. uniforms.useEDL.value = 0;//add
  219. } */
  220. let proj = camera.projectionMatrix;
  221. let projArray = new Float32Array(16);
  222. projArray.set(proj.elements);
  223. uniforms.uProj.value = projArray;
  224. uniforms.uEDLColor.value = (params.rtEDL || this.rtEDL).texture;
  225. //uniforms.uEDLDepth.value = (params.rtEDL || this.rtEDL).depthTexture; //其实没用到
  226. uniforms.opacity.value = viewer.edlOpacity; // HACK
  227. Utils.screenPass.render(viewer.renderer, this.edlMaterial, params.target);
  228. }else{
  229. //渲染点云 (直接用rtEDL上的会失去抗锯齿)
  230. viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, null , {
  231. shadowMaps: lights.length > 0 ? [this.shadowMap] : null,
  232. clipSpheres: viewer.scene.volumes.filter(v => (v instanceof SphereVolume))
  233. });
  234. }
  235. //viewer.dispatchEvent({type: "render.pass.end",viewer: viewer});
  236. }
  237. }