Gltf mesh with shader material

hi guys,
I am working on the shader material, it works fine wenn I just use build-in mesh von Babylonjs. I need to use the shader material now on the imported GLTF mesh now. I get confused because of the right-hand coordinate system and left-hand coordinate system. What does the clockweiseOrientation von PBRMaterial really do? I think I need build the same property in my shader material. Does anybody have some idea?

In Playground I put the shader material with build-in mesh (sphere) and glb file, you can check the result. The TestMat is a build-in PBRMaterial, the glb mesh with same correct setting(the clockweiseOrientation property) works fine with PBRMaterial, but I want to have this property in my shader material. I tried to change the vertex coordinate, it did nothing.

https://www.babylonjs-playground.com/#4AJ16M#45
gltf mesh with shader material

Hey!
So because glTF is right handed you need to have shaderMaterial.sideOrientation = BABYLON.Material.ClockWiseSideOrientation; for your material to work with your glb object:
https://www.babylonjs-playground.com/#4AJ16M#46

So unfortunately you will not be able to apply exactly the same material to a regular mesh as it will appear inverted then :slight_smile:

The trick will be to use observable to adapt the material:
https://www.babylonjs-playground.com/#4AJ16M#47

3 Likes

Hi! Thanks a lot!
:smile::smile:
I thought, that the ClockWiseSideOrientation property is a part of the material, and I need to convert it in the vertex shader, but it is actually a rendering setting for all material, for PBRMaterial and Shader Material too!! I got confused because the results between regular mesh and imported glb mesh were always different. In my case, I don’t need to use the shader material with the regular mesh, just need to be sure, that the shader material works fine with the gltf mesh.

1 Like

Perfect :slight_smile:

Hi,

@Deltakosh, I just find another issue,… wenn I just put the ShaderMaterial on the animated GLB file, the animation is somehow stopped. Do we have some settings here about the ShaderMaterial and the animation?

here is the Link in playground:https://www.babylonjs-playground.com/#4AJ16M#53
The animated GLB file works fine with PBRMaterial(in link is the TestMat), but wenn I use the ShaderMaterial, the mesh doesn’t move anymore.

Thanks,
Sonja

Off topic question — how do you upload .glb files to the babylon js playground?

hi John,
@John_Smith, this is a available Mesh in BabylonJS Playground : Available Meshes to Import - Babylon.js Documentation
also some textures are available here: Available Textures in the Playground - Babylon.js Documentation
They are good resources for builing the questions.

I work in my project with my own glb file, but the issue is the same, the animation doesn’t work.
:smile:

for animations (bones in this case) you have to add more code in your material to deal with the skeleton animation.

fortunately Babylon will provide you with the code for the shader:

1 Like

If you do not make it work, please create a playground with your current code:)

Hi,
The simpleMaterial is a so good example for learning about Babylonjs builtin Materials. I didn’t realize that the shaders in Babylonjs are so complicated until I see this simple-Material example:sweat_smile::sweat_smile::sweat_smile::sweat_smile:
I tried to begin with it, but got problem at the very first step. Does it work like the native glsl shader?
I see this [0..maxSimultaneousLights] repeating a lot of times in the shader, I think it is a loop for all of the lights. Builtin materials have maxSimultaneousLights property, for shaderMaterial I didn’t find maxSimultaneousLights property. Shoud I define it myself as a uniform? I see some definitions of maxSimultaneousLights in the material .ts file, but I don’t know how it works. When I just copy the shader code from simpleMaterial, and use them as a custom shaderMaterial, it doesn’t work, the error is Cannot read property 'maxSimultaneousLights' of undefined like the followed playground. https://www.babylonjs-playground.com/#S8DWQL#2
I don’t know if the shader include shader code already in shader store or not. When I just run it in my local computer with the full shader include code, it gets the same error.

No worries! Shader are hard and that’s why we have Babylon.js :smiley:
here is how you can fix it:
https://www.babylonjs-playground.com/#S8DWQL#3

the [0…xxx] construct is a way to tell to babylonjs to generate X times a specific include (one for each light here for instance)

The shaderMaterial does not have this property (only supported by regular materials). So in your case, you can just repalce it by 4 for instance

Also please make sure to declare all uniforms in the ShaderMaterial declaration (I see that the bones or instances ones are not present)

Hi!
The bones are moving! But the lights still don’t work.
https://www.babylonjs-playground.com/#S8DWQL#4
I’m still little bit confused about the uniforms.

  • some of them I can get from the scene automatically, that I don’t need to set them myself: "world", "worldViewProjection", "view","viewProjection"

  • some are properties of textures, which I can also get: "vDiffuseInfos", "diffuseMatrix"

  • for the skeleton, "mBones" works after the declaring

I get confused, because I don’t know which uniform I need to set. What about the connection of the light in the scene? How can I send the light into the shader? Is through this one "vLightsType"? "vEyePosition" takes the camera position automatically? And about the sampler2D, should I also declare it as uniform?

Sorry about so many questions, but I think the default uniforms should be somewhere…where I can’t find…

Thanks!:blush::blush::blush::blush::blush:

No worries, this is a pretty advanced topic you are working on :slight_smile:
This is the function that will help you probably:

Hi,
I checked all of the uniforms, actually BABYLONJS populate the scene-uniforms( the matrices), bone-uniforms, and the eyePosition-automatically for the shaderMaterial. What about the light uniforms?

What the .ts file does, is connecting the shader to the engine. Does it mean that we don’t have this connecting for lights in shaderMaterial? I see something like this:

uniform Light0
 {
vec4 vLightData;
vec4 vLightDiffuse;
vec3 vLightSpecular;

 #ifdef SPOTLIGHT0
vec4 vLightDirection;
#endif

#ifdef HEMILIGHT0
vec3 vLightGround;
#endif

vec4 shadowsInfo;
vec2 depthValues;
} light0;

I think, they are from #include<__decl__lightFragment>[0..maxSimultaneousLights], which I’m not sure how to use it for shaderMaterial. Just for testing, I put these info directly in shader, something happens. https://www.babylonjs-playground.com/#S8DWQL#5

vec4 vLightDiffuse = vec4(1.,1.,0., 1.);

vec3 vLightSpecular = vec3(1., 1., 0.);
vec3 diffuseColor = vDiffuseColor.rgb;
vec4 shadowsInfo = vec4(0.5, 0.5, 0.5,1.);
vec2 depthValues = vec2(1., 1.);
float glossiness = 0.;
lightingInfo info = computeLighting(viewDirectionW, normalW, vLightData, vLightDiffuse.rgb, vLightSpecular, vLightDiffuse.a, glossiness);
float shadow = 1.;
diffuseBase += info.diffuse * shadow;

Could I connect the lights from the scene somehow to the shader? When I need to do it manuelly like this way, I will have big problem with multi lights.

Thanks!:smile:

Lights will be auto populated but you need to use the importer for that as well:

This import will populate the diffuseBase vector for you:

to help you get the list of uniforms, you can call this function:

Like here:

Hey!
I think I’m getting closer…
With help from MaterialHelper and MaterialDefines, I can send the infos from Babylon to the shaders (theoretically, does it work like this?). But something is still missing, the light doesn’t work without rendering error.
https://www.babylonjs-playground.com/#S8DWQL#6
I add this to the ShaderMaterial, do I still miss something?

  var myrMaterialDefines = (function (_super) {
        __extends(myrMaterialDefines, _super);
        function myrMaterialDefines() {
            _super.call(this);
            this.BUMP = true;
            this.REFLECTION = true;
            this.CLIPPLANE = false;
            this.ALPHATEST = false;
            this.POINTSIZE = false;
            this.FOG = false;
            this.NORMAL = true;
            this.UV1 = true;
            this.UV2 = true;
            this.VERTEXCOLOR = false;
            this.VERTEXALPHA = false;
            this.NUM_BONE_INFLUENCERS = 4;
            this.BonesPerMesh = 8;
            this.INSTANCES = true;
            this.SPECULARTERM = true;
            this.rebuild();
        }
        return myrMaterialDefines;
    })(BABYLON.MaterialDefines);
    //BABYLON.MaterialDefines.markAsLightDirty;
    this._defines = new myrMaterialDefines();
    if (scene.lightsEnabled && !this.disableLighting) {
        BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, this._defines,true, 4);
    }

Thanks!

You did not update the uniforms list with all the uniforms required by lights

emmm… what do you mean by updating the uniforms? You mean I need to use PrepareUniformsAndSamplersList to generate all of the uniforms again and set the effect like this(:sweat_smile:I didn’t get the point…)? https://www.babylonjs-playground.com/#S8DWQL#8

I checked the shaderMaterial.ts and the simpleMaterial.ts again in github, actually nothing is written about lights and shadows in the shaderMaterial.ts. So what I’m doing here is to add the lights defines and uniforms and somehow update them…But what I’m doing there in the PG is redefining(overwriting) all of the Defines and Uniforms, and it still works…

The uniform list must be known when creating the shader. Same for defines.

But the point is: why not creating your own material ? like the SimpleMaterial for instance in the material library?

The shaderMaterial is meant to be used with your own shader code. If you want to reuse babylon.js one, maybe it is better to create a new Material that will inherit from Babylon material (like the SimpleMaterial).