Skip to content

Commit c61618d

Browse files
committed
Document createStorage
1 parent f54ec95 commit c61618d

3 files changed

Lines changed: 213 additions & 12 deletions

File tree

src/core/p5.Renderer3D.js

Lines changed: 150 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1996,7 +1996,156 @@ function renderer3D(p5, fn) {
19961996
p5.Renderer3D = Renderer3D;
19971997

19981998
/**
1999-
* Creates a storage buffer for use in compute shaders.
1999+
* Creates a <a href="#/p5/p5.StorageBuffer">`p5.StorageBuffer`</a>, which is
2000+
* a block of data that shaders can read from, and compute shaders
2001+
* can also write to. This is only available in WebGPU mode.
2002+
*
2003+
* To read or write the data inside a shader, use
2004+
* <a href="#/p5/uniformStorage">`uniformStorage()`</a>. To update its contents
2005+
* from JavaScript, call <a href="#/p5.StorageBuffer/update">`.update()`</a>
2006+
* on the result with new data.
2007+
*
2008+
* Pass an array of objects to store a list of items, each with named
2009+
* properties. The properties can be numbers, arrays of numbers, vectors
2010+
* created with <a href="#/p5/createVector">`createVector()`</a>, or colors
2011+
* created with <a href="#/p5/color">`color()`</a>. Inside the shader, each
2012+
* item is accessed by index, and its properties are available by name.
2013+
*
2014+
* ```js example
2015+
* let instanceData;
2016+
* let instancesShader;
2017+
* let instance;
2018+
* let count = 5;
2019+
*
2020+
* async function setup() {
2021+
* await createCanvas(200, 200, WEBGPU);
2022+
*
2023+
* let data = [];
2024+
* for (let i = 0; i < count; i++) {
2025+
* data.push({
2026+
* position: createVector(
2027+
* random(-1, 1) * width / 2,
2028+
* random(-1, 1) * height / 2,
2029+
* 0,
2030+
* ),
2031+
* color: color(
2032+
* random(255),
2033+
* random(255),
2034+
* random(255)
2035+
* )
2036+
* });
2037+
* }
2038+
* instanceData = createStorage(data);
2039+
* instance = buildGeometry(drawInstance);
2040+
* instancesShader = buildMaterialShader(drawInstances);
2041+
* }
2042+
*
2043+
* function drawInstance() {
2044+
* sphere(15);
2045+
* }
2046+
*
2047+
* function drawInstances() {
2048+
* let data = uniformStorage(instanceData);
2049+
* let itemColor = sharedVec4();
2050+
*
2051+
* worldInputs.begin();
2052+
* let item = data[instanceID()];
2053+
* itemColor = item.color;
2054+
* worldInputs.position += item.position;
2055+
* worldInputs.end();
2056+
*
2057+
* finalColor.begin();
2058+
* finalColor.set(itemColor);
2059+
* finalColor.end();
2060+
* }
2061+
*
2062+
* function draw() {
2063+
* background(220);
2064+
* lights();
2065+
* noStroke();
2066+
* shader(instancesShader);
2067+
* model(instance, count);
2068+
* }
2069+
* ```
2070+
*
2071+
* You can also store a plain list of numbers by passing an array of numbers.
2072+
* Inside the shader, each number is accessed by index directly. To create an
2073+
* empty list to be filled in by a compute shader, pass a count instead.
2074+
*
2075+
* ```js example
2076+
* let cells;
2077+
* let nextCells;
2078+
* let gameShader;
2079+
* let displayShader;
2080+
* const W = 100;
2081+
* const H = 100;
2082+
*
2083+
* async function setup() {
2084+
* await createCanvas(100, 100, WEBGPU);
2085+
*
2086+
* let initial = new Float32Array(W * H);
2087+
* for (let i = 0; i < initial.length; i++) {
2088+
* initial[i] = random() > 0.7 ? 1 : 0;
2089+
* }
2090+
* cells = createStorage(initial);
2091+
* nextCells = createStorage(W * H);
2092+
*
2093+
* gameShader = buildComputeShader(simulate);
2094+
* displayShader = buildFilterShader(display);
2095+
* }
2096+
*
2097+
* function simulate() {
2098+
* let current = uniformStorage(() => cells);
2099+
* let next = uniformStorage(() => nextCells);
2100+
* let w = uniformInt(() => W);
2101+
* let h = uniformInt(() => H);
2102+
* let x = index.x;
2103+
* let y = index.y;
2104+
*
2105+
* let n = 0;
2106+
* for (let dy = -1; dy <= 1; dy++) {
2107+
* for (let dx = -1; dx <= 1; dx++) {
2108+
* if (dx != 0 || dy != 0) {
2109+
* let nx = (x + dx + w) % w;
2110+
* let ny = (y + dy + h) % h;
2111+
* n += current[ny * w + nx];
2112+
* }
2113+
* }
2114+
* }
2115+
*
2116+
* let alive = current[y * w + x];
2117+
* let nextOutput = 0;
2118+
* if (alive == 1) {
2119+
* if (abs(n - 2) < 0.1 || abs(n - 3) < 0.1) {
2120+
* nextOutput = 1;
2121+
* }
2122+
* } else {
2123+
* if (abs(n - 3) < 0.1) {
2124+
* nextOutput = 1;
2125+
* }
2126+
* }
2127+
* next[y * w + x] = nextOutput;
2128+
* }
2129+
*
2130+
* function display() {
2131+
* let data = uniformStorage(() => cells);
2132+
* let w = uniformInt(() => W);
2133+
* let h = uniformInt(() => H);
2134+
*
2135+
* filterColor.begin();
2136+
* let x = floor(filterColor.texCoord.x * w);
2137+
* let y = floor(filterColor.texCoord.y * h);
2138+
* let alive = data[y * w + x];
2139+
* filterColor.set([alive, alive, alive, 1]);
2140+
* filterColor.end();
2141+
* }
2142+
*
2143+
* function draw() {
2144+
* compute(gameShader, W, H);
2145+
* [nextCells, cells] = [cells, nextCells];
2146+
* filter(displayShader);
2147+
* }
2148+
* ```
20002149
*
20012150
* @method createStorage
20022151
* @submodule p5.strands

src/strands/p5.strands.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,8 @@ if (typeof p5 !== "undefined") {
344344
* worldInputs.begin();
345345
* // Spread spheres evenly across the canvas based on their index
346346
* let spacing = width / count;
347-
* worldInputs.position.x += (instanceID() - (count - 1) / 2) * spacing;
347+
* worldInputs.position.x +=
348+
* (instanceID() - (count - 1) / 2) * spacing;
348349
* worldInputs.end();
349350
* }
350351
*
@@ -374,8 +375,16 @@ if (typeof p5 !== "undefined") {
374375
* let data = [];
375376
* for (let i = 0; i < count; i++) {
376377
* data.push({
377-
* position: createVector((i - (count - 1) / 2) * 40, 0, 0),
378-
* color: color(random(255), random(255), random(255)),
378+
* position: createVector(
379+
* random(-1, 1) * width / 2,
380+
* random(-1, 1) * height / 2,
381+
* 0,
382+
* ),
383+
* color: color(
384+
* random(255),
385+
* random(255),
386+
* random(255)
387+
* )
379388
* });
380389
* }
381390
* instanceData = createStorage(data);

src/webgl/loading.js

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -969,19 +969,15 @@ function loading(p5, fn){
969969
/**
970970
* Draws a <a href="#/p5.Geometry">p5.Geometry</a> object to the canvas.
971971
*
972-
* The parameter, `model`, is the
972+
* The first parameter, `model`, is the
973973
* <a href="#/p5.Geometry">p5.Geometry</a> object to draw.
974974
* <a href="#/p5.Geometry">p5.Geometry</a> objects can be built with
975975
* <a href="#/p5/buildGeometry">buildGeometry()</a>. They can also be loaded from
976976
* a file with <a href="#/p5/loadGeometry">loadGeometry()</a>.
977977
*
978978
* Note: `model()` can only be used in WebGL mode.
979979
*
980-
* @method model
981-
* @param {p5.Geometry} model 3D shape to be drawn.
982-
*
983-
* @param {Number} [count=1] number of instances to draw.
984-
* @example
980+
* ```js example
985981
* // Click and drag the mouse to view the scene from different angles.
986982
*
987983
* let shape;
@@ -1009,8 +1005,9 @@ function loading(p5, fn){
10091005
* function createShape() {
10101006
* cone();
10111007
* }
1008+
* ```
10121009
*
1013-
* @example
1010+
* ```js example
10141011
* // Click and drag the mouse to view the scene from different angles.
10151012
*
10161013
* let shape;
@@ -1056,8 +1053,9 @@ function loading(p5, fn){
10561053
* cylinder(3, 20);
10571054
* pop();
10581055
* }
1056+
* ```
10591057
*
1060-
* @example
1058+
* ```js example
10611059
* // Click and drag the mouse to view the scene from different angles.
10621060
*
10631061
* let shape;
@@ -1079,6 +1077,51 @@ function loading(p5, fn){
10791077
* // Draw the shape.
10801078
* model(shape);
10811079
* }
1080+
* ```
1081+
*
1082+
* Multiple instances can be drawn at once with `model(geometry, count)`. On its own,
1083+
* all the instances get drawn to the same spot, but you can use
1084+
* <a href="#/p5/instanceID">`instanceID()` inside of a shader to handle each instance.
1085+
* At large counts, this often runs faster than using a `for` loop.
1086+
*
1087+
* ```js example
1088+
* let instancesShader;
1089+
* let instance;
1090+
* let count = 5;
1091+
*
1092+
* function drawInstance() {
1093+
* sphere(15);
1094+
* }
1095+
*
1096+
* function setup() {
1097+
* createCanvas(200, 200, WEBGL);
1098+
* instance = buildGeometry(drawInstance);
1099+
* instancesShader = buildMaterialShader(drawSpaced);
1100+
* }
1101+
*
1102+
* function drawSpaced() {
1103+
* worldInputs.begin();
1104+
* // Spread spheres evenly across the canvas based on their index
1105+
* let spacing = width / count;
1106+
* worldInputs.position.x +=
1107+
* (instanceID() - (count - 1) / 2) * spacing;
1108+
* worldInputs.end();
1109+
* }
1110+
*
1111+
* function draw() {
1112+
* background(220);
1113+
* lights();
1114+
* noStroke();
1115+
* fill('red');
1116+
* shader(instancesShader);
1117+
* model(instance, count);
1118+
* }
1119+
* ```
1120+
*
1121+
* @method model
1122+
* @param {p5.Geometry} model 3D shape to be drawn.
1123+
*
1124+
* @param {Number} [count=1] number of instances to draw.
10821125
*/
10831126
fn.model = function (model, count = 1) {
10841127
this._assert3d('model');

0 commit comments

Comments
 (0)