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

看两眼
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
panoramaTexture.wrapS = THREE.RepeatWrapping
panoramaTexture.wrapT = THREE.RepeatWrapping
`
1、获取中心点(这个中心点,就是,相机拍全景图的位置)
2、现实中拍照时,y是水平的另一个方向,z是高度
three.js 时,z是水平的另一个方向,y是高度。`
let center = new THREE.Vector3(point.x / 100, point.z / 100, point.y / 100)
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] 范围内的值。


