Transparency alpha render issues

Are you changing/updating the layers in the meshes after you add the GLB models to the scene so that the outer shell is rendered last?

Not yet, as the fbx imported mesh in the editor does not need that.

I don’t understand how you change the layer via code. When you access the model component of the runtime loaded .glb you can’t differentiate between the single meshInstances. When I tried to set _layer on the shell meshInstance it had no effect.

Yes, it’s a bit complicated with the legacy model component. You will have to use the Layer class methods to add and remove mesh instances (remove it from the current layer, add it to the new one):

https://developer.playcanvas.com/api/pc.Layer.html#addMeshInstances

With the newer render component I think it would be easier.

I’d gladly use render component, but that doesn’t work with glbs loaded at runtime?

Ok I did it like this

this.app.scene.layers.getLayerByName("World").removeMeshInstances([meshInstances[0]]);
this.app.scene.layers.getLayerByName("TransparentLayer").addMeshInstances([meshInstances[0]]);

and it did help. When the shell is rendered later some overlapping disappears but not all.
The real question is, how to automate/script this when I have like 20 glbs that are going to be loaded at runtime and all have to be set up like this.

I think it works, check this forum post it links to an engine example:

That’s a good question, not sure how to best approach this.

If you need to pick certain mesh instances and do that you can run a for loop based on some logic e.g. node name.

maybe you need to ‘sort’ those mesh instance based on their distance from the center of the whole object? Kind of rendering it from inside out.

1 Like

can I do this then:


self.app.assets.loadFromUrlAndFilename(self.url3, null, "container", function (err, asset3) {

       

        self.entity.addComponent('model', {
            asset: asset3.resource.model
        });

        self.app.scene.layers.getLayerByName("World").addMeshInstances(asset3.resource.model);
    });

{I want to set refraction on externaly loaded GLB model [as in PlayCanvas 3D HTML5 Game Engine]}

You can use entity.findComponents to get all render components under a parent entity and change the layers there.

eg https://playcanvas.com/editor/scene/1019167

Correct link: https://playcanvas.com/project/871826/overview/change-render-component-layers

LoadGlb.attributes.add('glbAsset', { type: 'asset', assetType: 'binary'});
LoadGlb.attributes.add('layerNames', { type: 'string', array: true});

// initialize code called once per entity
LoadGlb.prototype.initialize = function() {
    var self = this;
    utils.loadGlbContainerFromAsset(this.glbAsset, null, this.glbAsset.name, function (err, asset) {
        /** @type {pc.Entity} */
        var renderRootEntity = asset.resource.instantiateRenderEntity();
        self.entity.addChild(renderRootEntity);

        // Get all the render components that have been created in the hierarchy 
        /** @type {pc.RenderComponent[]} */
        var renders = renderRootEntity.findComponents('render');
        var layerIds = [];
        var i;
        // Get the list of layer ids
        for (i = 0; i < self.layerNames.length; ++i) {
            var layer = self.app.scene.layers.getLayerByName(self.layerNames[i]);
            if (layer !== null) {
                layerIds.push(layer.id);
            }
        }

        for (i = 0; i < renders.length; ++i) {
            renders[i].layers = layerIds;
        }

        // If you need a list of materials to edit, you can use:
        // `asset.resource.materials` for an array of material assets
    });
};

The other thing you may need to do is disable depth write on the materials that are created when loading the GLB which I believe you did in the earlier test project?

1 Like

Ok, sound reasonable - but I don’t get a length at layerNames.length … looks empty

  • and thereby a cannot allocate the model to the World Layer
    PS: yes, I remember vaguely that I gave up the last time - but I dont think I tried the layer approach then

What do you mean by this? It is possible.

Have you parsed attributes on the script and added layer names into it?

(I’ve realised I posted the wrong link to the project. Here’s the correct one: PlayCanvas 3D HTML5 Game Engine)

I’m using MeshOpt glbs though. The load functions for them are done with model components. Simply exchanging them to render components doesn’t work.

Yes, in the meantime I found out - (here with out of context names:

meshKorrektOrder.layer =1;
console.log("Get LayID: " + meshKorrektOrder.layer);

)

But the problem remains regarding the externally loaded model

  • I wait for 20 frames to secure any mish-mash, but the model/entity will not output a layer ID:
    [here is the top of the refraction postUPdate]:
Refraction.prototype.postUpdate = function(dt) {

    if(this.app.root.findByName("RightHandUrHook_SwarowskiEx").script.lexg3.fr >20){

    if (this.firstRender) {

        this.firstRender = false;

       

        var self = this;

        var device = this.app.graphicsDevice;

       

        if (! this.layerRefraction) {

            console.log('Refraction: no "Refraction" layer found.');

            return;

        }

       

        // create render target

        this.resize();

       

        // for each entity marked as refract

        var entities = self.app.root.findByGuid("927307b2-ee29-483a-a62f-d0e70f77907e");

        console.log("LAYER1: "+ entities.layer); // this outputs undefined

That’s okay. Change the code I posted to look for model components instead.

Layers aren’t on the entity object. They are on model or render components.

1 Like

So I get an output of the loaded GLB-model’s meshes - so far so good.
But I am not able to set, the layers to each of (the model’s) meshinstances - for then finally the goal of refracting each meshinstance:

Refraction.prototype.postUpdate = function(dt) {

    if(this.app.root.findByName("RightHandUrHook_SwarowskiEx").script.lexg3.fr >20){

    if (this.firstRender) {

        this.firstRender = false;

       

        var self = this;

        var device = this.app.graphicsDevice;

       

        if (! this.layerRefraction) {

            console.log('Refraction: no "Refraction" layer found.');

            return;

        }

       

        // create render target

        this.resize();

       

        // for each entity marked as refract

        var loadedGLB = this.app.root.findByGuid(this.app.root.findByName("RightHandUrHook_SwarowskiEx").script.lexg3.ggu);// console.log("FF: "+loadedGLB.name);

        var entities = loadedGLB.model.meshInstances;

       

        if (entities.length === 0)

            console.log("LAYER1 Refraction: no entities found. Mark entities with `refract` tags.");

       

        for(var i = 0; i < entities.length; i++) {

            var mesh = entities[i];

            console.log("LAYER1: "+ entities.length);

            if (! mesh) {

                console.log('LAYER1 Refraction: entity "' + entities[i].name + '" have no model component.');

                continue;

            }

            entities[i].modelLayers = 1;

            var modelLayers = entities[i].modelLayers.slice(0);

            if (modelLayers.indexOf(this.layerWorld.id) === -1) {

                console.log('LAYER1 Refraction: entity "' + entities[i].name + '" is not on "World" layer.');

                continue;

            }

You don’t need to do it on the meshinstances directly, the model/render component will handle that for you when the layer id array is set on the component

Hmmm I think I am almost there:

Refraction.prototype.postUpdate = function(dt) {

    if(this.app.root.findByName("RightHandUrHook_SwarowskiEx").script.lexg3.fr >200){

    if (this.firstRender) {
        this.firstRender = false;    
        var device = this.app.graphicsDevice;
       if (! this.layerRefraction) {
            console.log('Refraction: no "Refraction" layer found.');
            return;
        }       

        // create render target
        this.resize();      

        // for each entity marked as refract
        var tmpval = this.app.root.findByName("RightHandUrHook_SwarowskiEx").script.lexg3.ggu; 
        var loadedGLB = this.app.root.findByName(tmpval);     var entities = loadedGLB.name;      

          // update materials

           var meshes = this.app.root.findByName("RightHandUrHook_SwarowskiEx").script.lexg3.meshes;

        for(var m = 0; m < meshes.length; m++) {      meshes[m].layer =1;
               meshes[m].material.chunks.refractionPS = this.chunkRefractFS.resource;
              meshes[m].depthWrite=false;
              meshes[m].material.update();

          }

        // render again
        this.layerRefraction.addMeshInstances(this.layerWorld.opaqueMeshInstances);
        this.layerRefraction.addMeshInstances(this.layerWorld.transparentMeshInstances);
     
        // set screenspace texture     
        device.scope.resolve('texture_screen').setValue(this.renderTarget.colorBuffer);
    }
    }

};

The code compiles, but no change in material / refraction

Here is the project: https://playcanvas.com/editor/scene/1314831

A post was split to a new topic: WebGL error when opening project in Editor