webgl_rxdz_vr.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. <template src="./webgl_rxdz_vr.html">
  2. </template>
  3. <script>
  4. import * as THREE from 'three';
  5. import Stats from 'three/addons/libs/stats.module.js';
  6. import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
  7. import { DragControls } from 'three/addons/controls/DragControls.js';
  8. import {getStorage} from '@/utils/localStorage';
  9. var requestId = "";
  10. const util = require('@/utils/util.js').default;
  11. import viewAI from '@/components/newBottomCom/viewAI/viewAI.vue';
  12. import commonPageMethod from '@/mixins/commonPageMethod.js';
  13. // import commonPageMethod from '@/common/commonPageMethod.js';
  14. export default {
  15. components: {
  16. viewAI
  17. },
  18. mixins: [commonPageMethod],
  19. /**
  20. * 页面的初始数据
  21. */
  22. data() {
  23. return {
  24. pvCurPageName: "add_AI_people",
  25. locusBehaviorName: "添加数字人",
  26. pvCurPageParams: null,
  27. houseId: "",
  28. pvId: 'p_2cmina_23080402',
  29. canvas: null,
  30. navbar: {
  31. showCapsule: 1,
  32. title: '添加数字人',
  33. titleColor: '#000',
  34. navPadding: 0,
  35. navPaddingBg: 'transparent',
  36. navBarColor: 'transparent',
  37. navBackColor: 'transparent',
  38. haveCallback: true, // 如果是 true 会接手 navbarBackClk
  39. fromShare: false,
  40. fromProject: 0,
  41. shareToken: "",
  42. pageName: this.pvCurPageName,
  43. },
  44. id: '', // 户型编号
  45. loader: null,
  46. scene: null,
  47. camera: null,
  48. controlStarPosition: {
  49. x: 0,
  50. y: 0,
  51. z: 0
  52. }, //控制器初始位置
  53. cameraStarPosition: {
  54. x: 0,
  55. y: 0,
  56. z: 5
  57. }, //摄像头初始位置
  58. cameraLastPosition: null, //摄像头上一次移动到的位置
  59. controlLastPosition: null, //观察点上一次移动到的位置
  60. canvasHeight: 408, //canvas视图的高度-计算得出
  61. myLoadingStatus: false,
  62. repeatFlag: false, //重复点击
  63. isIOS: false,
  64. }
  65. },
  66. beforeDestroy() {
  67. cancelAnimationFrame(requestId, this.canvas)
  68. this.worker && this.worker.terminate()
  69. if (this.renderer instanceof THREE.WebGLRenderer) {
  70. // 遍历场景中的所有子对象,找到类型为Mesh的对象并移除
  71. let deleList = this.scene.children.filter(object => {
  72. if (object instanceof THREE.Mesh) {
  73. return object
  74. }
  75. })
  76. if (deleList && deleList.length > 0) {
  77. this.scene.remove(...deleList);
  78. }
  79. this.scene.traverse(function(object) {
  80. if (object instanceof THREE.Mesh) {
  81. if (object.geometry && typeof(object.geometry.dispose) == 'function') {
  82. object.geometry.dispose();
  83. }
  84. if (object.material && typeof(object.material.dispose) == 'function') {
  85. object.material.dispose();
  86. }
  87. if (object.texture && typeof(object.texture.dispose) == 'function') {
  88. object.texture.dispose();
  89. }
  90. }
  91. });
  92. this.renderer.clear();
  93. this.renderer.dispose();
  94. this.renderer.forceContextLoss();
  95. this.renderer.context = null;
  96. this.renderer.domElement = null;
  97. this.renderer = null;;
  98. }
  99. console.warn("***beforeDestroy-webgl_rxdz_vr***");
  100. },
  101. mounted(options) {
  102. var that = this;
  103. console.warn("***webgl_rxdz_roam-options***", this.$route.query)
  104. this.isIOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
  105. this.videoUrl = this.$route.query.videoUrl || '';
  106. this.bgUrl = this.$route.query.bgUrl || 'https://dm.static.elab-plus.com/miniProgram/tears_of_steel_bridge_2k.jpg';
  107. // alert("***mounted-webgl_rxdz_roam***"+this.isIOS + this.curHouseObj)
  108. let screenWidth = window.screen.width;
  109. let screenHeight = window.screen.height;
  110. if (window.innerWidth && window.screen.width) {
  111. screenWidth = Math.min(window.innerWidth, window.screen.width)
  112. }
  113. if (window.innerHeight && window.screen.height) {
  114. screenHeight = Math.min(window.innerHeight, window.screen.height)
  115. }
  116. let unit = screenWidth / 750; //单位rpm 对应 px 的值
  117. // this.canvasHeight = screenHeight - (600 * unit) + (40 * unit);
  118. this.canvasHeight = screenWidth;
  119. this.houseId = this.$route.query.houseId ? this.$route.query.houseId : '';
  120. this.spaceId = this.$route.query.spaceId ? this.$route.query.spaceId : '';
  121. let container = this.$refs.webgl;
  122. let canvas3d = this.canvas = this.$refs.glcanvas;
  123. //uniapp 兼容写法,因为uni的页面对象的Vue 实例是$vm
  124. let camera = null,
  125. renderer = null;
  126. let needRender = false; //是否需要渲染 false表示不需要渲染;true 表示需要渲染
  127. let scene = this.scene = new THREE.Scene();
  128. let controls = null,
  129. boundary = null;
  130. let stats;
  131. let controls2 = null;
  132. let videoMesh = null;
  133. init();
  134. // this.clearEvent = clearEvent;
  135. // this.attendEvent = attendEvent;
  136. this.starRender = starRender; //对外暴露启动渲染的方法
  137. this.stopRender = stopRender; //对外暴露停止渲染的方法
  138. this.videoHandle = videoHandle; //视频处理方法
  139. function init() {
  140. // 创建相机位置
  141. camera = new THREE.PerspectiveCamera(120, screenWidth / that.canvasHeight, 0.1, 10000);
  142. // camera.up.set(0, 1, 0);//俯视状态,将相机的up向量设置为z轴负方向 {x:0,y:1,z:0}
  143. camera.position.set(that.cameraStarPosition.x, that.cameraStarPosition.y, that.cameraStarPosition.z);
  144. scene.add(camera);
  145. that.camera = camera;
  146. // 环境光会均匀的照亮场景中的所有物体
  147. // const ambientLight = new THREE.AmbientLight(0xFFEFE0, 3.5);
  148. // scene.add(ambientLight);
  149. // 辅助方格
  150. // const axesHelper = new THREE.AxesHelper( 50 );
  151. // scene.add( axesHelper );
  152. // const gridHelper = new THREE.GridHelper(50, 10, 0xcccccc, 0xcccccc);
  153. // gridHelper.position.y = 0;
  154. // gridHelper.position.x = 0;
  155. // scene.add(gridHelper);
  156. //加载环境720贴图
  157. const loader = new THREE.TextureLoader();
  158. const texture = loader.load(that.bgUrl, () => {
  159. const rt = new THREE.WebGLCubeRenderTarget(texture.image.height);
  160. rt.fromEquirectangularTexture(renderer, texture);
  161. scene.background = rt.texture;
  162. });
  163. //antialias 这个值得设置为false,不然IOS上截图会失效
  164. renderer = that.renderer = new THREE.WebGLRenderer({
  165. canvas: canvas3d,
  166. alpha: true,
  167. });
  168. renderer.setPixelRatio(window.devicePixelRatio);
  169. renderer.setSize(screenWidth, that.canvasHeight);
  170. container.appendChild(renderer.domElement);
  171. controls = new OrbitControls(camera, renderer.domElement);
  172. controls.enableDamping = true; //启动缓动
  173. controls.minDistance = 0.0001;
  174. controls.maxDistance = 30;
  175. controls.minPolarAngle = 0; // 默认0
  176. controls.maxPolarAngle = Math.PI / 2; // 默认Math.PI,即可以向下旋转到的视角。
  177. controls.enableZoom = true; //启用摄像机的缩放
  178. controls.enablePan = true; //禁用摄像机平移
  179. controls.enableRotate = true; //启用摄像机水平或垂直旋转
  180. // 监听相机移动事件-限制只能在当前空间范围内移动
  181. controls.addEventListener('change', () => {
  182. // 检查相机位置是否超出边界框
  183. if (boundary && !boundary.containsPoint(camera.position)) {
  184. let clampedPosition = new THREE.Vector3();
  185. boundary.clampPoint(camera.position, clampedPosition);
  186. if (clampedPosition) {
  187. camera.position.copy(clampedPosition);
  188. }
  189. }
  190. });
  191. camera.lookAt(that.controlStarPosition.x, that.controlStarPosition.y, that.controlStarPosition.z);
  192. starRender(); //启动渲染
  193. // setTimeout(() => {
  194. // videoHandle()
  195. // }, 500);
  196. }
  197. function videoHandle() {
  198. if(!that.videoUrl){
  199. return false;
  200. }
  201. if(videoMesh){
  202. that.scene.remove(videoMesh);
  203. controls2.dispose();
  204. }
  205. // 创建视频元素
  206. var video = document.createElement('video');
  207. video.src = that.videoUrl; // 视频文件的路径
  208. video.setAttribute("crossOrigin", "Anonymous");
  209. video.loop = true;
  210. video.muted = true;
  211. video.play();
  212. console.warn("***video***",video,video.width);
  213. // 创建视频纹理
  214. var videoTexture = new THREE.VideoTexture(video);
  215. // 过滤的颜色值
  216. var keyColorObject = new THREE.Color("#00ff05");
  217. var myuniforms = {
  218. pointTexture: {
  219. type: "t",
  220. value: videoTexture
  221. },
  222. color: {
  223. type: "c",
  224. value: keyColorObject
  225. },
  226. videowidth: {
  227. type: "f",
  228. value: 501.0
  229. },
  230. videoheight: {
  231. type: "f",
  232. value: 1024.0
  233. },
  234. filterType: {
  235. type: "i",
  236. value: 0
  237. },
  238. lightLevel: {
  239. type: "f",
  240. value: 0.2
  241. },
  242. gridSize: {
  243. type: "f",
  244. value: 0.8
  245. }
  246. };
  247. // 创建绿幕着色器
  248. let greenScreenShader = {
  249. uniforms: myuniforms,
  250. transparent: true,
  251. vertexShader: `
  252. varying vec2 vUv;
  253. void main() {
  254. vUv = uv;
  255. vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
  256. gl_Position = projectionMatrix * mvPosition;
  257. } `,
  258. fragmentShader: `
  259. precision mediump float;
  260. uniform sampler2D pointTexture;
  261. uniform sampler2D colorlut;
  262. uniform vec3 color;
  263. uniform float videowidth;
  264. uniform float videoheight;
  265. uniform int filterType;
  266. uniform float gridSize;
  267. uniform float lightLevel;
  268. varying vec2 vUv;
  269. float alter=3.0;
  270. float u_mode=0.0;
  271. float u_threshold=1.0;
  272. float u_clipBlack=0.9;
  273. float u_clipWhite=1.0;
  274. float rgb2cb(float r, float g, float b){
  275. return 0.5 + -0.168736*r - 0.331264*g + 0.5*b;
  276. }
  277. float rgb2cr(float r, float g, float b){
  278. return 0.5 + 0.5*r - 0.418688*g - 0.081312*b;
  279. }
  280. float smoothclip(float low, float high, float x){
  281. if (x <= low){
  282. return 0.0;
  283. }
  284. if(x >= high){
  285. return 1.0;
  286. }
  287. return (x-low)/(high-low);
  288. }
  289. vec4 greenscreen(vec4 colora, float Cb_key,float Cr_key, float tola,float tolb, float clipBlack, float clipWhite){
  290. float cb = rgb2cb(colora.r,colora.g,colora.b);
  291. float cr = rgb2cr(colora.r,colora.g,colora.b);
  292. float alpha = distance(vec2(cb, cr), vec2(Cb_key, Cr_key));
  293. alpha = smoothclip(tola, tolb, alpha);
  294. float r = max(gl_FragColor.r - (1.0-alpha)*color.r, 0.0);
  295. float g = max(gl_FragColor.g - (1.0-alpha)*color.g, 0.0);
  296. float b = max(gl_FragColor.b - (1.0-alpha)*color.b, 0.0);
  297. if(alpha < clipBlack){
  298. alpha = r = g = b = 0.0;
  299. }
  300. if(alpha > clipWhite){
  301. alpha = 1.0;
  302. }
  303. if(clipWhite < 1.0){
  304. alpha = alpha/max(clipWhite, 0.9);
  305. }
  306. return vec4(r,g,b, alpha);
  307. }
  308. void main()
  309. {
  310. gl_FragColor = texture2D( pointTexture, vUv );
  311. float tola = 0.0;
  312. float tolb = u_threshold/2.0;
  313. float cb_key = rgb2cb(color.r, color.g, color.b);
  314. float cr_key = rgb2cr(color.r, color.g, color.b);
  315. gl_FragColor = greenscreen(gl_FragColor, cb_key, cr_key, tola, tolb, u_clipBlack, u_clipWhite);
  316. if(u_mode > 0.5 && u_mode < 1.5){
  317. gl_FragColor = mix(vec4(1.0, 1.0, 1.0, 1.0), gl_FragColor, gl_FragColor.a);
  318. gl_FragColor.a = 1.0;
  319. }
  320. if(u_mode > 1.5 && u_mode < 2.5){
  321. gl_FragColor = vec4(gl_FragColor.a, gl_FragColor.a, gl_FragColor.a, 1.0);
  322. }
  323. if(filterType==1){
  324. float gray = 0.2989*gl_FragColor.r+0.5870*gl_FragColor.g+0.1140*gl_FragColor.b;
  325. gl_FragColor = vec4(gray,gray,gray , gl_FragColor.a);
  326. }else if(filterType==2){
  327. vec3 tColor2 = texture2D( pointTexture, vec2(vUv[0]+(1.0/videowidth) , vUv[1]) ).rgb;
  328. vec3 tColor3 = texture2D( pointTexture, vec2(vUv[0]-(1.0/videowidth) , vUv[1]) ).rgb;
  329. vec3 tColor4 = texture2D( pointTexture, vec2(vUv[0]+(1.0/videowidth) , vUv[1]+(1.0/videoheight)) ).rgb;
  330. vec3 tColor5 = texture2D( pointTexture, vec2(vUv[0]-(1.0/videowidth) , vUv[1]-(1.0/videoheight)) ).rgb;
  331. vec3 tColor6 = texture2D( pointTexture, vec2(vUv[0]+(1.0/videowidth) , vUv[1]-(1.0/videoheight)) ).rgb;
  332. vec3 tColor7 = texture2D( pointTexture, vec2(vUv[0]-(1.0/videowidth) , vUv[1]+(1.0/videoheight)) ).rgb;
  333. vec3 tColor8 = texture2D( pointTexture, vec2(vUv[0] , vUv[1]+(1.0/videoheight)) ).rgb;
  334. vec3 tColor9 = texture2D( pointTexture, vec2(vUv[0] , vUv[1]+(1.0/videoheight)) ).rgb;
  335. vec3 tColor10 = texture2D( pointTexture, vec2(vUv[0]+(2.0/videowidth) , vUv[1]) ).rgb;
  336. vec3 tColor11 = texture2D( pointTexture, vec2(vUv[0]+(2.0/videowidth) , vUv[1]) ).rgb;
  337. gl_FragColor = vec4( (gl_FragColor.r+tColor2[0]+tColor3[0]+tColor4[0]+tColor5[0]+tColor6[0]+tColor7[0]+tColor8[0]+tColor9[0]+tColor10[0]+tColor11[0])/11.0,
  338. (gl_FragColor.g+tColor2[1]+tColor3[1]+tColor4[1]+tColor5[1]+tColor6[1]+tColor7[1]+tColor8[1]+tColor9[1]+tColor10[1]+tColor11[1])/11.0,
  339. (gl_FragColor.b+tColor2[2]+tColor3[2]+tColor4[2]+tColor5[2]+tColor6[2]+tColor7[2]+tColor8[2]+tColor9[2]+tColor10[2]+tColor11[2])/11.0,
  340. gl_FragColor.a);
  341. }else if(filterType==3){
  342. float brightr=gl_FragColor.r+lightLevel;
  343. float brightg=gl_FragColor.g+lightLevel;
  344. float brightb=gl_FragColor.b+lightLevel;
  345. gl_FragColor = vec4(brightr,brightg,brightb , gl_FragColor.a);
  346. }else if(filterType==4){
  347. float reverser=1.0 - gl_FragColor.r;
  348. float reverseg=1.0 - gl_FragColor.g;
  349. float reverseb=1.0 - gl_FragColor.b;
  350. gl_FragColor = vec4(reverser,reverseg,reverseb,gl_FragColor.a);
  351. }else if(filterType==5){
  352. float dx = fract(sin(dot(vUv ,vec2(12.9898,78.233))) * 43758.5453);
  353. vec3 cResult = gl_FragColor.rgb + gl_FragColor.rgb * clamp( 0.1 + dx, 0.0, 1.0 );
  354. vec2 sc = vec2( sin( vUv.y * 4096.0 ), cos( vUv.y * 4096.0 ) );
  355. cResult += gl_FragColor.rgb * vec3( sc.x, sc.y, sc.x ) * 0.025;
  356. cResult = gl_FragColor.rgb + clamp( 0.35, 0.0,1.0 ) * ( cResult - gl_FragColor.rgb );
  357. if( false ) {
  358. cResult = vec3( cResult.r * 0.3 + cResult.g * 0.59 + cResult.b * 0.11 );
  359. }
  360. float oldr=0.393*cResult[0]+0.769*cResult[1]+0.189*cResult[2];
  361. float oldg=0.349*cResult[0]+0.686*cResult[1]+0.168*cResult[2];
  362. float oldb=0.272*cResult[0]+0.534*cResult[1]+0.131*cResult[2];
  363. gl_FragColor = vec4( oldr,oldg,oldb , gl_FragColor.a);
  364. }else if(filterType==6){
  365. float average = ( gl_FragColor.r + gl_FragColor.g + gl_FragColor.b ) / 2.0;
  366. float s = sin( 0.5 ), c = cos( 0.5 );
  367. vec2 tex = vUv * vec2(videowidth,videoheight) - vec2(0,0);
  368. vec2 point = vec2( c * tex.x - s * tex.y, s * tex.x + c * tex.y ) * gridSize;
  369. float pattern = ( sin( point.x ) * sin( point.y ) ) * 4.0;
  370. float seed = average * 10.0 - 5.0 + pattern ;
  371. gl_FragColor = vec4( seed*0.3+gl_FragColor.r*0.7,seed*0.3+gl_FragColor.g*0.7 ,seed*0.3+gl_FragColor.b*0.7, gl_FragColor.a );
  372. }
  373. }
  374. `,
  375. };
  376. // 创建绿幕材质
  377. let greenScreenMaterial = new THREE.ShaderMaterial(greenScreenShader);
  378. greenScreenMaterial.side = THREE.DoubleSide;
  379. let geometry = new THREE.PlaneGeometry(9, 16);
  380. // 应用绿幕材质到对象上
  381. let mesh = new THREE.Mesh(geometry, greenScreenMaterial);
  382. mesh.position.set(0, 0, -10);//设置视频位置
  383. // mesh.lookAt(camera.position);
  384. scene.add(mesh);
  385. videoMesh = mesh;
  386. controls2 = new DragControls([mesh], camera, renderer.domElement );
  387. controls2.addEventListener('dragstart', function ( event ) {
  388. controls.enabled = false;
  389. });
  390. controls2.addEventListener('dragend', function ( event ) {
  391. controls.enabled = true;
  392. });
  393. }
  394. function stopRender() {
  395. needRender = false;
  396. }
  397. function starRender() {
  398. if (needRender == true) { //如果已经在渲染中了,则不能再次开启,避免渲染过多
  399. false;
  400. }
  401. needRender = true;
  402. render(); //开始渲染
  403. }
  404. function render() {
  405. if (needRender == false) {
  406. return false;
  407. }
  408. // stats.update();
  409. if(videoMesh){
  410. videoMesh.lookAt(camera.position);
  411. }
  412. renderer.render(scene, camera); //单次渲染
  413. requestId = requestAnimationFrame(render, canvas3d);
  414. }
  415. },
  416. methods: {
  417. navbarBackClk() {
  418. },
  419. clearHandle() {
  420. this.clearEvent();
  421. },
  422. aiPeopleChange(item){
  423. console.warn("***aiPeopleChange***",item);
  424. if(!item || !item.url){
  425. return false;
  426. }
  427. this.videoUrl = item.url;
  428. this.videoHandle();
  429. }
  430. }
  431. }
  432. </script>
  433. <style lang="scss" scoped>
  434. @import "./webgl_rxdz_vr.scss";
  435. /* @import "@/common/css/common.css"; */
  436. </style>