3.js - 将 全景图 映射 到球体

着色器,从全景图上取对应的颜色

看一眼

  • sin:对边 / 斜边

  • cos:邻边 / 斜边

  • acos(nPos.y):如果给定一个余弦值(即某个角度的余弦值),acos函数可以返回这个角度本身(返回的角度以弧度为单位)

  • tan:对边 / 邻边

在这里插入图片描述

看两眼

// @ts-ignore
import * as THREE from 'three'

export default function WallShaderMaterial(panorama) {
	let point = panorama.point[0]
	let panoramaTexture = new THREE.TextureLoader().load(point.panoramaUrl)
	panoramaTexture.flipY = false // 纹理的翻转设置为false
	panoramaTexture.wrapS = THREE.RepeatWrapping // 纹理在S(U)方向上使用重复包裹模式
	panoramaTexture.wrapT = THREE.RepeatWrapping // 纹理在T(V)方向上使用重复包裹模式

	`
	  1、获取中心点(这个中心点,就是,相机拍全景图的位置)
	  2、现实中拍照时,y是水平的另一个方向,z是高度
	     three.js 时,z是水平的另一个方向,y是高度。`
	let center = new THREE.Vector3(point.x / 100, point.z / 100, point.y / 100) // three.js中常用的单位:米。

	return new THREE.ShaderMaterial({
		uniforms: {
			uPanorama: { value: panoramaTexture }, // 全景图
			uCenter: { value: center } // 中心点的位置
		},
		vertexShader: `
			varying vec2 vUv;
			uniform vec3 uCenter;
			varying vec3 vPosition;
			void main(){
				vUv = uv;
				vec4 modelPosition = modelMatrix * vec4(position, 1.0);
				vPosition = modelPosition.xyz;
				gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0);
			}`,
		fragmentShader: `
			const float PI = 3.14159265359;
			
			varying vec2 vUv;
			uniform vec3 uCenter;
			varying vec3 vPosition;
			uniform sampler2D uPanorama;
			
			void main(){
				vec3 nPos = normalize(vPosition - uCenter);
				
				// 正y轴 与 向量nPos 的夹角
				float theat = acos(nPos.y)/PI;
				
				float phi = (atan(nPos.z, nPos.x)+PI)/(2.0*PI);
				phi = phi + 0.75;
				vec4 pColor = texture2D(uPanorama, vec2(phi, theat));
				
				gl_FragColor = pColor;
			}`
	})
}

解释一下:vec3 nPos = normalize(vPosition - uCenter);

1、
	在着色器代码中,
	` vec3 nPos = normalize(vPosition - uCenter); `  
	执行的是:
		计算,顶点位置,相对于一个中心点的方向向量,并且,将这个方向向量归一化(即:将其长度缩放为1)。

2、	分解这行代码:
	'vPosition - uCenter':计算了,'当前顶点vPosition''中心点uCenter' 之间的向量差,
						   `结果是`:一个从中心点指向当前顶点的向量。
						   
	'normalize(...)': normalize函数,'接受'一个向量作为输入,并且,'返回'一个与该向量方向相同但长度为1的向量。
					   这是通过将原始向量的每个分量除以其长度来实现的。
					   归一化向量,在图形编程中非常有用,因为,它们可以表示方向,而不受原始向量长度的影响。
					   
	'vec3 nPos = ...':最后,将归一化后的向量赋值给nPos,
					   'nPos'现在是一个`单位长度的向量`,
					   表示:从中心点uCenter,到当前顶点vPosition的方向。
					   所以,`nPos 的 x、y、z 分量的值域都是 [-1, 1]`
					   x、y、z的这些值域,反映了:`nPos 可以指向的任何方向,从原点到单位球面上的任意点`3、
	具体来说,
	'全景图',通常,被映射到一个球体内部或外部,
	而'nPos向量',可以被视为,从球体中心,指向球体表面的一个点的方向,
	通过将这个方向,转换为球坐标系中的θ(theta,倾斜角)和φ(phi,方位角),可以索引到全景图上的正确位置,从而获取该方向对应的颜色。

解释一下:float theat = acos(nPos.y) / 3.14;

这行代码计算了,`向量nPos 与 y 轴正方向`之间的夹角(以弧度为单位),
并且,将这个角度值归一化到 [0, 1] 范围内。

`acos函数` 输入、输出:
	'acos函数',接收,一个位于 [-1, 1] 的值作为参数,表示某个角度的余弦值。
	'acos函数',返回,一个位于 [0, π] 的值。

解释一下:float phi = (atan(nPos.z, nPos.x)+3.14)/6.28;

这行代码计算了,`向量nPos 在xz平面上的投影,与 x轴正方向,之间的夹角(以弧度为单位)``atan(nPos.z, nPos.x)`的返回值是[-Math.PI  ~  Math.PI]
				然后,加上 π(以将范围从 [-π, π] 转换为 [0, 2π]),
				最后,除以 2π 以得到一个在 [0, 1] 范围内的值。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值