I’m working on supporting lightmaps exported from Unity in Three.js. They work a little differently from three.js’s implementation where a few global lightmaps are shared across materials. In this implementation multiple instances of the same mesh have their lightmap data baked into a single lightmap, the mesh has one uv2 set and each instance of the mesh has a lightmap offset/scale. Also each instance could theoretically be baked into a different lightmap.
In my implementation I’d like to solve this by having all the instances of the same mesh share a material. That way I can update uniforms in one place and ensure that they all share the same program. However, they do need to set a couple uniforms on a per-mesh basis. Here’s what my current solution looks like:
mesh = new Mesh(geometryObj, materialObj);
if (lightMap) {
const { offset, scale, intensity, texture: lightMapTexture } = lightMap;
const material = materialObj as MeshBasicMaterial | MeshStandardMaterial;
if (!material.userData.lightMapTransform) {
const lightMapTransformMatrix = new Matrix3().setUvTransform(0, 0, 1, 1, 0, 0, 0);
const lightMapTransform = new Uniform(lightMapTransformMatrix);
material.onBeforeCompile = (shader) => {
shader.uniforms.lightMapTransform = lightMapTransform;
};
material.needsUpdate = true;
material.userData.lightMapTransform = lightMapTransform;
}
mesh.onBeforeRender = () => {
material.lightMapIntensity = intensity * Math.PI;
material.lightMap = lightMapTexture.texture;
((material.userData.lightMapTransform as Uniform).value as Matrix3).setUvTransform(
offset[0],
offset[1],
scale[0],
scale[1],
0,
0,
0
);
};
}
The mesh.onBeforeRender hook ends up working out well, it gets called per-mesh and I can update the material right before it’s used. However, due to how uniform caching works, only the first mesh to get rendered in that frame sets its uniforms.
In previous versions of Three.js there were dynamic uniforms that could change multiple times in a frame. Is there any other way to force a material’s uniforms to be refreshed even if two objects with the same material render back to back?
It looks like this exists for ShaderMaterial Suggestion: Support refreshing specific uniforms independent of switching program / material · Issue #9870 · mrdoob/three.js · GitHub is there any work around for getting this to work with the MeshStandardMaterial?