Setting up shadermaterial for use in instanced mesh

So I created a shader for setting up curtain like effects on a plane drape but some instanced meshes.

I am already using defines: [’#define INSTANCES’] when setting up the material and

#include in the shader and #include in the main of the vertex shader.

What’s interesting is the meshes render at the correct postion. It it the instanced meshes that are out of postion. They render fine and wave like they are supposed to. They are just out of place for some reason.

export const drape_vertex = `
precision highp float;

attribute vec3 position;
attribute vec2 uv;
attribute vec2 uv2;
#include<instancesDeclaration>
// Uniforms
uniform mat4 worldViewProjection;
uniform mat4 worldView;
uniform bool vertexFogEnabled;
uniform float time;
uniform float frequency;
uniform float amplitude;
uniform float rate;

varying vec2 vUV0;
varying float fogFactor;

void main(void) {
  #include<instancesVertex>
  vec3 v = position;
  v.z += uv.x * sin(time*rate+uv.x*frequency) * amplitude;
  if(vertexFogEnabled){
float start = 47.0;
float end = 50.0;
float vDistance = length(worldView * vec4(v,1.0));
fogFactor = clamp((vDistance - start) / (end - start), 0.0, 1.0);
  }
  gl_Position = worldViewProjection * vec4(v, 1.0);
vUV0 = uv;

}
`;

Material Setup Code

this._drapeMaterial = new ShaderMaterial('drape_material', this._scene, drapeShader, {
  attributes: ['position', 'uv', 'uv2'],
  uniforms: ['worldview', 'time', 'frequency', 'worldViewProjection', 'amplitude', 'rate'],
  needAlphaBlending: true,
  needAlphaTesting: false,
  defines: ['#define INSTANCES'],
});
const albedo = new Texture('assets/textures/drapes.jpg', this._scene);
this._drapeMaterial.setTexture('albedo', albedo);
//this._drapeMaterial.setInt('vertexFogEnabled', 0);
this._drapeMaterial.setFloat('frequency', -3);
this._drapeMaterial.setFloat('amplitude', 0.7);
this._drapeMaterial.setFloat('rate', 0.9);
this._drapeMaterial.backFaceCulling = true;
this._drapeMaterial.forceDepthWrite = true;

Am I doing something wrong or missing something? I am on babylon v 4.1.0

Hi @Manas_Gangwani

Can you check if this thread helps? createInstance with ShaderMaterial does not render

I think the main difference is instead of using worldViewProjection, you should use finalWorld from #include<instancesVertex>

So
gl_Position = worldViewProjection * vec4(v, 1.0);
should be
gl_Position = viewProjection * finalWorld * vec4(v, 1.0);

In your JS code, make sure you have viewProjection declared in the uniforms.
uniforms: [‘worldview’, ‘time’, ‘frequency’, ‘worldViewProjection’, ‘amplitude’, ‘rate’],

1 Like

They show up on the screen and wave too. They are just out of place. The bounding box of the mesh when I check in the inspector is at the right position. But the actual mesh looks out of place

I updated my answer above. Can you check if it helps?

Tried it did not work. The screen is going crazy triangles all over the screen.

this._drapeMaterial = new ShaderMaterial('drape_material', this._scene, drapeShader, {

      attributes: ['position', 'uv', 'uv2'],

      uniforms: ['worldview', 'time', 'frequency', 'worldViewProjection', 'amplitude', 'rate', 'viewProjection'],

      needAlphaBlending: true,

      needAlphaTesting: false,

      defines: ['#define INSTANCES'],

    });

Shader code

precision highp float;

// Attributes

attribute vec3 position;

attribute vec2 uv;

attribute vec2 uv2;

#include<instancesDeclaration>

// Uniforms

uniform mat4 worldViewProjection;

uniform mat4 viewProjection;

uniform mat4 worldView;

uniform bool vertexFogEnabled;

uniform float time;

uniform float frequency;

uniform float amplitude;

uniform float rate;

// Varying

varying vec2 vUV0;

varying float fogFactor;

void main(void) {

  #include<instancesVertex>

  vec3 v = position;

  v.z += uv.x * sin(time*rate+uv.x*frequency) * amplitude;

  if(vertexFogEnabled){

    float start = 47.0;

    float end = 50.0;

    float vDistance = length(worldView * vec4(v,1.0));

    fogFactor = clamp((vDistance - start) / (end - start), 0.0, 1.0);

  }

  gl_Position = viewProjection * finalWorld * vec4(v, 1.0);

    vUV0 = uv;

    

}

Can you create the issue in a playground?

Sure. There you go. You can move the camera around check

https://playground.babylonjs.com/#WS42QV#6

And this is the original shader

https://playground.babylonjs.com/#WS42QV#5

I removed this line: defines: [’#define INSTANCES’],

And the crazy triangles are removed.
https://playground.babylonjs.com/#WS42QV#7

I need to have it in my project because of the way the assets are setup. Also the sphere disappears. There are three spheres.

Looks like the cloned sphere is the problem. The instanced sphere renders fine.

https://playground.babylonjs.com/#WS42QV#10

I can get the cloned instance shown by adding uniform ‘world’, and rename [’#define INSTANCES’] to something else. I guess INSTANCES has already been used in babylon.js. Can you use a different name?

https://playground.babylonjs.com/#WS42QV#11

1 Like

Yessss. That worked. I almost wasted my entire day over this. Thanks a lot

1 Like