var geometry = new THREE.Geometry();
for (var x = -50; x < 50; x++)
{
for (var z = -50; z < 50; z++)
geometry.vertices.push(new THREE.Vector3(x, 0, z));
}
ocean animation
shaders are basically stateless
pass in the same input, you always get the same output
how can we make the output change over time?
uniforms
so named because they remain constant for the entire draw call
we will pass one float into the shader each frame, representing time
every vertex will have access to this value
three.js is so great
var uniforms =
{
time: { type: 'f', value: 0 }, // f for float
};
var material = new THREE.ShaderMaterial(
{
vertexShader: document.getElementById('vs').textContent,
uniforms: uniforms,
});
// snip...
var clock = new THREE.Clock();
function render()
{
requestAnimationFrame(render);
uniforms.time.value = clock.getElapsedTime();
renderer.render(scene, camera);
}
render();
and the vertex shader
how can we make each vertex behave differently?
why can't we keep track of anything between vertices?
gpu actually processes many vertices simultaneously
attributes to the rescue
vertex declaration specifies what data is attached to each vertex
position
vec3
normal
vec3
texture coordinate
vec2
blend weights
vec4
instance transform
vec4
flux compression
float
three.js saves lives
var attributes =
{
offset: { type: 'f', value: [] },
};
var geometry = new THREE.Geometry();
for (var x = -50; x < 50; x++)
{
for (var z = -50; z < 50; z++)
{
geometry.vertices.push(new THREE.Vector3(x, 0, z));
attributes.offset.value.push((x + z) * 0.1);
}
}
var material = new THREE.ShaderMaterial(
{
vertexShader: document.getElementById('vs').textContent,
uniforms: uniforms,
attributes: attributes,
});
and the vertex shader
connecting the dots
so far we've sent individual vertices into a vertex buffer object (vbo) without connecting them
everything is made of triangles, even rectangles are constructed from two triangles
a triangle is basically three integers which point to vertices in the vbo
index buffer
the most common vertex attribute
normals
usually precalculated at design-time or during loading
of course three.js can do it for you, and even display them for debugging
let's do something fun with the normal
rasterization
automatically handled by the gpu
fragment shader
gpu program, executed for each rasterized pixel in a triangle
output is four floats (rgba) ranging from 0 to 1
baby's first fragment shader
what inputs can we have?
uniforms
data passed from the vertex shader, called "varyings"
varyings
vertex shader can output extra data to the pixel shader