Modifying ShaderMaterial to bind lights

I’ve duplicated shaderMaterial.ts and compared it to simpleMaterial.ts, and added lines that seem relevant to binding lights. However I’m likely missing something, I’m just getting black for the diffuse.

>     private _disableLighting = false;
>     @expandToProperty("_markAllSubMeshesAsLightsDirty")
>     public disableLighting: boolean;
>     @serialize("maxSimultaneousLights")
>     private _maxSimultaneousLights = 4;
>     @expandToProperty("_markAllSubMeshesAsLightsDirty")
>     public maxSimultaneousLights: number;
public isReady(mesh?: AbstractMesh, useInstances?: boolean, subMesh?: SubMesh): boolean {
>         // Lights
>         const needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
>         if (needNormals) {
>           defines.push("#define _needNormals");
>         }
            effect = engine.createEffect(
>                     indexParameters: {
>                       maxSimultaneousMorphTargets: numInfluencers,
>                       maxSimultaneousLights: this._maxSimultaneousLights,
>                     },
    public bind(world: Matrix, mesh?: Mesh, effectOverride?: Nullable<Effect>, subMesh?: SubMesh): void {
>             // Lights
>             const scene = this.getScene();
>             if (scene.lightsEnabled && !this.disableLighting) {
>               MaterialHelper.BindLights(scene, mesh, this._activeEffect, subMesh.materialDefines, this._maxSimultaneousLights);
>             }

Fragment shader:

#ifdef GL_ES
precision mediump float;

varying vec2 vUV;
varying vec3 vNormalW;
varying vec3 vPositionW;

uniform sampler2D diffuseTexture;
uniform float blend;
uniform vec3 blendColor;


void main(void) {
  vec4 baseColor = texture2D(diffuseTexture, vUV);

  vec3 normalW = normalize(vNormalW);
  float globalShadow = 0.;
  float shadowLightCount = 0.;
  vec3 diffuseColor = vec3(1., 1., 1.);
  vec3 diffuseBase = vec3(0., 0., 0.);
  lightingInfo info;
  float shadow = 1.;
  float glossiness = 0.;

  vec3 finalDiffuse = clamp(diffuseBase, 0.0, 1.0);

  gl_FragColor = vec4(finalDiffuse, 1);

Vertex Shader

#ifdef GL_ES
precision highp float;

attribute vec3 position;
attribute vec3 normal;
attribute vec2 uv;


uniform mat4 world;
uniform mat4 viewProjection;

varying vec2 vUV;
varying vec3 vNormalW;
varying vec3 vPositionW;

void main(void) {
  mat4 finalWorld = world;
  vec3 positionUpdated = position;


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

  vUV = uv;
  mat3 normalWorld = mat3(finalWorld);
  vNormalW = normalize(normalWorld * normal);
  vPositionW = vec3(finalWorld * vec4(positionUpdated, 1));

And as a sanity check I used StandardMaterial and it renders with lighting. Babylon 5.43

Any help would be appreciated!

Using a shader material with lights is complicated and not really supported. If possible, you should create a node material instead.

If you still want to go that route, this post may help:

1 Like

Hey, thanks for pointing me to that!

I did try using the NME but it resulted in the memory usage increasing from 500mb to 2.5gb. I did skim CustomMaterial but I couldn’t find any documentation.

I ended up getting my modified shaderMaterial.ts to work, needed to add a PrepareUniformsAndSamplersList() call to isReady() and updating it to use MaterialDefines.

Not sure what light features can’t be ported in, but at least the basic light case is possible.

If you are able to set up a repro, that would be great, it really shouldn’t happen!