Published
Edited
May 2, 2019
1 fork
Insert cell
Insert cell
Insert cell
{
// Creating a new buffer geometry to work on
var geometry = new THREE.BufferGeometry();

// We set up a simple triangle to work on
// Vertices axes start at the bottom left
var vertices = new Float32Array( [
//x, y, z
0, 0, 0, // bottom left
0, 1, 0, // top left
1, 1, 0, // top right
]);
// in three.js you add your vertices as 'position' attributes
geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
// We create a new basic material so that we can see the material
var material = new THREE.MeshBasicMaterial( {
color: 0xff0000, // red!
side: THREE.DoubleSide, // double sided as otherwise it might not show up if you are looking from the wrong side.
} );
// Create the mesh
const mesh = new THREE.Mesh( geometry, material );

// Render it here using the renderMesh helper function.
return renderMesh(mesh)
}
Insert cell
Insert cell
{
var geometry = new THREE.BufferGeometry();
var vertices = new Float32Array( [
0, 0, 0,
0, 1, 0,
1, 1, 0,
]);
geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
// The first thing I want to do is give this some colour using a shader.
const fragmentShader = `
void main() {
// Shaders in webgl expect gl_FragColor to be set as a vec4 value based on rgba values
gl_FragColor = vec4(
0.0, // Red
1.0, // Green
0.0, // Blue
1.0 // Alpha
);
}
`
// We now use a shader material so that we can add shaders
var material = new THREE.ShaderMaterial( {
color: 0xff0000, // red! (even though we set it to red here, it should be green as our fragment shader is making it green)
side: THREE.DoubleSide, // double sided as otherwise it might not show up if you are looking from the wrong side.
fragmentShader: fragmentShader,
} );

const mesh = new THREE.Mesh( geometry, material );
return renderMesh(mesh)
}
Insert cell
Insert cell
{
var geometry = new THREE.BufferGeometry();
var vertices = new Float32Array( [
0, 0, 0,
0, 1, 0,
1, 1, 0,
]);
geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
// Vertex shaders are responsible for the position of the vertices
// This code is run on each vertex. So in our case it is run three times.
const vertexShader = `
void main() {
vec3 newPosition = position + 0.5;

// We need to multiply our position by the projection matrix
// and model view matrix so that it comes out correctly in the
// final image.
// The returned value is the final place on the image, not in 3d space.

gl_Position = projectionMatrix *
modelViewMatrix *
vec4(newPosition, 1.0);
}
`
var material = new THREE.ShaderMaterial( {
color: 0xff0000,
side: THREE.DoubleSide,
vertexShader: vertexShader, // We are now using our vertex shader
} );

const mesh = new THREE.Mesh( geometry, material );
return renderMesh(mesh)
}
Insert cell
Insert cell
{
var geometry = new THREE.BufferGeometry();
var vertices = new Float32Array( [
0, 0, 0,
0, 1, 0,
1, 1, 0,
]);
geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
const vertexShader = `
uniform float time;

void main() {
vec3 newPosition = position + cos(time);

gl_Position = projectionMatrix *
modelViewMatrix *
vec4(newPosition, 1.0);
}
`
const uniforms = {
time: { type: "f", value: 1.0 },
}
var material = new THREE.ShaderMaterial( {
color: 0xff0000,
side: THREE.DoubleSide,
vertexShader: vertexShader,
uniforms: uniforms,
} );

const mesh = new THREE.Mesh( geometry, material );
const startTime = Date.now()
const render = meshRenderer(mesh)
while (true) {
uniforms.time.value = (startTime - Date.now())/1000
yield render()
}
}
Insert cell
md`So by now we have added the same transformation to each vertex.

How do we distinguish between individual vertices?

This is where attributes come in. We can add attributes to our material in three js. We are already using the position attribute. But we can also use any other attributes we want and give it out own data. `
Insert cell
{
var geometry = new THREE.BufferGeometry();
var vertices = new Float32Array( [
0, 0, 0,
0, 1, 0,
1, 1, 0,
]);
geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
geometry.addAttribute( 'displacement', new THREE.BufferAttribute( new Float32Array([
0, // 1st vertex
0, // 2nd vertex
.5, // 3rd vertex
]), 1 )) ;
// Vertex shaders are responsible for the position of the vertices
// This code is run on each vertex. So in our case it is run three times.
const vertexShader = `
// we have to specify that we need to load in the "displacement" attribute
attribute float displacement;
void main() {
vec3 newPosition = position + displacement;

gl_Position = projectionMatrix *
modelViewMatrix *
vec4(newPosition, 1.0);
}
`
var material = new THREE.ShaderMaterial( {
color: 0xff0000,
side: THREE.DoubleSide,
vertexShader: vertexShader, // We are now using our vertex shader
});

const mesh = new THREE.Mesh( geometry, material );
return renderMesh(mesh)
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more