Skip to content
Open
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
82 changes: 42 additions & 40 deletions examples/multi-draw-instanced.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@ import createContext from "../index.js";
import { perspective as createCamera, orbiter as createOrbiter } from "pex-cam";
import createGUI from "pex-gui";

import { cube, sphere, torus } from "primitive-geometry";
import { cube, plane, sphere, torus } from "primitive-geometry";
import typedArrayConcat from "typed-array-concat";
import merge from "geom-merge";
import splitVertices from "geom-split-vertices";
import computeNormals from "geom-normals";
import gridCells from "grid-cells";

import { viewportToCanvasPosition } from "./utils.js";
import basicFrag from "./shaders/basic.frag.js";
import basicMultiDrawVert from "./shaders/basic-multi-draw.vert.js";
import basicFrag from "./shaders/basic.frag.js";

const pixelRatio = devicePixelRatio;
const ctx = (window.ctx = createContext({ pixelRatio, debug: false }));
const ctx = createContext({ pixelRatio, debug: false });

const gui = createGUI(ctx, { theme: { columnWidth: 340 } });

Expand All @@ -37,49 +37,29 @@ const camera = createCamera({
position: [3, 1, 3],
target: [3, 0, 0],
});
createOrbiter({ camera });
createOrbiter({ camera, element: ctx.gl.canvas });

// Create geometries
const size = 0.3;
const planeGeometry = plane();
const sphereGeometry = sphere({ radius: size / 2 });
sphereGeometry.positions = sphereGeometry.positions.map((value, i) =>
i % 3 === 0 ? value - size * 1.2 : value,
);
const unindexedSphere = splitVertices(
sphereGeometry.positions,
sphereGeometry.cells,
);
const cubeGeometry = cube({ sx: size });
const unindexedCube = splitVertices(cubeGeometry.positions, cubeGeometry.cells);
const torusGeometry = torus({
radius: size * 0.5,
minorRadius: size * 0.5 * 0.4,
});
torusGeometry.positions = torusGeometry.positions.map((value, i) =>
i % 3 === 0 ? value + size * 1.2 : value,
);
const unindexedTorus = splitVertices(
torusGeometry.positions,
torusGeometry.cells,
);

const geometries = [sphereGeometry, cubeGeometry, torusGeometry];
const unindexedGeometries = [unindexedSphere, unindexedCube, unindexedTorus];
// if (unindexed) {
// geometries.forEach((geometry) => {
// geometry.normals = computeNormals(geometry.positions, geometry.cells);
// });
// }
const geometries = [planeGeometry, sphereGeometry, cubeGeometry, torusGeometry];
const unindexedGeometries = geometries.map((geometry) =>
splitVertices(geometry.positions, geometry.cells),
);
const indexedMergedGeometry = merge(geometries);
// const indexedMergedGeometry = {
// positions: typedArrayConcat(
// Float32Array,
// ...geometries.map((g) => g.positions)
// ),
// normals: typedArrayConcat(Float32Array, ...geometries.map((g) => g.normals)),
// // uvs: typedArrayConcat(Float32Array, ...geometries.map((g) => g.uvs)),
// cells: typedArrayConcat(CellsConstructor, ...geometries.map((g) => g.cells)),
// };
const unindexedMergedGeometry = merge(unindexedGeometries);

// Buffers
Expand All @@ -94,15 +74,15 @@ const offsets = new Int32Array(geometries.length);
const firsts = new Int32Array(geometries.length);
const baseVertices = new Int32Array(geometries.length);
const baseInstances = new Int32Array(geometries.length);
const instanceCounts = new Int32Array([3, 6, 9]); // 3 spheres, 6 cubes, 9 torii
const instanceCounts = new Int32Array([1, 3, 6, 9]); // 1 plane, 3 spheres, 6 cubes, 9 torii

const instancePositions = []; // 3 + 6 + 9 = 18 positions

for (let i = 0; i < geometries.length; i++) {
const numInstancesOfEachGeometry = instanceCounts[i];
for (let j = 0; j < numInstancesOfEachGeometry; j++) {
instancePositions.push([j, i, 0]);
// instancePositions.push([j - 3, i - (geometries.length - 1) / 2, 0]);
// instancePositions.push([j, i, 0]);
instancePositions.push([j - 3, i - (geometries.length - 1) / 2, 0]);
}

counts[i] = geometries[i].cells.length;
Expand All @@ -124,6 +104,9 @@ for (let i = 0; i < geometries.length; i++) {
}
}

// Ignore first geometry to test offsets
instancePositions.shift();

const instancedOffsets = ctx.vertexBuffer(instancePositions);

// Commands
Expand Down Expand Up @@ -161,6 +144,20 @@ ${basicMultiDrawVert}`,
uViewMatrix: camera.viewMatrix,
},
};
const drawInstancedBaseCmd = {
pipeline: ctx.pipeline({
depthTest: true,
vert: /* glsl */ `
${ctx.capabilities.multiDrawInstancedBase ? "#define USE_MULTI_DRAW_INSTANCED_BASE" : ""}
#define USE_INSTANCED_OFFSET
${basicMultiDrawVert}`,
frag: basicFrag,
}),
uniforms: {
uProjectionMatrix: camera.projectionMatrix,
uViewMatrix: camera.viewMatrix,
},
};

const commands = {
"MultiDraw Indexed": {
Expand Down Expand Up @@ -202,7 +199,7 @@ const commands = {
// Ignore first geometry to test offsets
countsOffset: 1,
offsetsOffset: 1,
instanceCountsOffset: 1,
instanceCountsOffset: 1, // offset in instanceCounts array
drawCount: geometries.length - 1,
},
},
Expand Down Expand Up @@ -274,14 +271,19 @@ ctx.frame(() => {
headers[header].setPosition(
...viewportToCanvasPosition(cell, H, pixelRatio).map((n) => n + 10),
);
ctx.submit(
options.multiDraw.instanceCounts ? drawInstancedCmd : drawCmd,
{
viewport: cell,
scissor: cell,
...options,
},
const hasBaseInstances = !!(
options.multiDraw.baseInstances || options.multiDraw.baseVertices
);
const cmd = options.multiDraw.instanceCounts
? hasBaseInstances
? drawInstancedBaseCmd
: drawInstancedCmd
: drawCmd;
ctx.submit(cmd, {
viewport: cell,
scissor: cell,
...options,
});
}
});

Expand Down
42 changes: 6 additions & 36 deletions examples/multi-draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ import { plane, cube, sphere, torus } from "primitive-geometry";
import merge from "geom-merge";
import splitVertices from "geom-split-vertices";

import basicMultiDrawVert from "./shaders/basic-multi-draw.vert.js";
import basicFrag from "./shaders/basic.frag.js";

const ctx = createContext({ pixelRatio: devicePixelRatio });

const camera = createCamera({
position: [0, 0, 3],
});
createOrbiter({ camera });
createOrbiter({ camera, element: ctx.gl.canvas });

const clearCmd = {
pass: ctx.pass({
Expand All @@ -28,20 +29,20 @@ const unindexed = true;
const planeGeometry = plane();
const sphereGeometry = sphere();
sphereGeometry.positions = sphereGeometry.positions.map((value, i) =>
i % 3 === 0 ? value - 1.25 : value
i % 3 === 0 ? value - 1.25 : value,
);
const torusGeometry = torus();
const cubeGeometry = cube();
cubeGeometry.positions = cubeGeometry.positions.map((value, i) =>
i % 3 === 0 ? value + 1.25 : value
i % 3 === 0 ? value + 1.25 : value,
);
const geometries = [
planeGeometry,
sphereGeometry,
torusGeometry,
cubeGeometry,
].map((geometry) =>
unindexed ? splitVertices(geometry.positions, geometry.cells) : geometry
unindexed ? splitVertices(geometry.positions, geometry.cells) : geometry,
);

const geometry = merge(geometries);
Expand All @@ -68,44 +69,13 @@ if (unindexed) {
}
}
}
console.log("geometry", geometry);
console.log("counts", counts);
console.log("offsets", offsets);
console.log("firsts", firsts);

const drawCmd = {
pipeline: ctx.pipeline({
depthTest: true,
vert: /* glsl */ `
${ctx.capabilities.multiDraw ? "#define USE_MULTI_DRAW" : ""}
#ifdef USE_MULTI_DRAW
#extension GL_ANGLE_multi_draw: require
#endif

attribute vec3 aPosition;

uniform mat4 uProjectionMatrix;
uniform mat4 uViewMatrix;

varying vec4 vColor;

void main () {
#ifdef USE_MULTI_DRAW
if (gl_DrawID == 0) {
vColor = vec4(1.0, 0.5, 0.5, 1.0);
} else if (gl_DrawID == 1) {
vColor = vec4(0.5, 1.0, 0.5, 1.0);
} else if (gl_DrawID == 2) {
vColor = vec4(0.5, 0.5, 1.0, 1.0);
} else {
vColor = vec4(1.0, 1.0, 0.5, 1.0);
}
#else
vColor = vec4(1.0, 1.0, 1.0, 1.0);
#endif

gl_Position = uProjectionMatrix * uViewMatrix * vec4(aPosition, 1.0);
}`,
${basicMultiDrawVert}`,
frag: basicFrag,
}),
attributes: {
Expand Down
9 changes: 4 additions & 5 deletions examples/shaders/basic-multi-draw.vert.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
export default /* glsl */ `
#ifdef USE_MULTI_DRAW
#if defined(USE_MULTI_DRAW) || defined(USE_MULTI_DRAW_INSTANCED_BASE)
#extension GL_ANGLE_multi_draw: require
#else
uniform highp int uDrawID;
#define gl_DrawID uDrawID
#endif

attribute vec3 aPosition;
Expand All @@ -21,7 +24,6 @@ void main () {
position.xyz += aOffset;
#endif

#ifdef USE_MULTI_DRAW
if (gl_DrawID == 0) {
vColor = vec4(1.0, 0.5, 0.5, 1.0);
} else if (gl_DrawID == 1) {
Expand All @@ -31,9 +33,6 @@ void main () {
} else {
vColor = vec4(1.0, 1.0, 0.5, 1.0);
}
#else
vColor = vec4(1.0, 1.0, 1.0, 1.0);
#endif

gl_Position = uProjectionMatrix * uViewMatrix * position;
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,6 @@
"engines": {
"node": ">=22.0.0",
"npm": ">=10.5.1",
"snowdev": ">=2.5.x"
"snowdev": ">=2.7.x"
}
}
Loading