I'm experimenting with Three.js ShaderMaterial and trying to implement lighting. I have working code for r70 but the same code (with minor changes - the MAX_POINT_LIGHTS constant has been renamed NUM_POINT_LIGHTS) doesn't work for r76.
Looking at a trace in WebGL Inspector it's clear that no light data is being sent to the shader. So, has lighting broken or do I need to set up something else to get it to work?
http://codepen.io/anon/pen/KzjXNr?editors=1010
Fragment Shader
uniform vec3 diffuse;
varying vec3 vPos;
varying vec3 vNormal;
uniform vec3 pointLightColor[MAX_POINT_LIGHTS];
uniform vec3 pointLightPosition[MAX_POINT_LIGHTS];
uniform float pointLightDistance[MAX_POINT_LIGHTS];
void main() {
vec4 addedLights = vec4(0.1, 0.1, 0.1, 1.0);
for(int l = 0; l < MAX_POINT_LIGHTS; l++) {
vec3 lightDirection = normalize(vPos - pointLightPosition[l]);
addedLights.rgb += clamp(dot(-lightDirection, vNormal), 0.0, 1.0) * pointLightColor[l];
}
gl_FragColor = addedLights;
}
JavaScript - setting up the Shadermaterial with UniformsUtils and UniformsLib
var uniforms = THREE.UniformsUtils.merge([
THREE.UniformsLib['lights'],
{ diffuse: { type: 'c', value: new THREE.Color(0xff00ff) } }
]);
var vertexShader = document.getElementById('vertexShader').text;
var fragmentShader = document.getElementById('fragmentShader').text;
material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: vertexShader,
fragmentShader: fragmentShader,
lights: true
});
var geometry = new THREE.BoxGeometry(200, 200, 200);
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
http://codepen.io/anon/pen/ZWdXLZ?editors=1010
Fragment Shader
uniform vec3 diffuse;
varying vec3 vPos;
varying vec3 vNormal;
uniform vec3 pointLightColor[NUM_POINT_LIGHTS];
uniform vec3 pointLightPosition[NUM_POINT_LIGHTS];
uniform float pointLightDistance[NUM_POINT_LIGHTS];
void main() {
vec4 addedLights = vec4(0.1, 0.1, 0.1, 1.0);
for(int l = 0; l < NUM_POINT_LIGHTS; l++) {
vec3 lightDirection = normalize(vPos - pointLightPosition[l]);
addedLights.rgb += clamp(dot(-lightDirection, vNormal), 0.0, 1.0) * pointLightColor[l];
}
gl_FragColor = addedLights;
}
JavaScript
Unchanged
The light uniforms have been changed to struct
s in r74 (Specifically in #7324). Note that though the change to struct
s happened in r74, the following works r75 and later.
A single array of struct
s is given for each light type. Each struct
has the position
and color
properties you need.
Fragment Shader
uniform vec3 diffuse;
varying vec3 vPos;
varying vec3 vNormal;
struct PointLight {
vec3 position;
vec3 color;
};
uniform PointLight pointLights[ NUM_POINT_LIGHTS ];
void main() {
vec4 addedLights = vec4(0.1, 0.1, 0.1, 1.0);
for(int l = 0; l < NUM_POINT_LIGHTS; l++) {
vec3 adjustedLight = pointLights[l].position + cameraPosition;
vec3 lightDirection = normalize(vPos - adjustedLight);
addedLights.rgb += clamp(dot(-lightDirection, vNormal), 0.0, 1.0) * pointLights[l].color;
}
gl_FragColor = addedLights;//mix(vec4(diffuse.x, diffuse.y, diffuse.z, 1.0), addedLights, addedLights);
}
Note that the light position is now relative to the camera so you offset the light position with the camera position.
Working Fiddle
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With