网站建设要懂哪些技术,阜宁网站建设,wordpress 发布文章 自定义栏目,4399小游戏网页版入口1、作用#xff1a;将物体从世界坐标系转换到相机坐标系#xff0c;相当于从世界坐标系转换到相机的局部(本地)坐标系。
2、基于LookAt函数的视图矩阵#xff1a;
相机位置eye#xff1a;(ex,ey,ez)#xff0c;世界坐标系下的位置
目标位置center#xff1a;(cx,cy,cz…1、作用将物体从世界坐标系转换到相机坐标系相当于从世界坐标系转换到相机的局部(本地)坐标系。
2、基于LookAt函数的视图矩阵
相机位置eye(ex,ey,ez)世界坐标系下的位置
目标位置center(cx,cy,cz)这是相机朝向的点也是世界坐标系下的位置
上方向up(ux,uy,uz)用于定义相机的上方向一般都是世界坐标系的上方向这样相机才是正对着物体而不是倾斜的
构建视图矩阵的步骤如下
计算相机的方向向量(z轴方向camera direction相机坐标系的“视线方向”在世界坐标系中的表示)从相机位置到目标位置的反方向用于定义新的Z轴 z e y e − c e n t e r ∣ e y e − c e n t e r ∣ \mathbf{z}\frac{\mathbf{eye}-\mathbf{center}}{|\mathbf{eye}-\mathbf{center}|} z∣eye−center∣eye−center计算相机的右方向向量(x轴方向camera right相机坐标系的“右方向”在世界坐标系中的表示)通过向上方向和摄像机方向的叉积计算出相机的右方向用于定义新的x轴 x u p × z ∣ u p × z ∣ \mathbf{x}\frac{\mathbf{up}×\mathbf{z}}{|\mathbf{up}×\mathbf{z}|} x∣up×z∣up×z计算相机的上方向向量(y轴方向camera up相机坐标系的“上方向”在世界坐标系中的表示)通过相机的Z轴和X轴的叉积得到新的Y轴方向 y z × x \mathbf{y}\mathbf{z}×\mathbf{x} yz×x构建视图矩阵根据上面计算的向量视图矩阵可以写成如下形式 V i e w M a t r i x [ x x x y x z − x ⋅ e y e y x y y y z − y ⋅ e y e z x z y z z − z ⋅ e y e 0 0 0 1 ] \mathbf{ViewMatrix}\begin{bmatrix} x_x x_y x_z −\mathbf{x⋅eye}\\ y_x y_y y_z −\mathbf{y⋅eye}\\ z_x z_y z_z −\mathbf{z⋅eye}\\ 0001\end{bmatrix} ViewMatrix xxyxzx0xyyyzy0xzyzzz0−x⋅eye−y⋅eye−z⋅eye1 3、示例代码
// matrix.js
const regPos /^-?\d(\.\d)?$/; // 支持整数和浮点数支持负号
function isVector3D(vector) {if (!Array.isArray(vector)) return false;if (vector.length ! 3) return false;return (regPos.test(vector[0]) regPos.test(vector[1]) regPos.test(vector[2]));
}function normalized(vector) {if (!isVector3D(vector)) return null;const vectorLength Math.sqrt(Math.pow(vector[0], 2) Math.pow(vector[1], 2) Math.pow(vector[2], 2));return vector.map((item) {return item / vectorLength;});
}function cross(v1, v2) {if (!isVector3D(v1)) return null;if (!isVector3D(v2)) return null;return [v1[1] * v2[2] - v1[2] * v2[1],v1[2] * v2[0] - v1[0] * v2[2],v1[0] * v2[1] - v1[1] * v2[0],];
}function dot(v1, v2) {if (!isVector3D(v1)) return null;if (!isVector3D(v2)) return null;return v1[0] * v2[0] v1[1] * v2[1] v1[2] * v2[2];
}function lookAt(eye, target, up [0, 1, 0]) {if (!isVector3D(eye)) return null;if (!isVector3D(target)) return null;if (!isVector3D(up)) return null;const eyeMinusTarget eye.map((item, index) item - target[index]);const z normalized(eyeMinusTarget); // Z轴const x normalized(cross(up, z)); // X轴const y cross(z, x); // Y轴// glsl中的mat4类型是列主序的这里也要改为列主序return new Float32Array([x[0],y[0],z[0],0,x[1],y[1],z[1],0,x[2],y[2],z[2],0,-dot(x, eye),-dot(y, eye),-dot(z, eye),1,]);
}export { isVector3D, normalized, dot, cross, lookAt };!DOCTYPE html
html langenheadmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titleWebGL2 视图矩阵示例/titlestylehtml,body {margin: 0;overflow: hidden;}canvas {position: fixed;top: 0;left: 0;outline: none;width: 100%;height: 100%;}/style
/headbodycanvas idwebgl-canvas/canvasdiv styledisplay: flex;position: fixed;left: 10px;top: 10px;button idfront从正面看/buttonbutton idback从背面看/button/divscript typemoduleimport { lookAt } from ./matrix.jsconst canvas document.getElementById(webgl-canvas);const gl canvas.getContext(webgl2);if (!gl) {console.log(WebGL2 not supported, falling back on WebGL);}const vertexShaderSource #version 300 esin vec4 aPosition;uniform mat4 uViewMatrix;void main() {gl_Position uViewMatrix * aPosition;};const fragmentShaderSource #version 300 esprecision highp float;out vec4 outColor;void main() {outColor vec4(1.0, 0.0, 0.0, 1.0); // Red color};function createShader(gl, type, source) {const shader gl.createShader(type);gl.shaderSource(shader, source);gl.compileShader(shader);if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {console.error(Shader compile failed:, gl.getShaderInfoLog(shader));gl.deleteShader(shader);return null;}return shader;}function createProgram(gl, vertexShader, fragmentShader) {const program gl.createProgram();gl.attachShader(program, vertexShader);gl.attachShader(program, fragmentShader);gl.linkProgram(program);if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {console.error(Program link failed:, gl.getProgramInfoLog(program));gl.deleteProgram(program);return null;}return program;}const vertexShader createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);const fragmentShader createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);const program createProgram(gl, vertexShader, fragmentShader);const positionBuffer gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);const size 0.5;const positions new Float32Array([-size, -size, size,size, -size, size,-size, size, size,size, -size, size,size, size, size,-size, size, size,]);gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);const vao gl.createVertexArray();gl.bindVertexArray(vao);const aPosition gl.getAttribLocation(program, aPosition);gl.enableVertexAttribArray(aPosition);gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, 0, 0);gl.useProgram(program);// 根据设备的像素比率调整 canvas 尺寸否则很模糊const pixelRatio window.devicePixelRatio || 1;canvas.width canvas.clientWidth * pixelRatio;canvas.height canvas.clientHeight * pixelRatio;gl.viewport(0, 0, canvas.width, canvas.height);// 设置视图矩阵const uViewMatrix gl.getUniformLocation(program, uViewMatrix);let viewMatrix new Float32Array([1, 0, 0, 0,0, 1, 0, 0,0, 0, 1, 0,0, 0, 0, 1])gl.uniformMatrix4fv(uViewMatrix, false, viewMatrix);document.getElementById(back).onclick (e) {// 相机在红色矩形的后面由于启用了背面剔除所以看不到viewMatrix lookAt([0, 0, -1], [0, 0, 0], [0, 1, 0])gl.uniformMatrix4fv(uViewMatrix, false, viewMatrix);alert(相机在(0,0,-1)处看向(0,0,0)处,相机在红色矩形的后面,由于启用了背面剔除所以看不到)}document.getElementById(front).onclick (e) {// 相机在红色矩形的前面可以看到viewMatrix lookAt([0, 0, 1], [0, 0, 0], [0, 1, 0])gl.uniformMatrix4fv(uViewMatrix, false, viewMatrix);alert(相机在(0,0,-1)处看向(0,0,0)处,相机在红色矩形的前面,所以可以看到)}function render() {gl.clearColor(0.0, 0.0, 0.0, 1.0);gl.clear(gl.COLOR_BUFFER_BIT);gl.enable(gl.DEPTH_TEST); // 开启深度测试防止面重叠gl.enable(gl.CULL_FACE); // 开启背面剔除gl.cullFace(gl.BACK); // 剔除背面gl.bindVertexArray(vao);gl.drawArrays(gl.TRIANGLES, 0, 6);requestAnimationFrame(render);}render();/script
/body/html