Danie Clawson
Danie Clawson

Reputation: 183

How do I assemble proper uniforms for Threejs shaders?

I am trying to figure out how to properly use Three.js' built in ShaderChunks for lighting and fog and such, and I figured a good first step was to just copy one of the ShaderLib shaders' setup. So to start with I used:

customMaterial = new ShaderMaterial({
    lights: true,
    uniforms: UniformsUtils.merge( [
      UniformsLib.common,
      UniformsLib.specularmap,
      UniformsLib.envmap,
      UniformsLib.aomap,
      UniformsLib.lightmap,
      UniformsLib.emissivemap,
      UniformsLib.fog,
      UniformsLib.lights,
      {
        emissive: { value: new Color( 0x000000 ) },
        diffuse: { value: new Color( 1,1,1 ) }
      }
    ]),
    vertexShader: document.getElementById("vertexShader").textContent,
    fragmentShader: document.getElementById("fragmentShader").textContent
  })

Where the shader code is just directly copied from meshlambert_vert.glsl and meshlambert_frag.glsl, and that section there is based on this entry in the ShaderLib

However, I am rendering my test scene from two different cameras/renderers at once, and I immediately noticed an issue. Changing one camera's perspective changes the second camera's lighting angle, for objects with this customMaterial applied.

I assume this is due to these UniformLib objects being referenced elsewhere?

I'm not sure what I should be passing here instead, nor why this doesn't work but the standard material does. I guess I'm skipping a step, but I don't understand what it might be.

Here is a codepen where I have isolated the problem as much as I can. Now it is almost a direct copy of the ShaderLib source. At this point I'm thinking this is a pass-by-reference where it should have been a copy, somewhere inside the WebGLRenderer. https://codepen.io/cl4ws0n/pen/dVewdZ

For whatever its worth, I also tried adding a second scene, and moving the objects between them. That didn't fix it, nor did separate objects in separate scenes sharing the material. preview of the codepen link

Upvotes: 0

Views: 311

Answers (2)

Danie Clawson
Danie Clawson

Reputation: 183

As Matjaz Drolc indicated with his comments, this is a bug in three r87. The needsUpdate flags are not functioning properly for ShaderMaterials. You can force an update before each render pass in my codepen link and it will render correctly. See the fork https://codepen.io/cl4ws0n/pen/qPYwzp

I have made an issue on the repo, if anyone would like to track it's progress it can be found here.

Upvotes: 0

Matjaž Drolc
Matjaž Drolc

Reputation: 386

WebGLRenderer has some hardcoded logic for certain materials. In this case it's looking for a flag called isMeshLambertMaterial: https://github.com/mrdoob/three.js/blob/r87/src/renderers/WebGLRenderer.js#L1780

So try setting isMeshLambertMaterial: true, isMeshBasicMaterial: false in your material.

Upvotes: 1

Related Questions