如何在node.js中渲染three.js?

24

我该如何在node.js中呈现three.js代码?

我想从Blender导出,然后通过fs打开导出文件,并对其进行场景渲染。

3个回答

26

这个实现方法有点臭,但需要记住的是创建几何图形的部分,其他部分都很简单。我主要是为了以后自己参考而将其放在这里,但它确实可行,使用nodejs进行3D渲染也很酷。哦对,还需要canvas来工作。

它依赖于three.js npm模块 https://github.com/uniba/node-three.js

fs = require("fs")

THREE = require("three.js")
join = require("path").join

app.get '/test/top_:top_id/side_:side_id/x_:x/y_:y.jpg', (req, res, next) =>

  width = 660
  height = 500

  camera = new THREE.PerspectiveCamera(50, width / height, 1, 1000)
  scene = new THREE.Scene()
  renderer = new THREE.CanvasRenderer( )
  renderer.setSize width, height

  camera.position.z = 100

  camera_container = new THREE.Object3D
  scene.add camera_container
  camera_container.add camera

  camera.position.z = 75

  # We have one background plane
  plane_image = new Image
  plane_image.src = fs.readFileSync TOP_DIR + "public/images/vtx_logo.jpg"
  texture = new THREE.Texture plane_image, new THREE.UVMapping()
  texture.needsUpdate = true

  loader = new THREE.JSONLoader()

  geometry = new THREE.PlaneGeometry(200, 200)
  material = new THREE.MeshBasicMaterial
    color       : 0x698144
    #shading        : THREE.SmoothShading
    map     : texture
    overdraw: true
  plane = new THREE.Mesh geometry, material
  plane.position.z = -50
  plane.position.y = -4
  plane.position.x = 4.5

  # We also have an object in the foreground
  scene.add plane
  geometry = false
  loader.createModel JSON.parse(fs.readFileSync(TOP_DIR + 'public/blender_export.json')), (done) =>
    geometry = done

  # Imager.texture gives us a canvas based on some code that grabs specific info
  texture = new THREE.Texture (Imager.texture req.params.side_id, req.params.top_id), new THREE.UVMapping()
  texture.needsUpdate = true

  material = new THREE.MeshBasicMaterial
    color: 0xaaaaaa
    map: texture
    overdraw: true
  mesh = new THREE.Mesh geometry, material

  mesh.rotation.x = parseFloat req.params.x
  mesh.rotation.y = parseFloat req.params.y

  scene.add mesh
  mesh.dynamic = true
  renderer.render scene, camera

  renderer.domElement.toBuffer (err, buf) ->
    res.contentType 'image/jpg'
    res.send buf

如果您遇到错误无法找到./lib/Three

我提到的three.js模块可能指向三维库的旧版本。我记得曾经需要进入该模块并编辑一个文件,将require('./lib/Three')修改为require('./lib/three')。我想他在package.json中包含了一个非特定的three,因此它被更新而没有更新他的npm模块。也许现在已经修复了。


3
TIL: Three.js 可以在 node.js 上运行。 - TheHippo
从r61开始,Three.js不再引用window,因此在node.js中可使用。很棒的代码@Funkodebat将缓冲区渲染为图像并传递回来。在线性能如何? - Darryl_Lehmann
所引用的库使用 jsdom 来创建一个假窗口,在其中打开三个窗口,沿途进行必要的更改。由于某种原因,它非常难找到,我留了一个链接。 - dansch
@Darryl_Lehmann 我没有注意到任何缓慢。这是备用方案的备用方案。它应该在客户端浏览器中运行webgl。如果失败了,它会转到应用程序服务器,应用程序服务器通过socket.io连接到一个带有打开浏览器窗口的本地GPU ubuntu盒子,该窗口将呈现webgl并将其传回服务器,再传回给客户端。如果我们的GPU ubuntu盒子出现问题,那么这段代码将运行并呈现图像,因为它只能做画布,看起来不太漂亮,但仍然很酷 :) - dansch
1
另外还有一点,我记得在提到的模块中不得不编辑 require('lib/Three') 为 require('lib/three')。我觉得他的 package.json 可能非常不具体。你应该会收到一个错误消息,说找不到 Three 库,但如果你查看,three 是存在的。 - dansch

-1

我不明白为什么你不能使用electron这样的东西,它允许你创建桌面应用程序并在其中实现node.js。虽然这并不是对问题的确切答案,但出于寻找这类解决方案的人们的考虑,我将发布此回答。


1
Node-webkit就像是一个未锁定的浏览器,它仍然在计算机上运行,而不是服务器上。我曾经使用过一种方法,其中虚拟机运行(带有视频卡),并在虚拟机的浏览器中呈现threejs,然后将屏幕截图发送到服务器,再发送给请求者。今天我会使用浏览器或nw来完成这个任务。我想你可以将服务器合并到渲染的NW实例中,但无论如何你仍需要一个带头的服务器。此外,当这个问题被提出时,NW还不存在于4年前。 - dansch

-16
你真的不应该在服务器上运行视觉代码,如果你正在服务器上进行计算密集型操作,你需要准备好投入相当多的资源。你需要将导出和渲染委托给客户端机器。

11
首先,这不是OP所要求的。其次 - Node.js 不仅仅用于服务器。 - klh
2
我是Node.js的坚定支持者,经常说服务网页只是Node最不有趣的特性。 - Weavermount
3
好的,让我们对任何考虑提供优化建议的人进行反对票。 - Jack Franzen
3
这取决于要求是什么。比如,如果我想批量渲染或合成图片以在社交媒体上分享,或制作可打印的艺术品,则没有支持Javascript的客户端可用,因此无头渲染非常理想。“不应该”假设了一个特定的情境,可能会让人感到非常恼火。相反,也许更好的做法是给OP以怀疑的态度,并建议他们在情况适用的情况下尝试其他方法。 - gid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接