Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ import './webgl/light';
import './webgl/loading';
import './webgl/material';
import './webgl/p5.Camera';
import './webgl/p5.DataArray';
import './webgl/p5.Geometry';
import './webgl/p5.Matrix';
import './webgl/p5.RendererGL.Immediate';
Expand Down
110 changes: 110 additions & 0 deletions src/webgl/p5.DataArray.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import p5 from '../core/main';

/**
* An internal class to store data that will be sent to a p5.RenderBuffer.
* Those need to eventually go into a Float32Array, so this class provides a
* variable-length array container backed by a Float32Array so that it can be
* sent to the GPU without allocating a new array each frame.
*
* Like a C++ vector, its fixed-length Float32Array backing its contents will
* double in size when it goes over its capacity.
*
* @example
* <div>
* <code>
* // Initialize storage with a capacity of 4
* const storage = new DataArray(4);
* console.log(storage.data.length); // 4
* console.log(storage.length); // 0
* console.log(storage.dataArray()); // Empty Float32Array
*
* storage.push(1, 2, 3, 4, 5, 6);
* console.log(storage.data.length); // 8
* console.log(storage.length); // 6
* console.log(storage.dataArray()); // Float32Array{1, 2, 3, 4, 5, 6}
* </code>
* </div>
*/
p5.DataArray = class DataArray {
constructor(initialLength = 128) {
this.length = 0;
this.data = new Float32Array(initialLength);
this.initialLength = initialLength;
}

/**
* Returns a Float32Array window sized to the exact length of the data
*/
dataArray() {
return this.subArray(0, this.length);
}

/**
* A "soft" clear, which keeps the underlying storage size the same, but
* empties the contents of its dataArray()
*/
clear() {
this.length = 0;
}

/**
* Can be used to scale a DataArray back down to fit its contents.
*/
rescale() {
if (this.length < this.data.length / 2) {
// Find the power of 2 size that fits the data
const targetLength = 1 << Math.ceil(Math.log2(this.length));
const newData = new Float32Array(targetLength);
newData.set(this.data.subarray(0, this.length), 0);
this.data = newData;
}
}

/**
* A full reset, which allocates a new underlying Float32Array at its initial
* length
*/
reset() {
this.clear();
this.data = new Float32Array(this.initialLength);
}

/**
* Adds values to the DataArray, expanding its internal storage to
* accommodate the new items.
*/
push(...values) {
this.ensureLength(this.length + values.length);
this.data.set(values, this.length);
this.length += values.length;
}

/**
* Returns a copy of the data from the index `from`, inclusive, to the index
* `to`, exclusive
*/
slice(from, to) {
return this.data.slice(from, Math.min(to, this.length));
}

/**
* Returns a mutable Float32Array window from the index `from`, inclusive, to
* the index `to`, exclusive
*/
subArray(from, to) {
return this.data.subarray(from, Math.min(to, this.length));
}

/**
* Expand capacity of the internal storage until it can fit a target size
*/
ensureLength(target) {
while (this.data.length < target) {
const newData = new Float32Array(this.data.length * 2);
newData.set(this.data, 0);
this.data = newData;
}
}
};

export default p5.DataArray;
73 changes: 37 additions & 36 deletions src/webgl/p5.Geometry.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,28 @@ import p5 from '../core/main';
* @param {Integer} [detailY] number of vertices along the y-axis.
* @param {function} [callback] function to call upon object instantiation.
*/
p5.Geometry = class {
p5.Geometry = class Geometry {
constructor(detailX, detailY, callback){
//an array containing every vertex
//@type [p5.Vector]
this.vertices = [];

//an array containing every vertex for stroke drawing
this.lineVertices = [];
this.lineVertices = new p5.DataArray();

// The tangents going into or out of a vertex on a line. Along a straight
// line segment, both should be equal. At an endpoint, one or the other
// will not exist and will be all 0. In joins between line segments, they
// may be different, as they will be the tangents on either side of the join.
this.lineTangentsIn = [];
this.lineTangentsOut = [];
this.lineTangentsIn = new p5.DataArray();
this.lineTangentsOut = new p5.DataArray();

// When drawing lines with thickness, entries in this buffer represent which
// side of the centerline the vertex will be placed. The sign of the number
// will represent the side of the centerline, and the absolute value will be
// used as an enum to determine which part of the cap or join each vertex
// represents. See the doc comments for _addCap and _addJoin for diagrams.
this.lineSides = [];
this.lineSides = new p5.DataArray();

//an array containing 1 normal per vertex
//@type [p5.Vector]
Expand All @@ -60,7 +60,7 @@ p5.Geometry = class {

// One color per line vertex, generated automatically based on
// vertexStrokeColors in _edgesToVertices()
this.lineVertexColors = [];
this.lineVertexColors = new p5.DataArray();
this.detailX = detailX !== undefined ? detailX : 1;
this.detailY = detailY !== undefined ? detailY : 1;
this.dirtyFlags = {};
Expand All @@ -72,16 +72,16 @@ p5.Geometry = class {
}

reset() {
this.lineVertices.length = 0;
this.lineTangentsIn.length = 0;
this.lineTangentsOut.length = 0;
this.lineSides.length = 0;
this.lineVertices.clear();
this.lineTangentsIn.clear();
this.lineTangentsOut.clear();
this.lineSides.clear();

this.vertices.length = 0;
this.edges.length = 0;
this.vertexColors.length = 0;
this.vertexStrokeColors.length = 0;
this.lineVertexColors.length = 0;
this.lineVertexColors.clear();
this.vertexNormals.length = 0;
this.uvs.length = 0;

Expand Down Expand Up @@ -261,10 +261,10 @@ p5.Geometry = class {
* @chainable
*/
_edgesToVertices() {
this.lineVertices.length = 0;
this.lineTangentsIn.length = 0;
this.lineTangentsOut.length = 0;
this.lineSides.length = 0;
this.lineVertices.clear();
this.lineTangentsIn.clear();
this.lineTangentsOut.clear();
this.lineSides.clear();

const potentialCaps = new Map();
const connected = new Set();
Expand Down Expand Up @@ -409,18 +409,20 @@ p5.Geometry = class {
const a = begin.array();
const b = end.array();
const dirArr = dir.array();
this.lineSides.push(1, -1, 1, 1, -1, -1);
this.lineSides.push(1, 1, -1, 1, -1, -1);
for (const tangents of [this.lineTangentsIn, this.lineTangentsOut]) {
tangents.push(dirArr, dirArr, dirArr, dirArr, dirArr, dirArr);
for (let i = 0; i < 6; i++) {
tangents.push(...dirArr);
}
}
this.lineVertices.push(a, a, b, b, a, b);
this.lineVertices.push(...a, ...b, ...a, ...b, ...b, ...a);
this.lineVertexColors.push(
fromColor,
fromColor,
toColor,
toColor,
fromColor,
toColor
...fromColor,
...toColor,
...fromColor,
...toColor,
...toColor,
...fromColor
);
return this;
}
Expand All @@ -446,12 +448,12 @@ p5.Geometry = class {
const tanInArray = tangent.array();
const tanOutArray = [0, 0, 0];
for (let i = 0; i < 6; i++) {
this.lineVertices.push(ptArray);
this.lineTangentsIn.push(tanInArray);
this.lineTangentsOut.push(tanOutArray);
this.lineVertexColors.push(color);
this.lineVertices.push(...ptArray);
this.lineTangentsIn.push(...tanInArray);
this.lineTangentsOut.push(...tanOutArray);
this.lineVertexColors.push(...color);
}
this.lineSides.push(-1, -2, 2, 2, 1, -1);
this.lineSides.push(-1, 2, -2, 1, 2, -1);
return this;
}

Expand Down Expand Up @@ -488,14 +490,13 @@ p5.Geometry = class {
const tanInArray = fromTangent.array();
const tanOutArray = toTangent.array();
for (let i = 0; i < 12; i++) {
this.lineVertices.push(ptArray);
this.lineTangentsIn.push(tanInArray);
this.lineTangentsOut.push(tanOutArray);
this.lineVertexColors.push(color);
}
for (const side of [-1, 1]) {
this.lineSides.push(side, 2 * side, 3 * side, side, 3 * side, 0);
this.lineVertices.push(...ptArray);
this.lineTangentsIn.push(...tanInArray);
this.lineTangentsOut.push(...tanOutArray);
this.lineVertexColors.push(...color);
}
this.lineSides.push(-1, -3, -2, -1, 0, -3);
this.lineSides.push(3, 1, 2, 3, 0, 1);
return this;
}

Expand Down
4 changes: 2 additions & 2 deletions src/webgl/p5.RenderBuffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ p5.RenderBuffer = class {
shader.enableAttrib(attr, this.size);
} else {
const loc = attr.location;
if (loc === -1 || !this._renderer.registerEnabled[loc]) { return; }
if (loc === -1 || !this._renderer.registerEnabled.has(loc)) { return; }
// Disable register corresponding to unused attribute
gl.disableVertexAttribArray(loc);
// Record register availability
this._renderer.registerEnabled[loc] = false;
this._renderer.registerEnabled.delete(loc);
}
}
};
Expand Down
13 changes: 3 additions & 10 deletions src/webgl/p5.RendererGL.Immediate.js
Original file line number Diff line number Diff line change
Expand Up @@ -226,15 +226,15 @@ p5.RendererGL.prototype.endShape = function(
if (this._doFill) {
if (
!this.geometryBuilder &&
this.immediateMode.geometry.vertices.length > 1
this.immediateMode.geometry.vertices.length >= 3
) {
this._drawImmediateFill();
}
}
if (this._doStroke) {
if (
!this.geometryBuilder &&
this.immediateMode.geometry.lineVertices.length > 1
this.immediateMode.geometry.lineVertices.length >= 1
) {
this._drawImmediateStroke();
}
Expand Down Expand Up @@ -499,10 +499,6 @@ p5.RendererGL.prototype._drawImmediateStroke = function() {
this._useLineColor =
(this.immediateMode.geometry.vertexStrokeColors.length > 0);

const faceCullingEnabled = gl.isEnabled(gl.CULL_FACE);
// Prevent strokes from getting removed by culling
gl.disable(gl.CULL_FACE);

const shader = this._getImmediateStrokeShader();
this._setStrokeUniforms(shader);
for (const buff of this.immediateMode.buffers.stroke) {
Expand All @@ -513,11 +509,8 @@ p5.RendererGL.prototype._drawImmediateStroke = function() {
gl.drawArrays(
gl.TRIANGLES,
0,
this.immediateMode.geometry.lineVertices.length
this.immediateMode.geometry.lineVertices.length / 3
);
if (faceCullingEnabled) {
gl.enable(gl.CULL_FACE);
}
shader.unbindShader();
};

Expand Down
16 changes: 8 additions & 8 deletions src/webgl/p5.RendererGL.Retained.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ p5.RendererGL.prototype.createBuffers = function(gId, model) {
buffers.vertexCount = model.vertices ? model.vertices.length : 0;
}

buffers.lineVertexCount = model.lineVertices ? model.lineVertices.length : 0;
buffers.lineVertexCount = model.lineVertices
? model.lineVertices.length / 3
: 0;

return buffers;
};
Expand All @@ -130,7 +132,11 @@ p5.RendererGL.prototype.drawBuffers = function(gId) {
const gl = this.GL;
const geometry = this.retainedMode.geometry[gId];

if (!this.geometryBuilder && this._doFill) {
if (
!this.geometryBuilder &&
this._doFill &&
this.retainedMode.geometry[gId].vertexCount > 0
) {
this._useVertexColor = (geometry.model.vertexColors.length > 0);
const fillShader = this._getRetainedFillShader();
this._setFillUniforms(fillShader);
Expand All @@ -148,19 +154,13 @@ p5.RendererGL.prototype.drawBuffers = function(gId) {

if (!this.geometryBuilder && this._doStroke && geometry.lineVertexCount > 0) {
this._useLineColor = (geometry.model.vertexStrokeColors.length > 0);
const faceCullingEnabled = gl.isEnabled(gl.CULL_FACE);
// Prevent strokes from getting removed by culling
gl.disable(gl.CULL_FACE);
const strokeShader = this._getRetainedStrokeShader();
this._setStrokeUniforms(strokeShader);
for (const buff of this.retainedMode.buffers.stroke) {
buff._prepareBuffer(geometry, strokeShader);
}
this._applyColorBlend(this.curStrokeColor);
this._drawArrays(gl.TRIANGLES, gId);
if (faceCullingEnabled) {
gl.enable(gl.CULL_FACE);
}
strokeShader.unbindShader();
}

Expand Down
Loading