shawn0326 / zen-3d

JavaScript 3D library.
MIT License
196 stars 24 forks source link

Maybe not exactly an issue... #10

Closed VanderSP closed 4 years ago

VanderSP commented 4 years ago

Rather a feature, but i dunno! First of all, thanks for this library and all your hard work on that!

You know that in mobile is so expensive to capture reflections with cube camera, so i use that technique of one shot and bang i got some nice reflections... But... there´s a very annoying issue with this -> even in desktop, with this one shot technique, something related with not being possible to know the time is required for the skybox complete loading... ending with empty reflection...

I kinda workarounded this using a "false prewarm" just waiting some frames.. but this is a bit inconsistent in some cases...

How would be easier for you help the library with this?

1 - Abstracting rotation/position in SkyboxShader 2 - some way for observing texture readiness for the CubeCamera environment?

Thanks Again! Thanks Again! Thanks Again! Thanks Again! Thanks Again! Thanks Again! Thanks Again!

shawn0326 commented 4 years ago

1 - Abstracting rotation/position in SkyboxShader

Now the SkyBox node must be in the same position as the camera. I usually put the SkyBox in the children of the camera. Maybe this is not a good way, and this will cause error when you use other cameras.

As for the rotation of the sky box, it is not yet supported. But i think i can support the rotation of the sky box through skyBox.euler or skyBox.quaternion.

2 - some way for observing texture readiness for the CubeCamera environment?

  1. You can load image first by zen3d.ImageLoader, and then create Texture2D/TextureCube synchronously.
new zen3d.ImageLoader().load('xxx.png', function(image) {  
  // callback

  // setup texture2d
  texture2d.image = image;
  texture2d.version++;

  // setup textureCube like this
  textureCube.images = [image1, image2, ...]; // six images
  textureCube.version++
});
  1. Or you can just add onload event listener to texture
var textureCube = zen3d.TextureCube.fromSrc([...]);
textureCube.addEventListener('onload', function() {
  // callback
});
VanderSP commented 4 years ago

Thanks for fast replying! So, the second option sounds like a nice internal hacking thing! i will test it later and let u know!

VanderSP commented 4 years ago

this is my skybox class

export class SkyBox extends zen3d.Mesh {
    constructor(skyBoxTextures) {
        const size = 4000 * SDSSSetup.resFact
        const geometry = new zen3d.CubeGeometry(size, size, size)
        const material = new zen3d.ShaderMaterial(SkyBoxShader)
        material.side = zen3d.DRAW_SIDE.BACK
        material.cubeMap = skyBoxTextures
        material.needsUpdate = true
        super(geometry, material)
        this.frustumCulled = false
    }
}

and this is where i load images... im using await so i think it should work

    let skyBoxTextures = await SDResourceManager.loadSkyBox( [
            'EnvMaps/ClearDay 512/right.jpg',
            'EnvMaps/ClearDay 512/left.jpg',
            'EnvMaps/ClearDay 512/top.jpg',
            'EnvMaps/ClearDay 512/bottom.jpg',
            'EnvMaps/ClearDay 512/front.jpg',
            'EnvMaps/ClearDay 512/back.jpg'   ],  'Clear Day' )

    this.skyBox = new SkyBox(skyBoxTextures)
    this.skyBox.position.set(400, -700, 0)
    this.interfaceScene.add(this.skyBox)

well, i use a flag set to true, so in render loop i check it, like a lock, and call a capture reflection just once.. i do it using envmappass.render things etc...

as im using async await it should work fine... now i even tried to set captureOnce=true inside onload of img, that´s inside my loader function, that finally calls fromSrc etc...

so i don´t feel it´s a asynchronicity problem in strict way, maybe some problem between uploading the shader to gpu

so the alternative 2, will not work i think... alternative 1 can work? or the shader sync problem is irremediable? (only guessing with a bit of timer?)

Thanks Shawn!

shawn0326 commented 4 years ago

Could you provide me a simple example to reproduce the problem ? And I will check what gose wrong.

VanderSP commented 4 years ago

Im creating a basic test based on your envmap example code, but i can´t change phong to pbr... don´t accept the same textures...

but before i finish the test, i would like to ask you what i need to achieve: the possibility of changing attributes like (x, y or rotation, for example) of the envmap reflection

the way i achieve that, was using envmappass render like that sixcube shot thing... but the problem is: as im capturing just one time, i cant discover how many frames the shader needs to became ready... so ocasionally not ending with a one not reflection shot... what i did before as i said, was counting some frames (a kind of settimeout), but it can be a bit inconsistent sometimes, you know trading a initial lag vs consistency in a wrong way haha

reftest.zip

shawn0326 commented 4 years ago

Sorry, I found that there is a bug here. Setting environment map of PRB material without directional light will cause error. Add a direct light to the scene and it will work. I'll fix the bug later.

but the problem is: as im capturing just one time, i cant discover how many frames the shader needs to became ready

Shader compilation can be seen as synchronous (for the web GL rendering process), so there is no state that the shader is not ready to complete. So I think the most likely problem is the texture loading.

VanderSP commented 4 years ago

oh i see! lol

i was unable to recreate my code but i tried the most, in my code im using async await etc..

in my case if i wait some frames i can capture, but as i said is inconsistent, but here in this example i only can capture if i call it everytime lol

reftest.zip

shawn0326 commented 4 years ago

@VanderSP

oh,I found the problem:

pbr.envMap = envMapPass.renderTexture;
pbr.needsUpdate = true; // After setting the evnmap, the material needs to be marked with update, just like threejs

then, you can capture after cube texture loaded:

cube_texture.addEventListener('onload', function () {
  captureOnce = true;
});
VanderSP commented 4 years ago

ONE ZILLION THANKS! YOU´RE AWESOME!