Jump to content

Babylon Headless on Server Side


Jeedy
 Share

Recommended Posts

Hi, I'm looking to make babylon run on server side, without a browser, to take screenshot of the 3D scene.

To achieve that I created a project with headless-gl, but I've always the same error. 

Who can help me with this error, or maybe I can use another library?

 

Here is the error:

Babylon.js engine (v3.2.0-beta.5) launched

BJS - [16:47:09]: Unable to compile effect:

BJS - [16:47:09]: Uniforms:  world, view, viewProjection, vEyePosition, vLightsType, vAmbientColor, vDiffuseColor, vSpecularColor, vEmissiveColor, vFogInfos, vFogColor, pointSize, vDiffuseInfos, vAmbientInfos, vOpacityInfos, vReflectionInfos, vEmissiveInfos, vSpecularInfos, vBumpInfos, vLightmapInfos, vRefractionInfos, mBones, vClipPlane, diffuseMatrix, ambientMatrix, opacityMatrix, reflectionMatrix, emissiveMatrix, specularMatrix, bumpMatrix, normalMatrix, lightmapMatrix, refractionMatrix, diffuseLeftColor, diffuseRightColor, opacityParts, reflectionLeftColor, reflectionRightColor, emissiveLeftColor, emissiveRightColor, refractionLeftColor, refractionRightColor, vReflectionPosition, vReflectionSize, logarithmicDepthConstant, vTangentSpaceParams, diffuseSampler, ambientSampler, opacitySampler, reflectionCubeSampler, reflection2DSampler, emissiveSampler, specularSampler, bumpSampler, lightmapSampler, refractionCubeSampler, refraction2DSampler

and the code:

package.json dependencies:

"dependencies": {
"babylonjs": "^3.2.0-beta.5",
"gl": "^4.0.4",
"jsdom-global": "^3.0.2",
},
 

scene.js

require('jsdom-global')()
var gl = require('gl')(400,400); //headless-gl
 
var BABYLON = require("babylonjs");
var mycanvas = {
getContext: () => gl,
addEventListener: function () { }
};
 
var engine = new BABYLON.Engine(mycanvas, true);
var scene = new BABYLON.Scene(engine);
var box = BABYLON.MeshBuilder.CreateBox('box', { size: 20 }, scene)
var camera = new BABYLON.FreeCamera('camera', BABYLON.Vector3.Zero(), scene);
var ground = BABYLON.Mesh.CreateGround('ground', 10, 10, 20, this.scene);
scene.render()
Link to comment
Share on other sites

Thanks, now it works, 

I found that I have the same behaviour either if I put the disableWebGL2Support parameter or if I pass the gl context directly to the engine rather than pass the canvas.

Now I can extract a PNG from the canvas, but unfortunately it seems to have a problem with the texture. Do you have an idea of what's going on? The texture seems to never be ready...

Here the code:

https://bitbucket.org/jddaigle/test_headless_gl

width = 400
height = 400
require('jsdom-global')()
var gl = require('gl')(width, height); //headless-gl
path = 'out2.png'
 
PNG = require('pngjs').PNG
fs = require('fs')
png = new PNG({
  width: width,
  height: height
})
 
var BABYLON = require("babylonjs");
 
var engine = new BABYLON.Engine(gl, true, {
  disableWebGL2Support: true
});
var scene = new BABYLON.Scene(engine);
var box = BABYLON.MeshBuilder.CreateBox('box', {
  size: 1
}, scene)
var camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 180 * 20, Math.PI / 180 * 70, 5, BABYLON.Vector3.Zero(), scene);
var ground = BABYLON.Mesh.CreateGround('ground', 10, 10, 20, this.scene);
var light2 = new BABYLON.PointLight("light2", new BABYLON.Vector3(0, 1, -1), scene);
 
// This is where you create and manipulate meshes
fs.exists('grass-old.jpg', (exists) => {
  if (exists) {
    console.log('grass-old.jpg exists')
  } else {
    console.log('grass-old.jpg exists')
  }
})
 
var texture = new BABYLON.Texture('grass-old.jpg', scene)
ground.diffuseTexture = texture
console.log(texture.isBlocking)
console.log(texture.isReadyOrNotBlocking())
console.log(texture.isReady())
 
scene.onAfterRenderObservable.add(() => {
  // create a pixel buffer of the correct size
  pixels = new Uint8Array(4 * width * height)
 
  // read back in the pixel buffer
  gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels)
 
  // lines are vertically flipped in the FBO / need to unflip them
  var i, j
  for (j = 0; j <= height; j++) {
    for (i = 0; i <= width; i++) {
      k = j * width + i
      r = pixels[4 * k]
      g = pixels[4 * k + 1]
      b = pixels[4 * k + 2]
      a = pixels[4 * k + 3]
 
      m = (height - j + 1) * width + i
      png.data[4 * m] = r
      png.data[4 * m + 1] = g
      png.data[4 * m + 2] = b
      png.data[4 * m + 3] = a
    }
  }
  // Now write the png to disk
  stream = fs.createWriteStream(path)
  png.pack().pipe(stream)
})
 
scene.render()

 

"dependencies": {
"babylonjs": "3.2.0-rc.3",
"eslint": "^4.19.1",
"express": "^4.16.3",
"fs": "0.0.1-security",
"gl": "^4.0.4",
"jsdom-global": "^3.0.2",
"mock-browser": "^0.92.14",
"node-gyp": "^3.6.2",
"pngjs": "^3.3.2"
},
"devDependencies": {
"@types/node": "^9.6.5",
"jsdom": "^11.8.0"
}
Link to comment
Share on other sites

How can I know? I tried to check with this:

console.log(texture.isBlocking) --> true

console.log(texture.isReadyOrNotBlocking()) --> undefined

console.log(texture.isReady()) --> undefined

So I think the texture is not loading and it's waiting for something, like the browser to popups, but I am headless...  I mean Babylon is headless :D

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...