XMaterialComponent.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. import XVideoRawYUV from "./XVideoRawYUV";
  2. import Logger from "./Logger.js";
  3. import XMaterialError from "./Error/XMaterialError";
  4. const logger = new Logger("Material");
  5. export default class XMaterialComponent {
  6. constructor(sceneManager, t) {
  7. this.yuvInfo
  8. this._panoInfo
  9. this._dynamic_size
  10. this._videoTexture
  11. this._videoElement
  12. this._lowModelShader
  13. this._defaultShader
  14. this._inputYUV420 = !0
  15. this._inputPanoYUV420 = !0
  16. this._isUpdateYUV = !0
  17. this._scenemanager = sceneManager
  18. this.scene = sceneManager.Scene
  19. this.engine = this.scene.getEngine()
  20. this.shaderMode = 1
  21. this._dynamic_textures = []
  22. this._dynamic_shaders = []
  23. this._dynamic_babylonpose = []
  24. this._videoRawYUVTexArray = new XVideoRawYUV(
  25. this.scene,
  26. t.videoResOriArray
  27. )
  28. this.shaderMode = t.shaderMode
  29. t.yuvInfo && (this.yuvInfo = t.yuvInfo),
  30. t.panoInfo && this.setPanoInfo(t.panoInfo);
  31. }
  32. initMaterial = async () => {
  33. return new Promise((resolve, t) => {
  34. this._initDefaultShader();
  35. if (this.shaderMode == 2) {
  36. this.initDynamicData(
  37. this._panoInfo.dynamicRange,
  38. this._panoInfo.width,
  39. this._panoInfo.height
  40. ).then(() => {
  41. this._initPureVideoShader();
  42. this._prepareRender(this.yuvInfo);
  43. });
  44. } else if (this.shaderMode == 1) {
  45. this._initPureVideoShader();
  46. this._prepareRender(this.yuvInfo);
  47. }
  48. // else if(this.shaderMode == 0){
  49. // resolve(!0)
  50. // }
  51. resolve(!0);
  52. // this.shaderMode == 2 ? this.initDynamicData(this._panoInfo.dynamicRange, this._panoInfo.width, this._panoInfo.height).then(()=>{
  53. // this._initPureVideoShader(),
  54. // this._prepareRender(this.yuvInfo)
  55. // }
  56. // ) : this.shaderMode == 1 ? (this._initPureVideoShader(),
  57. // this._prepareRender(this.yuvInfo)) : this.shaderMode == 0,
  58. // resolve(!0)
  59. })
  60. }
  61. _initPureVideoContent = (focal_width_height) => {
  62. if (this._inputYUV420) {
  63. if (this._videoRawYUVTexArray.getVideoYUVTex(0) != null) {
  64. this._lowModelShader.setTexture(
  65. "texture_video",
  66. this._videoRawYUVTexArray.getVideoYUVTex(0)
  67. );
  68. this._lowModelShader.setFloat("isYUV", 1);
  69. BABYLON.Texture.WhenAllReady(
  70. [this._videoRawYUVTexArray.getVideoYUVTex(0)],
  71. () => {
  72. this._changePureVideoLowModelShaderCanvasSize(focal_width_height);
  73. }
  74. );
  75. }
  76. }
  77. // else{
  78. // this._videoElement = e.videoElement;
  79. // this._videoTexture || (this._videoTexture = new VideoTexture("InterVideoTexture",this._videoElement,this.scene,!0,!1));
  80. // BABYLON.Texture.WhenAllReady([this._videoTexture], ()=>{
  81. // this._changePureVideoLowModelShaderCanvasSize({
  82. // width: this._videoElement.height,
  83. // height: this._videoElement.width,
  84. // fov: e.fov
  85. // })
  86. // });
  87. // this._lowModelShader.setTexture("texture_video", this._videoTexture);
  88. // this._lowModelShader.setFloat("isYUV", 0);
  89. // }
  90. }
  91. _changePureVideoLowModelShaderCanvasSize = (e) => {
  92. var lowModelShader;
  93. const fov = e.fov || 50;
  94. const width = e.width || 720;
  95. const height = e.height || 1280;
  96. const focus = width / (2 * Math.tan((Math.PI * fov) / 360));
  97. (lowModelShader = this._lowModelShader) == null ||
  98. lowModelShader.setVector3(
  99. "focal_width_height",
  100. new BABYLON.Vector3(focus, width, height)
  101. );
  102. }
  103. updateRawYUVData = (stream, width, height, fov = -1) => {
  104. fov == -1 && (fov = this.yuvInfo.fov);
  105. if (this._isUpdateYUV == !0) {
  106. console.log('执行:updateRawYUVData')
  107. const yuvInfo = { width, height, fov }
  108. const videosResOriArrayIndex = this._videoRawYUVTexArray.findId(width, height)
  109. const currentVideoId = this._videoRawYUVTexArray.getCurrentVideoTexId();
  110. if (currentVideoId < 0 || videosResOriArrayIndex != currentVideoId || fov != this.yuvInfo.fov) {
  111. this.yuvInfo.width = width;
  112. this.yuvInfo.height = height;
  113. this.yuvInfo.fov = fov;
  114. this._videoRawYUVTexArray.setCurrentVideoTexId(videosResOriArrayIndex);
  115. this._changeVideoRes(videosResOriArrayIndex); // 设置texture_video
  116. this._changePureVideoLowModelShaderCanvasSize(yuvInfo); // 设置focal_width_height
  117. this._scenemanager.cameraComponent.cameraFovChange(yuvInfo);
  118. this._scenemanager.yuvInfo = yuvInfo;
  119. }
  120. let VideoTexture = this._videoRawYUVTexArray.getVideoYUVTex(videosResOriArrayIndex)
  121. if (VideoTexture != null) {
  122. // 更新视频流
  123. VideoTexture.update(stream)
  124. VideoTexture.updateSamplingMode(BABYLON.Texture.BILINEAR_SAMPLINGMODE)
  125. }
  126. //var o, a
  127. //(o = this._videoRawYUVTexArray.getVideoYUVTex(videosResOriArrayIndex)) == null || o.update(stream),
  128. //(a = this._videoRawYUVTexArray.getVideoYUVTex(videosResOriArrayIndex)) == null || a.updateSamplingMode(BABYLON.Texture.BILINEAR_SAMPLINGMODE)
  129. }
  130. }
  131. _changeVideoRes = (e) => {
  132. this._lowModelShader.setTexture(
  133. "texture_video",
  134. this._videoRawYUVTexArray.getVideoYUVTex(e)
  135. );
  136. }
  137. initDynamicData = (dynamicRange, width, height) => {
  138. return new Promise((resolve, reject) => {
  139. this.setDynamicSize(dynamicRange).then((a) => {
  140. if (a) {
  141. for (let s = 0; s < dynamicRange; ++s)
  142. ((l) => {
  143. this.initDynamicTexture(l, width, height),
  144. this.initDynamicShaders(l).then(() => {
  145. this._updatePanoShaderInput(l);
  146. });
  147. })(s);
  148. resolve(!0);
  149. } else
  150. reject(
  151. new XMaterialError(
  152. `[Engine] DynamicRoomSize (${dynamicRange}) is too small`
  153. )
  154. );
  155. });
  156. }).catch((n) => logger.error(`[Engine] ${n}`))
  157. }
  158. _initDefaultShader = () => {
  159. if(this._defaultShader == null) {
  160. this._defaultShader = new BABYLON.GridMaterial(
  161. "GridShader",
  162. this.scene
  163. )
  164. this._defaultShader.gridRatio = 50
  165. this._defaultShader.lineColor = new BABYLON.Color3(0, 0, 0.5)
  166. this._defaultShader.majorUnitFrequency = 1
  167. this._defaultShader.mainColor = new BABYLON.Color3(0.6, 0.6, 0.6)
  168. this._defaultShader.backFaceCulling = !1
  169. }
  170. }
  171. _initPureVideoShader = () => {
  172. if (this._lowModelShader == null) {
  173. const material = new BABYLON.ShaderMaterial(
  174. "PureVideoShader",
  175. this.scene, {
  176. vertexSource: pureVideoVertex,
  177. fragmentSource: pureVideoFragment,
  178. }, {
  179. attributes: ["uv", "position", "world0", "world1", "world2", "world3"],
  180. uniforms: ["view", "projection", "worldViewProjection", "world"],
  181. defines: ["#define SHADOWFULLFLOAT"],
  182. }
  183. );
  184. material.setTexture("shadowSampler", null)
  185. material.setMatrix("lightSpaceMatrix", null)
  186. material.setFloat("haveShadowLight", 0)
  187. material.setTexture("texture_video", null)
  188. material.setFloat("isYUV", this._inputYUV420 ? 1 : 0)
  189. material.setFloat("fireworkLight", 0)
  190. material.setVector3("fireworkLightPosition", new BABYLON.Vector3(0, 0, 0))
  191. material.setVector3(
  192. "focal_width_height",
  193. new BABYLON.Vector3(772.022491, 720, 1280)
  194. )
  195. material.backFaceCulling = !1
  196. this._lowModelShader = material
  197. }
  198. }
  199. setDynamicSize = (e) => {
  200. return new Promise((t, r) => {
  201. e >= 1 && e <= 100
  202. ? ((this._dynamic_size = e), t(!0))
  203. : ((this._dynamic_size = 1), t(!1));
  204. })
  205. }
  206. _isInDynamicRange = (e) => {
  207. return e < this._dynamic_size && e >= 0
  208. }
  209. initDynamicTexture = (e, t, r) => {
  210. this._isInDynamicRange(e) &&
  211. (
  212. this._dynamic_textures[e] != null && (
  213. this._dynamic_textures[e].dispose(),
  214. (this._dynamic_textures[e] = null)
  215. ), (
  216. this._dynamic_textures[e] = new BABYLON.RawTexture(
  217. null,
  218. t,
  219. r * 1.5,
  220. BABYLON.Engine.TEXTUREFORMAT_LUMINANCE,
  221. this.scene,
  222. !1,
  223. !0,
  224. BABYLON.Texture.NEAREST_SAMPLINGMODE,
  225. BABYLON.Engine.TEXTURETYPE_UNSIGNED_BYTE
  226. )
  227. ), (
  228. this._dynamic_textures[e].name =
  229. "Pano_Dynamic_" + e + "_" + Date.now()
  230. )
  231. );
  232. }
  233. initDynamicShaders = (e) => {
  234. logger.info("[Engine] Material init dynamic shader.")
  235. return new Promise((resolve, r) => {
  236. this._dynamic_shaders[e] != null && this._dynamic_shaders[e].dispose();
  237. const material = new BABYLON.ShaderMaterial(
  238. "Pano_Shader_" + e,
  239. this.scene, {
  240. vertexSource: panoVertex,
  241. fragmentSource: panoFragment,
  242. }, {
  243. attributes: ["uv", "position", "world0", "world1", "world2", "world3"],
  244. uniforms: ["view", "projection", "worldViewProjection", "world"],
  245. defines: ["#define SHADOWFULLFLOAT"],
  246. }
  247. );
  248. material.setTexture("texture_pano", null)
  249. material.setVector3("centre_pose", new BABYLON.Vector3(0, 0, 0))
  250. material.setFloat("isYUV", this._inputPanoYUV420 ? 1 : 0)
  251. material.setTexture("shadowSampler", null)
  252. material.setMatrix("lightSpaceMatrix", null)
  253. material.setFloat("haveShadowLight", 0)
  254. material.setFloat("fireworkLight", 0)
  255. material.setVector3("fireworkLightPosition", new BABYLON.Vector3(0, 0, 0))
  256. material.backFaceCulling = !1
  257. this._dynamic_shaders[e] = material
  258. resolve(!0);
  259. })
  260. }
  261. stopYUVUpdate() {
  262. this._isUpdateYUV = !1;
  263. }
  264. allowYUVUpdate() {
  265. this._isUpdateYUV = !0;
  266. }
  267. setPanoInfo(e) {
  268. this._panoInfo = e;
  269. }
  270. _prepareRender(focal_width_height) {
  271. if (focal_width_height) {
  272. this._initPureVideoContent(focal_width_height);
  273. this._updatePureVideoShaderInput();
  274. }
  275. }
  276. getPureVideoShader() {
  277. return this._lowModelShader;
  278. }
  279. getDefaultShader() {
  280. return this._defaultShader;
  281. }
  282. updatePanoPartYUV(e, t, r) {
  283. const n = t.subarray(0, r.width * r.height),
  284. o = t.subarray(r.width * r.height, r.width * r.height * 1.25),
  285. a = t.subarray(r.width * r.height * 1.25),
  286. s = this._panoInfo.width,
  287. l = this._panoInfo.height;
  288. if (this._dynamic_textures[e] != null) {
  289. const u = this._dynamic_textures[e].getInternalTexture();
  290. if (u != null && u != null) {
  291. const c = this.engine._getTextureTarget(u);
  292. this.engine._bindTextureDirectly(c, u, !0),
  293. this.engine.updateTextureData(
  294. u,
  295. n,
  296. r.startX,
  297. l * 1.5 - r.startY - r.height,
  298. r.width,
  299. r.height
  300. ),
  301. this.engine.updateTextureData(
  302. u,
  303. o,
  304. r.startX * 0.5,
  305. (l - r.startY - r.height) * 0.5,
  306. r.width * 0.5 - 1,
  307. r.height * 0.5 - 1
  308. ),
  309. this.engine.updateTextureData(
  310. u,
  311. a,
  312. r.startX * 0.5 + s * 0.5,
  313. (l - r.startY - r.height) * 0.5,
  314. r.width * 0.5,
  315. r.height * 0.5
  316. ),
  317. this.engine._bindTextureDirectly(c, null);
  318. }
  319. }
  320. }
  321. changePanoImg(e, t) {
  322. if (
  323. (logger.info(
  324. `[Engine] changePanoImg, id=${e}, pose=${t.pose.position.x},${t.pose.position.y},${t.pose.position.z}`
  325. ),
  326. !this._isInDynamicRange(e))
  327. )
  328. return (
  329. logger.error(
  330. `[Engine] ${e} is bigger than dynamic size set in PanoInfo`
  331. ),
  332. Promise.reject(
  333. new XMaterialError(
  334. `[Engine] ${e} is bigger than dynamic size set in PanoInfo`
  335. )
  336. )
  337. );
  338. const r = ue4Position2Xverse(t.pose.position);
  339. return (
  340. r &&
  341. (this._dynamic_babylonpose[e] = {
  342. position: r,
  343. }),
  344. new Promise((n, o) => {
  345. try {
  346. typeof t.data == "string"
  347. ? (this.setPanoYUV420(!1),
  348. this._dynamic_textures[e].updateURL(t.data, null, () => {
  349. this._dynamic_textures[e].updateSamplingMode(
  350. BABYLON.Texture.NEAREST_SAMPLINGMODE
  351. );
  352. }))
  353. : (this.isPanoYUV420() == !1 &&
  354. this.initDynamicTexture(
  355. e,
  356. this._panoInfo.width,
  357. this._panoInfo.height
  358. ),
  359. this.setPanoYUV420(!0),
  360. this._dynamic_textures[e].update(t.data),
  361. this._dynamic_textures[e].updateSamplingMode(
  362. BABYLON.Texture.NEAREST_SAMPLINGMODE
  363. )),
  364. n(this);
  365. } catch (a) {
  366. o(new XMaterialError(`[Engine] ChangePanoImg Error! ${a}`));
  367. }
  368. }).then(
  369. (n) => (
  370. t.fov != null &&
  371. this._scenemanager.cameraComponent.changeCameraFov(
  372. (t.fov * Math.PI) / 180
  373. ),
  374. this._dynamic_shaders[e].setFloat(
  375. "isYUV",
  376. this._inputPanoYUV420 ? 1 : 0
  377. ),
  378. this._dynamic_shaders[e].setTexture(
  379. "texture_pano",
  380. this._dynamic_textures[e]
  381. ),
  382. this._dynamic_shaders[e].setVector3(
  383. "centre_pose",
  384. this._dynamic_babylonpose[e].position
  385. ),
  386. !0
  387. )
  388. )
  389. );
  390. }
  391. setYUV420(e) {
  392. this._inputYUV420 = e;
  393. }
  394. isYUV420() {
  395. return this._inputYUV420;
  396. }
  397. setPanoYUV420(e) {
  398. this._inputPanoYUV420 = e;
  399. }
  400. isPanoYUV420() {
  401. return this._inputPanoYUV420;
  402. }
  403. getDynamicShader(e) {
  404. return this._dynamic_shaders[e];
  405. }
  406. _updatePureVideoShaderInput() {
  407. /*
  408. var e, t, r, n, o, a, s, l, u, c;
  409. if(this.scene.getLightByName("AvatarLight")){
  410. (e = this._lowModelShader) == null || e.setFloat("haveShadowLight", 1);
  411. n = this._lowModelShader
  412. if(n != null){
  413. t = this.scene.getLightByName("AvatarLight")
  414. if(t == null){
  415. r = void 0
  416. }
  417. else{
  418. r = t.getShadowGenerator()
  419. }
  420. if(r == null){
  421. n.setTexture("shadowSampler",void 0)
  422. }
  423. else{
  424. n.setTexture("shadowSampler",r.getShadowMapForRendering())
  425. }
  426. }
  427. //(n = this._lowModelShader) == null || n.setTexture("shadowSampler", (r = (t = this.scene.getLightByName("AvatarLight")) == null ? void 0 : t.getShadowGenerator()) == null ? void 0 : r.getShadowMapForRendering());
  428. s = this._lowModelShader
  429. if(s != null){
  430. o = this.scene.getLightByName("AvatarLight")
  431. if(o == null){
  432. a = void 0
  433. }
  434. else{
  435. a = o.getShadowGenerator()
  436. }
  437. if(a == null){
  438. s.setMatrix("lightSpaceMatrix",void 0)
  439. }
  440. else{
  441. s.setMatrix("lightSpaceMatrix",a.getTransformMatrix())
  442. }
  443. }
  444. //(s = this._lowModelShader) == null || s.setMatrix("lightSpaceMatrix", (a = (o = this.scene.getLightByName("AvatarLight")) == null ? void 0 : o.getShadowGenerator()) == null ? void 0 : a.getTransformMatrix())
  445. }
  446. else{
  447. (l = this._lowModelShader) == null || l.setTexture("shadowSampler", this._videoTexture);
  448. (u = this._lowModelShader) == null || u.setMatrix("lightSpaceMatrix", new Matrix);
  449. (c = this._lowModelShader) == null || c.setFloat("haveShadowLight", 0);
  450. }
  451. */
  452. let lowModelShader = this._lowModelShader;
  453. if (lowModelShader != null) {
  454. if (this.scene.getLightByName("AvatarLight")) {
  455. lowModelShader.setFloat("haveShadowLight", 1);
  456. let avatarLight = this.scene.getLightByName("AvatarLight");
  457. let shadow = void 0;
  458. if (avatarLight != null) {
  459. shadow = avatarLight.getShadowGenerator();
  460. }
  461. if (shadow == null) {
  462. lowModelShader.setTexture("shadowSampler", void 0);
  463. lowModelShader.setMatrix("lightSpaceMatrix", void 0);
  464. } else {
  465. lowModelShader.setTexture(
  466. "shadowSampler",
  467. shadow.getShadowMapForRendering()
  468. );
  469. lowModelShader.setMatrix(
  470. "lightSpaceMatrix",
  471. shadow.getTransformMatrix()
  472. );
  473. }
  474. } else {
  475. lowModelShader.setTexture("shadowSampler", this._videoTexture);
  476. lowModelShader.setMatrix("lightSpaceMatrix", new Matrix());
  477. lowModelShader.setFloat("haveShadowLight", 0);
  478. }
  479. }
  480. if (this.scene.getLightByName("fireworkLight")) {
  481. this.scene.registerBeforeRender(() => {
  482. this._lowModelShader.setFloat(
  483. "fireworkLight",
  484. this.scene.getLightByName("fireworkLight").getScaledIntensity()
  485. );
  486. var fireworkLight = this.scene.getLightByName("fireworkLight");
  487. if (fireworkLight == null) {
  488. this._lowModelShader.setVector3("fireworkLightPosition", void 0);
  489. } else {
  490. this._lowModelShader.setVector3(
  491. "fireworkLightPosition",
  492. fireworkLight.position
  493. );
  494. }
  495. //this._lowModelShader.setVector3("fireworkLightPosition", (h = this.scene.getLightByName("fireworkLight")) == null ? void 0 : h.position);
  496. });
  497. } else {
  498. const pointLight = new BABYLON.PointLight(
  499. "fireworkLight",
  500. new BABYLON.Vector3(0, 0, 0),
  501. this.scene
  502. );
  503. pointLight.intensity = 0;
  504. }
  505. }
  506. _updatePanoShaderInput(e) {
  507. var n, s;
  508. if (this._isInDynamicRange(e)) {
  509. let shader = this._dynamic_shaders[e]
  510. let avatarLight = this.scene.getLightByName("AvatarLight")
  511. shader == null || (avatarLight ? (
  512. shader.setFloat("haveShadowLight", 1),
  513. shader.setTexture("shadowSampler", (n = avatarLight == null ? void 0 : avatarLight.getShadowGenerator()) == null ? void 0 : n.getShadowMapForRendering()),
  514. shader.setMatrix("lightSpaceMatrix", (s = avatarLight == null ? void 0 : avatarLight.getShadowGenerator()) == null ? void 0 : s.getTransformMatrix())
  515. ) : (
  516. shader.setTexture("shadowSampler", null),
  517. shader.setMatrix("lightSpaceMatrix", new Matrix),
  518. shader.setFloat("haveShadowLight", 0)
  519. ))
  520. let fireworkLight = this.scene.getLightByName("fireworkLight")
  521. if (fireworkLight) {
  522. this.scene.registerBeforeRender(() => {
  523. shader.setFloat("fireworkLight", fireworkLight.getScaledIntensity()),
  524. shader.setVector3("fireworkLightPosition", fireworkLight == null ? void 0 : fireworkLight.position)
  525. });
  526. } else {
  527. const f = new BABYLON.PointLight("fireworkLight", new BABYLON.Vector3(0, 0, 0), this.scene);
  528. f.intensity = 0
  529. }
  530. }
  531. }
  532. }