WebGL-Vue3-TS-Threejs:基础练习 / Javascript 3D library / demo

一、理解Three.js

Three.js是一个用于WebGL渲染的JavaScript库。它提供了一组工具和类,用于创建和渲染3D图形和动画。简单理解(并不十分准确),Three.js之于WebGL,好比,jQuery.js之于JavaScript。

OpenGL 是一个跨平台3D/2D的绘图标准,WebGL则是OpenGL 在浏览器上的一个实现。

web前端开发人员可以直接用WebGL接口进行编程,但 WebGL只是非常基础的绘图API,需要编程人员有很多的数学知识、绘图知识才能完成3D编程任务,而且代码量巨大。Threejs 对 WebGL 进行了封装,让前端开发人员在不需要掌握很多数学知识和绘图知识的情况下,也能够轻松进行web 3D开发,降低了门槛,同时大大提升了效率。

WebGL:开始学习 / 理解 WebGL / WebGL 需要掌握哪些知识 / 应用领域 / 前端值得学WebGL吗_webgl培训-CSDN博客

Three.js的主要特点

|----|------|-------------------------------|
| 序号 | 特点 | 描述 |
| 1 | 简单易用 | 它的API非常友好,易于理解和使用。 |
| 2 | 兼容性强 | 支持多种浏览器和设备,不需要其他插件和软件。 |
| 3 | 功能强大 | 提供了广泛的3D渲染功能,包括材质、灯光、相机等多种元素。 |
| 4 | 社区活跃 | 拥有庞大的开发者社区,可以找到大量的示例代码和教程。 |

通过Three.js,开发者可以快速创建并展示3D模型、场景、动画等内容。它支持多种文件格式,如obj、fbx、glb等,可以轻松导入和使用。同时,它还支持VR和AR等技术,可以创建更加沉浸式的体验。

关键词:场景、相机、光源、材质、贴图、建模、着色

二、文档

ThingJS 文档中心

https://threejs.org/

Three.js中文网

三、项目介绍

vue3 + ts + vite + three.js

四、安装

plain 复制代码
`pnpm add three
pnpm add @types/three`

"three": "^0.158.0",

"@types/three": "^0.154.0",

五、导入核心库,获取场景

<template>
    <div class="container">
      <span>threejs</span>
    </div>
</template>
  
<script setup lang="ts">
import * as THREE from 'three'
const scene = new THREE.Scene()
console.log('scene:', scene)
  
</script>
  
<style scoped lang="less">
</style>

六、基础练习

6.1、绘制一条直线

<template>
    <div ref="container" id="container" style="width: 200px;height: 200px;"></div>
</template>
  
<script setup lang="ts">
import * as THREE from 'three'
const container:any = ref(null)
onMounted(()=>{
  // 创建场景
  const scene = new THREE.Scene();
  scene.background = new THREE.Color(0xadacad);

  // 创建相机
  const camera = new THREE.PerspectiveCamera(
    45,
    container.value.clientWidth / container.value.clientHeight,
    0.1,
    100
  );
  camera.position.set(0, 0, 3);

  // 创建渲染器
  const renderer = new THREE.WebGLRenderer();
  console.log('24', container)
  renderer.setSize(container.value.clientWidth, container.value.clientHeight);
  container.value.appendChild(renderer.domElement);

  // 定义顶点数据
  const positions = [
    -1, 0, 0,
    0, 1, 0,
  ];

  // 创建一个 BufferGeometry 对象
  const geometry = new THREE.BufferGeometry();
  const positionAttribute = new THREE.Float32BufferAttribute(positions, 3);
  geometry.setAttribute('position', positionAttribute);

  // 创建一个 LineLoop 对象
  const material = new THREE.LineBasicMaterial({ color: 0xf00, linewidth: 5 });
  const line = new THREE.LineLoop(geometry, material);

  // 将线条添加到场景中
  scene.add(line);

  // 开始渲染循环
  function render() {
    renderer.render(scene, camera);
    requestAnimationFrame(render);
  }
  render();
})
</script>
  
<style scoped lang="less">
</style>

6.2、通过直线,绘制画一个正方形

本例中,我们首先创建了一个 div 元素引用,它将用作 three.js 的渲染器容器。然后创建了场景、相机和渲染器,并将渲染器的输出添加到页面中。

接着,我们定义了闭合线条的顶点数据,并使用 THREE.BufferGeometry 创建了几何体。然后我们使用 THREE.LineLoop 创建了线条对象,并将其添加到场景中。

<template>
    <div ref="container" id="container" style="width: 200px;height: 200px;"></div>
</template>
  
<script setup lang="ts">
import * as THREE from 'three'
const container:any = ref(null)
onMounted(()=>{
  // 创建场景
  const scene = new THREE.Scene();
  scene.background = new THREE.Color(0xadacad);

  // 创建相机
  const camera = new THREE.PerspectiveCamera(
    45,
    container.value.clientWidth / container.value.clientHeight,
    0.1,
    100
  );
  camera.position.set(0, 0, 3);

  // 创建渲染器
  const renderer = new THREE.WebGLRenderer();
  console.log('24', container)
  renderer.setSize(container.value.clientWidth, container.value.clientHeight);
  container.value.appendChild(renderer.domElement);

  // 定义顶点数据
  const positions = [
    -1, 0, 0,
    0, 1, 0,
    1, 0, 0,
    0, -1, 0,
    -1, 0, 0,
  ];

  // 创建一个 BufferGeometry 对象
  const geometry = new THREE.BufferGeometry();
  const positionAttribute = new THREE.Float32BufferAttribute(positions, 3);
  geometry.setAttribute('position', positionAttribute);

  // 创建一个 LineLoop 对象
  const material = new THREE.LineBasicMaterial({ color: 0xf00, linewidth: 5 });
  const line = new THREE.LineLoop(geometry, material);

  // 将线条添加到场景中
  scene.add(line);

  // 开始渲染循环
  function render() {
    renderer.render(scene, camera);
    requestAnimationFrame(render);
  }
  render();
})
</script>
  
<style scoped lang="less">
</style>

6.3、 vue3 typescript项目 在script使用setup语法糖的方式下,使用最新 threejs api 创建文字

待补充

使用THREE.TextGeometry创建文字的模型,并使用THREE.MeshBasicMaterialTHREE.Mesh将其渲染到场景中

6.4、绘制一个圆形

本例中,首先创建了一个Three.js场景、相机和渲染器。然后创建了一个圆形几何体和一个材质,并使用它们创建了一个网格。最后将圆形添加到场景中,并创建一个animate函数用于实现动画效果。

typescript 复制代码
<template>
  <div id="app"></div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import * as THREE from 'three';

export default defineComponent({
  name: 'HelloWorld',
  setup() {
    const scene = new THREE.Scene();

    const camera = new THREE.PerspectiveCamera(
      75,
      window.innerWidth / window.innerHeight,
      0.1,
      1000
    );

    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.getElementById('app')?.appendChild(renderer.domElement);

    const geometry = new THREE.CircleGeometry(50, 32);
    const material = new THREE.MeshBasicMaterial({
      color: 0xff0000,
      wireframe: true,
    });

    const circle = new THREE.Mesh(geometry, material);
    scene.add(circle);

    camera.position.z = 100;

    const animate = function () {
      requestAnimationFrame(animate);

      circle.rotation.x += 0.01;
      circle.rotation.y += 0.01;

      renderer.render(scene, camera);
    };

    animate();

    return { scene, camera, renderer };
  },
});
</script>

6.5、绘制一个圆锥

typescript 复制代码
<template>
  <div id="app"></div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import * as THREE from 'three';

export default defineComponent({
  name: 'HelloWorld',
  setup() {
    const scene = new THREE.Scene();

    const camera = new THREE.PerspectiveCamera(
      75,
      window.innerWidth / window.innerHeight,
      0.1,
      1000
    );

    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.getElementById('app')?.appendChild(renderer.domElement);

    const geometry = new THREE.ConeGeometry(50, 100, 32);
    const material = new THREE.MeshBasicMaterial({
      color: 0xff0000,
      wireframe: true,
    });

    const cone = new THREE.Mesh(geometry, material);
    scene.add(cone);

    camera.position.z = 100;

    const animate = function () {
      requestAnimationFrame(animate);

      cone.rotation.x += 0.01;
      cone.rotation.y += 0.01;

      renderer.render(scene, camera);
    };

    animate();

    return { scene, camera, renderer };
  },
});
</script>

6.6、绘制一个立方体

<template>
  <div id="app"></div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import * as THREE from 'three';

export default defineComponent({
  name: 'HelloWorld',
  setup() {
    const scene = new THREE.Scene();

    const camera = new THREE.PerspectiveCamera(
      75,
      window.innerWidth / window.innerHeight,
      0.1,
      1000
    );

    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.getElementById('app')?.appendChild(renderer.domElement);

    const geometry = new THREE.BoxGeometry(1, 1, 1);
    const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);

    camera.position.z = 5;

    const animate = function () {
      requestAnimationFrame(animate);

      cube.rotation.x += 0.01;
      cube.rotation.y += 0.01;

      renderer.render(scene, camera);
    };

    animate();

    return { scene, camera, renderer };
  },
});
</script>

6.7、绘制一个球体

typescript 复制代码
<template>
  <div ref="container"></div>
</template>

<script lang="ts">
import { defineComponent, onMounted, ref } from 'vue';
import * as THREE from 'three';

export default defineComponent({
  setup() {
    const container = ref(null);

    onMounted(() => {
      // 创建渲染器
      const renderer = new THREE.WebGLRenderer();
      renderer.setSize(window.innerWidth, window.innerHeight);

      // 将渲染器添加到DOM中
      if(container.value) {
        container.value.appendChild(renderer.domElement);
      }

      // 创建场景
      const scene = new THREE.Scene();

      // 创建相机
      const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
      camera.position.z = 5;

      // 添加环境光
      const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
      scene.add(ambientLight);

      // 添加点光源
      const pointLight = new THREE.PointLight(0xffffff, 1, 100);
      pointLight.position.set(0, 0, 5);
      scene.add(pointLight);

      // 创建红色球体
      const geometry = new THREE.SphereGeometry(1, 32, 32);
      const material = new THREE.MeshPhongMaterial({ color: 0xff0000, shininess: 100 });
      const sphere = new THREE.Mesh(geometry, material);
      scene.add(sphere);

      // 渲染场景
      const render = () => {
        requestAnimationFrame(render);
        sphere.rotation.x += 0.01;
        sphere.rotation.y += 0.01;
        renderer.render(scene, camera);
      };
      render();
    });

    return {
      container
    }
  }
});
</script>

在这个示例中,我们添加了一个点光源,并将球体的材质参数shininess设置为100,这使球体的表面更加光滑。

你还可以尝试调整环境光和点光源的强度和颜色,或者使用其他类型的光源和材质来改变球体的外观。

七、相关内容

canvas、canvas3D、playcanvas、tween、pixi、three.js、webGL、OpenGL

八、过程记录

8.1、学习目标

1、了解基础的3D数学和计算机图形学概念。学习向量、矩阵、坐标系、光照和着色器等基础知识。

2、熟悉WebGL技术,理解网页版3D渲染的基本原理,包括顶点着色器和片段着色器。

3、掌握Three.js的API,包括场景、相机、灯光、材质和几何体等基础概念,以及如何使用它们来创建3D图形。

4、学习如何使用Three.js创建复杂的3D场景,包括如何向场景添加3D模型、纹理、动画和粒子效果。

5、探索Three.js的高级功能,如阴影、反射、抗锯齿和后期处理。

6、将Three.js与其他技术集成,如HTML、CSS和JavaScript,以创建功能丰富且交互性强的3D应用程序。

7、学习如何与其他Web技术集成。将Three.js集成到Web应用程序中,并与其他技术,如HTML、CSS和JavaScript一起使用。

8、练习并参与开源项目,在实践中提高技能水平。

学习Three.js需要一定数学和图形学基础,需要耐心和实践。建议先从基础开始,逐步学习和实践,掌握基本概念和技能后再进行高级的应用。

8.2、Three.js之于WebGL,好比,jQuery.js之于JavaScript,,这样理解有合理性吗

这个比喻在某些方面是有合理性的,但不是完全准确的。

类比中的相似之处在于,jQuery.js在JavaScript世界中扮演了许多网站开发人员的角色。Three.js也在WebGL世界中扮演着相似的角色。jQuery.js使用DOM元素并操作它们,类似地,Three.js使用WebGL上下文并操作它们。这是比喻的相似之处。

然而,WebGL在功能和范围上远远超过了DOM操作,因此Three.js提供了比jQuery.js更加复杂的功能和API。Three.js的目的是演示和创建3D图形和交互式应用程序,并且具有原生优化的性能。与jQuery.js不同,Three.js是专注于3D图形编程的库。

因此,比喻可以作为一种简单的概括,但它并不完全准确,并且可以误导人们对Three.js和WebGL的理解。

8.3、使用Three.js创建一个简单的立方体场景的基本步骤

1、设置照相机 camera = new THREE.Camera(); 用于观察物体

2、设置场景 scene = new THREE.Scene() 用于承载物体

3、建立物体 geometry = new THREE.CubeGeometry(200, 200, 200);

4、创建网格 mesh = new THREE.Mesh(geometry, material) 5、渲染呈现 renderer.render(scene, camera) 这是啥

8.4、npm插件'three'和'@types/three'的区别如下

`npm`插件`three`是`Three.js`的`JavaScript`实现,是用于在`JavaScript`中创建和渲染`3D`图形的框架。

`@types/three`是TypeScript类型定义的`npm`包,它提供了`TypeScript`开发环境中`Three.js`库的类型定义文件。这些类型定义文件可以帮助`TypeScript`编译器检查代码类型,并提供提示和自动完成。

因此,`npm`插件`three`是`Three.js`库本身,而`@types/three`则提供了`TypeScript`开发环境所需的类型定义文件。如果你在使用`TypeScript`开发`Three.js`应用程序,则需要安装`npm`包`@types/three`,以获取`Three.js`库的类型定义文件,从而可以在开发过程中获得更好的类型安全支持和代码提示。如果你只是在使用标准的`JavaScript`进行开发,则只需要安装`npm`包`three`即可。

8.5、THREE.Geometry方法不存在新版本了吗

是的,从版本 r125 开始,three.js 废弃了 THREE.Geometry,并引入了 THREE.BufferGeometry 作为建模的首选选择。这是为了提高性能,并使开发人员更容易控制顶点数据。

因此,如果您使用的是最新版本的 three.js,建议使用 THREE.BufferGeometry 来代替 THREE.Geometry

8.6、需要在onmounted声明周期,确保DOM元素已经加载完成

需要注意的是,在使用Three.js时,需要确保DOM元素已经加载完成,否则会出现错误。上述示例中使用了安全访问运算符(?.)和类型断言(!),以确保能够正确获取DOM元素。

8.7、playcanvas.js 和 three.js 有什么相同异同

PlayCanvas和Three.js都是用于创建和显示3D图形的JavaScript库,但它们有一些关键的区别。

|----|-------------------------------------------------------------------------------------------------------|
| 序号 | 相同 |
| 1 | 两者都是用于创建和显示3D图形的JavaScript库 |
| 2 | 两者都提供了一系列的API来方便开发者创建和控制3D图形 |
| 3 | 两者都支持在浏览器中运行,而且都能很好地支持各种主流的浏览器 |
| 4 | 两者都提供了一些基本的3D功能,如3D模型的加载和呈现、材质和纹理的应用、动画和物理效果等 |
| 5 | 两者都是开源的项目,并且都有一个活跃的社区在支持和维护 |
| 序号 | 不同 |
| 1 | PlayCanvas.js的定位更多是在线多人游戏的开发,它在多人游戏的网络性能优化方面有更好的表现。而Three.js的应用范围更广泛,包括但不限于游戏开发,定位更多是用于3D呈现和交互式场景的创建。 |
| 2 | PlayCanvas提供了一套完整的游戏开发框架,包括物理引擎、碰撞检测、声音系统等,而Three.js主要专注于图形渲染。 |
| 3 | PlayCanvas提供了实时渲染功能,可以在浏览器中实现流畅的3D游戏体验,而Three.js虽然也支持实时渲染,但通常需要配合其他库(如WebGL或WebGPU)来实现更好的效果。 |
| 4 | PlayCanvas的文档和社区比Three.js更加完善,API更加简洁易用,对于开发者来说更容易上手和使用。而Three.js的API更加底层,需要开发者有一定的3D编程经验。 |
| 5 | PlayCanvas支持组件化开发,可以通过组合不同的组件来快速构建复杂的3D场景,而Three.js则需要更多的手动设置和调整。 |
| 6 | PlayCanvas支持多种输入方式(如键盘、鼠标、触摸等),适合开发各种类型的交互式应用,而Three.js则更侧重于图形渲染方面的输入控制。 |

九、老语法 --》新语法

|-----|--------------------------|-------------------------------------------|
| 序号 | 老语法 | 新语法 |
| 1 | new THREE.FontLoader() | TextureLoader THREE.TypefaceLoader |
| 2 | new THREE.TextGeometry() | THREE.TextBufferGeometry??? THREE.Mesh??? |
| 待补充 | 待补充 | 待补充 |

十、参考链接

补间动画tween.js_tween补间动画-CSDN博客

和我一起学 Three.js【初级篇】:2. 掌握几何体 - 知乎

关于javascript:Three.js新的THREE.TextBufferGeometry()无法读取未定义错误的属性'yMax' | 码农家园

Three.js API手册 / LineBasicMaterial - 汇智网

Caught error TypeError: THREE.Geometry is not a constructor

Three.js中文网

https://www.cnblogs.com/tiandi/p/17053774.html

vue3项目中使用three.js的操作步骤_vue.js_脚本之家

开始第一个Hello world! | 码上动力

Lamborghini Huracán STO 2020

three.js全网最全最新入门课程(2023年10月更新)【搞定前端前沿技术】_哔哩哔哩_bilibili

threejs-vite-vue实战课程_哔哩哔哩_bilibili

带你入门three.js------从0到1实现一个3d可视化地图 - 知乎

相关推荐
也无晴也无风雨1 小时前
深入剖析输入URL按下回车,浏览器做了什么
前端·后端·计算机网络
Martin -Tang2 小时前
Vue 3 中,ref 和 reactive的区别
前端·javascript·vue.js
皮皮陶2 小时前
Unity WebGL交互通信
unity·交互·webgl
FakeOccupational4 小时前
nodejs 020: React语法规则 props和state
前端·javascript·react.js
放逐者-保持本心,方可放逐4 小时前
react 组件应用
开发语言·前端·javascript·react.js·前端框架
曹天骄5 小时前
next中服务端组件共享接口数据
前端·javascript·react.js
阮少年、5 小时前
java后台生成模拟聊天截图并返回给前端
java·开发语言·前端
mirrornan6 小时前
产品如何3D建模?如何根据使用场景选购3D扫描仪?
科技·3d·3d建模·3d模型·三维扫描
兔老大的胡萝卜6 小时前
关于 3D Engine Design for Virtual Globes(三维数字地球引擎设计)
人工智能·3d
郝晨妤6 小时前
鸿蒙ArkTS和TS有什么区别?
前端·javascript·typescript·鸿蒙