Shaders & structs - three.js

Edit 16 August, 2016
I finally managed to get it to throw an error that might expose what's going on. In my latest code edit, I was adding the ability to hot-swap between fragment shaders. This works fine for shaders with singleton uniforms, but swapping to a shader with a structure throws the following error:
Uncaught TypeError: Cannot read property 'x' of undefined
Call stack:
setValue3fv # three.js:31915
THREE.WebGLUniforms.StructuredUniform.setValue # three.js:32148
THREE.WebGLUniforms.WebGLUniforms.upload # three.js:32285
setProgram # three.js:26733 renderBufferDirect # three.js:25492
renderObjects # three.js:26303
render # three.js:26044
draw # VM160:191doStructs # VM86:148
It looks like it's building the structure uniforms incorrectly (it's trying to reference property value for a THREE.Color which only has r, g, and ,b). I'm continuing to dig, but maybe this new info will trigger a lightbulb for someone.
Original Post & Code
According to a conversation here, Three.js has the ability to use structs as shader uniforms. I'm now trying to use a shader that has structs, simplified to the bare minimum, and still can't get it to recognize them as structs.
In the fiddle below, just change the WITH_STRUCTS value to true/false and re-run to see the difference.
I've also tried defining the uniforms like this, but it didn't make a difference.
uniforms: {
"colorValues": {
"color": { type: "c", value: new THREE.Color(0x00ff00) }
},
"opacityValues": {
"opacity": { type: "f", value: 1.0 }
}
}
Did I miss some properties, or am I approaching this entirely incorrectly?
jsFiddle:
http://jsfiddle.net/TheJim01/546syLur/
HTML:
<script src="http://threejs.org/build/three.js"></script>
<script src="http://threejs.org/examples/js/controls/TrackballControls.js"></script>
<script src="http://threejs.org/examples/js/libs/stats.min.js"></script>
<div id="host"></div>
<script>
// INITIALIZE
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight,
FOV = 35,
NEAR = 1,
FAR = 1000;
var renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(WIDTH, HEIGHT);
document.getElementById('host').appendChild(renderer.domElement);
var camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
camera.position.z = 250;
var trackballControl = new THREE.TrackballControls(camera, renderer.domElement);
trackballControl.rotateSpeed = 5.0; // need to speed it up a little
var scene = new THREE.Scene();
var light = new THREE.PointLight(0xffffff, 1, Infinity);
light.position.copy(camera.position);
scene.add(light);
function draw(){
light.position.copy(camera.position);
renderer.render(scene, camera);
}
trackballControl.addEventListener('change', draw);
function navStartHandler(e) {
renderer.domElement.addEventListener('mousemove', navMoveHandler);
renderer.domElement.addEventListener('mouseup', navEndHandler);
}
function navMoveHandler(e) {
trackballControl.update();
}
function navEndHandler(e) {
renderer.domElement.removeEventListener('mousemove', navMoveHandler);
renderer.domElement.removeEventListener('mouseup', navEndHandler);
}
renderer.domElement.addEventListener('mousedown', navStartHandler);
renderer.domElement.addEventListener('mousewheel', navMoveHandler);
</script>
<fieldset id="controls">
<legend>Controls</legend>
<input id="drawButton" type="button" value="DRAW" />
<input id="useStructsCheck" type="checkbox" /><label for="useStructsCheck">Use Structs</label>
</fieldset>
CSS:
html, body{
padding: 0;
margin: 0;
width: 100%;
overflow: hidden;
}
#controls {
position: absolute;
top: 20px;
left: 20px;
z-index: 99;
color: white;
border-radius: 10px;
}
#host {
width: 100%;
height: 100%;
}
JavaScript:
// NOTE: To run this demo, you MUST use the HTTP protocol, not HTTPS!
var WITH_STRUCTS = false;
var vShaderCode = [
"precision highp float;",
"precision highp int;",
"uniform mat4 modelViewMatrix;",
"uniform mat4 projectionMatrix;",
"attribute vec3 position;",
"void main() {",
"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
"gl_Position = projectionMatrix * mvPosition;",
"}"
].join("\n");
var fShaderCode_structs = [
"precision highp float;",
"precision highp int;",
"struct ColorStruct{",
"vec3 value;",
"};",
"struct OpacityStruct{",
"float value;",
"};",
"uniform ColorStruct color;",
"uniform OpacityStruct opacity;",
"void main() {",
"gl_FragColor = vec4(color.value, opacity.value);",
"}"
].join("\n");
var fShaderCode_nostructs = [
"precision highp float;",
"precision highp int;",
"uniform vec3 color;",
"uniform float opacity;",
"void main() {",
"gl_FragColor = vec4(color, opacity);",
"}"
].join("\n");
var geo = new THREE.BoxBufferGeometry(30, 30, 30);
var mat = new THREE.RawShaderMaterial({
uniforms: {
"color": { type: "c", value: new THREE.Color(0xff0000) },
"opacity": { type: "1f", value: 1.0 },
"color.value": { type: "c", value: new THREE.Color(0x00ff00) },
"opacity.value": { type: "1f", value: 1.0 }
},
vertexShader: vShaderCode,
fragmentShader: (WITH_STRUCTS) ? fShaderCode_structs : fShaderCode_nostructs
});
var msh = new THREE.Mesh(geo, mat);
scene.add(msh);
draw();
// Draw button
// Making this an external function rather than referencing draw directly, in case we want to update draw with parameters.
function doDraw() {
draw();
}
document.getElementById("drawButton").addEventListener("click", doDraw);
// Use Structs checkbox
function doStructs() {
WITH_STRUCTS = !WITH_STRUCTS;
if (WITH_STRUCTS) {
mat.fragmentShader = fShaderCode_structs;
}
else {
mat.fragmentShader = fShaderCode_nostructs;
}
mat.needsUpdate = true;
draw();
}
document.getElementById("useStructsCheck").addEventListener("click", doStructs);

This is a lesson in how a couple small and stupid mistakes can make the whole thing crash and burn.
I had named my singleton uniforms the same thing as my structured uniforms. When the uniform parser was trying to assign values, it tried to assign the singleton value onto the structure object. That didn't work, naturally, and the whole thing fell apart.
It also seems that the "alternate" uniform definition was the way to go. I'm not sure why it din't work originally, but I have a feeling it was due to a naming mismatch, like above.
Here's the working code chunks, and I've update the fiddle linked in my original post.
New Fragment Shader (only the one WITH structs)
var fShaderCode_structs = [
"precision highp float;",
"precision highp int;",
"struct ColorStruct{",
"vec3 cvalue;",
"};",
"struct OpacityStruct{",
"float ovalue;",
"};",
"uniform ColorStruct colorS;",
"uniform OpacityStruct opacityS;",
"void main() {",
"gl_FragColor = vec4(colorS.cvalue, opacityS.ovalue);",
"}"
].join("\n");
New Material Definition
var mat = new THREE.RawShaderMaterial({
uniforms: {
"color": { type: "c", value: new THREE.Color(0xff0000) },
"opacity": { type: "1f", value: 1.0 },
"colorS": {
value: { type: "c", cvalue: new THREE.Color(0x00ff00) },
},
"opacityS": {
value: { type: "1f", ovalue: 1.0 }
}
},
vertexShader: vShaderCode,
fragmentShader: (WITH_STRUCTS) ? fShaderCode_structs : fShaderCode_nostructs
});

Related

threejs radial gradient effect on a sphere

I want to do a sort of "inner glow", where a partially transparent color is more intense towards the outside of a sphere, as the user looks at it.
In plain ol' CSS it would be pretty simple:
.gradient{
height: 500px;
width: 500px;
border-radius: 50%;
box-shadow:0 0 50px 1px inset rgba(0,225,255,0.8);
background: rgba(0,225,255,0.1);
}
<div class="gradient"></div>
This tutorial has this effect, and I have a separate question here about an issue I ran into implementing if anyone else has trouble.
Some custom GL shaders: this is GL code that lives in a string to get compiled later:
const vertexShader = `
uniform vec3 viewVector;
uniform float c;
uniform float p;
varying float intensity;
void main()
{
vec3 vNormal = normalize( normalMatrix * normal );
vec3 vNormel = normalize( normalMatrix * viewVector );
intensity = pow( c - dot(vNormal, vNormel), p );
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}`;
const fragmentShader = `
uniform vec3 glowColor;
varying float intensity;
void main()
{
vec3 glow = glowColor * intensity;
gl_FragColor = vec4( glow, 1.0 );
}`;
This is the material to create the effect. Play with c and p values for intensity/depth of the "gradient".
const customMaterial = new THREE.ShaderMaterial({
uniforms: {
"c": { type: "f", value: 1.5 },
"p": { type: "f", value: 2 },
glowColor: { type: "c", value: new THREE.Color(0x00e1ff) },
viewVector: { type: "v3", value: camera.position }
},
vertexShader: vertexShader,
fragmentShader: fragmentShader,
side: THREE.FrontSide,
blending: THREE.AdditiveBlending,
transparent: true
});
You'll want to apply it to your geometry, and scalar your geometry up to the size of "shell" you desire.
const moonGlow = new THREE.Mesh( Orb, customMaterial);
moonGlow.position = moon.position;
moonGlow.scale.multiplyScalar(1.2);
scene.add( moonGlow );
Finally, facing is important. In you're changing up positions, like in an animation loop with motion controls, add this:
customMaterial.uniforms.viewVector.value = camera.position;

Threejs latest version 0.130.1 is not rendering shadermaterial

We were using Three 0.115 version and everything was working. Since we got vulnerability issues for < 0.125, we decided to upgrade to latest version. Then we are getting issues with shader material.
We have an application that uses Point cloud rendered with buffer geometry(positions, sizes and colors bufferattributes) and shadermaterial.
function vertexShader() {
return `attribute float size;
attribute vec3 customColor;
varying vec3 vColor;
attribute float visibility;
varying float vVisible;
void main() {
vColor = customColor;
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
gl_PointSize = size * ( 300.0 / -mvPosition.z );
gl_Position = projectionMatrix * mvPosition;
vVisible = visibility;
}`
}
function fragmentShader() {
return `uniform vec3 color;
uniform sampler2D pointTexture;
varying vec3 vColor;
varying float vVisible;
void main() {
gl_FragColor = vec4( color * vColor, 1.0 );
gl_FragColor = gl_FragColor * texture2D( pointTexture, gl_PointCoord );
if ( gl_FragColor.a < ALPHATEST ) discard;
if (vVisible < 0.5) discard;
}`
}
and in our javascript init code.
const material = new THREE.ShaderMaterial({
uniforms: {
color: { value: new THREE.Color(0xffffff) },
texture: { value: new THREE.TextureLoader().load(circle) },
resolution: { value: new THREE.Vector2() },
},
vertexShader: vertexShader(),
fragmentShader: fragmentShader(),
alphaTest: 0.9,
blending: THREE.AdditiveBlending
});
there is no error in console. But points are not rendered. we use raycast for detecting points and that works without any issue.
Any idea why after upgrading to latest version of three, rendering of points fails? is this something to do with shadermaterial?
Thanks for the help :)
You define the texture uniform like so:
texture: { value: new THREE.TextureLoader().load(circle) },
and in the shader you have this line
uniform sampler2D pointTexture;
I don't understand how this code ever worked since the uniform names do not match. I've aligned the names in the following example which is loosely based on your code.
let camera, scene, renderer;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 10);
camera.position.z = 3;
scene = new THREE.Scene();
const geometry = new THREE.BufferGeometry().setFromPoints([new THREE.Vector3(1, 0, 0), new THREE.Vector3()]);
const material = new THREE.ShaderMaterial({
uniforms: {
color: {
value: new THREE.Color(0xffffff)
},
pointTexture: {
value: new THREE.TextureLoader().load('https://threejs.org/examples/textures/sprite.png')
},
resolution: {
value: new THREE.Vector2()
},
},
vertexShader: vertexShader(),
fragmentShader: fragmentShader(),
alphaTest: 0.9,
blending: THREE.AdditiveBlending
});
const points = new THREE.Points(geometry, material);
scene.add(points);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
function vertexShader() {
return `
void main() {
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
gl_PointSize = ( 300.0 / -mvPosition.z );
gl_Position = projectionMatrix * mvPosition;
}`
}
function fragmentShader() {
return `
uniform sampler2D pointTexture;
void main() {
gl_FragColor = texture2D( pointTexture, gl_PointCoord );
}`
}
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.130.1/build/three.min.js"></script>

Three.js InstancedMesh: Shader is NOT changed after updating instance matrix

I am using InstancedMesh with an custom outline shader:
<script type="x-shader/x-vertex" id="vertexShader">
uniform float offset;
void main() {
vec4 pos = modelViewMatrix * vec4( position + normal * offset, 1.0 );
gl_Position = projectionMatrix * pos;
}
</script>
<script type="x-shader/x-fragment" id="fragmentShader">
uniform vec3 color;
uniform float intensity;
void main() {
gl_FragColor = vec4( color, intensity );
}
</script>
Then, I created shader material:
var uniforms = {
offset: { type: 'f', value: 0.001 },
color: { type: 'c', value: new THREE.Color(0x6B6B6B) },
intensity: { type: 'f', value: 1.0 },
};
var outlineMaterial = new THREE.ShaderMaterial( {
uniforms: uniforms,
vertexShader: document.getElementById( 'vertexShader' ).textContent,
fragmentShader: document.getElementById( 'fragmentShader' ).textContent
});
Then I created an InstancedMesh with a box geometry and this material. However, when I update instance matrix, the shader seems NOT be affected.
var dummy = new THREE.Object3D();
var outlineGometry = new THREE.BoxGeometry(1, 1, 1);
var outline = new THREE.InstancedMesh(outlineGometry, outlineMaterial, 1);
dummy.position.set(0, 0, 0);
dummy.rotation.set(0, Math.PI/4, 0);
dummy.scale.set(0.1, 0.1, 0.1);
dummy.updateMatrix();
outline.setMatrixAt( 0, dummy.matrix );
outline.instanceMatrix.needsUpdate = true;
Please check the fiddle link below: I updated the instance rotation and scale, but shader is NOT changed.
Fiddle Link
Do you know how to solve this problem?
Thanks.
According to the Westlangley suggestion, I can use instanceMatrix in vertex shader to solve the problem based on the document https://threejs.org/docs/#api/en/renderers/webgl/WebGLProgram

I Can’t get derivatives (dFdx) working in my shader with WebGL1 or 2

I hope someone can help me with this. I am at the end of my rope, having gone through all of the discussions and examples I have found and still can’t get dFdx working, neither for WebGl1 or WebGL2. Partial code is shown below.
Thanks for you help.
The fragment shader uses:
#extension GL_OES_standard_derivatives : enable
precision highp float;
varying vec3 vNormal;
varying vec2 vUv;
varying vec3 vViewPosition;
uniform vec3 color;
uniform float animateRadius;
uniform float animateStrength;
vec3 faceNormal(vec3 pos) {
vec3 fdx = vec3(dFdx(pos.x), dFdx(pos.y), dFdx(pos.z));
vec3 fdy = vec3(dFdy(pos.x), dFdy(pos.y), dFdy(pos.z));
//vec3 fdx = dFdx(pos);
//vec3 fdy = dFdy(pos);
return normalize(cross(fdx, fdy));
}
The console shows the following:
THREE.WebGLProgram: shader error: 0 35715 false gl.getProgramInfoLog Must have an compiled fragment shader attached. <empty string> THREE.WebGLShader: gl.getShaderInfoLog() fragment
WARNING: 0:2: 'GL_OES_standard_derivatives' : extension is not supported
ERROR: 0:14: 'GL_OES_standard_derivatives' : extension is not supported
ERROR: 0:14: 'GL_OES_standard_derivatives' : extension is not supported
ERROR: 0:14: 'GL_OES_standard_derivatives' : extension is not supported
ERROR: 0:15: 'GL_OES_standard_derivatives' : extension is not supported
ERROR: 0:15: 'GL_OES_standard_derivatives' : extension is not supported
ERROR: 0:15: 'GL_OES_standard_derivatives' : extension is not supported1: #define lengthSegments 300.0
2: #extension GL_OES_standard_derivatives : enable
3: precision highp float;
4:
5: varying vec3 vNormal;
6: varying vec2 vUv;
7: varying vec3 vViewPosition;
Here is also part of the Javascript:
module.exports = function (app) {
const totalMeshes = isMobile ? 30 : 40;
const isSquare = false;
const subdivisions = isMobile ? 200 : 300;
const numSides = isSquare ? 4 : 8;
const openEnded = false;
const geometry = createTubeGeometry(numSides, subdivisions, openEnded);
// add to a parent container
const container = new THREE.Object3D();
const lines = [];
//lines.length = 0;
ShaderLoader("scripts/Grp3D/Phys4646A2/tube.vert", "scripts/Grp3D/Phys4646A2/tube.frag", function (vertex, fragment) {
const baseMaterial = new THREE.RawShaderMaterial({
vertexShader: vertex,
fragmentShader: fragment,
side: THREE.FrontSide,
extensions: {
derivatives: true
},
defines: {
lengthSegments: subdivisions.toFixed(1),
ROBUST: false,
ROBUST_NORMALS: false,
FLAT_SHADED: isSquare
},
uniforms: {
thickness: { type: 'f', value: 1 },
time: { type: 'f', value: 0 },
color: { type: 'c', value: new THREE.Color('#303030') },
animateRadius: { type: 'f', value: 0 },
animateStrength: { type: 'f', value: 0 },
index: { type: 'f', value: 0 },
totalMeshes: { type: 'f', value: totalMeshes },
radialSegments: { type: 'f', value: numSides },
wavelength: { type: 'f', value: 2.0 }
}
});
for( var i = 0; i < totalMeshes; i++){
var t = totalMeshes <= 1 ? 0 : i / (totalMeshes - 1);
var material = baseMaterial.clone();
material.uniforms = THREE.UniformsUtils.clone(material.uniforms);
material.uniforms.index.value = t;
material.uniforms.thickness.value = randomFloat(0.005, 0.0075);
material.uniforms.wavelength.value = 2.0;
var mesh = new THREE.Mesh(geometry, material);
mesh.frustumCulled = false;
lines.push(mesh);
container.add(mesh);
}
});
return {
object3d: container,
update,
setPalette
};
function update (dt,wvl) {
dt = dt / 1000;
lines.forEach(mesh => {
//console.log(dt);
mesh.material.uniforms.time.value += dt;
mesh.material.uniforms.wavelength.value = wvl;
});
}
};
...
In WebGL2 with version 300 es shaders they are supported by default, no extension needed.
<canvas></canvas>
<script type="module">
import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r122/build/three.module.js';
const canvas = document.querySelector('canvas');
const renderer = new THREE.WebGLRenderer({canvas});
const material = new THREE.RawShaderMaterial({
vertexShader: `#version 300 es
in vec4 position;
out vec4 vPosition;
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * position;
vPosition = gl_Position;
}
`,
fragmentShader: `#version 300 es
precision mediump float;
in vec4 vPosition;
out vec4 outColor;
void main() {
outColor = vec4(normalize(vec3(dFdx(vPosition.x), dFdy(vPosition.y), 0)) * 0.5 + 0.5, 1);
}
`,
});
const geo = new THREE.BoxBufferGeometry();
const mesh = new THREE.Mesh(geo, material);
const scene = new THREE.Scene();
scene.add(mesh);
mesh.rotation.set(0.4, 0.4, 0);
const camera = new THREE.PerspectiveCamera(45, 2, 0.1, 10);
camera.position.z = 3;
renderer.render(scene, camera);
</script>
Note:
const fs = `#version 300 es
...
`;
Has #version 300 es as the first line
const fs = `
#version 300 es
...
`;
Has #version 300 es as the 2nd line (error)
With WebGL1 your code should work but three.js auto-chooses WebGL2 if it exists. To test WebGL1 we could force it to WebGL1 by creating the WebGL context ourselves,
const canvas = document.querySelector(selectorForCanvas);
const context = canvas.getContext('webgl');
const renderer = new THREE.WebGLRenderer({canvas, context});
Or, we can use a helper script to effectively disable webgl2
<script src="https://greggman.github.io/webgl-helpers/webgl2-disable.js"></script>
<canvas></canvas>
<script type="module">
import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r122/build/three.module.js';
const canvas = document.querySelector('canvas');
const renderer = new THREE.WebGLRenderer({canvas});
const material = new THREE.RawShaderMaterial({
vertexShader: `
attribute vec4 position;
varying vec4 vPosition;
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * position;
vPosition = gl_Position;
}
`,
fragmentShader: `
#extension GL_OES_standard_derivatives : enable
precision mediump float;
varying vec4 vPosition;
void main() {
gl_FragColor = vec4(normalize(vec3(dFdx(vPosition.x), dFdy(vPosition.y), 0)) * 0.5 + 0.5, 1);
}
`,
});
const geo = new THREE.BoxBufferGeometry();
const mesh = new THREE.Mesh(geo, material);
const scene = new THREE.Scene();
scene.add(mesh);
mesh.rotation.set(0.4, 0.4, 0);
const camera = new THREE.PerspectiveCamera(45, 2, 0.1, 10);
camera.position.z = 3;
renderer.render(scene, camera);
</script>
Otherwise you can look at renderer.capabilities.isWebGL2 to see if three.js choose WebGL2 and adjust your shaders as appropriate.
As for why your code used to work and doesn't work now, two ideas:
your machine didn't support WebGL2 before and now it does
you upgraded three.js to a version that chooses WebGL2 automatically and the previous version you were using didn't.

How to maintain the glow effect of a json model rotating in three.js scene?

I add a json model with glow effect into the scene.
As follows:
I try to rotate the json model automatically.
However, it looks weird when it is rotating.
The glow effect of the model does not work.
I assume that the position of the json model does not be changed when this model is rotating. As the result, the viewVector.value of the ShaderMaterial is constant when this model is rotating(I do not change position of the camera).
if(jsonMesh){
jsonMesh.rotation.y += 0.1;
jsonMesh.material.uniforms.viewVector.value =
new THREE.Vector3().subVectors( camera.position, jsonMesh.position );
}
This is the Three.ShaderMaterial.
VertexShader and FragmentShader
<script id="vertexShader" type="x-shader/x-vertex">
uniform vec3 viewVector;
uniform float c;
uniform float p;
varying float intensity;
void main()
{
vec3 vNormal = normalize( normalMatrix * normal );
vec3 vNormel = normalize( normalMatrix * viewVector );
intensity = pow( c - dot(vNormal, vNormel), p );
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
uniform vec3 glowColor;
varying float intensity;
void main()
{
vec3 glow = glowColor * intensity;
gl_FragColor = vec4( glow, 1.0 );
}
</script>
Three.ShaderMaterial.
var customMaterial = new THREE.ShaderMaterial(
{
uniforms:
{
"c": { type: "f", value: 1.0 },
"p": { type: "f", value: 1.4 },
glowColor: { type: "c", value: new THREE.Color(0xffff00) },
viewVector: { type: "v3", value: camera.position }
},
vertexShader: document.getElementById( 'vertexShader' ).textContent,
fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
side: THREE.FrontSide,
blending: THREE.AdditiveBlending,
transparent: true
}
);
How should I modify the code in this case?
Here is the Demo and source code.
You can use built in three.js functions for this. Instead of using the camera position, I chose to show you how to set a light source position in the world. That way you can match the light source on your custom shader to any light sources you plan to add later to your 3d world. Feel free to change the worldLightPoint value to camera.position instead of new THREE.Vector3(100,100,100). and in that case the effect will remain constant with the camera position.
var v = new THREE.Vector3();
//var worldLightPoint = camera.position;
var worldLightPoint = new THREE.Vector3(100,100,100);
function update()
{
controls.update();
stats.update();
if(jsonMesh){
jsonMesh.rotation.y += 0.1;
jsonMesh.material.uniforms.viewVector.value = jsonMesh.worldToLocal(v.copy(worldLightPoint));
}
}

Resources