Reputation: 21476
I'm trying to get a THREE.js example for version 58 to run on a current version of THREE.js - here's the original example.
There were a few errors I was able to get rid of by just commenting stuff out, but one trickier error is this:
THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead. THREE.ShaderMaterial: 'attributes' is not a property of this material.
The offending code is this:
var shaderMaterial = new THREE.ShaderMaterial( {
uniforms: uniforms,
attributes: attributes,
vertexShader: document.getElementById( 'vertexshader_lines' ).textContent,
fragmentShader: document.getElementById( 'fragmentshader_lines' ).textContent,
});
Where attributes
is defined a few lines above as:
var attributes = {
draw: { type: 'f', value: [] },
seed: { type: 'f', value: [] },
seed2: { type: 'f', value: [] },
customColor: { type: 'c', value: [] },
index2: { type: 'f', value: [] },
norm: { type: 'v3', value: [] },
};
I tried to fix this by commenting out the attributes
parameter passed to the THREE.ShaderMaterial
constructor, and instead converting the THREE.Geometry
from the original version (named lineGeo
) into a THREE.BufferedGeometry
and then passing in the attributes using its addAttribute
method, like so:
var bufferLineGeo = new THREE.BufferGeometry();
bufferLineGeo.fromGeometry(lineGeo);
var values_bColor = new Float32Array(values_color.length * 3);
var values_bNorm = new Float32Array(values_norm.length * 3);
bufferLineGeo.addAttribute('draw', new THREE.BufferAttribute(new Float32Array(values_draw), 1));
bufferLineGeo.addAttribute('seed', new THREE.BufferAttribute(new Float32Array(values_seed), 1));
bufferLineGeo.addAttribute('seed2', new THREE.BufferAttribute(new Float32Array(values_seed2), 1));
bufferLineGeo.addAttribute('customColor', new THREE.BufferAttribute(values_bColor, 3).copyColorsArray( values_color));
bufferLineGeo.addAttribute('index2', new THREE.BufferAttribute(new Float32Array(values_index2), 1));
bufferLineGeo.addAttribute('norm', new THREE.BufferAttribute(values_bNorm, 3).copyVector3sArray(values_norm));
This didn't work and I'm at a dead end now for what to try next. It renders nothing - I'm left with a black screen and nothing in the console to tell me what went wrong.
Minimal, Complete Example of it not working with current versions of THREE.js
<!doctype html>
<html lang="en">
<head>
<title>Long hair</title>
<style type="text/css">
body {
background:#000000;
}
</style>
</head>
<body>
<!--<script src="../build_r58/three.min.js"></script>-->
<script src="../js/three.min.js"></script>
<script type="x-shader/x-vertex" id="vertexshader_lines">
uniform float globalTime;
uniform vec3 gravity;
uniform vec3 gravity2;
uniform float spacing;
attribute vec3 customColor;
attribute float seed;
attribute float seed2;
attribute float draw;
attribute float index2;
attribute vec3 norm;
varying vec3 vColor;
varying float vDraw;
varying vec3 vNormal;
void main() {
vDraw = draw;
vColor = customColor;
vec3 displacement = vec3(0.0,0.0,0.0);
vec3 forceDirection = vec3(0.0,0.0,0.0);
float displacementFactor = pow(index2, 1.2);
float displacementFactor2 = pow(index2, 2.5);
float displacementFactor3 = pow(1.0-index2, 1.0);
// "gravity"
vec3 g = gravity;
g.x *= displacementFactor2*seed2;
// "wind"
forceDirection.x = sin(globalTime*0.1+seed2*5.0+index2*1.0) * 0.1*displacementFactor;
forceDirection.y = cos(globalTime*0.7+seed2*5.0+index2*1.0) * 0.1*displacementFactor3;
forceDirection.z = sin(globalTime*0.7+seed2*5.0+index2*4.0) * 0.1*displacementFactor2;
displacement = g + forceDirection + ((1.0-index2)*gravity2)*seed;
vec3 aNormal = norm;
aNormal.xyz += displacement*displacementFactor;
vNormal = norm*(1.0-index2);
vNormal += (gravity2-gravity)*0.05;
vec3 animated = position;
// curl it slightly
animated.x += aNormal.x*index2*30.0*displacementFactor3;
animated += aNormal*index2*(spacing*seed);
if (animated.y < -150.0+seed2*20.0) {
animated.y = -150.0+seed2*20.0;
vDraw = 0.0;
}
vec4 mvPosition = modelViewMatrix * vec4( animated, 1.0 );
gl_Position = projectionMatrix * mvPosition;
}
</script>
<script type="x-shader/x-fragment" id="fragmentshader_lines">
uniform vec3 color;
varying vec3 vColor;
varying float vDraw;
varying vec3 vNormal;
void main() {
if (vDraw == 0.0) {
discard;
}
float depth = gl_FragCoord.z / gl_FragCoord.w;
float fogFactor = smoothstep( 450.0, 300.0, depth );
// light
vec3 light = vec3(0.5,1.0,0.8);
float d = pow(max(0.25,dot(vNormal.xyz, light))*2.0, 1.5);
gl_FragColor = vec4( (color * vColor) * d * fogFactor, 1.0 );
}
</script>
<script>
var camera, scene, renderer;
var delta;
var time;
var oldTime;
var uniforms;
var hair;
var gravity = new THREE.Vector3(0,-5,0);
var gravity2 = new THREE.Vector3(0,-5,0);
init();
render();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 400;
camera.lookAt(scene.position);
scene.add( camera );
var attributes = {
draw: { type: 'f', value: [] },
seed: { type: 'f', value: [] },
seed2: { type: 'f', value: [] },
customColor: { type: 'c', value: [] },
index2: { type: 'f', value: [] },
norm: { type: 'v3', value: [] },
};
uniforms = {
color: { type: "c", value: new THREE.Color( 0xe4b67b ) },
globalTime: { type: "f", value: 0.0 },
gravity: { type: "v3", value: gravity },
gravity2: { type: "v3", value: gravity2 },
spacing: { type: "f", value: 25.0 },
};
var shaderMaterial = new THREE.ShaderMaterial( {
uniforms: uniforms,
//attributes: attributes,
vertexShader: document.getElementById( 'vertexshader_lines' ).textContent,
fragmentShader: document.getElementById( 'fragmentshader_lines' ).textContent,
});
shaderMaterial.linewidth = 1;
var lineGeo = new THREE.Geometry();
var radius = 15;
var num = 70;
var baseGeo = new THREE.SphereGeometry(radius, num, num, undefined, undefined, 0.2, Math.PI*0.8);
for (var i = 0; i < baseGeo.vertices.length; i++) {
baseGeo.vertices[i].x += Math.random()*4-2;
baseGeo.vertices[i].y += Math.random()*4-2;
baseGeo.vertices[i].z += Math.random()*4-2;
}
var seedArray = [];
var seedArray2 = [];
var colorArray = [];
var drawArray = [];
var index2Array = [];
var normArray = [];
for (var i = 0; i < baseGeo.vertices.length; i++) {
var num = 30;
var base = baseGeo.vertices[i];
var seed = 1+Math.random()*0.5;
var seed2 = 0.25 + Math.random()*0.75;
var norm = new THREE.Vector3().copy(base).normalize();
norm = norm.normalize();
var black = 0.65+Math.random()*0.75;
for (var j = 0; j < num; j++) {
var vertex = new THREE.Vector3().copy(base);
var color = new THREE.Color(0xffffff);
color.setRGB(1.0*black,1.0*black,1.0*black);
lineGeo.vertices.push( vertex );
colorArray.push( color );
seedArray.push( seed );
seedArray2.push( seed2 );
index2Array.push( j/num );
normArray.push( norm );
if (j == num-1 || j == 0) {
drawArray.push( 0 );
} else {
drawArray.push( 1 );
}
}
}
var vertices = lineGeo.vertices;
var values_color = attributes.customColor.value;
var values_seed = attributes.seed.value;
var values_seed2 = attributes.seed2.value;
var values_draw = attributes.draw.value;
var values_index2 = attributes.index2.value;
var values_norm = attributes.norm.value;
for( var v = 0; v < vertices.length; v++ ) {
values_seed[ v ] = seedArray[v];
values_seed2[ v ] = seedArray2[v];
values_draw[ v ] = drawArray[v];
values_color[ v ] = colorArray[v];
values_index2[ v ] = index2Array[v];
values_norm[ v ] = normArray[v];
}
var bufferLineGeo = new THREE.BufferGeometry();
bufferLineGeo.fromGeometry(lineGeo);
var values_bColor = new Float32Array(values_color.length * 3);
var values_bNorm = new Float32Array(values_norm.length * 3);
bufferLineGeo.addAttribute('draw', new THREE.BufferAttribute(new Float32Array(values_draw), 1));
bufferLineGeo.addAttribute('seed', new THREE.BufferAttribute(new Float32Array(values_seed), 1));
bufferLineGeo.addAttribute('seed2', new THREE.BufferAttribute(new Float32Array(values_seed2), 1));
bufferLineGeo.addAttribute('customColor', new THREE.BufferAttribute(values_bColor, 3).copyColorsArray( values_color));
bufferLineGeo.addAttribute('index2', new THREE.BufferAttribute(new Float32Array(values_index2), 1));
bufferLineGeo.addAttribute('norm', new THREE.BufferAttribute(values_bNorm, 3).copyVector3sArray(values_norm));
hair = new THREE.Line(bufferLineGeo,
//lineGeo,
shaderMaterial, THREE.LineStrip );
scene.add(hair);
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function render() {
requestAnimationFrame(render);
time = new Date().getTime();
delta = time - oldTime;
oldTime = time;
if (isNaN(delta) || delta > 1000 || delta == 0 ) {
delta = 1000/60;
}
uniforms.globalTime.value += delta * 0.005;
renderer.render( scene, camera );
}
</script>
</body>
</html>
Nearly Identical code as above, but successfully runs on version 58 of THREE.js
<!doctype html>
<html lang="en">
<head>
<title>Long hair</title>
<style type="text/css">
body {
background:#000000;
}
</style>
</head>
<body>
<script src="../build_r58/three.min.js"></script>
<!--<script src="../js/three.min.js"></script>-->
<script type="x-shader/x-vertex" id="vertexshader_lines">
uniform float globalTime;
uniform vec3 gravity;
uniform vec3 gravity2;
uniform float spacing;
attribute vec3 customColor;
attribute float seed;
attribute float seed2;
attribute float draw;
attribute float index2;
attribute vec3 norm;
varying vec3 vColor;
varying float vDraw;
varying vec3 vNormal;
void main() {
vDraw = draw;
vColor = customColor;
vec3 displacement = vec3(0.0,0.0,0.0);
vec3 forceDirection = vec3(0.0,0.0,0.0);
float displacementFactor = pow(index2, 1.2);
float displacementFactor2 = pow(index2, 2.5);
float displacementFactor3 = pow(1.0-index2, 1.0);
// "gravity"
vec3 g = gravity;
g.x *= displacementFactor2*seed2;
// "wind"
forceDirection.x = sin(globalTime*0.1+seed2*5.0+index2*1.0) * 0.1*displacementFactor;
forceDirection.y = cos(globalTime*0.7+seed2*5.0+index2*1.0) * 0.1*displacementFactor3;
forceDirection.z = sin(globalTime*0.7+seed2*5.0+index2*4.0) * 0.1*displacementFactor2;
displacement = g + forceDirection + ((1.0-index2)*gravity2)*seed;
vec3 aNormal = norm;
aNormal.xyz += displacement*displacementFactor;
vNormal = norm*(1.0-index2);
vNormal += (gravity2-gravity)*0.05;
vec3 animated = position;
// curl it slightly
animated.x += aNormal.x*index2*30.0*displacementFactor3;
animated += aNormal*index2*(spacing*seed);
if (animated.y < -150.0+seed2*20.0) {
animated.y = -150.0+seed2*20.0;
vDraw = 0.0;
}
vec4 mvPosition = modelViewMatrix * vec4( animated, 1.0 );
gl_Position = projectionMatrix * mvPosition;
}
</script>
<script type="x-shader/x-fragment" id="fragmentshader_lines">
uniform vec3 color;
varying vec3 vColor;
varying float vDraw;
varying vec3 vNormal;
void main() {
if (vDraw == 0.0) {
discard;
}
float depth = gl_FragCoord.z / gl_FragCoord.w;
float fogFactor = smoothstep( 450.0, 300.0, depth );
// light
vec3 light = vec3(0.5,1.0,0.8);
float d = pow(max(0.25,dot(vNormal.xyz, light))*2.0, 1.5);
gl_FragColor = vec4( (color * vColor) * d * fogFactor, 1.0 );
}
</script>
<script>
var camera, scene, renderer;
var delta;
var time;
var oldTime;
var uniforms;
var hair;
var gravity = new THREE.Vector3(0,-5,0);
var gravity2 = new THREE.Vector3(0,-5,0);
init();
render();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 400;
camera.lookAt(scene.position);
scene.add( camera );
var attributes = {
draw: { type: 'f', value: [] },
seed: { type: 'f', value: [] },
seed2: { type: 'f', value: [] },
customColor: { type: 'c', value: [] },
index2: { type: 'f', value: [] },
norm: { type: 'v3', value: [] },
};
uniforms = {
color: { type: "c", value: new THREE.Color( 0xe4b67b ) },
globalTime: { type: "f", value: 0.0 },
gravity: { type: "v3", value: gravity },
gravity2: { type: "v3", value: gravity2 },
spacing: { type: "f", value: 25.0 },
};
var shaderMaterial = new THREE.ShaderMaterial( {
uniforms: uniforms,
attributes: attributes,
vertexShader: document.getElementById( 'vertexshader_lines' ).textContent,
fragmentShader: document.getElementById( 'fragmentshader_lines' ).textContent,
});
shaderMaterial.linewidth = 1;
var lineGeo = new THREE.Geometry();
var radius = 15;
var num = 70;
var baseGeo = new THREE.SphereGeometry(radius, num, num, undefined, undefined, 0.2, Math.PI*0.8);
for (var i = 0; i < baseGeo.vertices.length; i++) {
baseGeo.vertices[i].x += Math.random()*4-2;
baseGeo.vertices[i].y += Math.random()*4-2;
baseGeo.vertices[i].z += Math.random()*4-2;
}
var seedArray = [];
var seedArray2 = [];
var colorArray = [];
var drawArray = [];
var index2Array = [];
var normArray = [];
for (var i = 0; i < baseGeo.vertices.length; i++) {
var num = 30;
var base = baseGeo.vertices[i];
var seed = 1+Math.random()*0.5;
var seed2 = 0.25 + Math.random()*0.75;
var norm = new THREE.Vector3().copy(base).normalize();
norm = norm.normalize();
var black = 0.65+Math.random()*0.75;
for (var j = 0; j < num; j++) {
var vertex = new THREE.Vector3().copy(base);
var color = new THREE.Color(0xffffff);
color.setRGB(1.0*black,1.0*black,1.0*black);
lineGeo.vertices.push( vertex );
colorArray.push( color );
seedArray.push( seed );
seedArray2.push( seed2 );
index2Array.push( j/num );
normArray.push( norm );
if (j == num-1 || j == 0) {
drawArray.push( 0 );
} else {
drawArray.push( 1 );
}
}
}
var vertices = lineGeo.vertices;
var values_color = attributes.customColor.value;
var values_seed = attributes.seed.value;
var values_seed2 = attributes.seed2.value;
var values_draw = attributes.draw.value;
var values_index2 = attributes.index2.value;
var values_norm = attributes.norm.value;
for( var v = 0; v < vertices.length; v++ ) {
values_seed[ v ] = seedArray[v];
values_seed2[ v ] = seedArray2[v];
values_draw[ v ] = drawArray[v];
values_color[ v ] = colorArray[v];
values_index2[ v ] = index2Array[v];
values_norm[ v ] = normArray[v];
}
/*var bufferLineGeo = new THREE.BufferGeometry();
bufferLineGeo.fromGeometry(lineGeo);
var values_bColor = new Float32Array(values_color.length * 3);
var values_bNorm = new Float32Array(values_norm.length * 3);
bufferLineGeo.addAttribute('draw', new THREE.BufferAttribute(new Float32Array(values_draw), 1));
bufferLineGeo.addAttribute('seed', new THREE.BufferAttribute(new Float32Array(values_seed), 1));
bufferLineGeo.addAttribute('seed2', new THREE.BufferAttribute(new Float32Array(values_seed2), 1));
bufferLineGeo.addAttribute('customColor', new THREE.BufferAttribute(values_bColor, 3).copyColorsArray( values_color));
bufferLineGeo.addAttribute('index2', new THREE.BufferAttribute(new Float32Array(values_index2), 1));
bufferLineGeo.addAttribute('norm', new THREE.BufferAttribute(values_bNorm, 3).copyVector3sArray(values_norm));*/
hair = new THREE.Line(//bufferLineGeo,
lineGeo,
shaderMaterial, THREE.LineStrip );
scene.add(hair);
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function render() {
requestAnimationFrame(render);
time = new Date().getTime();
delta = time - oldTime;
oldTime = time;
if (isNaN(delta) || delta > 1000 || delta == 0 ) {
delta = 1000/60;
}
uniforms.globalTime.value += delta * 0.005;
renderer.render( scene, camera );
}
</script>
</body>
</html>
You can get a copy of three.min.js for version 58 here.
You can get the current version of three.min.js from here.
Upvotes: 1
Views: 2668
Reputation: 104783
This line
bufferLineGeo.fromGeometry( lineGeo );
will not populate the position attribute if no faces are defined.
Do this instead
var positions = new Float32Array( vertices.length * 3 );
bufferLineGeo.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ).copyVector3sArray( vertices ) );
three.js r.89
Upvotes: 2