基本概念
模型坐标
也常被称为局部空间或物体空间,是指一个三维模型在其自身坐标系下定义的顶点位置。
关键特性 :
独立性: 模型坐标完全不知道它将来会被放在场景的哪个位置,也不知道它会有多大,会如何旋转。
方便性: 对于建模者来说,这是最自然、最方便的坐标系统。他们只需关心物体本身的形状,无需考虑复杂的场景。
本质 :
模型: 指的是这个坐标系是专门为某个特定的模型(物体) 所定义的。
坐标: 指的是模型上各个顶点在这个专属坐标系下的位置信息。
所以,"模型坐标"直译就是"属于模型本身的坐标"。它强调的是坐标的"所有权"和"局部性"。
备注:在webgl 中,我们要先将模型坐标和 世界坐标系进行处理,让他们重合,这样可以减少计算量
世界坐标系
画布的坐标系统
观察坐标系(视图坐标系)
类似相机拍照时的可视范围,原点位置就是相机的位置。
对于相机位置的话,往前是 Z 轴,上面是 Y 轴,右边是 X 轴。
可视范围有两种情况(会影响展现的形状):
正摄投影:(理想的状态)展现的形状是不变的,还是物体本身的形状
透视投影:会根据相机的距离改变物体的局部大小。会有远小近大的感觉
视点与视线
视点:观察者所处的位置
视线:从视点触发沿着观察方向的射线
观察者默认状态
1、视点位于 webgl 坐标系统原点
2、视线为 z 轴负方向(向里)
可视空间
分类:
1、长方体可视空间,也称为盒状空间,由正射投影产生
2、四棱锥金字塔可视空间,由透视投影产生
例如正常眼睛的可视范围是一个扇形的区域
裁剪坐标系
没有在可视范围的点就会被裁剪,剩余的点就是裁剪坐标
立方体


html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas width="500" height="500" id="myCanvas"></canvas>
<script src="./cuon-matrix.js"></script>
<script type="vertex" id="vertex">
attribute vec3 a_position;
attribute vec4 a_color;
varying vec4 v_color;
uniform mat4 u_Matrix;
void main() {
gl_Position = u_Matrix * vec4(a_position, 1);
v_color = a_color;
}
</script>
<script type="fragment" id="fragment">
precision mediump float;
varying vec4 v_color;
void main() {
gl_FragColor = v_color;
}
</script>
<script>
let myCanvas = document.getElementById("myCanvas");
let gl = myCanvas.getContext("webgl");// IE8 之前的浏览器不兼容
if(!gl) {
alert("浏览器不支持 webgl!")
}
// 创建着色器
function createShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
let isSuccess = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
return isSuccess ? shader : console.log(gl.getShaderInfoLog(shader))
}
// 获取着色器中的文本内容字符串
function getInnerText(id) {
return document.getElementById(id).innerText;
}
const vertexStr = getInnerText("vertex");
const fragmentStr = getInnerText("fragment");
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexStr)
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentStr);
// 创建程序
function createProgram(gl, vertexShader, fragmentShader) {
let program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
let isSuccess = gl.getProgramParameter(program, gl.LINK_STATUS);
return isSuccess ? program : console.log(gl.getProgramInfoLog(program));
}
let program = createProgram(gl, vertexShader, fragmentShader);
gl.useProgram(program);
// 获取顶点着色器中变量
let a_position = gl.getAttribLocation(program, 'a_position');
let a_color = gl.getAttribLocation(program, 'a_color');
let u_Matrix = gl.getUniformLocation(program, 'u_Matrix');
let positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
let indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.enable(gl.DEPTH_TEST); //深度检测
// gl.enable(gl.CULL_FACE); // 隐藏背面
let deg = 10
function rotate() {
let viewMatrix = new Matrix4();
viewMatrix.setOrtho(-3, 3, -3, 3, -100, 100);
let projectMatrix = new Matrix4();
projectMatrix.setRotate(deg, 1, 1, 0);
let matrix = viewMatrix.multiply(projectMatrix);
gl.uniformMatrix4fv(u_Matrix, false, matrix.elements);
draw()
}
// setInterval(() => {
// deg++
// rotate(deg)
// },30)
rotate()
draw()
function draw() {
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
// 前
-0.5, -0.5, -0.5, 1, 0, 0,
0.5, -0.5, -0.5, 1, 0, 0,
0.5, 0.5, -0.5, 1, 0, 0,
-0.5, 0.5, -0.5, 1, 0, 0,
// 后
-0.5, -0.5, 0.5, 1, 0, 1,
-0.5, 0.5, 0.5, 1, 0, 1,
0.5, 0.5, 0.5, 1, 0, 1,
0.5, -0.5, 0.5, 1, 0, 1,
// 左
-0.5, -0.5, 0.5, 1, 1, 0,
-0.5, -0.5, -0.5, 1, 1, 0,
-0.5, 0.5, -0.5, 1, 1, 0,
-0.5, 0.5, 0.5, 1, 1, 0,
// 右
0.5, 0.5, -0.5, 0, 1, 0,
0.5, -0.5, -0.5, 0, 1, 0,
0.5, 0.5, 0.5, 0, 1, 0,
0.5, -0.5, 0.5, 0, 1, 0,
// 上面
-0.5, 0.5, -0.5, 1, 0, 1,
0.5, 0.5, -0.5, 1, 0, 1,
0.5, 0.5, 0.5, 1, 0, 1,
-0.5, 0.5, 0,5, 1, 0, 1,
-0.5, -0.5, -0.5, 1, 0, 1,
-0.5, -0.5, 0,5, 1, 0, 1,
0.5, -0.5, 0.5, 1, 0, 1,
0.5, -0.5, -0.5, 1, 0, 1,
]), gl.STATIC_DRAW);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([
0, 1, 2,
2, 3, 0,
4, 5, 6,
6, 7, 4,
8, 9, 10,
10, 11, 8,
12, 13, 14,
14, 15, 12,
16, 17, 18,
18, 19, 16,
20, 21, 22,
22, 23, 20,
]), gl.STATIC_DRAW);
gl.vertexAttribPointer(a_position, 3, gl.FLOAT, false, 4 * 6, 0);
gl.vertexAttribPointer(a_color, 3, gl.FLOAT, false, 4* 6, 4 * 3);
// 启用这个位置数据
gl.enableVertexAttribArray(a_position);
gl.enableVertexAttribArray(a_color);
// 绘制三角形
gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);
}
</script>
</body>
</html