使用 WebGL 创建交互式的 3D 场景

紫色蔷薇 2022-09-19 ⋅ 11 阅读

介绍

WebGL 是一种基于 JavaScript 的 3D 图形库,用于在网页上创建交互式和动态的 3D 场景。它可以在现代浏览器中运行,并且不需要安装任何插件。在本博客中,我们将探讨一些使用 WebGL 创建交互式 3D 场景的技巧。

准备工作

在开始之前,确保你的浏览器支持 WebGL。大多数现代浏览器都支持 WebGL,但有些浏览器需要手动启用该功能。请确保你的浏览器已更新到最新版本。

创建一个 WebGL 场景

首先,我们需要一个 WebGL 上下文来创建和显示场景。我们可以通过在 HTML 文件中添加一个 <canvas> 元素,并在 JavaScript 中获取该元素的上下文来实现。

<canvas id="webgl-canvas"></canvas>

接下来,我们将使用 JavaScript 来获取该 <canvas> 元素,并创建 WebGL 上下文。

const canvas = document.getElementById('webgl-canvas');
const gl = canvas.getContext('webgl');

现在,我们已经拥有了一个 WebGL 上下文,我们可以开始创建 3D 场景了。

创建一个简单的 3D 场景

首先,我们需要定义场景中的几何体。我们可以使用顶点数据来定义每个几何体的形状。一个几何体由一组顶点组成,每个顶点都有一个三维坐标。

const vertices = [
  // 顶点坐标
  -0.5, -0.5, 0.0,  // 第一个顶点
   0.5, -0.5, 0.0,  // 第二个顶点
   0.5,  0.5, 0.0,  // 第三个顶点
  -0.5,  0.5, 0.0   // 第四个顶点
];

现在,我们需要使用这些顶点数据来创建一个几何体对象。

const positionBuffer = gl.createBuffer(); // 创建缓冲区对象
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); // 绑定缓冲区对象
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); // 将顶点数据存入缓冲区

定义了几何体之后,我们需要使用这些顶点数据来创建一个着色器程序。着色器程序用于确定 3D 场景中每个顶点的颜色、光照等属性。

// 顶点着色器代码
const vertexShaderSource = `
  attribute vec3 aVertexPosition; // 顶点坐标属性

  void main() {
    gl_Position = vec4(aVertexPosition, 1.0); // 通过设置 gl_Position 来修改顶点位置
  }
`;

// 片段着色器代码
const fragmentShaderSource = `
  precision mediump float;

  void main() {
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 使用红色作为片段的颜色
  }
`;

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

// 编译片段着色器
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);

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

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

现在,我们可以将几何体绘制到屏幕上。

const positionAttributeLocation = gl.getAttribLocation(shaderProgram, 'aVertexPosition');
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 3, gl.FLOAT, false, 0, 0);

gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);

添加交互性

为了使 3D 场景更具交互性,我们可以添加鼠标或触摸事件来控制场景的旋转和缩放。

首先,我们需要定义一些变量来跟踪鼠标或触摸事件的状态。

let isDragging = false;
let startX, startY;
let currentX = 0, currentY = 0;
let zoom = 1.0;

然后,我们需要监听鼠标或触摸事件,并根据事件的类型更新场景的状态。

canvas.addEventListener('mousedown', handleMouseDown);
canvas.addEventListener('mouseup', handleMouseUp);
canvas.addEventListener('mousemove', handleMouseMove);
canvas.addEventListener('wheel', handleMouseWheel);

canvas.addEventListener('touchstart', handleTouchStart);
canvas.addEventListener('touchend', handleTouchEnd);
canvas.addEventListener('touchmove', handleTouchMove);
canvas.addEventListener('touchcancel', handleTouchEnd);

function handleMouseDown(event) {
  isDragging = true;
  startX = event.clientX;
  startY = event.clientY;
}

function handleMouseUp(event) {
  isDragging = false;
}

function handleMouseMove(event) {
  if (isDragging) {
    const deltaX = event.clientX - startX;
    const deltaY = event.clientY - startY;
    
    // 根据鼠标的移动距离旋转场景
    // ...

    startX = event.clientX;
    startY = event.clientY;
  }
}

function handleMouseWheel(event) {
  // 更新缩放因子
  // ...
}

function handleTouchStart(event) {
  if (event.touches.length === 1) {
    isDragging = true;
    startX = event.touches[0].clientX;
    startY = event.touches[0].clientY;
  }
}

function handleTouchEnd(event) {
  isDragging = false;
}

function handleTouchMove(event) {
  if (event.touches.length === 1 && isDragging) {
    const deltaX = event.touches[0].clientX - startX;
    const deltaY = event.touches[0].clientY - startY;
    
    // 根据触摸移动距离旋转场景
    // ...

    startX = event.touches[0].clientX;
    startY = event.touches[0].clientY;
  }
}

通过监听这些事件并根据鼠标或触摸移动的距离来翻转和缩放 3D 场景,我们可以为用户提供交互式的体验。

结论

通过使用 WebGL,我们可以在网页上创建交互式的 3D 场景。在本博客中,我们了解了如何创建一个简单的 3D 场景,并添加了一些交互性。希望这些技巧对您创建令人惊叹的 3D 场景有所帮助。

请记住,本博客只是一个入门指南,还有很多其他高级的技术和技巧可以使用。如果你对 WebGL 感兴趣,建议继续学习和探索更多有关 WebGL 的资料和教程。

参考资源:

Happy coding!


全部评论: 0

    我有话说: