Jump to content

Instanced meshes with ShaderMaterial are not drawn


jahow
 Share

Recommended Posts

Hi all,

 

I found something weird while optimizing my code: I was using InstancedMesh as much as possible, and switched all my materials to ShaderMaterial. And then boom, everything disappeared.

After a bit of research, it seems instanced meshes will simply not be drawn when their source has a ShaderMaterial assigned. Playground repro: http://www.babylonjs-playground.com/#TWDEA#6

Uncomment lines 40 to 44 to see for yourself. It's actually a bit more complex than that: when you assign a shader material to it, even the source mesh disappears if it has been instantiated (?), but only if its instances are in the field of view.

 

I'm currently looking at BJS code and ANGLE_instanced_arrays doc (the extension used for drawing instanced meshes), but I thought I'd come here to fish for ideas...

FYI these are two errors I noticed in the log when this problem showed (errors not always there):

drawElementsInstancedANGLE: at least one enabled attribute must have a divisor of 0glDrawElementsInstancedANGLE: attempt to draw with all attributes having non-zero divisors

Thanks :)

Link to comment
Share on other sites

A very(!) uneducated guess:

All Materials have useInstances variable in their isReady() function, shader material is missing it.

StandardMaterial adds this:

defines.push("#define INSTANCES");attribs.push("world0");attribs.push("world1");attribs.push("world2");attribs.push("world3");

if useInstance is set to true. Maybe this is a place to check?

Link to comment
Share on other sites

Yeah, I'm starting to understand the issue, and it's related to the lines you point at.

 

Basically, only the StandardMaterial supports instances by default, since it's the only one that passes the transformation matrix as an attribute when drawing instanced meshes.

 

I got it to work almost perfectly by adding these to the shader material object:

- attributes: world0, world1, world2, world3 (these are actually the world transform matrix of the current instance, decomposed in vertices)

- uniform: viewProjection

 

Here it is: http://www.babylonjs-playground.com/#TWDEA#9

 

It's not perfect yet: when there is no instanced mesh on screen but only the original one (left ball), the rendering process switches to no-instance rendering and doesn't provide these attributes anymore, and then a WebGL error pops out. The StandarMaterial uses the lines pointed out by RaananW to make that switch, but the ShaderMaterial doesn't handle that.

 

For now I'll make my own custom material class to handle this, but I believe it would be a good thing for BJS to handle this case by default. Although that may require some serous change on the ShaderMaterial class...

Link to comment
Share on other sites

Is this ShaderMaterial a real boost / short cut?  If so, may want to incorporate into my Blender source code generator. 

 

Here is a sample of a scene with 3 materials.  I was being explicit like the way FileLoader is.  Is there a better pattern to use?  Here is the Javascript variant.  There is also a Typescript variant.

    var matLoaded = false;    function defineMaterials(scene, materialsRootDir) {        if (!materialsRootDir) { materialsRootDir = "./"; }        if (!BABYLON.Engine.Version || Number(BABYLON.Engine.Version.substr(0, BABYLON.Engine.Version.lastIndexOf("."))) < 2.0) throw "Babylon version too old";        if (matLoaded) return;        BABYLON.Tools.Log('In defineMaterials');        if (materialsRootDir.lastIndexOf("/") + 1  !== materialsRootDir.length) { materialsRootDir  += "/"; }        var material;        var texture;        material = new BABYLON.StandardMaterial("shape_key.cloth-like", scene);        material.ambientColor  = new BABYLON.Color3(1,1,1);        material.diffuseColor  = new BABYLON.Color3(0.8,0.8,0.8);        material.specularColor = new BABYLON.Color3(0.5,0.5,0.5);        material.emissiveColor = new BABYLON.Color3(0,0,0);        material.specularPower = 50;        material.alpha =  1;        material.backFaceCulling = false;        texture = new BABYLON.Texture(materialsRootDir + "tableCloth.jpg", scene);        texture.name = materialsRootDir + "tableCloth.jpg";        texture.hasAlpha = true;        texture.level = 1;        texture.coordinatesIndex = 0;        texture.coordinatesMode = 0;        texture.uOffset = 0;        texture.vOffset = 0;        texture.uScale = 1;        texture.vScale = 1;        texture.uAng = 0;        texture.vAng = 0;        texture.wAng = 0;        texture.wrapU = 1;        texture.wrapV = 1;        material.diffuseTexture = texture;        material = new BABYLON.StandardMaterial("shape_key.ground-like", scene);        material.ambientColor  = new BABYLON.Color3(0.8,0.8,0.8);        material.diffuseColor  = new BABYLON.Color3(0.64,0.64,0.64);        material.specularColor = new BABYLON.Color3(0.5,0.5,0.5);        material.emissiveColor = new BABYLON.Color3(0,0,0);        material.specularPower = 50;        material.alpha =  1;        material.backFaceCulling = true;        texture = new BABYLON.Texture(materialsRootDir + "tmage512.png", scene);        texture.name = materialsRootDir + "tmage512.png";        texture.hasAlpha = true;        texture.level = 1;        texture.coordinatesIndex = 0;        texture.coordinatesMode = 0;        texture.uOffset = 0;        texture.vOffset = 0;        texture.uScale = 1;        texture.vScale = 1;        texture.uAng = 0;        texture.vAng = 0;        texture.wAng = 0;        texture.wrapU = 1;        texture.wrapV = 1;        material.diffuseTexture = texture;        material = new BABYLON.StandardMaterial("shape_key.table", scene);        material.ambientColor  = new BABYLON.Color3(0,0,1);        material.diffuseColor  = new BABYLON.Color3(0,0,0.8);        material.specularColor = new BABYLON.Color3(0.5,0.5,0.5);        material.emissiveColor = new BABYLON.Color3(0,0,0);        material.specularPower = 50;        material.alpha =  1;        material.backFaceCulling = true;        matLoaded = true;    }    shape_key.defineMaterials = defineMaterials;
Link to comment
Share on other sites

  • 1 year later...

Was this ever fixed? I am seeming to run into this issue now. @Deltakosh

I need to have instances specifically not clones with different shader params.  Ive tried cloning the shader tot he new instance and I get the same weird results.

I have a video demonstrating it on this page.  If I do the same process with my water hex instance and just don't use my shader it goes to the correct position.  But I can not replicate on the playground so Im kinda at a loss, then I came across this from 2015.

I even simplified my shader to just output white, and still get odd results.

Link to comment
Share on other sites

I did a search against the repo for the include needed to process instances inside of Eclipse.  Looks like some vertex shaders are covered, but not all.  Looking at this old thread, there was only StandardMaterial (default shader), so something was done.  Supported here.  BTW, if vertex and fragment shaders were in separate directories, it would be easier.

istances.jpg

Link to comment
Share on other sites

  • 5 months later...

The ShaderMaterial let you provide the code so if you want to support instances you will have to write the shader code :)

Here are some hints to help:

- First of all everythng happens in the vertex shader

- You need to include this shader include: https://github.com/BabylonJS/Babylon.js/blob/master/src/Shaders/default.vertex.fx#L24 to get all declarations done

- Then add this one in your vertex code(https://github.com/BabylonJS/Babylon.js/blob/master/src/Shaders/default.vertex.fx#L99)

- Makes sure you are using a variable named finalWorld to compute your vertex position

- You need to add a shader define names INSTANCES

- Material helper can help you providing the required uniforms: https://github.com/BabylonJS/Babylon.js/blob/master/src/Materials/babylon.materialHelper.ts#L304

 

Link to comment
Share on other sites

  • 3 months later...
  • 2 months later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...