Published
Edited
Dec 16, 2020
Insert cell
md`# WebGL Triangle #5: Instancing(pos, size)`
Insert cell
canvas = DOM.canvas(width, height);
Insert cell
{
// drawWithoutInstancing()
drawWithInstancing()
}
Insert cell
vao = {
const vao = gl.createVertexArray()
gl.bindVertexArray(vao)
{
// connect buffers and attributes
const numComponents = 2;
const type = gl.FLOAT;
const normalize = false;
const stride = 0;
const offset = 0;
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.vertexAttribPointer(
attributeLocations.position,
numComponents,
type,
normalize,
stride,
offset);
gl.enableVertexAttribArray(attributeLocations.position);
}
{
// connect buffers and attributes
const numComponents = 4;
const type = gl.FLOAT;
const normalize = false;
const stride = 0;
const offset = 0;
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.vertexAttribPointer(
attributeLocations.color,
numComponents,
type,
normalize,
stride,
offset);
gl.enableVertexAttribArray(attributeLocations.color);
}
{
// EBO
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebo)
}
return vao
}
Insert cell
vaoForInstancing = {
const vao = gl.createVertexArray()
gl.bindVertexArray(vao)
{
// connect buffers and attributes
const numComponents = 2;
const type = gl.FLOAT;
const normalize = false;
const stride = 0;
const offset = 0;
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.vertexAttribPointer(
attributeLocationsForInstancing.position,
numComponents,
type,
normalize,
stride,
offset);
gl.enableVertexAttribArray(attributeLocationsForInstancing.position);
}

{
// connect buffers and attributes
const numComponents = 4;
const type = gl.FLOAT;
const normalize = false;
const stride = 0;
const offset = 0;
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.vertexAttribPointer(
attributeLocationsForInstancing.color,
numComponents,
type,
normalize,
stride,
offset);
gl.enableVertexAttribArray(attributeLocationsForInstancing.color);
}

{
// connect buffers and attributes
const numComponents = 2;
const type = gl.FLOAT;
const normalize = false;
const stride = 0;
const offset = 0;
gl.bindBuffer(gl.ARRAY_BUFFER, centerPosBuffer);
gl.vertexAttribPointer(
attributeLocationsForInstancing.centerPos,
numComponents,
type,
normalize,
stride,
offset);
gl.enableVertexAttribArray(attributeLocationsForInstancing.centerPos);
gl.vertexAttribDivisor(attributeLocationsForInstancing.centerPos, 1);
}

{
// connect buffers and attributes
const numComponents = 1;
const type = gl.FLOAT;
const normalize = false;
const stride = 0;
const offset = 0;
gl.bindBuffer(gl.ARRAY_BUFFER, sizeBuffer);
gl.vertexAttribPointer(
attributeLocationsForInstancing.size,
numComponents,
type,
normalize,
stride,
offset);
gl.enableVertexAttribArray(attributeLocationsForInstancing.size);
gl.vertexAttribDivisor(attributeLocationsForInstancing.size, 1);
}

{
// EBO
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebo)
}

return vao
}
Insert cell
function drawWithInstancing() {
// clear
gl.clearColor(1., 1., 1., 1.);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

// use program
gl.useProgram(programForInstancing);

// bind VAO
gl.bindVertexArray(vaoForInstancing)

{
// connect uniforms
gl.uniform2f(uniformLocationsForInstancing.resolution, width, height);
}
// draw
const offset = 0;
const vertexCount = 6;
const indexType = gl.UNSIGNED_SHORT;
const instanceCount = transformData.centerPos.length;
gl.drawElementsInstanced(gl.TRIANGLES, vertexCount, indexType, offset, instanceCount)
}
Insert cell
function drawWithoutInstancing() {
// clear
gl.clearColor(1., 1., 1., 1.);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

// use program
gl.useProgram(program);

// bind VAO
gl.bindVertexArray(vao)

{
// connect uniforms
gl.uniform2f(uniformLocations.resolution, width, height);
}

for (let i = 0; i < transformData.centerPos.length; i++) {
gl.uniform2fv(uniformLocations.centerPos, new Float32Array(transformData.centerPos[i]));
gl.uniform1f(uniformLocations.size, transformData.size[i]);

// draw
const offset = 0;
const vertexCount = 6;
const indexType = gl.UNSIGNED_SHORT;
gl.drawElements(gl.TRIANGLES, vertexCount, indexType, offset)
}
}
Insert cell
Insert cell
indices = [
0, 1, 2,
0, 1, 3
]
Insert cell
Insert cell
centerPosBuffer = createBuffer(gl, transformData.centerPos.flat())
Insert cell
sizeBuffer = createBuffer(gl, transformData.size)
Insert cell
positionBuffer = createBuffer(gl, data.positions)
Insert cell
colorBuffer = createBuffer(gl, data.colors)
Insert cell
ebo = createIndexBuffer(gl, indices)
Insert cell
attributeLocationsForInstancing = {
return {
position: gl.getAttribLocation(programForInstancing, "in_position"),
color: gl.getAttribLocation(programForInstancing, "in_color"),
centerPos: gl.getAttribLocation(programForInstancing, "in_centerPos"),
size: gl.getAttribLocation(programForInstancing, "in_size"),
}
}
Insert cell
attributeLocations = {
return {
position: gl.getAttribLocation(program, "in_position"),
color: gl.getAttribLocation(program, "in_color")
}
}
Insert cell
uniformLocationsForInstancing = {
return {
resolution: gl.getUniformLocation(programForInstancing, "u_resolution"),
}
}
Insert cell
uniformLocations = {
return {
resolution: gl.getUniformLocation(program, "u_resolution"),
centerPos: gl.getUniformLocation(program, "u_centerPos"),
size: gl.getUniformLocation(program, "u_size"),
}
}
Insert cell
programForInstancing = createProgram(gl, vertexShaderSourceForInstancing, fragmentShaderSource)
Insert cell
program = createProgram(gl, vertexShaderSource, fragmentShaderSource)
Insert cell
gl = canvas.getContext('webgl2')
Insert cell
height = width * 0.75
Insert cell
width
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