Shader Material doesn't work with instances

Shader Materials don’t work with instances. Even after including instancesDeclaration and instancesVertex, the material doesn’t work because its missing the attributes “world0”, “world1”, “world2”, “world3”. I have fixed it by adding them in the materials instance, however during the process I found out that the code for it was there yet it didn’t work. The problem is in :

MaterialHelper.PrepareAttributesForInstances = function (attribs, defines) {
if (defines[“INSTANCES”]) {
attribs.push(“world0”);
attribs.push(“world1”);
attribs.push(“world2”);
attribs.push(“world3”);
}
};

More exactly the if (defines[“INSTANCES”]) is never true, seems like the value isn’t “INSTANCES” but “#include INSTANCES”.

The test has been done with BABYLON 4.0.

Cheers!

When creating your shaderMaterial using the constructor you can just add the defines your want. Just include INSTANCES in the list of custom defines.

If this does not work, please create a PG as this is supposed to work

Good Day @Deltakosh .

I attempted the “INSTANCES” defines approach without success.
I followed up by manually adding the world0, world1, world2, and world3 vec4 attributes but it results in weird clipping effects. Can you please provide some guidance?

Here are two playgrounds:

  1. Using defines “INSTANCES”.
  2. Manual hack.

Adding @Evgeni_Popov who is amazing with instances :slight_smile:

1 Like

This thread should help:

3 Likes

Thanks @Evgeni_Popov . Any idea why I am getting this error:

VERTEX SHADER ERROR: 0:21: 'flat' : Illegal use of reserved word

I know I am not making use of the gl_InstanceID yet, but I would like to in the future.

https://www.babylonjs-playground.com/#QENFPC#63

I don’t have this error, everything is ok on my side…

I do have the error in WebGL1, though, so I assume this keyword is illegal in WebGL1 (maybe you are testing with Safari which is using WebGL1?). In any case, I think int variables are not supported in WebGL1.

1 Like

Good to know thanks @Evgeni_Popov .

In the same setup the first 6 instances are not rendering. Any clue to why?

https://www.babylonjs-playground.com/#QENFPC#66

You don’t have to manage the world0->world3 buffers, it is done automatically by the system:

https://www.babylonjs-playground.com/#QENFPC#67

1 Like

Bless you @Evgeni_Popov !

1 Like

I am attempting to pull in just the morphTarget position logic and run a test on the first target set at full influence. I get this error:


Error: VERTEX SHADER ERROR: 0:32: 'readVector3FromRawSampler' : no matching overloaded function found

I see this function in the Babylon source clearly as shown below which takes the integer pointing to the morphTarget index and the float associated with the vertexIndex. I don’t understand why it then says there is NO MATCHING OVERLOADED FUNCTION.

Here is the PG.

#ifdef MORPHTARGETS
	uniform float morphTargetInfluences[NUM_MORPH_INFLUENCERS];

	#ifdef MORPHTARGETS_TEXTURE	
		precision mediump sampler2DArray;		
		uniform float morphTargetTextureIndices[NUM_MORPH_INFLUENCERS];
		uniform vec3 morphTargetTextureInfo;
		uniform sampler2DArray morphTargets;

		vec3 readVector3FromRawSampler(int targetIndex, float vertexIndex)
		{			
			float y = floor(vertexIndex / morphTargetTextureInfo.y);
			float x = vertexIndex - y * morphTargetTextureInfo.y;
			vec3 textureUV = vec3((x + 0.5) / morphTargetTextureInfo.y, (y + 0.5) / morphTargetTextureInfo.z, morphTargetTextureIndices[targetIndex]);
			return texture(morphTargets, textureUV).xyz;
		}
	#endif
#endif

You can use the #includes that already exist to inject the morph target code:

https://www.babylonjs-playground.com/#QENFPC#75

Also, you should let the ShaderMaterial class add the correct #defines depending on the fact you use instances / morph targets (that’s why I pass an empty defines array).

Note however that for the time being, the ShaderMaterial class does not handle morph targets that are using a texture, so you must pass the right parameters by hand (see PG lines 118-119).

Note also that there’s no morphing going on in your PG because basisModel.morphTargetManager.numInfluencers = 0: I have used another model in the PG above that does have numInfluencers > 0, so you will see that it works.

2 Likes

Thank you @Evgeni_Popov ! Have a wonderful day!

Good Day @Evgeni_Popov !

I am attempting to store some offset data in a raw texture and and trying to retrieve it in the vertex shader. The offsets for updating the vertex positions don’t seem to be working in this PG. Do you know why?

It does work but you should use bigger values than 1 because you get an offset of 1/255 in the shader, which is not really visible:

https://playground.babylonjs.com/#7SUTUC#4

Also, I think you will need to disable mip mapping and use a nearest filter for your texture to avoid having trilinear/bilinear filtering when doing the lookup.

2 Likes

PR to add support for morph target texture to ShaderMaterial:

Once it’s in, this PG will work: https://playground.babylonjs.com/#QENFPC#79

1 Like

Thanks @Evgeni_Popov ! In the meantime, I am trying a simpler, somewhat lossy approach to passing the morph positions via an RGBTexture uniform. It seems that this would work just as the simple box geometry example I did earlier however I test the recovered offsets from the texture method and they all seem to return zero. Any idea why the recovered offsets from the texture method all return zero @Evgeni_Popov ?

The goal in this example is to fully morph to a single chosen target per instance.

I have console logged the original positions along with the expected tranforms and lossy inverse transforms of the morph target position data for each target.

The inverse transform function I use for console logging is slightly different from that in the vertex shader due to the expectation that the texture sampling method will return normalized results.

You have to pass a Uint8Array to CreateRGBTexture, not a regular array:

https://playground.babylonjs.com/#WPJKLA#12

1 Like

Thank you @Evgeni_Popov . :heart: I am getting unexpected results from the applied morph position offsets. Is it perhaps because I didn’t inject a 255 for the alpha channel every fourth element of the data array @Evgeni_Popov ? I say this because the texture method sample returns a vec4 and I am only constituting the data array with r,g,b not a. Or is the CreateRBGTexture method setting the texture binding level to GL_RGB thus informing the texture method to always assign 1.0f to the 4th component?

In the following PG, the clone in the middle is alternating between the two morph representations which I am expecting to see in the instances on either side.

The sampling mode is not passed correctly when creating the texture, it should be the 7th parameter:

https://playground.babylonjs.com/#WPJKLA#17

In effect, you had a Y inversion on your texture.

2 Likes