The main idea behind this ShaderMaterial wrapper is to have lights attached to the material, so it’s possible to illuminate any object with any light(s), also I wanted to have more control over shadows and experiment with different ways to create them.
The lighting for this material is based on per-pixel Lambertian diffusion plus specular highlights.
The material currently supports texture map, bump map, translucency, gamma and any number of ambient, direct and point lights and 3 shadow modes for fun.
Point lights have attenuation over distance, light shadows have 4 levels of blur and strength.
Lights can be built-in THREE lights or stand-alone JavaScript objects.
This is still a work in progress but I wanted to share a couple of scenes.
Here is one with multiple objects illuminated by a custom material and UI to play with its settings (clickable link):
And now, when I married this material with instanced meshes, I could test it on more complex geometry, illuminating different groups of meshes with different lights (clickable link):
An example of material setup:
dir.userData.shadow = {
blur: 5,
strength: 0.9,
tex: { w: 1000, h: 1000 },
cam: new THREE.OrthographicCamera(-700/9, 700/9, 700/9, -700/9, 50, 300),
lookat: dir_lookat,
};
pnt0.userData.shadow = {
blur: 5,
strength: 1,
tex: { w: 1050, h: 875 },
cam: new THREE.PerspectiveCamera(55, 1, 30, 300),
lookat: lookAt,
};
...
const mat_main = cust.material('lamb', {
uni: {
color: { value: [1, 1, 1] },
amb: {
get color() { return [amb.color.r, amb.color.g, amb.color.b] },
get intensity() { return amb.intensity },
},
dir: {
get color() { return [dir.color.r, dir.color.g, dir.color.b] },
get intensity() { return dir.intensity },
position: [dir.position.x, dir.position.y, dir.position.z],
lookat: dir_lookat,
shadow: dir.userData.shadow,
},
pnt: [{
get color() { return [pnt0.color.r, pnt0.color.g, pnt0.color.b] },
get intensity() { return pnt0.userData.power },
position: [pnt0.position.x, pnt0.position.y, pnt0.position.z],
get decay() { return pnt0.userData.decay },
shadow: pnt0.userData.shadow,
},{
get color() { return [pnt1.color.r, pnt1.color.g, pnt1.color.b] },
get intensity() { return pnt1.userData.power },
position: [pnt1.position.x, pnt1.position.y, pnt1.position.z],
get decay() { return pnt1.userData.decay },
shadow: pnt1.userData.shadow,
}],
specular: {
get position() {
const pos = camera.position;
return [pos.x, pos.y, pos.z];
},
get strength() { return ui.spec.str },
get falloff() { return ui.spec.fo },
},
shad_mode: { get value() { return ui.shad_mode } },
map: ['/_v1_jsm/textures/uv.png', () => { callback('r') }, ],
}
});