EDLRenderer.js 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  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. export class EDLRenderer{//old
  7. constructor(viewer){
  8. this.viewer = viewer;
  9. this.edlMaterial = null;
  10. this.rtRegular;
  11. this.rtEDL;
  12. this.gl = viewer.renderer.getContext();
  13. this.shadowMap = new PointCloudSM(this.viewer.pRenderer);
  14. }
  15. initEDL(){
  16. if (this.edlMaterial != null) {
  17. return;
  18. }
  19. this.edlMaterial = new EyeDomeLightingMaterial();
  20. this.edlMaterial.depthTest = true;
  21. this.edlMaterial.depthWrite = true;
  22. this.edlMaterial.transparent = true;
  23. this.rtEDL = new THREE.WebGLRenderTarget(1024, 1024, {
  24. minFilter: THREE.NearestFilter,
  25. magFilter: THREE.NearestFilter,
  26. format: THREE.RGBAFormat,
  27. type: THREE.FloatType,
  28. depthTexture: new THREE.DepthTexture(undefined, undefined, THREE.UnsignedIntType)
  29. });
  30. this.rtRegular = new THREE.WebGLRenderTarget(1024, 1024, {
  31. minFilter: THREE.NearestFilter,
  32. magFilter: THREE.NearestFilter,
  33. format: THREE.RGBAFormat,
  34. depthTexture: new THREE.DepthTexture(undefined, undefined, THREE.UnsignedIntType)
  35. });
  36. };
  37. resize(width, height){
  38. if(this.screenshot){
  39. width = this.screenshot.target.width;
  40. height = this.screenshot.target.height;
  41. }
  42. this.rtEDL.setSize(width , height);
  43. this.rtRegular.setSize(width , height);
  44. }
  45. makeScreenshot(camera, size, callback){
  46. if(camera === undefined || camera === null){
  47. camera = this.viewer.scene.getActiveCamera();
  48. }
  49. if(size === undefined || size === null){
  50. size = this.viewer.renderer.getSize(new THREE.Vector2());
  51. }
  52. let {width, height} = size;
  53. //let maxTextureSize = viewer.renderer.capabilities.maxTextureSize;
  54. //if(width * 4 <
  55. width = 2 * width;
  56. height = 2 * height;
  57. let target = new THREE.WebGLRenderTarget(width, height, {
  58. format: THREE.RGBAFormat,
  59. });
  60. this.screenshot = {
  61. target: target
  62. };
  63. // HACK? removed because of error, was this important?
  64. //this.viewer.renderer.clearTarget(target, true, true, true);
  65. this.render();
  66. let pixelCount = width * height;
  67. let buffer = new Uint8Array(4 * pixelCount);
  68. this.viewer.renderer.readRenderTargetPixels(target, 0, 0, width, height, buffer);
  69. // flip vertically
  70. let bytesPerLine = width * 4;
  71. for(let i = 0; i < parseInt(height / 2); i++){
  72. let j = height - i - 1;
  73. let lineI = buffer.slice(i * bytesPerLine, i * bytesPerLine + bytesPerLine);
  74. let lineJ = buffer.slice(j * bytesPerLine, j * bytesPerLine + bytesPerLine);
  75. buffer.set(lineJ, i * bytesPerLine);
  76. buffer.set(lineI, j * bytesPerLine);
  77. }
  78. this.screenshot.target.dispose();
  79. delete this.screenshot;
  80. return {
  81. width: width,
  82. height: height,
  83. buffer: buffer
  84. };
  85. }
  86. clearTargets(){
  87. const viewer = this.viewer;
  88. const {renderer} = viewer;
  89. const oldTarget = renderer.getRenderTarget();
  90. renderer.setRenderTarget( this.rtEDL );
  91. renderer.clear( true, true, true );
  92. renderer.setRenderTarget( this.rtRegular );
  93. renderer.clear( true, true, false );
  94. renderer.setRenderTarget(oldTarget);
  95. }
  96. clear(){
  97. this.initEDL();
  98. const viewer = this.viewer;
  99. const {renderer, background} = viewer;
  100. if(background === "skybox"){
  101. renderer.setClearColor(0x000000, 0);
  102. } else if (background === 'gradient') {
  103. renderer.setClearColor(0x000000, 0);
  104. } else if (background === 'black') {
  105. renderer.setClearColor(0x000000, 1);
  106. } else if (background === 'white') {
  107. renderer.setClearColor(0xFFFFFF, 1);
  108. } else {
  109. renderer.setClearColor(0x000000, 0);
  110. }
  111. renderer.clear();
  112. this.clearTargets();
  113. }
  114. renderShadowMap(visiblePointClouds, camera, lights){
  115. const {viewer} = this;
  116. const doShadows = lights.length > 0 && !(lights[0].disableShadowUpdates);
  117. if(doShadows){
  118. let light = lights[0];
  119. this.shadowMap.setLight(light);
  120. let originalAttributes = new Map();
  121. for(let pointcloud of viewer.scene.pointclouds){
  122. // TODO IMPORTANT !!! check
  123. originalAttributes.set(pointcloud, pointcloud.material.activeAttributeName);
  124. pointcloud.material.disableEvents();
  125. pointcloud.material.activeAttributeName = "depth";
  126. //pointcloud.material.pointColorType = PointColorType.DEPTH;
  127. }
  128. this.shadowMap.render(viewer.scene.scenePointCloud, camera);
  129. for(let pointcloud of visiblePointClouds){
  130. let originalAttribute = originalAttributes.get(pointcloud);
  131. // TODO IMPORTANT !!! check
  132. pointcloud.material.activeAttributeName = originalAttribute;
  133. pointcloud.material.enableEvents();
  134. }
  135. viewer.shadowTestCam.updateMatrixWorld();
  136. viewer.shadowTestCam.matrixWorldInverse.copy(viewer.shadowTestCam.matrixWorld).invert();
  137. viewer.shadowTestCam.updateProjectionMatrix();
  138. }
  139. }
  140. render(params){
  141. this.initEDL();
  142. const viewer = this.viewer;
  143. let camera = params.camera ? params.camera : viewer.scene.getActiveCamera();
  144. const {width, height} = this.viewer.renderer.getSize(new THREE.Vector2());
  145. viewer.dispatchEvent({type: "render.pass.begin",viewer: viewer});
  146. this.resize(width, height);
  147. const visiblePointClouds = viewer.scene.pointclouds.filter(pc => pc.visible);
  148. if(this.screenshot){
  149. let oldBudget = Potree.pointBudget;
  150. Potree.pointBudget = Math.max(10 * 1000 * 1000, 2 * oldBudget);
  151. let result = Potree.updatePointClouds(
  152. viewer.scene.pointclouds,
  153. camera,
  154. viewer.renderer);
  155. Potree.pointBudget = oldBudget;
  156. }
  157. let lights = [];
  158. viewer.scene.scene.traverse(node => {
  159. if(node.type === "SpotLight"){
  160. lights.push(node);
  161. }
  162. });
  163. if(viewer.background === "skybox"){
  164. viewer.skybox.camera.rotation.copy(viewer.scene.cameraP.rotation);
  165. viewer.skybox.camera.fov = viewer.scene.cameraP.fov;
  166. viewer.skybox.camera.aspect = viewer.scene.cameraP.aspect;
  167. viewer.skybox.parent.rotation.x = 0;
  168. viewer.skybox.parent.updateMatrixWorld();
  169. viewer.skybox.camera.updateProjectionMatrix();
  170. viewer.renderer.render(viewer.skybox.scene, viewer.skybox.camera);
  171. } else if (viewer.background === 'gradient') {
  172. viewer.renderer.render(viewer.scene.sceneBG, viewer.scene.cameraBG);
  173. }
  174. //TODO adapt to multiple lights
  175. this.renderShadowMap(visiblePointClouds, camera, lights);
  176. { // COLOR & DEPTH PASS
  177. for (let pointcloud of visiblePointClouds) {
  178. let octreeSize = pointcloud.pcoGeometry.boundingBox.getSize(new THREE.Vector3()).x;
  179. let material = pointcloud.material;
  180. material.weighted = false;
  181. material.useLogarithmicDepthBuffer = false;
  182. material.useEDL = true;
  183. material.screenWidth = width;
  184. material.screenHeight = height;
  185. material.uniforms.visibleNodes.value = pointcloud.material.visibleNodesTexture;
  186. material.uniforms.octreeSize.value = octreeSize;
  187. material.spacing = pointcloud.pcoGeometry.spacing; // * Math.max(pointcloud.scale.x, pointcloud.scale.y, pointcloud.scale.z);
  188. }
  189. // TODO adapt to multiple lights
  190. viewer.renderer.setRenderTarget(this.rtEDL);
  191. if(lights.length > 0){
  192. viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, this.rtEDL, {
  193. clipSpheres: viewer.scene.volumes.filter(v => (v instanceof SphereVolume)),
  194. shadowMaps: [this.shadowMap],
  195. transparent: false,
  196. });
  197. }else{
  198. // let test = camera.clone();
  199. // test.matrixAutoUpdate = false;
  200. // //test.updateMatrixWorld = () => {};
  201. // let mat = new THREE.Matrix4().set(
  202. // 1, 0, 0, 0,
  203. // 0, 0, 1, 0,
  204. // 0, -1, 0, 0,
  205. // 0, 0, 0, 1,
  206. // );
  207. // mat.invert()
  208. // test.matrix.multiplyMatrices(mat, test.matrix);
  209. // test.updateMatrixWorld();
  210. //test.matrixWorld.multiplyMatrices(mat, test.matrixWorld);
  211. //test.matrixWorld.multiply(mat);
  212. //test.matrixWorldInverse.invert(test.matrixWorld);
  213. //test.matrixWorldInverse.multiplyMatrices(test.matrixWorldInverse, mat);
  214. viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, this.rtEDL, {
  215. clipSpheres: viewer.scene.volumes.filter(v => (v instanceof SphereVolume)),
  216. transparent: false,
  217. });
  218. }
  219. }
  220. viewer.dispatchEvent({type: "render.pass.scene", viewer: viewer, renderTarget: this.rtRegular});
  221. viewer.renderer.setRenderTarget(null);
  222. viewer.renderer.render(viewer.scene.scene, camera);
  223. { // EDL PASS
  224. const uniforms = this.edlMaterial.uniforms;
  225. uniforms.screenWidth.value = width;
  226. uniforms.screenHeight.value = height;
  227. let proj = camera.projectionMatrix;
  228. let projArray = new Float32Array(16);
  229. projArray.set(proj.elements);
  230. uniforms.uNear.value = camera.near;
  231. uniforms.uFar.value = camera.far;
  232. uniforms.uEDLColor.value = this.rtEDL.texture;
  233. uniforms.uEDLDepth.value = this.rtEDL.depthTexture;
  234. uniforms.uProj.value = projArray;
  235. uniforms.edlStrength.value = viewer.edlStrength;
  236. uniforms.radius.value = viewer.edlRadius;
  237. uniforms.opacity.value = viewer.edlOpacity; // HACK
  238. Utils.screenPass.render(viewer.renderer, this.edlMaterial);
  239. if(this.screenshot){
  240. Utils.screenPass.render(viewer.renderer, this.edlMaterial, this.screenshot.target);
  241. }
  242. }
  243. viewer.dispatchEvent({type: "render.pass.scene", viewer: viewer});
  244. viewer.renderer.clearDepth();
  245. viewer.transformationTool.update();
  246. viewer.dispatchEvent({type: "render.pass.perspective_overlay",viewer: viewer});
  247. viewer.renderer.render(viewer.controls.sceneControls, camera);
  248. viewer.renderer.render(viewer.clippingTool.sceneVolume, camera);
  249. viewer.renderer.render(viewer.transformationTool.scene, camera);
  250. viewer.dispatchEvent({type: "render.pass.end",viewer: viewer});
  251. }
  252. }