前端面经-WebGL/threeJS

06-01 1455阅读

WebGL/threeJS面试题扫描与总结-CSDN博客

1.什么是 WebGL?什么是 Three.js?请解释three.js中的WebGL和Canvas的区别?

WebGL(全写Web Graphics Library)是一种3D绘图协议,这种绘图技术标准允许把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的一个JavaScript绑定,WebGL可以为HTML5 Canvas提供硬件3D加速渲染,这样Web开发人员就可以借助系统显卡来在浏览器里更流畅地展示3D场景和模型了,还能创建复杂的导航和数据视觉化。WebGL技术标准免去了开发网页专用渲染插件的麻烦,可被用于创建具有复杂3D结构的网站页面,甚至可以用来设计3D网页游戏等等。

Three.js是一款基于JavaScript可直接运行GPU驱动游戏与图形驱动应用于浏览器的WebGL引擎,其库提供的特性与API以绘制3D场景于浏览器。

Canvas与WebGL的区别是canvas API提供二维绘图方式,图形的绘制主要通过CanvasRenderingContext2D接口完成,通过 canvas.getContext(‘2d’) 获取二维图像绘图上下文;而WebGL API可以在任何兼容canvas中的渲染2d和3d图形,WebGL API 提供三维接口,图形绘制主要通过WebGLRenderingContext接口完成,通过canvas.getContext(‘webgl’)来获取WebGL上下文。

2.Three.js它有什么特点和优势?以及它为什么会被广泛使用?

Three.js提供了一系列简化的API和工具,使得创建三维图形更加容易的展现在浏览器端。其抽象了底层的复杂性,提供了简单、一致的接口。提供基本的渲染功能之外,还包括了丰富的扩展,如光照、贴图、粒子系统等,可以满足不同类型的三维图形需求。Three.js有一个活跃的社区,提供了大量的文档、教程和示例,方便开发者学习和解决问题。

随着社会的信息化的发展,在数据可视化、图形/游戏引擎、交互演示、图形渲染、地图、VR、物品展示、室内设计、城市规划等方面Web端展示3D的需求大量增多,人们迫切需求一款能打开浏览器即可使用的便捷式3D开发引擎,而基于JavaScript的WebGL引擎Threejs恰好可以满足这一要求,所以得以大规模应用。

3.如何在网页中引入 Three.js 库?

方法一:CDN 导入

1.
2.  {
3.    "imports": {
4.      "three": "https://unpkg.com/three@/build/three.module.js",
5.      "three/addons/": "https://unpkg.com/three@/examples/jsm"
6.    }
7.  }
8.

方法二:npm安装导入

npm install three --save

方法三: 模块化导入

import * as THREE from './node_modules/three/build/three.module.js';
var scene = new THREE.Scene()

方法四:script标签方式引入


    var scene = new THREE.Scene()
    console.log(scene)

4.Three.js的基本组件和类有哪些?

Three.js的基本组件有场景(Scene)、相机(Camera)、渲染器(Renderer);

常见的类有Object3D、BufferGeometry、Geometry、BufferAttribute、Layers、Raycaster等;

Object3D类:Object3D是ThreeJs中对物体抽象的基类,包括相机和灯光都是Object3D的子类.一般情况下,我们不会直接使用这个类,对于构造物体,一般我们都是使用的Mesh.

BufferGeometry类:是面片、线或点几何体的有效表述.包括顶点位置,面片索引、法相量、颜色值、UV坐标和自定义缓存属性值.使用BufferGeometry可以有效减少向 GPU 传输上述数据所需的开销.

前端面经-WebGL/threeJS
(图片来源网络,侵删)

Geometry类:Geometry 是对 BufferGeometry 的替代,Geometry利用Vector3或Color存储了几何体的相关 attributes(如顶点位置,面信息,颜色等),但比起BufferGeometry更容易读写,但是运行效率不如有类型的队列.

BufferAttribute类:这个类用于存储与BufferGeometry相关联的attribute(例如顶点位置向量,面片索引,法向量,颜色值,UV坐标以及任何自定义attribute).利用BufferAttribute,可以更高效的向GPU传递数据.详情和例子见该页.

前端面经-WebGL/threeJS
(图片来源网络,侵删)

在BufferAttribute中,数据被存储为任意长度的矢量(通过itemSize进行定义),下列函数如无特别说明, 函数参数中的index会自动乘以矢量长度进行计算. 当想要处理类似向量的数据时, 可以使用在Vector2,Vector3,Vector4以及Color这些类中的.fromBufferAttribute(attribute,index) 方法来更为便捷地处理.

Layers类:Layers对象为Object3D分配1个到32个图层.32个图层从0到31编号标记.在内部实现上,每个图层对象被存储为一个bit mask,默认的,所有Object3D对象都存储在第0个图层上.图层对象可以用于控制对象的显示.当camera的内容被渲染时与其共享图层相同的物体会被显示.每个对象都需要与一个camera共享图层.每个继承自Object3D的对象都有一个Object3D.layers对象.

前端面经-WebGL/threeJS
(图片来源网络,侵删)

Raycaster类:这个类用于进行raycasting(光线投射).光线投射用于进行鼠标拾取(在三维空间中计算出鼠标移过了什么物体).

5.three.js中的场景 (scene)、相机 (camera)和渲染器 (renderer)的作用?

场景是Three.js 中所有 3D 对象的容器。它定义了 3D 空间中的位置、方向和光照。

相机定义了 3D 场景中的视角。通过设置相机的位置和角度,可以控制场景中的视觉效果。

渲染器将场景和相机中的 3D 对象渲染到屏幕上。Three.js 提供了多个渲染器,包括 CanvasRenderer、WebGLRenderer 和 SVGRenderer。

6.three.js中的常见几何体(例如立方体、球体、圆柱体等)是如何被创建的?

6.1. 立方体(BoxGeometry)

// 参数:宽度、高度、深度、宽度分段数、高度分段数、深度分段数
const geometry = new THREE.BoxGeometry(1, 1, 1);

核心参数:

width:X 轴方向的宽度(默认 1)。

height:Y 轴方向的高度(默认 1)。

depth:Z 轴方向的深度(默认 1)。

widthSegments、heightSegments、depthSegments:控制细分程度,影响平滑度和性能。

6.2. 球体(SphereGeometry)

// 参数:半径、横向分段数、纵向分段数
const geometry = new THREE.SphereGeometry(1, 32, 16);

核心参数:

radius:球体半径(默认 1)。

widthSegments:横向分段数(默认 32),值越大越平滑。

heightSegments:纵向分段数(默认 16),控制两极的细分。

phiStart、phiLength:水平起始角度和弧度范围(默认 0 到 2π)。

thetaStart、thetaLength:垂直起始角度和弧度范围(默认 0 到 π)。

6.3 圆柱体(CylinderGeometry)

// 参数:顶部半径、底部半径、高度、径向分段数、高度分段数
const geometry = new THREE.CylinderGeometry(0.5, 1, 2, 32);

核心参数:

radiusTop:顶部半径(默认 1)。

radiusBottom:底部半径(默认 1)。

height:圆柱体高度(默认 1)。

radialSegments:径向分段数(默认 32),控制侧面的多边形数量。

heightSegments:高度分段数(默认 1),控制高度方向的细分。

openEnded:是否开放两端(默认 false,即封闭)。

6.4 平面(PlaneGeometry)

// 参数:宽度、高度、宽度分段数、高度分段数
const geometry = new THREE.PlaneGeometry(10, 10, 1, 1);

核心参数:

width、height:平面的宽和高(默认 1)。

widthSegments、heightSegments:控制细分程度,用于复杂变形或物理模拟。

6.5 圆锥体(ConeGeometry)

// 参数:半径、高度、径向分段数
const geometry = new THREE.ConeGeometry(1, 2, 32);

核心参数:

radius:底部半径(默认 1)。

height:高度(默认 1)。

radialSegments:径向分段数(默认 32)。

openEnded:是否开放底部(默认 false)。

6.6 圆环(TorusGeometry)

// 参数:圆环半径、管道半径、径向分段数、管道分段数
const geometry = new THREE.TorusGeometry(3, 1, 16, 100);

核心参数:

radius:圆环中心到管道中心的距离(默认 1)。

tube:管道半径(默认 0.4)。

radialSegments:径向分段数(默认 16)。

tubularSegments:管道分段数(默认 100)。

arc:圆环弧度(默认 2π,即完整圆环)。

6.7 圆环结(TorusKnotGeometry)

// 参数:半径、管道半径、分段数、缠绕数
const geometry = new THREE.TorusKnotGeometry(2, 0.5, 100, 16);

核心参数:

radius:圆环结中心到管道中心的距离(默认 1)。

tube:管道半径(默认 0.4)。

tubularSegments:管道分段数(默认 64)。

radialSegments:径向分段数(默认 8)。

p、q:控制缠绕方式的整数(默认 3 和 2)。

7.如何在Three.js中创建自定义几何体 **( **Custom Geometry **) **?

在 Three.js 中创建自定义几何体主要通过BufferGeometry类实现,它是现代 Three.js 中表示几何体的标准方式,相比旧版的Geometry类,BufferGeometry在性能和内存使用上更高效。以下是创建自定义几何体的核心步骤和示例:

7.1基础原理

BufferGeometry通过 ** 缓冲区属性(BufferAttribute)** 存储顶点数据,主要包括:

顶点位置(position):每个顶点的三维坐标(x, y, z)。

顶点法线(normal):用于光照计算的方向向量。

UV 坐标(uv):用于纹理映射的二维坐标。

颜色(color):顶点颜色(可选)。

7.2创建自定义几何体的步骤

7.2.1. 创建 BufferGeometry 实例

const geometry = new THREE.BufferGeometry();

7.2.2 定义顶点数据

使用Float32Array或Uint16Array存储顶点信息:

// 示例:创建一个三角形的顶点位置数据
const vertices = new Float32Array([
  0, 0, 0,    // 顶点1坐标
  1, 0, 0,    // 顶点2坐标
  0, 1, 0     // 顶点3坐标
]);

7.2.3 创建缓冲区属性并设置到几何体

// 参数:数据数组,每个顶点的分量数(如position为3个分量:x,y,z)
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));

7.2.4(可选)设置顶点法线和 UV 坐标

// 设置法线(用于光照计算)
const normals = new Float32Array([
  0, 0, 1,    // 顶点1的法线方向(垂直屏幕向外)
  0, 0, 1,    // 顶点2的法线方向
  0, 0, 1     // 顶点3的法线方向
]);
geometry.setAttribute('normal', new THREE.BufferAttribute(normals, 3));
// 设置UV坐标(用于纹理映射)
const uvs = new Float32Array([
  0, 0,        // 顶点1的UV坐标
  1, 0,        // 顶点2的UV坐标
  0, 1         // 顶点3的UV坐标
]);
geometry.setAttribute('uv', new THREE.BufferAttribute(uvs, 2));

7.2。5 (可选)设置索引(优化多个三角形共享顶点)

// 使用索引可以复用顶点,减少内存占用
const indices = new Uint16Array([
  0, 1, 2      // 表示一个由顶点0、1、2组成的三角形
]);
geometry.setIndex(indices);

7.2.6 创建材质并渲染几何体

const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

7.3示例:创建自定义四边形

// 创建BufferGeometry
const geometry = new THREE.BufferGeometry();
// 定义四个顶点的位置(顺时针排列)
const vertices = new Float32Array([
  -1, -1, 0,   // 左下 (顶点0)
   1, -1, 0,   // 右下 (顶点1)
   1,  1, 0,   // 右上 (顶点2)
  -1,  1, 0    // 左上 (顶点3)
]);
// 设置位置属性
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));
// 设置法线(所有顶点法线朝上)
const normals = new Float32Array([
  0, 0, 1,     // 顶点0法线
  0, 0, 1,     // 顶点1法线
  0, 0, 1,     // 顶点2法线
  0, 0, 1      // 顶点3法线
]);
geometry.setAttribute('normal', new THREE.BufferAttribute(normals, 3));
// 设置UV坐标
const uvs = new Float32Array([
  0, 0,        // 左下UV
  1, 0,        // 右下UV
  1, 1,        // 右上UV
  0, 1         // 左上UV
]);
geometry.setAttribute('uv', new THREE.BufferAttribute(uvs, 2));
// 设置索引(两个三角形组成四边形)
const indices = new Uint16Array([
  0, 1, 2,     // 第一个三角形:左下-右下-右上
  0, 2, 3      // 第二个三角形:左下-右上-左上
]);
geometry.setIndex(indices);
// 创建材质和网格
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

7.4高级技巧:创建复杂几何体

7.4.1.从数学函数生成几何体

例如创建一个正弦波平面:

const width = 10;
const height = 10;
const segments = 100;
const vertices = new Float32Array((segments + 1) * (segments + 1) * 3);
let index = 0;
for (let i = 0; i 
  for (let j = 0; j 
    const x = (j / segments) * width - width / 2;
    const y = Math.sin(x) * Math.cos(i / segments * height);
    const z = (i / segments) * height - height / 2;
    
    vertices[index++] = x;
    vertices[index++] = y;
    vertices[index++] = z;
  }
}
// 设置位置属性并计算索引...
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

相关阅读

目录[+]

取消
微信二维码
微信二维码
支付宝二维码