NativeScript / canvas

Apache License 2.0
88 stars 18 forks source link

Sprite material / TextureLoader rendering glitchy graphics #77

Closed tremho closed 2 years ago

tremho commented 2 years ago

I am trying to create a THREE.Sprite with an image texture. I am using the THREE library as loaded by @nativescript/canvas-three

I apply the following code (scene and camera already set up):

    let tpath = app.Path.join(app.Path.assetsPath, 'sprite', 'trilobyte.png')
    let loader = new THREE.TextureLoader()
    let t:THREE.Texture = loader.load(tpath)
    let sm = new THREE.SpriteMaterial({ map:t, color:0xffffff})
    testSprite = new THREE.Sprite(sm)
    scene.add(testSprite)

    animate()

What I get from this code in a web implementation looks like this: web canvas version

What I get in nativescript (android) is this: nativescript canvas version

From what I can see by tracing through the code, it looks like the document.createElementNS replacement is creating a faux HTMLImageElement and loading the PNG image, which is the same as what the web version does. And the end result does in fact have a NativeImage _asset that looks right (width/height at least). And yet...

My application will be relying heavily on sprite use like this, so this has become a bit of a blocker for me (at least on the nativescript front).

Any suggestions appreciated!

tremho commented 2 years ago

Update: The bug is with texture resizing, so it's not exactly as described above. As we know, a GL texture must be sized as a power of 2. I thought I had done that, but my asset had a height of 111 instead of 128, so it was being resized (by either THREE or GL, I'm not sure at what level). and that is where the distortion come from. If I start with a properly sized image that doesn't resize, things work as expected.

So I'm not blocked! Huzzah! (but there's still a bug with resize that would probably be a good thing to look into)

As an aside: In a separate test app to help me figure this out, I also have a mesh (the standard cube from the readme example). If I add the both the mesh and the sprite to the scene under Android, nothing is rendered. It works under iOS, though. On Android I can render either the mesh or the sprite, but not both. Very odd.

tremho commented 2 years ago

Final update: On the suggestion that I try to use the 'webgl2' context instead of just 'webgl', the problem becomes a non-issue. The gl2 context doesn't seem to have the power of 2 requirements. As a bonus, the android version now works with both the mesh and sprite. So the solution seems to be use webgl2. I'm closing this report as a result of this finding (it may still be a bug w/rt the original spec and expectation, but the workaround is a no-hassle fix).