返回

WebGL起飞:3D编程的序曲

前端

3D编程的黎明:从灯泡到像素

计算机图形学的曙光微露于一盏闪烁的灯泡。程序员操纵这些灯泡,创造出光点和符号,将计算结果呈现给用户。这种"灯泡编程"揭开了计算机图形学的序幕。

WebGL:3D世界的画笔

随着时代的变迁,WebGL应运而生,为Web浏览器赋予了3D渲染能力。WebGL使用JavaScript作为编程语言,让开发者可以在浏览器中创建交互式的3D场景。

WebGL的力量:解锁3D可能性

WebGL赋予开发者构建令人惊叹的3D体验的能力。从逼真的游戏到交互式数据可视化,WebGL无处不在。它的轻量级和跨平台性使其成为3D编程的理想选择。

掌握计算机图形学:3D编程的垫脚石

深入理解计算机图形学是3D编程的关键。它涵盖了渲染、光照、纹理贴图等基本概念。通过掌握这些概念,开发者可以创造出视觉震撼的3D效果。

点燃你的3D编程激情

踏入3D编程的奇妙世界,你需要点燃自己的激情。从学习WebGL基础知识开始,逐步探索它的高级特性。在线教程、社区论坛和大量代码示例将成为你的向导。

示例代码:旋转立方体

// 创建 WebGL 画布
const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');

// 定义立方体顶点坐标
const vertices = [
  -1, -1, -1,   1, -1, -1,   1,  1, -1,   -1,  1, -1,
  -1, -1,  1,   1, -1,  1,   1,  1,  1,   -1,  1,  1,
  -1, -1, -1,   -1,  1, -1,   -1,  1,  1,   -1, -1,  1
];

// 定义立方体索引
const 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
];

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

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

// 编译着色器程序
const vertexShader = compileShader(gl, gl.VERTEX_SHADER, `
  attribute vec3 aPosition;
  uniform mat4 uModelViewMatrix;
  uniform mat4 uProjectionMatrix;

  void main() {
    gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(aPosition, 1.0);
  }
`);

const fragmentShader = compileShader(gl, gl.FRAGMENT_SHADER, `
  void main() {
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
  }
`);

const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);

// 获取 uniform 变量的位置
const modelViewMatrixLocation = gl.getUniformLocation(program, 'uModelViewMatrix');
const projectionMatrixLocation = gl.getUniformLocation(program, 'uProjectionMatrix');

// 创建模型视图矩阵和投影矩阵
const modelViewMatrix = mat4.create();
const projectionMatrix = mat4.create();

// 设置视口和清除颜色
gl.viewport(0, 0, canvas.width, canvas.height);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

// 设置深度测试
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);

// 绑定顶点位置属性
const positionAttributeLocation = gl.getAttribLocation(program, 'aPosition');
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.vertexAttribPointer(positionAttributeLocation, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(positionAttributeLocation);

// 主循环
function render() {
  requestAnimationFrame(render);

  // 更新模型视图矩阵
  mat4.translate(modelViewMatrix, modelViewMatrix, [0.0, 0.0, -6.0]);
  mat4.rotateX(modelViewMatrix, modelViewMatrix, degToRad(0.03));
  mat4.rotateY(modelViewMatrix, modelViewMatrix, degToRad(0.05));

  // 更新投影矩阵
  mat4.perspective(projectionMatrix, degToRad(45.0), canvas.width / canvas.height, 0.1, 100.0);

  // 传递 uniform 变量
  gl.uniformMatrix4fv(modelViewMatrixLocation, false, modelViewMatrix);
  gl.uniformMatrix4fv(projectionMatrixLocation, false, projectionMatrix);

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

render();

// 编译着色器
function compileShader(gl, type, source) {
  const shader = gl.createShader(type);
  gl.shaderSource(shader, source);
  gl.compileShader(shader);
  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
    console.error('Error compiling shader: ', gl.getShaderInfoLog(shader));
    return null;
  }
  return shader;
}

// 度数转弧度
function degToRad(degrees) {
  return degrees * Math.PI / 180.0;
}

拥抱3D编程的未来

WebGL为3D编程带来了无限可能。作为一名技术博客创作专家,我鼓励你踏上这段充满创造力和满足感的旅程。在3D图形学的海洋中遨游,释放你的想象力,打造非凡的3D体验。