stackgl / headless-gl

🎃 Windowless WebGL for node.js
1.73k stars 166 forks source link

Headless-gl with Babylonjs #128

Open jddaigle opened 6 years ago

jddaigle commented 6 years ago

Hi, do anyone try to make Headless-gl works with Babylonjs? I'm trying but without success... Tks!

jddaigle commented 6 years ago

Hi guys, I did some successful tests, but still have problems with textures... Can someone help me?

Here a working example, but without texture. (https://bitbucket.org/jddaigle/test_headless_gl)

width = 400
height = 400
require('jsdom-global')()
var gl = require('gl')(width, height); //headless-gl
path = 'out_test3.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
});

// same code as test_browser.js
var scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color3(0.8, 0.8, 0.8);
const camera = new BABYLON.ArcRotateCamera('Camera', Math.PI / 180 * -30, Math.PI / 180 * 55, 5, new BABYLON.Vector3(0, 0, 0), scene)
var light = new BABYLON.PointLight("light", new BABYLON.Vector3(10, 10, 0), scene);
var light = new BABYLON.PointLight("light", new BABYLON.Vector3(-10, 10, 10), scene);
var box = BABYLON.Mesh.CreateBox("box", 2, scene);

var boxMaterial = new BABYLON.StandardMaterial("material", scene);
var texture = new BABYLON.Texture('https://bbcdn.githack.com/jddaigle/test_headless_gl/raw/master/grass-old.jpg', scene)
boxMaterial.diffuseTexture = texture
box.material = boxMaterial;
console.log(texture.isBlocking)
console.log(texture.isReadyOrNotBlocking())
console.log(texture.isReady())
// end

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();
{
  "name": "babylon-tests",
  "version": "1.0.0",
  "description": "",
  "main": "Scene.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "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"
  }
}
matthewtoast commented 5 years ago

@jddaigle Did you ever discover a workaround for textures?

raphaelsetin commented 3 years ago

@jddaigle I was trying to render a model in ThreeJS using headless-gl, and after trying everything possible for 2-3 days straight, I was able to solve my problem using Puppeteer. I would advise you to do that instead as headless-gl didn't seem to work well, at least in AWS Lambda.

Maybe it could work well on other Linux environments. The AWS Lambda environment is close to CentOS 7 btw, if you were wondering.

njahic commented 8 months ago

You need to use RawTexture or in my instance RawCubeTexture const texture = new this.RawCubeTexture(this.scene, buffers, textureWidth: 512)

When providing buffers, you need to ensure that length of each buffer equals to widht(512) height(512) channels. I used sharp library to ensure raw bytes: sharp(url).ensureAlpha().resize(512, 512).raw().toBuffer()