Node.js 渲染三维模型并导出为图片
1. 前言
本文将介绍如何在 Node.js
中使用 Three.js
进行 3D 模型渲染。通过结合 gl
和 canvas
这两个主要依赖库,我们能够在服务器端实现高效的 3D 渲染。这个方法解决了在服务器端生成和处理 3D 图形的需求,使得可以在各种平台上展示复杂的 3D 内容
2. 渲染环境准备
在服务端渲染并导出threeJS
模型,难点在于需要在服务端准备一套threeJS
模型的渲染环境
2.1 步骤
- 服务端提供环境需要依赖两个库
canvas
和gl
○canvas
:使服务端能够创建canvas元素,提供一个"地方"给threeJS绘制模型
○gl
:提供threeJS
绘制的环境
在安装
canvas
依赖的时候,需要安装一些前置依赖
node-gyp
GTK2
libjpeg-turbo
前置依赖安装步骤:https://github.com/Automattic/node-canvas/wiki/Installation:-Windows其中在安装
node-gyp
时
- 需要安装
python39
,这里好像只有python39的版本才行,使用最新的版本的Python安装canvas的时候会报错- 需要安装 C++的编译环境
安装步骤:https://github.com/nodejs/node-gyp?tab=readme-ov-file#on-windows
- 推荐一个一键式依赖 :node-canvas-webgl,这个依赖整合了上面两个依赖,但是安装这个依赖也需要安装canvas依赖的前置依赖
如果安装了node-canvas-webgl
这个依赖,就不需要再安装canvas
和gl
这两个依赖了,或者是 如果同时安装的node-canvas-webgl
依赖和canvas、gl
依赖,那么最好是确保node-canvas-webgl
所依赖的canvas、gl
的版本和你所安装的canvas
和gl
依赖的版本一致,不然会因为安装的版本不一致导致在创建webGLRenderer
的时候出错
这里推荐直接安装node-canvas-webgl
依赖
- 由于我们在服务端,没有浏览器里面的一些内置对象(
window、document
),所以需要模拟一些浏览器内置对象,这样在创建 ThreeJS的场景、渲染器的时候才不会报错
使用mock-browser
库是进行模拟window
和document
对象
2.2 步骤总结
- 安装
node-canvas-webgl
依赖,为threeJS
模型提供渲染环境
安装
node-canvas-webgl
时,需要准备canvas
所需要的一些前置依赖。因为node-canvas-webgl
这个依赖也是依赖了canvas
这个依赖的,所以需要准备canvas
所需要的前置条件,canvas前置条件准备步骤
- 安装
mock-browser
,构造window
和document
对象
3. 代码实现
这是我安装的依赖
步骤1-3都是一些前置工作,在node环境准备好了Three.js的渲染环境,接下来就可以编写代码将三维模型导出为图片
在nodeJS的入口(主)文件挂载window、document等对象,方便后续创建Three.js的渲染环境
ts
// app.ts
const MockBrowser = require('mock-browser').mocks.MockBrowser
const document = MockBrowser.createDocument()
const window = MockBrowser.createWindow()
// https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/globalThis
// 在 node 环境下获取全局变量必须使用 global
// 所以将全局变量挂载到 global 下
global.window = window
global.document = document
global.navigator = window.navigator
生成三维模型并导出图片
ts
// generateWebGL.ts
// nodeJS 目前是支持 ES6 的模块化的
import * as THREE from 'three';
// 这里使用了 node-canvas-webgl 这个依赖
const {createCanvas} = require('node-canvas-webgl/lib');
const fs = require('fs');
const width = window.innerWidth, height = window.innerHeight;
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, width / height, 0.1, 1000 );
// 使用库创建一个 canvas 元素
const canvas = createCanvas(width, height);
// 在创建渲染器的时候,需要提供我们之前创建的 canvas 元素供渲染器进行绘制输出
const renderer = new THREE.WebGLRenderer({canvas: canvas});
renderer.setSize(width, height);
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;
renderer.render( scene, camera );
// 生成图片
// 使用 canvas 的 toDataURL() 方法转成 base64
const base64 = renderer.domElement.toDataURL('image/png', 1.0)
const base64Image = base64.split(';base64,').pop()
// 将 base64 转成 二进制数据
const bufferData = Buffer.from(base64Image, 'base64')
// 这里替换为你自己需要保存的文件路径
const path = `C:/Users/abc123/Desktop/nodeImages/image1.png`
// 使用 fs 模块将图片保存到桌面的 nodeImages 文件夹
fs.writeFileSync(path, bufferData)