Explorar o código

附加webgl截图

zjs_project hai 1 ano
pai
achega
1d8bc73c56

+ 102 - 53
src/mixins/screenshot.js

@@ -1,5 +1,7 @@
 // const util = require('@/static/utils/util.js');
+	import * as THREE from 'three';
 const config = require('@/services/urlConfig.js');
+	import { MessageBox } from 'mint-ui';
 export default {
 	data() {
 		return {
@@ -29,22 +31,22 @@ export default {
 		},
 		// 翻转Y轴-像素方案
 		flip(pixels, w, h, c) {
+			if (!w || !h){
+				return false;
+			};
 			// handle Arrays
 			if (Array.isArray(pixels)) {
-				var result = this.flip(new Float64Array(pixels), w, h, c);
+				var result = this.flip(new Uint8Array(pixels), w, h, c);
 				for (var i = 0; i < pixels.length; i++) {
 					pixels[i] = result[i];
 				}
 				return pixels;
 			}
-		
-			if (!w || !h) throw Error('Bad dimensions');
-			if (!c) c = pixels.length / (w * h);
-		
+			// try{
+			if (!c) c = pixels.length / (w * h);	
 			var h2 = h >> 1;
 			var row = w * c;
 			var Ctor = pixels.constructor;
-		
 			// make a temp buffer to hold one row
 			var temp = new Ctor(w * c);
 			for (var y = 0; y < h2; ++y) {
@@ -57,6 +59,50 @@ export default {
 				// copy the copy of the top half row to the bottom half
 				pixels.set(temp, bottomOffset);
 			}
+			// }catch(e){
+			// 	//TODO handle the exception
+			// 	alert(e+row+":"+topOffset+'-'+bottomOffset)
+			// }
+			
+		},
+		
+		getClipPicUrl(resolve){
+			let gl = this.renderer.getContext();
+			let frameBuffer = new THREE.Vector2();
+			let pix = window.devicePixelRatio;
+			// this.renderer.getDrawingBufferSize(frameBuffer);//返回一个包含渲染器绘图缓存宽度和高度(单位像素)的对象。
+			let width = parseInt(this.width*pix )|| frameBuffer.x;
+			let height = parseInt(this.height*pix) || frameBuffer.y;
+			console.warn("***getClipPicUrl***",width,height,this.bottomLeftX*pix,this.bottomLeftY*pix);
+			let pixelData = new Uint8Array(width * height * 4);
+			gl.readPixels(this.bottomLeftX*pix, this.bottomLeftY*pix, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixelData);
+			this.flip(pixelData, width, height, 4);//入参必须是整数 width height
+			//参考 Threejs WebGLRenderer.readRenderTargetPixels
+			// let drawCanvasCtx = this.canvas.getContext('2d');
+			// let canvas = document.createElement('canvas');
+			// this.canvas2d = document.getElementById('canvas');
+			const canvas = document.getElementById('canvas');
+			let context = canvas.getContext('2d');
+			
+			let img = context.createImageData(width, height);
+			for (var i = 0; i < img.data.length; i += 4) {
+			    img.data[i + 0] = pixelData[i + 0];
+			    img.data[i + 1] = pixelData[i + 1];
+			    img.data[i + 2] = pixelData[i + 2];
+			    img.data[i + 3] = pixelData[i + 3];
+			}
+			// img.data = pixelData;
+			canvas.height = img.height;
+			canvas.width = img.width;
+			context.putImageData(img, 0, 0);
+			
+		    // let data = drawCanvasCtx.getImageData(100, 100, 200, 200);
+		    // canvas.width = 100;
+		    // canvas.height = 100;
+		    // context.putImageData(data, 0, 0)
+			let imgBase64 = canvas.toDataURL();
+			this.uploadFile(imgBase64,resolve);
+		    // return 
 		},
 		/**
 		 * 截图
@@ -65,55 +111,58 @@ export default {
 			// let currUniPage = getCurrentPages()[getCurrentPages().length - 1].$vm;
 			//时机合适时-像素存在则触发生成
 			return new Promise(resolve => {
-				this.screenPromiseShot().then((param) => {
-					if(param){
-						this.flip(param[0], param[1], param[2], 4);
-						const canvas = this.canvas2d;
-						const ctx = canvas.getContext('2d');
-						//  ImageData 对象,data是像素 一维数组,包含以 RGBA 顺序的数据,数据使用 0 至 255(包含)的整数表示
-						const img = canvas.createImageData(param[0], param[1], param[2]);
-						canvas.height = img.height;
-						canvas.width = img.width;
-						ctx.putImageData(img, 0, 0);
-						uni.canvasToTempFilePath({
-							x: 0,
-							y: 0,
-							destWidth:  canvas.width,
-							destHeight: canvas.height,
-							canvasId: "canvas",
-							canvas: canvas,
-							fileType: 'jpg',
-							quality: 1,
-							success: (res)=> {
-								console.log("***canvasToTempFilePath-success***", res)
-								this.upload(res.tempFilePath,resolve);
-							},
-							fail: (res)=> {
-								console.warn("***canvasToTempFilePath-fail***", res);
-								if(this && this.starRender && typeof(this.starRender)=='function'){
-									this.starRender()//启动渲染
+				if(type==3){
+					this.getClipPicUrl(resolve)
+				}else{
+					this.screenPromiseShot().then((param) => {
+						if(param){
+							this.flip(param[0], param[1], param[2], 4);
+							const canvas = this.canvas2d;
+							const ctx = canvas.getContext('2d');
+							//  ImageData 对象,data是像素 一维数组,包含以 RGBA 顺序的数据,数据使用 0 至 255(包含)的整数表示
+							const img = canvas.createImageData(param[0], param[1], param[2]);
+							canvas.height = img.height;
+							canvas.width = img.width;
+							ctx.putImageData(img, 0, 0);
+							uni.canvasToTempFilePath({
+								x: 0,
+								y: 0,
+								destWidth:  canvas.width,
+								destHeight: canvas.height,
+								canvasId: "canvas",
+								canvas: canvas,
+								fileType: 'jpg',
+								quality: 1,
+								success: (res)=> {
+									console.log("***canvasToTempFilePath-success***", res)
+									this.upload(res.tempFilePath,resolve);
+								},
+								fail: (res)=> {
+									console.warn("***canvasToTempFilePath-fail***", res);
+									if(this && this.starRender && typeof(this.starRender)=='function'){
+										this.starRender()//启动渲染
+									}
+									resolve('')
 								}
-								resolve('')
-							}
-						})
-					}else{
-						// let imgBase64 = this.canvas.toDataURL();
-						// this.base64src(imgBase64, (res) => {
-						// 	console.warn('转化后的url:', res)
-						// 	this.upload(res,resolve);
-						// })
-						
-						// let img = new Image();
-						// img.src = this.canvas.toDataURL('image/jpeg');// toDataURL :图片格式转成 base64
-						let imgBase64 = this.canvas.toDataURL();
-						if(type==2){
-							resolve(imgBase64)
+							})
 						}else{
-							this.uploadFile(imgBase64,resolve)
-						}
-						// this.uploadFile(imgBase64,resolve)
-					}					
-				})
+							// let imgBase64 = this.canvas.toDataURL();
+							// this.base64src(imgBase64, (res) => {
+							// 	console.warn('转化后的url:', res)
+							// 	this.upload(res,resolve);
+							// })
+							
+							// let img = new Image();
+							// img.src = this.canvas.toDataURL('image/jpeg');// toDataURL :图片格式转成 base64
+							let imgBase64 = this.canvas.toDataURL();
+							if(type==2){
+								resolve(imgBase64)
+							}else if(type==1){
+								this.uploadFile(imgBase64,resolve)
+							}
+						}					
+					})
+				}
 			})
 		},
 		async uploadFile(file, cb = null) {

+ 1 - 1
src/mixins/touchHandle.js

@@ -17,7 +17,7 @@ export default {
         mytouchmove(e) {
         	let startX = this.startX // 开始x坐标 
         	let startY = this.startY //开始y坐标
-        	let touchMoveX = e.changedTouches[0].clientx //滑动变化坐标 
+        	let touchMoveX = e.changedTouches[0].clientX //滑动变化坐标 
         	let touchMoveY = e.changedTouches[0].clientY //滑动变化坐标 
         	this.clientX = touchMoveX - startX;
         	this.clientY = touchMoveY - startY;

+ 31 - 0
src/pages/webgl_rxdz_720/webgl_rxdz_720.html

@@ -0,0 +1,31 @@
+<!--
+ * @Author: caodongdong caodongdoong@gmail.com
+ * @Date: 2023-05-17 15:46:34
+ * @LastEditors: caodongdong caodongdoong@gmail.com
+ * @LastEditTime: 2023-06-30 16:20:04
+ * @FilePath: \h5-uniApp-miniprogrgm\webgl\pages\webgl_rxdz\webgl_rxdz.html
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+-->
+<div class="main-view">
+	<mynavbar :barData='navbar' @navbarBackCallback="navbarBackClk" />
+	<!-- 主要操作视图 -->
+	<!-- <viewShell pageType="2" :spaceObj="curSpaceObj" @hideOrShowActor="hideOrShowActor"></viewShell> -->
+	<!-- <my-loading ref="myLoading" :myLoadingStatus="myLoadingStatus"></my-loading>
+	<div id="status" style="position:fixed;top:100px;left:30px;cursor:pointer;opacity:0.9;z-index:10000">
+		<canvas id="FPS" type="2d" style="width:80px;height:48px"></canvas>
+		<canvas id="MS" type="2d" style="width:80px;height:48px"></canvas>
+	</div> -->
+	<div id="mapDiv" ref="webgl"></div>
+	<canvas id="canvas_webgl" type="webgl" ref="glcanvas"
+		 width="100vw" height="100vh">
+	</canvas>
+	<div class="guide-mask" id="guide-mask">
+		<img src="https://dm.static.elab-plus.com/guide-mask.png">
+	</div>
+	<!-- AI结果覆盖层 -->
+	<!-- <viewMask ref="viewMask" @switchActor="switchActor" style="z-index: 13;"
+	  :spaceObj="curSpaceObj" ></viewMask> -->
+	<!-- 生成截屏的画布对象 -->
+	<canvas id="canvas" type="2d" :style="{'height':'100vh','top':'100vh'}"></canvas>
+	<!-- <video id="myvideo" loop muted autoplay width="304" height="540" webkit-playsinline="webkit-playsinline" playsinline="playsinline" src="https://dm.static.elab-plus.com/miniProgram/001.mp4"></video> -->
+</div>

+ 55 - 0
src/pages/webgl_rxdz_720/webgl_rxdz_720.scss

@@ -0,0 +1,55 @@
+.main-view{
+	width:100vw;
+	height:100vh;
+	overflow: hidden;
+}
+canvas { width:100vw; height:calc(100vh - 408px);z-index: 10;}
+#mapDiv{
+	background-color: #fff;
+}
+page {
+    -webkit-user-select: none;
+    user-select: none;
+    width: 100%;
+	height:100vh;
+    overflow-x: hidden;
+    overflow-y: hidden;
+}
+/* 生成截屏的画布对象 */
+#canvas {
+	width: 100vw;
+	z-index: -1;
+	// position: absolute;
+	left:0px;
+}
+.canvas-view{
+	position:relative;
+}
+.guide-mask {
+	width: 100%;
+	height: 100%;
+	top: 0;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	background: rgba(0, 0, 0, 0.3);
+	z-index: 9;
+	position: fixed;
+	margin: auto;
+	pointer-events: none;
+	transition: opacity 0.5s ease-out;
+}
+
+.guide-mask>img {
+	width: 280px;
+	height: 406px;
+	bottom: 100px;
+	right: 0;
+	margin: auto;
+	position: fixed;
+	left: 0;
+}
+.guide-mask-hide {
+	opacity: 0;
+	pointer-events: none;
+}

+ 427 - 0
src/pages/webgl_rxdz_720/webgl_rxdz_720.vue

@@ -0,0 +1,427 @@
+<template src="./webgl_rxdz_720.html">
+
+</template>
+<script>
+	import * as THREE from 'three';
+	import Stats from 'three/addons/libs/stats.module.js';
+	import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
+	import {getStorage} from '@/utils/localStorage';
+	var requestId = "";
+	const util = require('@/utils/util.js').default;
+	import commonPageMethod from '@/mixins/commonPageMethod.js';
+	// import commonPageMethod from '@/common/commonPageMethod.js';
+	export default {
+		mixins: [commonPageMethod],
+		/**
+		 * 页面的初始数据
+		 */
+		data() {
+			return {
+				pvCurPageName: "webgl_720",
+				locusBehaviorName: "720展示",
+				pvCurPageParams: null,
+				houseId: "",
+				pvId: 'p_2cmina_23121201',
+				canvas: null,
+				navbar: {
+					showCapsule: 1,
+					title: '',
+					titleColor: '#000',
+					navPadding: 0,
+					navPaddingBg: 'transparent',
+					navBarColor: 'transparent',
+					navBackColor: 'transparent',
+					haveCallback: true, // 如果是 true 会接手 navbarBackClk
+					fromShare: false,
+					fromProject: 0,
+					shareToken: "",
+					pageName: this.pvCurPageName,
+				},
+				id: '', // 户型编号
+				loader: null,
+				scene: null,
+				camera: null,
+				controlStarPosition: {
+					x: 0,
+					y: 0,
+					z: 0
+				}, //控制器初始位置
+				cameraStarPosition: {
+					x: 0,
+					y: 0,
+					z: 5
+				}, //摄像头初始位置
+				cameraLastPosition: null, //摄像头上一次移动到的位置
+				controlLastPosition: null, //观察点上一次移动到的位置
+				myLoadingStatus: false,
+				repeatFlag: false, //重复点击
+				canvasHeight:'',
+				isIOS: false,
+				videoUrl:'',	//绿幕视频地址
+				bgUrl:'',
+			}
+		},
+		beforeDestroy() {
+			cancelAnimationFrame(requestId, this.canvas)
+			this.worker && this.worker.terminate()
+			if (this.renderer instanceof THREE.WebGLRenderer) {
+				// 遍历场景中的所有子对象,找到类型为Mesh的对象并移除
+				let deleList = this.scene.children.filter(object => {
+					if (object instanceof THREE.Mesh) {
+						return object
+					}
+				})
+				if (deleList && deleList.length > 0) {
+					this.scene.remove(...deleList);
+				}
+				this.scene.traverse(function(object) {
+					if (object instanceof THREE.Mesh) {
+						if (object.geometry && typeof(object.geometry.dispose) == 'function') {
+							object.geometry.dispose();
+						}
+						if (object.material && typeof(object.material.dispose) == 'function') {
+							object.material.dispose();
+						}
+						if (object.texture && typeof(object.texture.dispose) == 'function') {
+							object.texture.dispose();
+						}
+					}
+				});
+				this.renderer.clear();
+				this.renderer.dispose();
+				this.renderer.forceContextLoss();
+				this.renderer.context = null;
+				this.renderer.domElement = null;
+				this.renderer = null;;
+			}
+			console.warn("***beforeDestroy-webgl_rxdz_720***");
+		},
+		mounted(options) {
+			var that = this;
+			console.warn("***webgl_rxdz_roam-options***", this.$route.query)
+			this.isIOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
+			this.videoUrl = this.$route.query.videoUrl || 'https://dm.static.elab-plus.com/miniProgram/005.mp4';
+			this.bgUrl = this.$route.query.bgUrl || 'https://dm.static.elab-plus.com/miniProgram/tears_of_steel_bridge_2k.jpg';
+			let screenWidth = window.screen.width;
+			let screenHeight = window.screen.height;
+			if (window.innerWidth && window.screen.width) {
+				screenWidth = Math.min(window.innerWidth, window.screen.width)
+			}
+			if (window.innerHeight && window.screen.height) {
+				screenHeight = Math.min(window.innerHeight, window.screen.height)
+			}
+			let unit = screenWidth / 750; //单位rpm 对应 px 的值
+			this.canvasHeight = screenHeight;
+			this.houseId = this.$route.query.houseId ? this.$route.query.houseId : '';
+			this.spaceId = this.$route.query.spaceId ? this.$route.query.spaceId : '';
+			let container = this.$refs.webgl;
+			let canvas3d = this.canvas = this.$refs.glcanvas;
+			//uniapp 兼容写法,因为uni的页面对象的Vue 实例是$vm
+
+			let camera = null,
+				renderer = null;
+			let needRender = false; //是否需要渲染 false表示不需要渲染;true 表示需要渲染
+			let scene = this.scene = new THREE.Scene();
+			let controls = null,
+				boundary = null;
+			let stats;
+			let videoMesh = null;
+			init();
+			// this.clearEvent = clearEvent;
+			// this.attendEvent = attendEvent;
+			this.starRender = starRender; //对外暴露启动渲染的方法
+			this.stopRender = stopRender; //对外暴露停止渲染的方法
+
+			function init() {
+				// 创建相机位置
+				camera = new THREE.PerspectiveCamera(120, screenWidth / that.canvasHeight, 0.1, 10000);
+				// camera.up.set(0, 1, 0);//俯视状态,将相机的up向量设置为z轴负方向 {x:0,y:1,z:0}
+				camera.position.set(that.cameraStarPosition.x, that.cameraStarPosition.y, that.cameraStarPosition.z);
+				scene.add(camera);
+				that.camera = camera;
+
+				// 环境光会均匀的照亮场景中的所有物体
+				// const ambientLight = new THREE.AmbientLight(0xFFEFE0, 3.5);
+				// scene.add(ambientLight);
+				// 辅助方格
+				// const axesHelper = new THREE.AxesHelper( 50 );
+				// scene.add( axesHelper );
+				// const gridHelper = new THREE.GridHelper(50, 10, 0xcccccc, 0xcccccc);
+				// gridHelper.position.y = 0;
+				// gridHelper.position.x = 0;
+				// scene.add(gridHelper);
+				//加载环境720贴图
+				const loader = new THREE.TextureLoader();
+				const texture = loader.load(that.bgUrl, () => {
+					const rt = new THREE.WebGLCubeRenderTarget(texture.image.height);
+					rt.fromEquirectangularTexture(renderer, texture);
+					scene.background = rt.texture;
+				});
+				//antialias 这个值得设置为false,不然IOS上截图会失效
+				renderer = that.renderer = new THREE.WebGLRenderer({
+					canvas: canvas3d,
+					alpha: true,
+				});
+				renderer.setPixelRatio(window.devicePixelRatio);
+				renderer.setSize(screenWidth, that.canvasHeight);
+				container.appendChild(renderer.domElement);
+
+				controls = new OrbitControls(camera, renderer.domElement);
+				controls.enableDamping = true; //启动缓动
+				controls.minDistance = 0.0001;
+				controls.maxDistance = 30;
+				// controls.minPolarAngle = 0; // 默认0
+				// controls.maxPolarAngle = Math.PI / 2; // 默认Math.PI,即可以向下旋转到的视角。
+				controls.enableZoom = true; //启用摄像机的缩放
+				controls.enablePan = true; //禁用摄像机平移
+				controls.enableRotate = true; //启用摄像机水平或垂直旋转
+
+				// 监听相机移动事件-限制只能在当前空间范围内移动
+				// controls.addEventListener('change', () => {
+				// 	// 检查相机位置是否超出边界框
+				// 	if (boundary && !boundary.containsPoint(camera.position)) {
+				// 		let clampedPosition = new THREE.Vector3();
+				// 		boundary.clampPoint(camera.position, clampedPosition);
+				// 		if (clampedPosition) {
+				// 			camera.position.copy(clampedPosition);
+				// 		}
+				// 	}
+				// });
+				camera.lookAt(that.controlStarPosition.x, that.controlStarPosition.y, that.controlStarPosition.z);
+				starRender(); //启动渲染
+				videoHandle();
+				var guideMask = document.querySelector('#guide-mask');
+				document.addEventListener("touchstart", function () {
+					guideMask.classList.add('guide-mask-hide');
+				}, false);
+			}
+
+			function videoHandle() {
+				// 创建视频元素
+				var video = document.createElement('video');
+				video.src = that.videoUrl; // 视频文件的路径
+				video.setAttribute("crossOrigin", "Anonymous");
+				video.loop = true;
+				video.muted = true;
+				video.play();
+				
+				console.warn("***video***",video,video.width);
+				// 创建视频纹理
+				var videoTexture = new THREE.VideoTexture(video);
+				// videoTexture.minFilter = THREE.LinearFilter;
+				// videoTexture.format = THREE.RGBFormat;
+
+				var keyColorObject = new THREE.Color("#00ff05");
+				var myuniforms = {
+				    pointTexture: {
+				        type: "t",
+				        value: videoTexture
+				    },
+				    color: {
+				        type: "c",
+				        value: keyColorObject
+				    },
+				    videowidth: {
+				        type: "f",
+				        value: 501.0
+				    },
+				    videoheight: {
+				        type: "f",
+				        value: 1024.0
+				    },
+				    filterType: {
+				        type: "i",
+				        value: 0
+				    },
+				    lightLevel: {
+				        type: "f",
+				        value: 0.2
+				    },
+				    gridSize: {
+				        type: "f",
+				        value: 0.8
+				    }
+				};
+				// 创建绿幕着色器
+				let greenScreenShader = {
+					uniforms: myuniforms,
+					transparent: true,
+					vertexShader: `    
+						varying vec2 vUv;    
+						void main() {
+							vUv = uv;
+							vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
+							gl_Position = projectionMatrix * mvPosition;
+						}  `,
+					fragmentShader: `
+						precision mediump float;
+						uniform sampler2D pointTexture;
+						uniform sampler2D colorlut;
+						uniform vec3 color;
+						uniform float videowidth;
+						uniform float videoheight;
+						uniform int filterType;
+						uniform float gridSize;
+						uniform float lightLevel;
+						
+						varying vec2 vUv;
+						float alter=3.0;
+						float u_mode=0.0;
+						float u_threshold=1.0;
+						float u_clipBlack=0.9;
+						float u_clipWhite=1.0;
+						
+						float rgb2cb(float r, float g, float b){
+							return 0.5 + -0.168736*r - 0.331264*g + 0.5*b;
+						}
+						float rgb2cr(float r, float g, float b){
+							return 0.5 + 0.5*r - 0.418688*g - 0.081312*b;
+						}
+						float smoothclip(float low, float high, float x){
+							if (x <= low){
+								return 0.0;
+							}
+							if(x >= high){
+								return 1.0;
+							}
+							return (x-low)/(high-low);
+						}
+						vec4 greenscreen(vec4 colora, float Cb_key,float Cr_key, float tola,float tolb, float clipBlack, float clipWhite){
+							float cb = rgb2cb(colora.r,colora.g,colora.b);
+							float cr = rgb2cr(colora.r,colora.g,colora.b);
+							float alpha = distance(vec2(cb, cr), vec2(Cb_key, Cr_key));
+							alpha = smoothclip(tola, tolb, alpha);
+							float r = max(gl_FragColor.r - (1.0-alpha)*color.r, 0.0);
+							float g = max(gl_FragColor.g - (1.0-alpha)*color.g, 0.0);
+							float b = max(gl_FragColor.b - (1.0-alpha)*color.b, 0.0);
+							if(alpha < clipBlack){
+								alpha = r = g = b = 0.0;
+							}
+							if(alpha > clipWhite){
+								alpha = 1.0;
+							}
+							if(clipWhite < 1.0){
+								alpha = alpha/max(clipWhite, 0.9);
+							}
+							return vec4(r,g,b, alpha);
+						}
+						
+						void main()
+						{
+							gl_FragColor = texture2D( pointTexture, vUv );
+							float tola = 0.0;
+							float tolb = u_threshold/2.0;
+							float cb_key = rgb2cb(color.r, color.g, color.b);
+							float cr_key = rgb2cr(color.r, color.g, color.b);
+							gl_FragColor = greenscreen(gl_FragColor, cb_key, cr_key, tola, tolb, u_clipBlack, u_clipWhite);
+							if(u_mode > 0.5 && u_mode < 1.5){
+								gl_FragColor = mix(vec4(1.0, 1.0, 1.0, 1.0), gl_FragColor, gl_FragColor.a);
+								gl_FragColor.a = 1.0;
+							}
+							if(u_mode > 1.5 && u_mode < 2.5){
+								gl_FragColor = vec4(gl_FragColor.a, gl_FragColor.a, gl_FragColor.a, 1.0);
+							}
+							if(filterType==1){
+								float gray = 0.2989*gl_FragColor.r+0.5870*gl_FragColor.g+0.1140*gl_FragColor.b;
+								gl_FragColor = vec4(gray,gray,gray , gl_FragColor.a);
+							}else if(filterType==2){
+								vec3 tColor2 = texture2D( pointTexture, vec2(vUv[0]+(1.0/videowidth) , vUv[1]) ).rgb;
+								vec3 tColor3 = texture2D( pointTexture, vec2(vUv[0]-(1.0/videowidth) , vUv[1]) ).rgb;
+								vec3 tColor4 = texture2D( pointTexture, vec2(vUv[0]+(1.0/videowidth) , vUv[1]+(1.0/videoheight)) ).rgb;
+								vec3 tColor5 = texture2D( pointTexture, vec2(vUv[0]-(1.0/videowidth) , vUv[1]-(1.0/videoheight)) ).rgb;
+								vec3 tColor6 = texture2D( pointTexture, vec2(vUv[0]+(1.0/videowidth) , vUv[1]-(1.0/videoheight)) ).rgb;
+								vec3 tColor7 = texture2D( pointTexture, vec2(vUv[0]-(1.0/videowidth) , vUv[1]+(1.0/videoheight)) ).rgb;
+								vec3 tColor8 = texture2D( pointTexture, vec2(vUv[0] , vUv[1]+(1.0/videoheight)) ).rgb;
+								vec3 tColor9 = texture2D( pointTexture, vec2(vUv[0] , vUv[1]+(1.0/videoheight)) ).rgb;
+								vec3 tColor10 = texture2D( pointTexture, vec2(vUv[0]+(2.0/videowidth) , vUv[1]) ).rgb;
+								vec3 tColor11 = texture2D( pointTexture, vec2(vUv[0]+(2.0/videowidth) , vUv[1]) ).rgb;
+								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,
+								(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,
+								(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,
+								gl_FragColor.a);
+							}else if(filterType==3){
+								float brightr=gl_FragColor.r+lightLevel;
+								float brightg=gl_FragColor.g+lightLevel;
+								float brightb=gl_FragColor.b+lightLevel;
+								gl_FragColor = vec4(brightr,brightg,brightb , gl_FragColor.a);
+							}else if(filterType==4){
+								float reverser=1.0 - gl_FragColor.r;
+								float reverseg=1.0 - gl_FragColor.g;
+								float reverseb=1.0 - gl_FragColor.b;
+								gl_FragColor = vec4(reverser,reverseg,reverseb,gl_FragColor.a);
+							}else if(filterType==5){
+								float dx = fract(sin(dot(vUv ,vec2(12.9898,78.233))) * 43758.5453);
+								vec3 cResult = gl_FragColor.rgb + gl_FragColor.rgb * clamp( 0.1 + dx, 0.0, 1.0 );
+								vec2 sc = vec2( sin( vUv.y * 4096.0 ), cos( vUv.y * 4096.0 ) );
+								cResult += gl_FragColor.rgb * vec3( sc.x, sc.y, sc.x ) * 0.025;
+								cResult = gl_FragColor.rgb + clamp( 0.35, 0.0,1.0 ) * ( cResult - gl_FragColor.rgb );
+								if( false ) {
+									cResult = vec3( cResult.r * 0.3 + cResult.g * 0.59 + cResult.b * 0.11 );
+								}
+								float oldr=0.393*cResult[0]+0.769*cResult[1]+0.189*cResult[2];
+								float oldg=0.349*cResult[0]+0.686*cResult[1]+0.168*cResult[2];
+								float oldb=0.272*cResult[0]+0.534*cResult[1]+0.131*cResult[2];
+								gl_FragColor =  vec4( oldr,oldg,oldb , gl_FragColor.a);
+							}else if(filterType==6){
+								float average = ( gl_FragColor.r + gl_FragColor.g + gl_FragColor.b ) / 2.0;
+								float s = sin( 0.5 ), c = cos( 0.5 );
+								vec2 tex = vUv * vec2(videowidth,videoheight) - vec2(0,0);
+								vec2 point = vec2( c * tex.x - s * tex.y, s * tex.x + c * tex.y ) * gridSize;
+								float pattern =  ( sin( point.x ) * sin( point.y ) ) * 4.0;
+								float seed = average * 10.0 - 5.0 + pattern ;
+								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 );
+							}
+						}
+					`,
+				};
+				// 创建绿幕材质
+				let greenScreenMaterial = new THREE.ShaderMaterial(greenScreenShader);
+				greenScreenMaterial.side = THREE.DoubleSide;
+				let geometry = new THREE.PlaneGeometry(9, 16);
+				// 应用绿幕材质到对象上
+				let mesh = new THREE.Mesh(geometry, greenScreenMaterial);
+				mesh.position.set(0, 0, -10);//设置视频位置
+				// mesh.lookAt(camera.position);
+				scene.add(mesh);
+				videoMesh = mesh;
+			}
+
+			function stopRender() {
+				needRender = false;
+			}
+
+			function starRender() {
+				if (needRender == true) { //如果已经在渲染中了,则不能再次开启,避免渲染过多
+					false;
+				}
+				needRender = true;
+				render(); //开始渲染
+			}
+
+			function render() {
+				if (needRender == false) {
+					return false;
+				}
+				// stats.update();
+				if(videoMesh){
+					videoMesh.lookAt(camera.position);
+				}
+				renderer.render(scene, camera); //单次渲染
+				requestId = requestAnimationFrame(render, canvas3d);
+			}
+
+		},
+		methods: {
+			navbarBackClk() {
+
+			},
+			clearHandle() {
+				this.clearEvent();
+			},
+		}
+	}
+</script>
+<style lang="scss" scoped>
+	@import "./webgl_rxdz_720.scss";
+	/* @import "@/common/css/common.css"; */
+</style>

+ 30 - 0
src/pages/webgl_rxdz_clipImg/webgl_rxdz_clipImg.html

@@ -0,0 +1,30 @@
+<div class="main-view">
+	<mynavbar :barData='navbar' @navbarBackCallback="navbarBackClk" />
+	<div id="mapDiv" ref="webgl"></div>
+	<canvas id="canvas_webgl" type="webgl" ref="glcanvas"
+		 width="100vw" height="100vh">
+	</canvas>
+	<!-- <div class="guide-mask" id="guide-mask">
+		<img src="https://dm.static.elab-plus.com/coverTips.png">
+	</div> -->
+	<div class="cover-box" :style="{'width':width+'px','height':height+'px','left':left+'px','top':top+'px'}">
+		<div class="box-empty"></div>
+		<div class="left-top boundary"></div>
+		<div class="right-top boundary"></div>
+		<div class="left-bottom boundary"></div>
+		<div class="right-bottom boundary"></div>
+		<div class="operate operate1" @touchstart.stop="mytouchstart($event,'1')" @touchmove.stop="mytouchmove"></div>
+		<div class="operate operate2" @touchstart.stop="mytouchstart($event,'2')" @touchmove.stop="mytouchmove"></div>
+		<div class="operate operate3" @touchstart.stop="mytouchstart($event,'3')" @touchmove.stop="mytouchmove"></div>
+		<div class="operate operate4" @touchstart.stop="mytouchstart($event,'4')" @touchmove.stop="mytouchmove"></div>
+	</div>
+	<div class="cover-btn rows justify-center" @click.stop="clipImgHandle">
+		确认为封面
+	</div>
+	<!-- AI结果覆盖层 -->
+	<!-- <viewMask ref="viewMask" @switchActor="switchActor" style="z-index: 13;"
+	  :spaceObj="curSpaceObj" ></viewMask> -->
+	<!-- 生成截屏的画布对象 -->
+	<canvas id="canvas" type="2d" :style="{'height':'200px','top':'200px'}"></canvas>
+	<video id="myvideo" style="display: none;" loop muted autoplay webkit-playsinline="webkit-playsinline" playsinline="playsinline" :src="videoUrl"></video>
+</div>

+ 149 - 0
src/pages/webgl_rxdz_clipImg/webgl_rxdz_clipImg.scss

@@ -0,0 +1,149 @@
+.main-view{
+	width:100vw;
+	height:100vh;
+	overflow: hidden;
+}
+canvas:focus {
+  outline:none;
+}
+#mapDiv{
+	background-color: #fff;
+}
+page {
+    -webkit-user-select: none;
+    user-select: none;
+    width: 100%;
+	height:100vh;
+    overflow-x: hidden;
+    overflow-y: hidden;
+}
+/* 生成截屏的画布对象 */
+#canvas {
+	width: 100vw;
+	z-index: -1;
+	// position: absolute;
+	left:0px;
+}
+.canvas-view{
+	position:relative;
+}
+.guide-mask {
+	width: 100%;
+	height: 100%;
+	top: 0;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	// background: rgba(0, 0, 0, 0.3);
+	z-index: 7;
+	position: fixed;
+	margin: auto;
+	pointer-events: none;
+	transition: opacity 0.5s ease-out;
+}
+
+.guide-mask>img {
+	width: 280px;
+	height: 406px;
+	bottom: 200px;
+	right: 0;
+	margin: auto;
+	position: fixed;
+	left: 0;
+}
+.guide-mask-hide {
+	opacity: 0;
+	pointer-events: none;
+}
+.cover-box{
+	position: absolute;
+	max-width:100vw;
+	// top:50%;
+	// left: 50%;
+	// transform: translate(-50%,-50%);
+	// width: 620px;
+	// height: 620px;
+	background: transparent;
+	z-index: 10;
+	pointer-events: none;
+	.box-empty{
+		// position: absolute;
+		width: calc(100% - 20px);
+		height: calc(100% - 20px);
+		margin-top: 6px;
+		margin-left: 6px;
+		border: 4px solid #fff;
+		box-sizing: content-box;
+		box-shadow: rgba(0,0,0,.8) 0px 0px 0px 2005px;
+	}
+	.boundary{
+		position: absolute;
+		width: 20px;
+		height: 20px;
+		border: solid 4px #fff;
+		pointer-events: auto;
+		z-index: 8;
+	}
+	.left-top{
+		top: 0px;
+		left: 0px;
+		border-right: none;
+		border-bottom: none;
+	}
+	.right-top{
+		top: 0px;
+		right: 0px;
+		border-left: none;
+		border-bottom: none;
+	}
+	.left-bottom{
+		bottom: 0px;
+		left: 0px;
+		border-right: none;
+		border-top: none;
+	}
+	.right-bottom{
+		bottom: 0px;
+		right: 0px;
+		border-left: none;
+		border-top: none;
+	}
+	.operate{
+		position: absolute;
+		pointer-events: auto;
+		width: 100px;
+		height: 100px;
+		z-index: 9;
+	}
+	.operate1{
+		left: -0px;
+		top: -0px;
+	}
+	.operate2{
+		right: -0px;
+		top: -0px;
+	}
+	.operate3{
+		right: -0px;
+		bottom: -0px;
+	}
+	.operate4{
+		left: -0px;
+		bottom: -0px;
+	}
+}
+.cover-btn{
+	position: absolute;
+	left: 50%;
+	transform: translateX(-50%);
+	bottom: 132px;
+	width: 292px;
+	height: 80px;
+	border-radius: 40px;
+	background: #fff;
+	font-family: "DIN Alternate Bold";
+	font-weight: 700;
+	font-size: 32px;
+	color: #222;
+	z-index: 11;
+}

+ 574 - 0
src/pages/webgl_rxdz_clipImg/webgl_rxdz_clipImg.vue

@@ -0,0 +1,574 @@
+<template src="./webgl_rxdz_clipImg.html">
+
+</template>
+<script>
+	import * as THREE from 'three';
+	import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
+	import {getStorage} from '@/utils/localStorage';
+	import { MessageBox } from 'mint-ui';
+	var requestId = "";
+	const util = require('@/utils/util.js').default;
+	import commonPageMethod from '@/mixins/commonPageMethod.js';
+	import screenshot from '@/mixins/screenshot.js';
+	// import commonPageMethod from '@/common/commonPageMethod.js';
+	export default {
+		mixins: [commonPageMethod,screenshot],
+		/**
+		 * 页面的初始数据
+		 */
+		data() {
+			return {
+				pvCurPageName: "webgl_720",
+				locusBehaviorName: "720展示",
+				pvCurPageParams: null,
+				houseId: "",
+				pvId: 'p_2cmina_23121201',
+				canvas: null,
+				navbar: {
+					showCapsule: 1,
+					title: '',
+					titleColor: '#000',
+					navPadding: 0,
+					navPaddingBg: 'transparent',
+					navBarColor: 'transparent',
+					navBackColor: 'transparent',
+					haveCallback: true, // 如果是 true 会接手 navbarBackClk
+					fromShare: false,
+					fromProject: 0,
+					shareToken: "",
+					pageName: this.pvCurPageName,
+				},
+				id: '', // 户型编号
+				loader: null,
+				scene: null,
+				camera: null,
+				controlStarPosition: {
+					x: 0,
+					y: 0,
+					z: 0
+				}, //控制器初始位置
+				cameraStarPosition: {
+					x: 0,
+					y: 0,
+					z: 5
+				}, //摄像头初始位置
+				cameraLastPosition: null, //摄像头上一次移动到的位置
+				controlLastPosition: null, //观察点上一次移动到的位置
+				myLoadingStatus: false,
+				repeatFlag: false, //重复点击
+				canvasHeight:'',
+				isIOS: false,
+				videoUrl:'',	//绿幕视频地址
+				bgUrl:'',
+				width:'620',
+				height:'620',
+				left:'65',
+				top:'300',
+				startX:0,
+				startY:0,
+				clientX:0,
+				clientY:0,
+				unit:0.5,
+				screenWidth:0,
+				screenHeight:0,
+				type:1,
+				bottomLeftX:0,
+				bottomLeftY:0,
+			}
+		},
+		beforeDestroy() {
+			cancelAnimationFrame(requestId, this.canvas)
+			this.worker && this.worker.terminate()
+			if (this.renderer instanceof THREE.WebGLRenderer) {
+				// 遍历场景中的所有子对象,找到类型为Mesh的对象并移除
+				let deleList = this.scene.children.filter(object => {
+					if (object instanceof THREE.Mesh) {
+						return object
+					}
+				})
+				if (deleList && deleList.length > 0) {
+					this.scene.remove(...deleList);
+				}
+				this.scene.traverse(function(object) {
+					if (object instanceof THREE.Mesh) {
+						if (object.geometry && typeof(object.geometry.dispose) == 'function') {
+							object.geometry.dispose();
+						}
+						if (object.material && typeof(object.material.dispose) == 'function') {
+							object.material.dispose();
+						}
+						if (object.texture && typeof(object.texture.dispose) == 'function') {
+							object.texture.dispose();
+						}
+					}
+				});
+				this.renderer.clear();
+				this.renderer.dispose();
+				this.renderer.forceContextLoss();
+				this.renderer.context = null;
+				this.renderer.domElement = null;
+				this.renderer = null;;
+			}
+			console.warn("***beforeDestroy-webgl_rxdz_clipImg***");
+		},
+		mounted(options) {
+			var that = this;
+			console.warn("***webgl_rxdz_roam-options***", this.$route.query)
+			this.isIOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
+			this.videoUrl = this.$route.query.videoUrl || 'https://dm.static.elab-plus.com/miniProgram/007.mp4';
+			this.bgUrl = this.$route.query.bgUrl || 'https://dm.static.elab-plus.com/miniProgram/tears_of_steel_bridge_2k.jpg';
+			let screenWidth = window.screen.width;
+			let screenHeight = window.screen.height;
+			if (window.innerWidth && window.screen.width) {
+				this.screenWidth = screenWidth = Math.min(window.innerWidth, window.screen.width);
+			}
+			if (window.innerHeight && window.screen.height) {
+				this.screenHeight = screenHeight = Math.min(window.innerHeight, window.screen.height)
+			}
+			let unit = screenWidth / 750; //单位rpm 对应 px 的值
+			this.unit = unit;
+			this.width = this.width * unit;
+			this.height = this.height * unit;
+			this.left = this.left * unit;
+			this.top = this.top * unit;
+			this.canvasHeight = screenHeight;
+			this.houseId = this.$route.query.houseId ? this.$route.query.houseId : '';
+			this.spaceId = this.$route.query.spaceId ? this.$route.query.spaceId : '';
+			let container = this.$refs.webgl;
+			let canvas3d = this.canvas = this.$refs.glcanvas;
+			//uniapp 兼容写法,因为uni的页面对象的Vue 实例是$vm
+
+			let camera = null,
+				renderer = null;
+			let needRender = false; //是否需要渲染 false表示不需要渲染;true 表示需要渲染
+			let scene = this.scene = new THREE.Scene();
+			let controls = null,
+				boundary = null;
+			let videoMesh = null;
+			init();
+			// this.clearEvent = clearEvent;
+			// this.attendEvent = attendEvent;
+			this.starRender = starRender; //对外暴露启动渲染的方法
+			this.stopRender = stopRender; //对外暴露停止渲染的方法
+
+			function init() {
+				// 创建相机位置
+				camera = new THREE.PerspectiveCamera(120, screenWidth / that.canvasHeight, 0.1, 10000);
+				// camera.up.set(0, 1, 0);//俯视状态,将相机的up向量设置为z轴负方向 {x:0,y:1,z:0}
+				camera.position.set(that.cameraStarPosition.x, that.cameraStarPosition.y, that.cameraStarPosition.z);
+				scene.add(camera);
+				that.camera = camera;
+
+				// 环境光会均匀的照亮场景中的所有物体
+				// const ambientLight = new THREE.AmbientLight(0xFFEFE0, 3.5);
+				// scene.add(ambientLight);
+				// 辅助方格
+				// const axesHelper = new THREE.AxesHelper( 50 );
+				// scene.add( axesHelper );
+				// const gridHelper = new THREE.GridHelper(50, 10, 0xcccccc, 0xcccccc);
+				// gridHelper.position.y = 0;
+				// gridHelper.position.x = 0;
+				// scene.add(gridHelper);
+				//加载环境720贴图
+				const loader = new THREE.TextureLoader();
+				const texture = loader.load(that.bgUrl, () => {
+					const rt = new THREE.WebGLCubeRenderTarget(texture.image.height);
+					rt.fromEquirectangularTexture(renderer, texture);
+					scene.background = rt.texture;
+				});
+				//antialias 这个值得设置为false,不然IOS上截图会失效
+				renderer = that.renderer = new THREE.WebGLRenderer({
+					canvas:canvas3d,
+					alpha: true, 
+					antialias:false,
+					// 如果想保存three.js canvas画布上的信息,注意设置preserveDrawingBuffer
+					preserveDrawingBuffer: true,
+				});
+				renderer.setPixelRatio(window.devicePixelRatio);
+				renderer.setSize(screenWidth, that.canvasHeight);
+				container.appendChild(renderer.domElement);
+
+				controls = new OrbitControls(camera, renderer.domElement);
+				controls.enableDamping = true; //启动缓动
+				controls.minDistance = 0.0001;
+				controls.maxDistance = 30;
+				// controls.minPolarAngle = 0; // 默认0
+				// controls.maxPolarAngle = Math.PI / 2; // 默认Math.PI,即可以向下旋转到的视角。
+				controls.enableZoom = true; //启用摄像机的缩放
+				controls.enablePan = true; //禁用摄像机平移
+				controls.enableRotate = true; //启用摄像机水平或垂直旋转
+
+				// 监听相机移动事件-限制只能在当前空间范围内移动
+				// controls.addEventListener('change', () => {
+				// 	// 检查相机位置是否超出边界框
+				// 	if (boundary && !boundary.containsPoint(camera.position)) {
+				// 		let clampedPosition = new THREE.Vector3();
+				// 		boundary.clampPoint(camera.position, clampedPosition);
+				// 		if (clampedPosition) {
+				// 			camera.position.copy(clampedPosition);
+				// 		}
+				// 	}
+				// });
+				camera.lookAt(that.controlStarPosition.x, that.controlStarPosition.y, that.controlStarPosition.z);
+				starRender(); //启动渲染
+				// var guideMask = document.querySelector('#guide-mask');
+				document.addEventListener("touchstart",  ()=> {
+					// guideMask.classList.add('guide-mask-hide');
+					setTimeout(()=>{
+						videoHandle();
+					},200)
+				}, false);
+			}
+
+			function videoHandle() {
+				if(videoMesh){
+					return false
+				}
+				// 创建视频元素
+				var video = document.createElement('video');
+				video.src = that.videoUrl; // 视频文件的路径
+				video.setAttribute("crossOrigin", "Anonymous");
+				video.loop = true;
+				video.muted = true;
+				video.play();
+				
+				console.warn("***video***",video,video.width);
+				// 创建视频纹理
+				var videoTexture = new THREE.VideoTexture(video);
+				// videoTexture.minFilter = THREE.LinearFilter;
+				// videoTexture.format = THREE.RGBFormat;
+
+				var keyColorObject = new THREE.Color("#00ff05");
+				var myuniforms = {
+				    pointTexture: {
+				        type: "t",
+				        value: videoTexture
+				    },
+				    color: {
+				        type: "c",
+				        value: keyColorObject
+				    },
+				    videowidth: {
+				        type: "f",
+				        value: 501.0
+				    },
+				    videoheight: {
+				        type: "f",
+				        value: 1024.0
+				    },
+				    filterType: {
+				        type: "i",
+				        value: 0
+				    },
+				    lightLevel: {
+				        type: "f",
+				        value: 0.2
+				    },
+				    gridSize: {
+				        type: "f",
+				        value: 0.8
+				    }
+				};
+				// 创建绿幕着色器
+				let greenScreenShader = {
+					uniforms: myuniforms,
+					transparent: true,
+					vertexShader: `    
+						varying vec2 vUv;    
+						void main() {
+							vUv = uv;
+							vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
+							gl_Position = projectionMatrix * mvPosition;
+						}  `,
+					fragmentShader: `
+						precision mediump float;
+						uniform sampler2D pointTexture;
+						uniform sampler2D colorlut;
+						uniform vec3 color;
+						uniform float videowidth;
+						uniform float videoheight;
+						uniform int filterType;
+						uniform float gridSize;
+						uniform float lightLevel;
+						
+						varying vec2 vUv;
+						float alter=3.0;
+						float u_mode=0.0;
+						float u_threshold=1.0;
+						float u_clipBlack=0.9;
+						float u_clipWhite=1.0;
+						
+						float rgb2cb(float r, float g, float b){
+							return 0.5 + -0.168736*r - 0.331264*g + 0.5*b;
+						}
+						float rgb2cr(float r, float g, float b){
+							return 0.5 + 0.5*r - 0.418688*g - 0.081312*b;
+						}
+						float smoothclip(float low, float high, float x){
+							if (x <= low){
+								return 0.0;
+							}
+							if(x >= high){
+								return 1.0;
+							}
+							return (x-low)/(high-low);
+						}
+						vec4 greenscreen(vec4 colora, float Cb_key,float Cr_key, float tola,float tolb, float clipBlack, float clipWhite){
+							float cb = rgb2cb(colora.r,colora.g,colora.b);
+							float cr = rgb2cr(colora.r,colora.g,colora.b);
+							float alpha = distance(vec2(cb, cr), vec2(Cb_key, Cr_key));
+							alpha = smoothclip(tola, tolb, alpha);
+							float r = max(gl_FragColor.r - (1.0-alpha)*color.r, 0.0);
+							float g = max(gl_FragColor.g - (1.0-alpha)*color.g, 0.0);
+							float b = max(gl_FragColor.b - (1.0-alpha)*color.b, 0.0);
+							if(alpha < clipBlack){
+								alpha = r = g = b = 0.0;
+							}
+							if(alpha > clipWhite){
+								alpha = 1.0;
+							}
+							if(clipWhite < 1.0){
+								alpha = alpha/max(clipWhite, 0.9);
+							}
+							return vec4(r,g,b, alpha);
+						}
+						
+						void main()
+						{
+							gl_FragColor = texture2D( pointTexture, vUv );
+							float tola = 0.0;
+							float tolb = u_threshold/2.0;
+							float cb_key = rgb2cb(color.r, color.g, color.b);
+							float cr_key = rgb2cr(color.r, color.g, color.b);
+							gl_FragColor = greenscreen(gl_FragColor, cb_key, cr_key, tola, tolb, u_clipBlack, u_clipWhite);
+							if(u_mode > 0.5 && u_mode < 1.5){
+								gl_FragColor = mix(vec4(1.0, 1.0, 1.0, 1.0), gl_FragColor, gl_FragColor.a);
+								gl_FragColor.a = 1.0;
+							}
+							if(u_mode > 1.5 && u_mode < 2.5){
+								gl_FragColor = vec4(gl_FragColor.a, gl_FragColor.a, gl_FragColor.a, 1.0);
+							}
+							if(filterType==1){
+								float gray = 0.2989*gl_FragColor.r+0.5870*gl_FragColor.g+0.1140*gl_FragColor.b;
+								gl_FragColor = vec4(gray,gray,gray , gl_FragColor.a);
+							}else if(filterType==2){
+								vec3 tColor2 = texture2D( pointTexture, vec2(vUv[0]+(1.0/videowidth) , vUv[1]) ).rgb;
+								vec3 tColor3 = texture2D( pointTexture, vec2(vUv[0]-(1.0/videowidth) , vUv[1]) ).rgb;
+								vec3 tColor4 = texture2D( pointTexture, vec2(vUv[0]+(1.0/videowidth) , vUv[1]+(1.0/videoheight)) ).rgb;
+								vec3 tColor5 = texture2D( pointTexture, vec2(vUv[0]-(1.0/videowidth) , vUv[1]-(1.0/videoheight)) ).rgb;
+								vec3 tColor6 = texture2D( pointTexture, vec2(vUv[0]+(1.0/videowidth) , vUv[1]-(1.0/videoheight)) ).rgb;
+								vec3 tColor7 = texture2D( pointTexture, vec2(vUv[0]-(1.0/videowidth) , vUv[1]+(1.0/videoheight)) ).rgb;
+								vec3 tColor8 = texture2D( pointTexture, vec2(vUv[0] , vUv[1]+(1.0/videoheight)) ).rgb;
+								vec3 tColor9 = texture2D( pointTexture, vec2(vUv[0] , vUv[1]+(1.0/videoheight)) ).rgb;
+								vec3 tColor10 = texture2D( pointTexture, vec2(vUv[0]+(2.0/videowidth) , vUv[1]) ).rgb;
+								vec3 tColor11 = texture2D( pointTexture, vec2(vUv[0]+(2.0/videowidth) , vUv[1]) ).rgb;
+								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,
+								(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,
+								(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,
+								gl_FragColor.a);
+							}else if(filterType==3){
+								float brightr=gl_FragColor.r+lightLevel;
+								float brightg=gl_FragColor.g+lightLevel;
+								float brightb=gl_FragColor.b+lightLevel;
+								gl_FragColor = vec4(brightr,brightg,brightb , gl_FragColor.a);
+							}else if(filterType==4){
+								float reverser=1.0 - gl_FragColor.r;
+								float reverseg=1.0 - gl_FragColor.g;
+								float reverseb=1.0 - gl_FragColor.b;
+								gl_FragColor = vec4(reverser,reverseg,reverseb,gl_FragColor.a);
+							}else if(filterType==5){
+								float dx = fract(sin(dot(vUv ,vec2(12.9898,78.233))) * 43758.5453);
+								vec3 cResult = gl_FragColor.rgb + gl_FragColor.rgb * clamp( 0.1 + dx, 0.0, 1.0 );
+								vec2 sc = vec2( sin( vUv.y * 4096.0 ), cos( vUv.y * 4096.0 ) );
+								cResult += gl_FragColor.rgb * vec3( sc.x, sc.y, sc.x ) * 0.025;
+								cResult = gl_FragColor.rgb + clamp( 0.35, 0.0,1.0 ) * ( cResult - gl_FragColor.rgb );
+								if( false ) {
+									cResult = vec3( cResult.r * 0.3 + cResult.g * 0.59 + cResult.b * 0.11 );
+								}
+								float oldr=0.393*cResult[0]+0.769*cResult[1]+0.189*cResult[2];
+								float oldg=0.349*cResult[0]+0.686*cResult[1]+0.168*cResult[2];
+								float oldb=0.272*cResult[0]+0.534*cResult[1]+0.131*cResult[2];
+								gl_FragColor =  vec4( oldr,oldg,oldb , gl_FragColor.a);
+							}else if(filterType==6){
+								float average = ( gl_FragColor.r + gl_FragColor.g + gl_FragColor.b ) / 2.0;
+								float s = sin( 0.5 ), c = cos( 0.5 );
+								vec2 tex = vUv * vec2(videowidth,videoheight) - vec2(0,0);
+								vec2 point = vec2( c * tex.x - s * tex.y, s * tex.x + c * tex.y ) * gridSize;
+								float pattern =  ( sin( point.x ) * sin( point.y ) ) * 4.0;
+								float seed = average * 10.0 - 5.0 + pattern ;
+								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 );
+							}
+						}
+					`,
+				};
+				// 创建绿幕材质
+				let greenScreenMaterial = new THREE.ShaderMaterial(greenScreenShader);
+				greenScreenMaterial.side = THREE.DoubleSide;
+				let geometry = new THREE.PlaneGeometry(9, 16);
+				// 应用绿幕材质到对象上
+				let mesh = new THREE.Mesh(geometry, greenScreenMaterial);
+				mesh.position.set(0, 0, -10);//设置视频位置
+				// mesh.lookAt(camera.position);
+				scene.add(mesh);
+				videoMesh = mesh;
+			}
+
+			function stopRender() {
+				needRender = false;
+			}
+
+			function starRender() {
+				if (needRender == true) { //如果已经在渲染中了,则不能再次开启,避免渲染过多
+					false;
+				}
+				needRender = true;
+				render(); //开始渲染
+			}
+
+			function render() {
+				if (needRender == false) {
+					return false;
+				}
+				if(videoMesh){
+					videoMesh.lookAt(camera.position);
+				}
+				renderer.render(scene, camera); //单次渲染
+				requestId = requestAnimationFrame(render, canvas3d);
+			}
+
+		},
+		methods: {
+			async clipImgHandle(){
+				this.bottomLeftX = this.left;
+				this.bottomLeftY = this.screenHeight - this.top - this.height;
+				console.warn("***clipImgHandle***")
+				let shottingImg = await this.shottingAction(3) + "?x-oss-process=image/auto-orient,1/quality,Q_46/format,jpg";//开始截图
+				console.warn("***clipImgHandle1***",shottingImg);
+				// alert(shottingImg)
+				// alert('getClipPicUrl3'+img.width)
+				// MessageBox({
+				// 	title: '提示',
+				// 	message: shottingImg,
+				// 	showCancelButton: true
+				// });
+				// window.open(shottingImg, "_blank");
+			},
+			navbarBackClk() {
+
+			},
+			clearHandle() {
+				this.clearEvent();
+			},
+			mytouchstart(e,type) {
+				console.warn("***mytouchstart***",type)
+				this.type = type;
+				this.startLeft = this.left;
+				// this.clientX = 0;
+				// this.clientY = 0;
+				this.startX = e.changedTouches[0].clientX;
+				this.startY = e.changedTouches[0].clientY;
+			},
+			mytouchmove(e) {
+				let startX = this.startX; 	// 开始x坐标 
+				let startY = this.startY; 	//开始y坐标
+				let touchMoveX = e.changedTouches[0].clientX //滑动变化坐标 
+				let touchMoveY = e.changedTouches[0].clientY //滑动变化坐标 
+				// this.clientX = touchMoveX - startX;
+				// this.clientY = touchMoveY - startY;
+				this.widthHandle(touchMoveX,1);
+			},
+			mytouchend(e) {
+				
+			},
+			widthHandle(touchMoveX){
+				let clientX = touchMoveX - this.startX;
+				if(this.type==1){//左上角
+					if(clientX < 0){//左移动
+						let _juli = Math.abs(clientX);
+						this.left = this.startLeft - _juli;
+						this.width = this.screenWidth - (this.left * 2);
+						if(this.left < 0){
+							this.left = 0;
+							this.width = this.screenWidth;
+						}
+					}else if(clientX > 0){//右移动
+						let _juli = Math.abs(clientX);
+						this.left = this.startLeft + _juli;
+						this.width = this.screenWidth - (this.left * 2);
+						if(this.left > (this.screenWidth - 200)/2){
+							this.left = (this.screenWidth - 200)/2;
+							this.width = 200;
+						}
+					}
+					this.height = this.width;
+				}else if(this.type==2){//右上角
+					if(clientX < 0){//左移动
+						let _juli = Math.abs(clientX);
+						this.left = this.startLeft + _juli;
+						this.width = this.screenWidth - (this.left * 2);
+						if(this.left > (this.screenWidth - 200)/2){
+							this.left = (this.screenWidth - 200)/2;
+							this.width = 200;
+						}
+					}else if(clientX > 0){//右移动
+						let _juli = Math.abs(clientX);
+						this.left = this.startLeft - _juli;
+						this.width = this.screenWidth - (this.left * 2);
+						if(this.left < 0){
+							this.left = 0;
+							this.width = this.screenWidth;
+						}
+					}
+					this.height = this.width;
+				}else if(this.type==3){//右下角
+					if(clientX < 0){//左移动
+						let _juli = Math.abs(clientX);
+						this.left = this.startLeft + _juli;
+						this.width = this.screenWidth - (this.left * 2);
+						if(this.left > (this.screenWidth - 200)/2){
+							this.left = (this.screenWidth - 200)/2;
+							this.width = 200;
+						}
+					}else if(clientX > 0){//右移动
+						let _juli = Math.abs(clientX);
+						this.left = this.startLeft - _juli;
+						this.width = this.screenWidth - (this.left * 2);
+						if(this.left < 0){
+							this.left = 0;
+							this.width = this.screenWidth;
+						}
+					}
+					this.height = this.width;
+				}else if(this.type==4){//左下角
+					if(clientX < 0){//左移动
+						let _juli = Math.abs(clientX);
+						this.left = this.startLeft - _juli;
+						this.width = this.screenWidth - (this.left * 2);
+						if(this.left < 0){
+							this.left = 0;
+							this.width = this.screenWidth;
+						}
+					}else if(clientX > 0){//右移动
+						let _juli = Math.abs(clientX);
+						this.left = this.startLeft + _juli;
+						this.width = this.screenWidth - (this.left * 2);
+						if(this.left > (this.screenWidth - 200)/2){
+							this.left = (this.screenWidth - 200)/2;
+							this.width = 200;
+						}
+					}
+					this.height = this.width;
+				}
+				// this.unit = unit;
+				// this.width = this.width * unit;
+				// this.height = this.height * unit;
+				// this.left = this.left * unit;
+				// this.top = this.top * unit;
+			}
+		}
+	}
+</script>
+<style lang="scss" scoped>
+	@import "./webgl_rxdz_clipImg.scss";
+	/* @import "@/common/css/common.css"; */
+</style>

+ 10 - 11
src/pages/webgl_rxdz_vr/webgl_rxdz_vr.vue

@@ -109,7 +109,9 @@
 			var that = this;
 			console.warn("***webgl_rxdz_roam-options***", this.$route.query)
 			this.isIOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
-
+			this.videoUrl = this.$route.query.videoUrl || 'https://dm.static.elab-plus.com/miniProgram/005.mp4';
+			this.bgUrl = this.$route.query.bgUrl || 'https://dm.static.elab-plus.com/miniProgram/tears_of_steel_bridge_2k.jpg';
+			
 			// alert("***mounted-webgl_rxdz_roam***"+this.isIOS + this.curHouseObj)
 			let screenWidth = window.screen.width;
 			let screenHeight = window.screen.height;
@@ -162,12 +164,11 @@
 				scene.add(gridHelper);
 				//加载环境720贴图
 				const loader = new THREE.TextureLoader();
-				const texture = loader.load(
-					'https://dm.static.elab-plus.com/miniProgram/tears_of_steel_bridge_2k.jpg', () => {
-						const rt = new THREE.WebGLCubeRenderTarget(texture.image.height);
-						rt.fromEquirectangularTexture(renderer, texture);
-						scene.background = rt.texture;
-					});
+				const texture = loader.load(that.bgUrl, () => {
+					const rt = new THREE.WebGLCubeRenderTarget(texture.image.height);
+					rt.fromEquirectangularTexture(renderer, texture);
+					scene.background = rt.texture;
+				});
 				//antialias 这个值得设置为false,不然IOS上截图会失效
 				renderer = that.renderer = new THREE.WebGLRenderer({
 					canvas: canvas3d,
@@ -208,7 +209,7 @@
 			function videoHandle() {
 				// 创建视频元素
 				var video = document.createElement('video');
-				video.src = 'https://dm.static.elab-plus.com/miniProgram/005.mp4'; // 视频文件的路径
+				video.src = that.videoUrl; // 视频文件的路径
 				video.setAttribute("crossOrigin", "Anonymous");
 				video.loop = true;
 				video.muted = true;
@@ -217,9 +218,7 @@
 				console.warn("***video***",video,video.width);
 				// 创建视频纹理
 				var videoTexture = new THREE.VideoTexture(video);
-				// videoTexture.minFilter = THREE.LinearFilter;
-				// videoTexture.format = THREE.RGBFormat;
-
+				// 过滤的颜色值
 				var keyColorObject = new THREE.Color("#00ff05");
 				var myuniforms = {
 				    pointTexture: {

+ 44 - 26
src/router/index.js

@@ -10,6 +10,8 @@ import webgl_rxdz_look from '@/pages/webgl_rxdz_look/webgl_rxdz_look.vue'
 import webgl_rxdz_customize from '@/pages/webgl_rxdz_customize/webgl_rxdz_customize'
 
 import webgl_rxdz_vr from '@/pages/webgl_rxdz_vr/webgl_rxdz_vr.vue'
+import webgl_rxdz_720 from '@/pages/webgl_rxdz_720/webgl_rxdz_720.vue'
+import webgl_rxdz_clipImg from '@/pages/webgl_rxdz_clipImg/webgl_rxdz_clipImg';//webgl 截图功能
 
 Vue.use(Router)
 const router = new Router({
@@ -17,54 +19,70 @@ const router = new Router({
     // mode: 'history',
     routes: [
         // 页面初始化
-        {
-            path: '/',
-            redirect: '/pages/webgl_rxdz'
-        },
 		{
-		    path: '/pages/webgl_rxdz',
-		    name: 'webgl_rxdz',
-		    component: webgl_rxdz,
+			path: '/',
+			redirect: '/pages/webgl_rxdz'
+		},
+		{
+			path: '/pages/webgl_rxdz',
+			name: 'webgl_rxdz',
+			component: webgl_rxdz,
 			meta:{
 				keepAlive:true
 			}
 		},
-        {
-            path: '/pages/webgl_rxdz_roam',
-            name: 'webgl_rxdz_roam',
-            component: webgl_rxdz_roam,
+		{
+			path: '/pages/webgl_rxdz_roam',
+			name: 'webgl_rxdz_roam',
+			component: webgl_rxdz_roam,
+			meta:{
+				keepAlive:false
+			}
+		},
+		{
+			path: '/pages/webgl_rxdz_look',
+			name: 'webgl_rxdz_look',
+			component: webgl_rxdz_look,
+			meta:{
+				keepAlive:false
+			}
+		},
+		{
+			path: '/pages/webgl_rxdz_customize',
+			name: 'webgl_rxdz_customize',
+			component: webgl_rxdz_customize,
 			meta:{
 				keepAlive:false
 			}
-        },
+		},
 		{
-		    path: '/pages/webgl_rxdz_look',
-		    name: 'webgl_rxdz_look',
-		    component: webgl_rxdz_look,
+			path: '/pages/mapComponent',
+			name: 'mapComponent',
+			component: mapComponent,
 			meta:{
 				keepAlive:false
 			}
 		},
-        {
-            path: '/pages/webgl_rxdz_customize',
-            name: 'webgl_rxdz_customize',
-            component: webgl_rxdz_customize,
+		{
+			path: '/pages/webgl_rxdz_vr',
+			name: 'webgl_rxdz_vr',
+			component: webgl_rxdz_vr,
 			meta:{
 				keepAlive:false
 			}
-        },
+		},
 		{
-		    path: '/pages/mapComponent',
-		    name: 'mapComponent',
-		    component: mapComponent,
+			path: '/pages/webgl_rxdz_720',
+			name: 'webgl_rxdz_720',
+			component: webgl_rxdz_720,
 			meta:{
 				keepAlive:false
 			}
 		},
 		{
-		    path: '/pages/webgl_rxdz_vr',
-		    name: 'webgl_rxdz_vr',
-		    component: webgl_rxdz_vr,
+			path: '/pages/webgl_rxdz_clipImg',
+			name: 'webgl_rxdz_clipImg',
+			component: webgl_rxdz_clipImg,
 			meta:{
 				keepAlive:false
 			}