返回

揭秘WebGL坐标系及深度:洞悉三维虚拟世界的奥秘

前端

WebGL坐标系统
WebGL使用右手坐标系,如下所示:

+y
|
|
|
+x------>
|
|
|
+z
  • x轴指向右。
  • y轴指向向上。
  • z轴指向向外。

WebGL中的坐标系原点位于屏幕的中心。x轴和y轴的范围从-1到1。z轴的范围从-1到1,其中-1表示最接近相机的平面,1表示最远处的平面。

WebGL深度

WebGL中的深度用于确定片段在屏幕上的前后顺序。较近的片段将在较远的片段之前绘制。深度范围从0到1,其中0表示最接近相机的片段,1表示最远处的片段。

WebGL坐标系及深度的相互关系

WebGL坐标系和深度紧密相关。片段在屏幕上的位置由其坐标和深度共同决定。较近的片段将在较远的片段之前绘制,即使较近的片段在屏幕上的坐标比较远的片段更靠后。

实例:使用WebGL坐标系和深度创建三维图形

以下是一个简单的WebGL程序,该程序创建一个旋转的立方体:

<!DOCTYPE html>
<html>
<head>

<script type="text/javascript">

// 顶点着色器
var vertexShaderSource = `
attribute vec3 position;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;

void main() {
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;

// 片段着色器
var fragmentShaderSource = `
void main() {
  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;

// 创建WebGL上下文
var canvas = document.getElementById("canvas");
var gl = canvas.getContext("webgl");

// 编译顶点着色器和片段着色器
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);

var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);

// 创建着色器程序
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);

// 获取着色器程序中的属性和uniform变量
var positionAttribute = gl.getAttribLocation(program, "position");
var modelViewMatrixUniform = gl.getUniformLocation(program, "modelViewMatrix");
var projectionMatrixUniform = gl.getUniformLocation(program, "projectionMatrix");

// 创建立方体的顶点数据
var vertices = [
  // 前面的顶点
  -1.0, -1.0,  1.0,
   1.0, -1.0,  1.0,
   1.0,  1.0,  1.0,
  -1.0,  1.0,  1.0,

  // 后面的顶点
  -1.0, -1.0, -1.0,
  -1.0,  1.0, -1.0,
   1.0,  1.0, -1.0,
   1.0, -1.0, -1.0,

  // 顶面的顶点
  -1.0,  1.0, -1.0,
  -1.0,  1.0,  1.0,
   1.0,  1.0,  1.0,
   1.0,  1.0, -1.0,

  // 底面的顶点
  -1.0, -1.0, -1.0,
   1.0, -1.0, -1.0,
   1.0, -1.0,  1.0,
  -1.0, -1.0,  1.0,

  // 左面的顶点
  -1.0, -1.0, -1.0,
  -1.0,  1.0, -1.0,
  -1.0,  1.0,  1.0,
  -1.0, -1.0,  1.0,

  // 右面的顶点
   1.0, -1.0, -1.0,
   1.0,  1.0, -1.0,
   1.0,  1.0,  1.0,
   1.0, -1.0,  1.0
];

// 创建立方体的索引数据
var indices = [
  0,  1,  2,      0,  2,  3,    // 前面
  4,  5,  6,      4,  6,  7,    // 后面
  8,  9,  10,     8,  10, 11,   // 顶面
  12, 13, 14,     12, 14, 15,   // 底面
  16, 17, 18,     16, 18, 19,   // 左面
  20, 21, 22,     20, 22, 23    // 右面
];

// 创建缓冲区对象
var vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

var indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);

// 启用顶点属性数组
gl.enableVertexAttribArray(positionAttribute);

// 绑定顶点属性数组到缓冲区对象
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.vertexAttribPointer(positionAttribute, 3, gl.FLOAT, false, 0, 0);

// 设置模型视图矩阵
var modelViewMatrix = mat4.create();
mat4.translate(modelViewMatrix, modelViewMatrix, [0.0, 0.0, -6.0]);
mat4.rotateX(modelViewMatrix, modelViewMatrix, degToRad(45));
mat4.rotateY(modelViewMatrix, modelViewMatrix, degToRad(30));

// 设置投影矩阵
var projectionMatrix = mat4.create();
mat4.perspective(projectionMatrix, 45, canvas.width / canvas.height, 0.1, 100.0);

// 清除颜色缓冲区和深度缓冲区
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clearDepth(1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

// 使用着色器程序
gl.useProgram(program);

// 设置uniform变量
gl.uniformMatrix4fv(modelViewMatrixUniform, false, modelViewMatrix);
gl.uniformMatrix4fv(projectionMatrixUniform, false, projectionMatrix);

// 绘制立方体
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);

</script>
</head>
<body>
<canvas id="canvas" width="500" height="500"></canvas>
</body>
</html>

该程序将创建一个旋转的立方体。您可以通过修改modelViewMatrix和projectionMatrix矩阵来改变立方体的旋转角度和位置。

结论

WebGL坐标系和深度是WebGL三维图形编程的基础知识。通过理解WebGL坐标系和深度,您可以创建出更复杂的三维图形。