Skip to content

Commit

Permalink
Move buffering into util
Browse files Browse the repository at this point in the history
  • Loading branch information
mikekucera committed Jun 21, 2024
1 parent daa575f commit 7f1cab2
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 136 deletions.
117 changes: 43 additions & 74 deletions src/extensions/renderer/canvas/webgl/drawing-edges-webgl.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,55 +83,35 @@ export class EdgeDrawing {
const vao = gl.createVertexArray();
gl.bindVertexArray(vao);

{ // vertices
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(instanceGeometry), gl.STATIC_DRAW);
gl.vertexAttribPointer(program.aPosition, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(program.aPosition);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
}

const stride = 2 * 4; // 2 vertices * 4 bytes
{ // source points
this.sourceData = new Float32Array(this.maxInstances * 2);
this.sourceBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.sourceBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this.maxInstances * stride, gl.DYNAMIC_DRAW);
gl.enableVertexAttribArray(program.aSource);
gl.vertexAttribPointer(program.aSource, 2, gl.FLOAT, false, this.sourceBuffer.stride, 0);
gl.vertexAttribDivisor(program.aSource, 1);
}
{ // target points
this.targetData = new Float32Array(this.maxInstances * 2);
this.targetBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.targetBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this.maxInstances * stride, gl.DYNAMIC_DRAW);
gl.enableVertexAttribArray(program.aTarget);
gl.vertexAttribPointer(program.aTarget, 2, gl.FLOAT, false, stride, 0);
gl.vertexAttribDivisor(program.aTarget, 1);
}

{ // widths
this.widthData = new Float32Array(this.maxInstances);
this.widthBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.widthBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this.maxInstances * 4, gl.DYNAMIC_DRAW);
gl.enableVertexAttribArray(program.aWidth);
gl.vertexAttribPointer(program.aWidth, 1, gl.FLOAT, false, 4, 0);
gl.vertexAttribDivisor(program.aWidth, 1);
}

// TODO allow different color for source and target
{ // colors
this.colorData = new Float32Array(this.maxInstances * 4);
this.colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this.maxInstances * 4 * 4, gl.DYNAMIC_DRAW);
gl.enableVertexAttribArray(program.aColor);
gl.vertexAttribPointer(program.aColor, 4, gl.FLOAT, false, 4 * 4, 0);
gl.vertexAttribDivisor(program.aColor, 1);
}
util.createFloatBufferStaticDraw(gl, {
attributeLoc: program.aPosition,
dataArray: instanceGeometry,
size: 2
});

this.sourceBuffer = util.createFloatBufferDynamicDraw(gl, {
attributeLoc: program.aSource,
maxInstances: this.maxInstances,
size: 2
});

this.targetBuffer = util.createFloatBufferDynamicDraw(gl, {
attributeLoc: program.aTarget,
maxInstances: this.maxInstances,
size: 2
});

this.widthBuffer = util.createFloatBufferDynamicDraw(gl, {
attributeLoc: program.aWidth,
maxInstances: this.maxInstances,
size: 1
});

this.colorBuffer = util.createFloatBufferDynamicDraw(gl, {
attributeLoc: program.aColor,
maxInstances: this.maxInstances,
size: 4
});

gl.bindVertexArray(null);
return vao;
Expand All @@ -142,8 +122,6 @@ export class EdgeDrawing {
this.panZoomMatrix = panZoomMatrix;
}
this.instanceCount = 0;
this.sourcePoints = [];
this.targetPoints = [];
}


Expand All @@ -159,10 +137,11 @@ export class EdgeDrawing {

const width = edge.pstyle('width').pfValue;

this.sourceData.set([sp.x, sp.y], this.instanceCount * 2);
this.targetData.set([tp.x, tp.y], this.instanceCount * 2);
this.widthData.set([width], this.instanceCount);
this.colorData.set([r, g, b, a], this.instanceCount * 4);
const i = this.instanceCount;
this.sourceBuffer.setDataAt([sp.x, sp.y], i);
this.targetBuffer.setDataAt([tp.x, tp.y], i);
this.widthBuffer.setDataAt([width], i);
this.colorBuffer.setDataAt([r, g, b, a], i);

this.instanceCount++;

Expand All @@ -173,37 +152,27 @@ export class EdgeDrawing {


endBatch() {
if(this.instanceCount === 0)
const count = this.instanceCount;
if(count === 0)
return;

console.log('drawing edges', this.instanceCount);
console.log('drawing edges', count);
const { gl, program, vao } = this;

gl.useProgram(program);
gl.bindVertexArray(vao);

// TODO bufferSubData calls should only buffer this.instanceCount amount of data
// source points
gl.bindBuffer(gl.ARRAY_BUFFER, this.sourceBuffer);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.sourceData); //, 0, this.instanceCount * 2);

// target points
gl.bindBuffer(gl.ARRAY_BUFFER, this.targetBuffer);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.targetData);

// widths
gl.bindBuffer(gl.ARRAY_BUFFER, this.widthBuffer);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.widthData);

// colors
gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.colorData);
// buffer the attribute data
this.sourceBuffer.bufferSubData(count);
this.targetBuffer.bufferSubData(count);
this.widthBuffer.bufferSubData(count);
this.colorBuffer.bufferSubData(count);

// Set the projection matrix uniform
gl.uniformMatrix3fv(program.uPanZoomMatrix, false, this.panZoomMatrix);

// draw!
gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, this.instanceCount); // 6 verticies per edge
gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, count); // 6 verticies per edge

gl.bindVertexArray(null);

Expand Down
88 changes: 27 additions & 61 deletions src/extensions/renderer/canvas/webgl/drawing-nodes-webgl.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,46 +111,22 @@ export class NodeDrawing {
const vao = gl.createVertexArray();
gl.bindVertexArray(vao);

{ // node quad
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(unitQuad), gl.STATIC_DRAW);
gl.vertexAttribPointer(program.aPosition, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(program.aPosition);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
}
{ // texture coords
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(texQuad), gl.STATIC_DRAW);
gl.vertexAttribPointer(program.aTexCoord, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(program.aTexCoord);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
}
{ // matrix data
const matrixSize = 9; // 3x3 matrix
this.matrixData = new Float32Array(this.maxInstances * matrixSize);

// use matrix views to set values directly into the matrixData array
this.matrixViews = new Array(this.maxInstances);
for(let i = 0; i < this.maxInstances; i++) {
const byteOffset = i * matrixSize * 4; // 4 bytes per float
this.matrixViews[i] = new Float32Array(this.matrixData.buffer, byteOffset, matrixSize); // array view
}

this.matrixBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.matrixBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this.matrixData.byteLength, gl.DYNAMIC_DRAW);

// each row of the matrix needs to be a separate attribute
for(let i = 0; i < 3; i++) {
const loc = program.aNodeMatrix + i;
gl.enableVertexAttribArray(loc);
gl.vertexAttribPointer(loc, 3, gl.FLOAT, false, 3 * 12, i * 12);
gl.vertexAttribDivisor(loc, 1);
}
gl.bindBuffer(gl.ARRAY_BUFFER, null);
}
util.createFloatBufferStaticDraw(gl, {
attributeLoc: program.aPosition,
dataArray: unitQuad,
size: 2
});

util.createFloatBufferStaticDraw(gl, {
attributeLoc: program.aTexCoord,
dataArray: texQuad,
size: 2
});

this.matrixBuffer = util.create3x3MatrixBufferDynamicDraw(gl, {
attributeLoc: program.aNodeMatrix,
maxInstances: this.maxInstances
});

gl.bindVertexArray(null);
return vao;
Expand Down Expand Up @@ -178,22 +154,11 @@ export class NodeDrawing {
return textureCanvas;
}

function bufferTexture(textureCanvas) {
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize, texSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, textureCanvas);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
gl.generateMipmap(gl.TEXTURE_2D); // important!
gl.bindTexture(gl.TEXTURE_2D, null);
return texture;
}

const styleKey = opts.getKey(node);
let texture = this.styleKeyToTexture.get(styleKey);
if(!texture) {
const canvas = drawTextureCanvas();
texture = bufferTexture(canvas);
texture = util.bufferTexture(gl, texSize, canvas);
this.styleKeyToTexture.set(styleKey, texture);
texture.styleKey = styleKey; // for debug
}
Expand Down Expand Up @@ -239,12 +204,14 @@ export class NodeDrawing {
draw(node, type) {
const opts = this.renderTypes.get(type);

// pass the array view to setTransformMatrix, no need to create a new instance every draw call
const matrixView = this.matrixViews[this.instanceCount];
// pass the array view to setTransformMatrix
const matrixView = this.matrixBuffer.getMatrixView(this.instanceCount);
this.setTransformMatrix(node, opts, matrixView);

// create the texture if needed
const texture = this.createTexture(node, opts);
this.textures.push(texture);

this.instanceCount++;

if(this.instanceCount >= this.maxInstances) {
Expand All @@ -253,22 +220,21 @@ export class NodeDrawing {
}

endBatch() {
if(this.instanceCount === 0)
const count = this.instanceCount;
if(count === 0)
return;

console.log('drawing nodes', this.instanceCount);
console.log('drawing nodes', count);
const { gl, program, vao } = this;

gl.useProgram(program);
gl.bindVertexArray(vao);

// upload the new matrix data
gl.bindBuffer(gl.ARRAY_BUFFER, this.matrixBuffer);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.matrixData);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
this.matrixBuffer.bufferSubData();

// Activate all the texture units that we need
for(let i = 0; i < this.instanceCount; i++) {
for(let i = 0; i < count; i++) {
gl.activeTexture(gl.TEXTURE0 + i);
gl.bindTexture(gl.TEXTURE_2D, this.textures[i]);
gl.uniform1i(program.uTextures[i], i);
Expand All @@ -278,7 +244,7 @@ export class NodeDrawing {
gl.uniformMatrix3fv(program.uPanZoomMatrix, false, this.panZoomMatrix);

// draw!
gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, this.instanceCount); // 6 verticies per node
gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, count); // 6 verticies per node

gl.bindVertexArray(null);
gl.bindTexture(gl.TEXTURE_2D, null); // TODO is this right when having multiple texture units?
Expand Down
Loading

0 comments on commit 7f1cab2

Please sign in to comment.