ModelTextureMaterial.js 15 KB

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