在浏览器中渲染大尺寸 3D 模型:Speckle 处理空间抖动的方法
WebGL/Cesium 大空间相机抖动 RTE(Relative to Eye)实现原理简析
注:
相机空间
和视图空间
概念等效混用
1、实现的关键代码
const material = new THREE.RawShaderMaterial({
uniforms: {
cameraPostion: { value: null },
modelViewMatrixRTE: { value: null },
},
vertexShader: `
attribute vec3 position;
uniform vec3 cameraPostion;
uniform mat4 modelViewMatrixRTE;
uniform mat4 projectionMatrix;
void main() {
// key1
vec4 mvPosition = vec4(position.xyz - cameraPostion, 1.);
gl_Position = projectionMatrix * modelViewMatrixRTE * mvPosition;
}`,
fragmentShader: `
void main() {
gl_FragColor = vec4(vec3(0.5),1.);
}`
});
// 模型视图矩阵相对于相机。
const modelViewMatrixRTE = new THREE.Matrix4();
function updateMat(box) {
camera.updateMatrixWorld();
modelViewMatrixRTE.multiplyMatrices(camera.matrixWorldInverse, box.matrixWorld);
// key2
modelViewMatrixRTE.elements[12] = 0;
modelViewMatrixRTE.elements[13] = 0;
modelViewMatrixRTE.elements[14] = 0;
box.material.uniforms.cameraPostion.value = camera.position;
box.material.uniforms.modelViewMatrixRTE.value = modelViewMatrixRTE;
}
2、原理赏析
顶点的变换流程依然满足这个流程。
正常的矩阵变换过程, 模型顶点都是是基于原点(0,0,0)进行的变换。但是大场景会出现抖动情况。于是将顶点位置改为基于相机位置进行后面的变换。
那么每个顶点都应该减去相机位置。但是这个工作完全可以在顶点着色器中完成, 于是将该操作延迟。那么这里假设已经完成了世界空间
到视图空间
的平移变换。
modelViewMatrixRTE 依然是用于将模型空间
中的点转换到视图空间
中。但是因为模型顶点已经是相对于相机位置了(该操作被延迟执行), 因此不需要再进行平移操作。
modelViewMatrixRTE.elements[12] = 0;
modelViewMatrixRTE.elements[13] = 0;
modelViewMatrixRTE.elements[14] = 0;
最后, 将世界空间
到相机空间
的平移操作延迟到顶点着色器中执行。
vec4 mvPosition = vec4(position.xyz - cameraPostion, 1.);
gl_Position = projectionMatrix * modelViewMatrixRTE * mvPosition;