ModelTextureMaterial.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. import * as THREE from "../../../libs/three.js/build/three.module.js";
  2. import Common from '../utils/Common.js'
  3. import {Features} from "../../Features.js";
  4. const prefixVertex ="precision highp float;\nprecision highp int;\n\nuniform mat4 modelMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat3 normalMatrix;\nuniform vec3 cameraPosition;\nattribute vec3 position;\nattribute vec3 normal;\nattribute vec2 uv;\n"
  5. const prefixFragment ="precision highp float;\nprecision highp int;\n\nuniform mat4 viewMatrix;\nuniform vec3 cameraPosition;\n"
  6. let shader = {
  7. uniforms: {
  8. opacity: {
  9. type: "f",
  10. // value: 1
  11. },
  12. progress: {
  13. type: "f",
  14. value: 0
  15. },
  16. pano0Map: {
  17. type: "t",
  18. value: null
  19. },
  20. pano1Map: {
  21. type: "t",
  22. value: null
  23. },
  24. depthMap0: {
  25. type: "t",
  26. value: null
  27. },
  28. depthMap1: {
  29. type: "t",
  30. value: null
  31. },
  32. pano0Position: {
  33. type: "v3",
  34. value: new THREE.Vector3
  35. },
  36. pano0Matrix: {
  37. type: "m4",
  38. value: new THREE.Matrix4
  39. },
  40. pano1Position: {
  41. type: "v3",
  42. value: new THREE.Vector3
  43. },
  44. pano1Matrix: {
  45. type: "m4",
  46. value: new THREE.Matrix4
  47. },
  48. /* pano1Matrix2: {
  49. type: "m4",
  50. value: new THREE.Matrix4
  51. },
  52. */
  53. inverseProjectionMatrix: {
  54. value: new THREE.Matrix4
  55. },
  56. /* projectionMatrix:{//需要再写一遍吗
  57. value: new THREE.Matrix4
  58. }, */
  59. viewport: {
  60. value: new THREE.Vector4
  61. },
  62. //如 {x: 0, y: 0, z: 428, w: 969} xy应该是offset, zw是宽高
  63. cameraHeight0: {
  64. type: "f",
  65. value: 1
  66. },
  67. cameraHeight1: {
  68. type: "f",
  69. value: 1
  70. },
  71. ceilHeight0:{
  72. type: "f",
  73. value: 2
  74. },
  75. ceilHeight1:{
  76. type: "f",
  77. value: 2
  78. },
  79. },
  80. vertexShader: prefixVertex + `
  81. uniform vec3 pano0Position;
  82. uniform mat4 pano0Matrix;
  83. uniform vec3 pano1Position;
  84. uniform mat4 pano1Matrix;
  85. //uniform mat4 pano1Matrix2;
  86. varying vec2 vUv;
  87. varying vec3 vWorldPosition0;
  88. varying vec3 vWorldPosition1;
  89. varying vec3 vWorldPosition12;
  90. vec3 transformAxis( vec3 direction ) //navvis->4dkk
  91. {
  92. float y = direction.y;
  93. direction.y = direction.z;
  94. direction.z = -y;
  95. return direction;
  96. }
  97. void main() {
  98. vUv = uv;
  99. vec4 worldPosition = modelMatrix * vec4(position, 1.0);
  100. vec3 positionLocalToPanoCenter0 = worldPosition.xyz - pano0Position;
  101. vWorldPosition0 = (vec4(positionLocalToPanoCenter0, 1.0) * pano0Matrix).xyz;
  102. vWorldPosition0.x *= -1.0;
  103. vWorldPosition0 = transformAxis(vWorldPosition0);
  104. vec3 positionLocalToPanoCenter1 = worldPosition.xyz - pano1Position;
  105. vWorldPosition1 = (vec4(positionLocalToPanoCenter1, 1.0) * pano1Matrix).xyz;
  106. vWorldPosition1.x *= -1.0;
  107. vWorldPosition1 = transformAxis(vWorldPosition1);
  108. /*
  109. vec3 positionLocalToPanoCenter12 = worldPosition.xyz - pano1Position;
  110. vWorldPosition12 = (vec4(positionLocalToPanoCenter12, 1.0) * pano1Matrix2).xyz;
  111. vWorldPosition12.x *= -1.0;
  112. vWorldPosition12 = transformAxis(vWorldPosition12);
  113. */
  114. gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
  115. }
  116. `,
  117. fragmentShader: prefixFragment + `
  118. #extension GL_EXT_frag_depth : enable
  119. #define PI 3.141592653
  120. uniform float modelAlpha;
  121. uniform float opacity;
  122. uniform float progress;
  123. uniform int blackout;
  124. uniform vec3 pano0Position;
  125. uniform vec3 pano1Position;
  126. uniform float maxDistance;
  127. uniform float minDistance;
  128. uniform float minOpa;
  129. /* uniform sampler2D pano0Map;
  130. uniform sampler2D pano1Map; */
  131. uniform samplerCube pano0Map;
  132. uniform samplerCube pano1Map;
  133. varying vec2 vUv;
  134. varying vec3 vWorldPosition0;
  135. varying vec3 vWorldPosition1;
  136. //varying vec3 vWorldPosition12;
  137. /* vec2 getSamplerCoord( vec3 direction )
  138. {
  139. direction = normalize(direction);
  140. float tx=atan(direction.x,-direction.y)/(PI*2.0)+0.5;
  141. float ty=acos(direction.z)/PI;
  142. return vec2(tx,ty);
  143. } */
  144. vec2 getSamplerCoord2( vec3 direction )
  145. {
  146. direction = normalize(direction);
  147. float tx=atan(direction.x,direction.z)/(PI*2.0)+0.5;
  148. float ty=acos(direction.y)/PI;
  149. return vec2(tx,ty);
  150. }
  151. #if defined(GL_EXT_frag_depth) && defined(hasDepthTex)
  152. uniform sampler2D depthMap0;
  153. uniform sampler2D depthMap1;
  154. uniform mat4 inverseProjectionMatrix;
  155. uniform mat4 projectionMatrix;
  156. uniform vec4 viewport;
  157. uniform float cameraHeight0;
  158. uniform float cameraHeight1;
  159. uniform float ceilHeight0;
  160. uniform float ceilHeight1;
  161. vec2 getDepth(vec3 dir, sampler2D depthMap, float heightDown, float heightUp, vec4 eyePos){
  162. vec2 depthValue = vec2(0.0, 0.0);
  163. vec2 uv2 = getSamplerCoord2( dir.xyz); //暂时只用基于目标漫游点的方向
  164. uv2.x -= 0.25; //全景图和Cube的水平采样起始坐标相差90度,这里矫正 0.25 个采样偏移
  165. vec4 depth = texture2D(depthMap, uv2);
  166. //float distance = depth.r + 256. * (depth.g + 256. * depth.b);
  167. //distance *= 255. * .001; // distance is now in meters
  168. //更改
  169. float distance = (depth.g + depth.r / 256.) * 255.; //为什么要乘以255
  170. if(distance == 0.0){//漫游点底部识别不到的区域,给一个地板高度
  171. if(uv2.y < depthTexUVyLimit) distance = heightUp / dir.y;
  172. else if(uv2.y > 1.0 - depthTexUVyLimit) distance = heightDown / -dir.y;
  173. else distance = 100000.0;//给个超级远的值
  174. }
  175. if(distance == 0.0)distance = 100000.0;//给个超级远的值
  176. depthValue.x = distance;
  177. // return r[1] + r[0] / 256
  178. distance += .1; // add a safety margin
  179. vec4 eyePos2 = vec4(normalize(eyePos.xyz) * distance, 1.);
  180. vec4 clipPos2 = projectionMatrix * eyePos2;
  181. vec4 ndcPos2 = clipPos2 * 1. / clipPos2.w;
  182. depthValue.y = 0.5 * ((gl_DepthRange.far - gl_DepthRange.near) * ndcPos2.z
  183. + gl_DepthRange.near + gl_DepthRange.far);
  184. return depthValue;
  185. }
  186. //注:未加载好的话,depth为0,导致第一次漫游过去的时候许多mesh会立刻被遮挡,所以要确保加载完
  187. #endif
  188. void main()
  189. {
  190. vec3 vWorldPosition0N = normalize(vWorldPosition0);
  191. vec3 vWorldPosition1N = normalize(vWorldPosition1);
  192. vec4 colorFromPano0 = vec4(0.0,0.0,0.0,0.0);
  193. #if defined(usePanoMap0)
  194. //即progress < 1.0 通常是1
  195. colorFromPano0=textureCube(pano0Map,vWorldPosition0N.xyz);
  196. #endif
  197. vec4 colorFromPano1=textureCube(pano1Map,vWorldPosition1N.xyz);
  198. gl_FragColor=mix(colorFromPano0,colorFromPano1,progress);
  199. //深度图修改深度
  200. #if defined(GL_EXT_frag_depth) && defined(hasDepthTex)
  201. vec4 ndcPos;
  202. ndcPos.xy = ((2.0 * gl_FragCoord.xy) - (2.0 * viewport.xy)) / (viewport.zw) - 1.;
  203. ndcPos.z = (2.0 * gl_FragCoord.z - gl_DepthRange.near - gl_DepthRange.far) /
  204. (gl_DepthRange.far - gl_DepthRange.near);
  205. ndcPos.w = 1.0;
  206. vec4 clipPos = ndcPos / gl_FragCoord.w;
  207. vec4 eyePos = inverseProjectionMatrix * clipPos;
  208. vec2 depth0 = vec2(0.0,0.0);
  209. #if defined(usePanoMap0)
  210. depth0 = getDepth(vWorldPosition0N, depthMap0, cameraHeight0, ceilHeight0, eyePos);
  211. #endif
  212. vec2 depth1 = getDepth(vWorldPosition1N, depthMap1, cameraHeight1, ceilHeight1, eyePos);
  213. gl_FragDepthEXT = mix(depth0.y,depth1.y,progress);
  214. #endif
  215. }
  216. `
  217. }
  218. //注:gl_FragDepthEXT 修改了确实能像真实mesh那样遮挡住在后面的物体。但是为过渡时不能直接像有模型那样,和角度有关。
  219. export default class ModelTextureMaterial extends THREE.RawShaderMaterial {
  220. constructor( ){
  221. let defines = {depthTexUVyLimit: Potree.config.depthTexUVyLimit}
  222. super({
  223. fragmentShader: shader.fragmentShader,
  224. vertexShader: shader.vertexShader,
  225. uniforms: THREE.UniformsUtils.clone(shader.uniforms),
  226. side:THREE.DoubleSide,
  227. name: "ModelTextureMaterial",
  228. defines
  229. })
  230. let setSize = (e)=>{
  231. let viewport = e.viewport
  232. //let viewportOffset = viewport.offset || new Vector2()
  233. let resolution = viewport.resolution2
  234. //this.uniforms.viewport.value.set(viewportOffset.x, viewportOffset.y, resolution.x, resolution.y)
  235. this.uniforms.viewport.value.set(0,0, resolution.x, resolution.y);// xy是在viewport中的left和bottom,和整个窗口没有关系,所以不是viewportOffset。几乎都是0,0
  236. }
  237. let viewport = viewer.mainViewport;
  238. setSize({viewport})
  239. viewer.addEventListener('resize',(e)=>{
  240. if(e.viewport.name != "MainView")return
  241. setSize(e)
  242. })
  243. //var supportExtDepth = !!Features.EXT_DEPTH.isSupported()
  244. {
  245. //add
  246. viewer.addEventListener('camera_changed', (e)=>{
  247. if(e.viewport.name != "MainView")return
  248. //this.uniforms.projectionMatrix.value.copy(e.camera.projectionMatrix)
  249. e.camera && this.uniforms.inverseProjectionMatrix.value.copy(e.camera.projectionMatrixInverse)
  250. })
  251. }
  252. let progress = 0
  253. Object.defineProperty(this.uniforms.progress, 'value', {
  254. get: function () {
  255. return progress
  256. },
  257. set: e => {
  258. if (e < 1) {
  259. if (!('usePanoMap0' in this.defines)) {
  260. this.defines.usePanoMap0 = ''
  261. this.needsUpdate = true
  262. }
  263. } else {
  264. if ('usePanoMap0' in this.defines) {
  265. delete this.defines.usePanoMap0
  266. this.needsUpdate = true
  267. }
  268. }
  269. progress = e
  270. },
  271. })
  272. //-------------------------------------
  273. }
  274. /**
  275. *
  276. * @param {Panorama} pano0
  277. * @param {Panorama} pano1
  278. * @param {boolean} flag
  279. 更新全景图的材质uniforms
  280. */
  281. setProjectedPanos(pano0, pano1, progressValue ){
  282. progressValue!=void 0 && (this.uniforms.progress.value = progressValue);
  283. //pano0.ensureSkyboxReadyForRender();
  284. if(pano0){
  285. this.uniforms.pano0Map.value = pano0.getSkyboxTexture();//pano0.texture
  286. this.uniforms.pano0Position.value.copy(pano0.position)
  287. this.uniforms.pano0Matrix.value.copy(pano0.panoMatrix/* pano0.mesh.matrixWorld */ );
  288. //pano1.ensureSkyboxReadyForRender();
  289. }
  290. this.uniforms.pano1Map.value = pano1.getSkyboxTexture()//pano1.texture;
  291. this.uniforms.pano1Position.value.copy(pano1.position)
  292. this.uniforms.pano1Matrix.value.copy(pano1.panoMatrix /* pano1.mesh.matrixWorld */ );
  293. this.pano0 = pano0
  294. this.pano1 = pano1
  295. this.updateDepthTex(pano0)
  296. this.updateDepthTex(pano1)
  297. //console.log('setProjectedPanos', pano0&&pano0.id, pano1&&pano1.id)
  298. this.needsUpdate = true;
  299. }
  300. updateDepthTex(pano, extra){
  301. if( !Potree.settings.useDepthTex || !pano || !pano.depthTex || pano!=this.pano0 && pano!=this.pano1)return
  302. //console.log('updateDepthTex', pano.id, this.pano0 && this.pano0.id, this.pano1 && this.pano1.id)
  303. if(this.pano0){
  304. this.uniforms.depthMap0.value = this.pano0.entered ? this.pano0.depthTex : null; //dispose了就不要赋值否则dispose会失败
  305. this.uniforms.cameraHeight0.value = this.pano0.floorPosition.distanceTo(this.pano0.position)
  306. this.uniforms.ceilHeight0.value = this.pano0.getCeilHeight() - this.pano0.position.z
  307. }
  308. if(this.pano1){
  309. this.uniforms.depthMap1.value = this.pano1.depthTex //pano1还没entered时也需要,可能在飞入
  310. this.uniforms.cameraHeight1.value = this.pano1.floorPosition.distanceTo(this.pano1.position)
  311. this.uniforms.ceilHeight1.value = this.pano1.getCeilHeight() - this.pano1.position.z
  312. }
  313. this.updateDepthTexEnable()
  314. }
  315. updateDepthTexEnable(){
  316. let hasDepthTex = this.pano0 && this.pano1 && this.pano0.pointcloud.hasDepthTex && this.pano1.pointcloud.hasDepthTex //暂时不知道一个有图一个没图怎么写所以
  317. Potree.Utils.addOrRemoveDefine(this, 'hasDepthTex', hasDepthTex?'add':'remove' )
  318. }
  319. /* EnableDepthTex(){//开启DepthTex
  320. if(this.defines['hasDepthTex']){
  321. return
  322. }
  323. this.defines['hasDepthTex'] = ''
  324. this.needsUpdate = true;
  325. } */
  326. }