简体   繁体   中英

Is it possible to run Three.js WebGLRenderer on node.js server?

I am in need of running WebGLRenderer on the server, but there are different voices regarding this. Some say that it's not possible and some say they are trying to get it working, but that's when the discussions end.

Is it possible to do it and in that case, what is the approach? Is it possible using moch-browser combined with node-gl or something?

[edit] Added solution

This is my own solution to the problem. Depending on the size of the scene and its objects, it might take some time. In my case I want to return pretty small versions of the object, but still takes about 400ms to respond with a 400x400px png. Hope this helps someone out there!

在此处输入图片说明

Server.js

var THREE = require("three.js");

// Create a DOM
var MockBrowser = require('mock-browser').mocks.MockBrowser;
var mock = new MockBrowser();
var document = MockBrowser.createDocument();
var window = MockBrowser.createWindow();

//REST API
var express     = require('express');      
var app         = express();    
var bodyParser  = require('body-parser');
var router = express.Router();

var gl = require('gl')(1,1); //headless-gl

var pngStream = require('three-png-stream');
var port = process.env.PORT || 8080;

router.get('/render', function(req, res){

    var scene = new THREE.Scene();
    var camera = new THREE.PerspectiveCamera(75, this.width / this.height, 0.1, 1000);
    var renderer = new THREE.WebGLRenderer({context:gl});

    scene.add(camera);

    renderer.setSize(this.width, this.height);
    renderer.setClearColor(0xFFFFFF, 1);

    /*...
        Add your objects & light to the scene 
    ...*/

    var target = new THREE.WebGLRenderTarget(this.width, this.height);
    renderer.render(scene, camera, target);


   res.setHeader('Content-Type', 'image/png');
   pngStream(renderer, target).pipe(res);
});

app.use('/api', router);

app.listen(port);
console.log('Server active on port: ' + port);

You could try headless-gl but you'd need to use some other libraries to emulate the DOM and Image tags (for texture loading) and Canvas tags and/or Canvas2D if you need that as well.

Otherwise you could shell to a browser running on top of OSMESA maybe or try headless chromium

I managed to do this, the trick is to render to a canvas and take out a png image object.

 var fs = require("fs") var self = {}; var ratio = 16/9.0; var canvasWidth = 500; var canvasHeight = 500; var window = { innerWidth: canvasWidth, innerHeight: canvasHeight }; var document = { createElement: function(name) { if (name == "canvas") { //return new Canvas(canvasWidth, canvasHeight); } var Canvas = require('canvas') return new Canvas(500,500) }, createElementNS: function(name) { var Canvas = require('canvas') return new Canvas(500,500) } }; var THREE = require("./threejs/three.js") eval(fs.readFileSync("threejs/additionalRenderers.js").toString()) eval(fs.readFileSync("threejs/SceneUtils.js").toString()) const EventEmitter = require('events'); //var OS = new ShereOS() class ThreeClient extends EventEmitter { constructor() { super() var self = this this.appId = 667 self.loaded = false this.bgColor = '#282c34' this.textColor = '#fff' this.tildeColor = '#0000ff' this.selectColor = '#ffffff' this.width = 500 this.height = 500 this.renderer = new THREE.CanvasRenderer(); this.renderer.setSize(this.width, this.height); this.camera = new THREE.PerspectiveCamera(75, this.width / this.height, 0.001, 3000); this.camera.position.z = 2; this.scene = new THREE.Scene(); this.scene.background = new THREE.Color( 0xECF8FF ); this.scene.add( new THREE.HemisphereLight( 0x606060, 0x404040 ) ); this.light = new THREE.DirectionalLight( 0xffffff ); this.light.position.set( 1, 1, 1 ).normalize(); this.scene.add( this.light ); //console.log(this.scene.children) this.updated = false /* var geometry = new THREE.SphereGeometry( 0.1, 32, 32 ); var material = new THREE.MeshBasicMaterial( {color: 0xFF0000} ); this.sphere = new THREE.Mesh( geometry, material ); this.scene.add( this.sphere ); */ } getTexture() { this.renderer.render(this.scene, this.camera); var data = this.renderer.domElement.toDataURL().substr("data:image/png;base64,".length) var buf = new Buffer(data, 'base64'); fs.writeFile('image.png', buf); //return this.renderer.domElement.toDataURL().substr("data:image/png;base64,".length); } } var THREEClient = new ThreeClient();

npm install avros

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM