Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Table extra fields in js object #155

Closed
edubart opened this issue Jun 16, 2019 · 5 comments
Closed

Table extra fields in js object #155

edubart opened this issue Jun 16, 2019 · 5 comments

Comments

@edubart
Copy link

edubart commented Jun 16, 2019

I am trying to port this example of three.js to Fengari:
https://threejs.org/examples/?q=shader#webgl_shader

However I am getting these errors and the example does not work:

THREE.ShaderMaterial: 'apply' is not a property of this material.
THREE.ShaderMaterial: 'invoke' is not a property of this material.
THREE.ShaderMaterial: 'get' is not a property of this material.
THREE.ShaderMaterial: 'has' is not a property of this material.

Looks like when I create a table the js objects will always
have these fields and make Three.js error. How do I fix this?

For reference my ported code of the example is this:

  local js = require 'js'
  local THREE = js.global.THREE
  local document, window, new = js.global.document, js.global.window, js.new
  local container, camera, scene, renderer, uniforms
  local function onWindowResize()
    renderer:setSize(window.innerWidth, window.innerHeight)
  end
  local function init()
    container = document:getElementById('container')
    camera = new(THREE.OrthographicCamera, -1, 1, 1, -1, 0, 1)
    scene = new(THREE.Scene)
    local geometry = new(THREE.PlaneBufferGeometry, 2, 2)
    uniforms = {
      time = { value = 1.0 }
    }
    local material = new(THREE.ShaderMaterial, {
      uniforms= uniforms,
      vertexShader= document:getElementById('vertexShader').textContent,
      fragmentShader= document:getElementById('fragmentShader').textContent
    })
    local mesh = new(THREE.Mesh, geometry, material)
    scene:add(mesh)
    renderer = new(THREE.WebGLRenderer)
    renderer:setPixelRatio(window.devicePixelRatio)
    container:appendChild(renderer.domElement)
    onWindowResize()
    window:addEventListener('resize', onWindowResize, false)
  end
  local function animate(_, timestamp)
    timestamp = timestamp or 0
    window:requestAnimationFrame(animate)
    uniforms.time.value = timestamp / 1000
    renderer:render(scene, camera)
  end
  init()
  animate(nil, 1)
@edubart
Copy link
Author

edubart commented Jun 16, 2019

I've found a workaround, doing this:

    local material = new(THREE.ShaderMaterial)
    material.uniforms= uniforms
    material.vertexShader= document:getElementById('vertexShader').textContent
    material.fragmentShader= document:getElementById('fragmentShader').textContent

but I still want to know how to make the other way work. And now I am having another issue the animation is static, unlike the pure js example the line uniforms.time.value = timestamp / 1000 does not seems to work, I think its because maybe the lua object is not linked with the js object? If so how could I make it work?

@edubart
Copy link
Author

edubart commented Jun 16, 2019

I have found a solution for both problems by creating a JS object explicitly:

  local object = function(t)
    return js.new(function(o)
      for k,v in pairs(t) do
        o[k] = v
      end
    end)
  end

Then instead of using plain tables I use:

    uniforms = object{
      time = object{ value = 1.0 }
    }
    local material = new(THREE.ShaderMaterial, object{
      uniforms= uniforms,
      vertexShader= document:getElementById('vertexShader').textContent,
      fragmentShader= document:getElementById('fragmentShader').textContent
    })

Took me a while to try this, I think a function for creating JS objects similar to this one could be implemented in fengari-interop or at least this behavior could be documented for new users trying to use fengari with other JS libs.

@catwell
Copy link

catwell commented Jun 17, 2019

I agree, we all have helpers like this (see mine), they could be in interop.

@daurnimator
Copy link
Member

However I am getting these errors and the example does not work:

THREE.ShaderMaterial: 'apply' is not a property of this material.
THREE.ShaderMaterial: 'invoke' is not a property of this material.
THREE.ShaderMaterial: 'get' is not a property of this material.
THREE.ShaderMaterial: 'has' is not a property of this material.

Looks like when I create a table the js objects will always
have these fields and make Three.js error. How do I fix this?

Lua tables are not exposed as JS objects, but as Map-like objects with get/set methods.
As you've discovered, you'll need to convert your table to a JS object, or alternatively use js.createproxy.

@daurnimator
Copy link
Member

I agree, we all have helpers like this (see mine), they could be in interop.

I'm going to close this issue as a duplicate of fengari-lua/fengari-interop#44

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants