Skip to content

[WIP] Docs: Add initial draft of Strands documentation (feedback wanted) #7940

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: dev-2.0
Choose a base branch
from
Open
Changes from 2 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
156 changes: 156 additions & 0 deletions src/webgl/ShaderGenerator.js
Original file line number Diff line number Diff line change
Expand Up @@ -1638,3 +1638,159 @@ export default shadergenerator;
if (typeof p5 !== 'undefined') {
p5.registerAddon(shadergenerator)
}



/* ------------------------------------------------------------- */
/**
* @typedef {Object} Vertex
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also not sure that typedef docs will show up in the reference, even though this does simplify the writing of the function parameter. If you test your branch on the p5.js-website repo, what does this look like? If it doesn't render, we may need to either document this object inline, or update the website to be able to support this syntax.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@davepagurek Thank you for the guidance on the @typedef issue. I've removed it and documented the vertex object properties inline in the parameter description to ensure clarity and compatibility with the documentation pipeline.

* @property {{x: number, y: number, z: number}} position - The position of the vertex in world space.
* @property {{x: number, y: number, z: number}} normal - The normal vector at the vertex in world space.
* @property {{x: number, y: number}} texCoord - The texture coordinates (x, y) for the vertex.
* @property {{r: number, g: number, b: number, a: number}} color - The color at the vertex.
*/

/**
* @function getWorldInputs
* @experimental
* @description
* Registers a callback to modify the world-space properties of each vertex in a shader. This hook can be used inside {@link p5.baseMaterialShader}.modify() and similar shader modify calls to customize vertex positions, normals, texture coordinates, and colors before rendering. "World space" refers to the coordinate system of the 3D scene, before any camera or projection transformations are applied.
*
* This hook is available in:
* - {@link p5.baseMaterialShader}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think although this is valid JSDoc, we don't yet support it in p5's jsdoc-to-reference pipeline. Currently we use <a href="...">, e.g.:

* <a href="#/p5/setup">setup()</a> before using the result.

Copy link
Author

@Abhayaj247 Abhayaj247 Jun 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @davepagurek ,
I've updated all references to use the <a href="..."> syntax that p5.js supports, following the pattern from p5.Font.js. All links now use the format <a href="#/p5/baseMaterialShader">baseMaterialShader()</a>.

* - {@link p5.baseNormalShader}
* - {@link p5.baseColorShader}
* - {@link p5.baseStrokeShader}
*
* @param {function(Vertex): Vertex} callback
* A callback function which receives and returns a Vertex struct.
*
* @see {@link p5.baseMaterialShader}
* @see {@link p5.Shader#modify}
*
* @example
* <div modernizr='webgl'>
* <code>
* let myShader;
* function setup() {
* createCanvas(200, 200, WEBGL);
* myShader = baseMaterialShader().modify(() => {
* getWorldInputs(inputs => {
* // Move the vertex up and down in a wave
* inputs.position.y += 20 * sin(
* millis() * 0.001 + inputs.position.x * 0.05
* );
* return inputs;
* });
* });
* }
* function draw() {
* background(255);
* shader(myShader);
* lights();
* noStroke();
* fill('red');
* sphere(50);
* }
* </code>
* </div>
*/

/**
* @function combineColors
* @experimental
* @description
* Registers a callback to customize how color components are combined in the fragment shader. This hook can be used inside {@link p5.baseMaterialShader}.modify() and similar shader modify calls to control the final color output of a material. The callback receives a ColorComponents struct and should return an object with a `color` property ({ r, g, b }) and an `opacity` property (number).
*
* This hook is available in:
* - {@link p5.baseMaterialShader}
* - {@link p5.baseNormalShader}
* - {@link p5.baseColorShader}
* - {@link p5.baseStrokeShader}
*
* @param {function(ColorComponents): { color: {r: number, g: number, b: number}, opacity: number }} callback
* A callback function which receives a ColorComponents struct and returns the final color and opacity.
*
* @see {@link p5.baseMaterialShader}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to above, we probably don't support @see yet, but feel free to use regular links in a paragraph explaining why you might want to check out these related references!

Copy link
Author

@Abhayaj247 Abhayaj247 Jun 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@davepagurek , I've removed all @see tags since they're not supported in the current documentation pipeline. The documentation now relies on clear descriptions and contextual examples to guide users to related references.

* @see {@link p5.Shader#modify}
*
* @example
* <div modernizr='webgl'>
* <code>
* let myShader;
* function setup() {
* createCanvas(200, 200, WEBGL);
* myShader = baseMaterialShader().modify(() => {
* combineColors(components => {
* // Custom color combination: add a red tint
* let color = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although you can access .r, .g, .b, and .a properties, the return value would need to be either [r, g, b, a] as an array, or more explicitly, vec4(r, g, b, a) -- we don't yet support an object notation for this. (Also it will need to be just the one object, and not an object with separate color and opacity properties, for it to compile correctly I think.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also makes me wonder what the best way to document the inputs object is, since it's not exactly any normal type. @lukeplowden do you have any thoughts on this? We could call it a vec4 and then explain in the description of the function what this means, or even not give it a type at all, and just have an explanation in the description.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although you can access .r, .g, .b, and .a properties, the return value would need to be either [r, g, b, a] as an array, or more explicitly, vec4(r, g, b, a) -- we don't yet support an object notation for this. (Also it will need to be just the one object, and not an object with separate color and opacity properties, for it to compile correctly I think.)

@davepagurek , I've corrected the combineColors example to return vec4(r, g, b, a) instead of object notation. The example now properly demonstrates the correct return format that will compile successfully.

This also makes me wonder what the best way to document the inputs object is, since it's not exactly any normal type. @lukeplowden do you have any thoughts on this? We could call it a vec4 and then explain in the description of the function what this means, or even not give it a type at all, and just have an explanation in the description.

Excellent point about the input object documentation. I've updated the parameter descriptions to clearly specify the available properties without using complex type annotations. For getWorldInputs, I've documented the vertex object properties inline, and for combineColors, I've listed all available color component properties in the description.

* r: components.baseColor.r * components.diffuse.r +
* components.ambientColor.r * components.ambient.r +
* components.specularColor.r * components.specular.r +
* components.emissive.r + 0.2,
* g: components.baseColor.g * components.diffuse.g +
* components.ambientColor.g * components.ambient.g +
* components.specularColor.g * components.specular.g +
* components.emissive.g,
* b: components.baseColor.b * components.diffuse.b +
* components.ambientColor.b * components.ambient.b +
* components.specularColor.b * components.specular.b +
* components.emissive.b
* };
* return { color, opacity: components.opacity };
* });
* });
* }
* function draw() {
* background(255);
* shader(myShader);
* lights();
* noStroke();
* fill('red');
* sphere(50);
* }
* </code>
* </div>
*/

/**
* @function getPointSize
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a heads up -- currently the only public base shaders are:

The point shader, while it has some hooks, is currently still private, as we may end up using the stroke shader to render points in the future.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/**
 * @function getPointSize
 * @experimental
 * @description
 * Registers a callback to modify the size of points when rendering with a shader.
 *
 * This hook can be used inside the following shader modify functions:
 * - <a href="#/p5/baseMaterialShader">baseMaterialShader()</a>.modify()
 * - <a href="#/p5/baseNormalShader">baseNormalShader()</a>.modify()
 * - <a href="#/p5/baseColorShader">baseColorShader()</a>.modify()
 * - <a href="#/p5/baseStrokeShader">baseStrokeShader()</a>.modify()
 * - <a href="#/p5/baseFilterShader">baseFilterShader()</a>.modify()
 *
 * Use this hook when drawing points (for example, with the point() function in WEBGL mode).
 * The callback receives the current point size (number) and should return the new size (number).
 *
 * This hook is available in:
 * - <a href="#/p5/baseMaterialShader">baseMaterialShader()</a>
 * - <a href="#/p5/baseNormalShader">baseNormalShader()</a>
 * - <a href="#/p5/baseColorShader">baseColorShader()</a>
 * - <a href="#/p5/baseStrokeShader">baseStrokeShader()</a>
 * - <a href="#/p5/baseFilterShader">baseFilterShader()</a>
 *
 * @param {function} callback
 *        A callback function which receives and returns the point size.
 *
 * @example
 * <div modernizr='webgl'>
 * <code>
 * let myShader;
 * function setup() {
 *   createCanvas(200, 200, WEBGL);
 *   myShader = baseMaterialShader().modify(() => {
 *     getPointSize(size => {
 *       // Make points pulse in size over time
 *       return size * (1.0 + 0.5 * sin(millis() * 0.002));
 *     });
 *   });
 * }
 * function draw() {
 *   background(255);
 *   shader(myShader);
 *   strokeWeight(20);
 *   stroke('blue');
 *   point(0, 0);
 * }
 * </code>
 * </div>
 */
 

@davepagurek Thank you for the clarification regarding public base shaders. I’ve updated the documentation for getPointSize to reference only the public shaders and removed any mention of private or internal shaders. Please let me know if you have any further suggestions or preferences.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think getPointSize itself is only present in the base point shader, so I think we don't need this one.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think getPointSize itself is only present in the base point shader, so I think we don't need this one.

@davepagurek Thank you for clarifying! I have removed the documentation for getPointSize since it is only present in the base point shader and not part of the public shaders.
Please let me know if there’s anything else I should update.

* @experimental
* @description
* Registers a callback to modify the size of points when rendering with a shader. This hook can be used inside {@link p5.baseMaterialShader}.modify() or similar, when drawing points (e.g., with the point() function in WEBGL mode). The callback receives the current point size (number) and should return the new size (number).
*
* This hook is available in:
* - {@link p5.baseMaterialShader}
* - {@link p5.baseNormalShader}
* - {@link p5.baseColorShader}
* - {@link p5.baseStrokeShader}
*
* @param {function(size: number): number} callback
* A callback function which receives and returns the point size.
*
* @see {@link p5.baseMaterialShader}
* @see {@link p5.Shader#modify}
*
* @example
* <div modernizr='webgl'>
* <code>
* let myShader;
* function setup() {
* createCanvas(200, 200, WEBGL);
* myShader = baseMaterialShader().modify(() => {
* getPointSize(size => {
* // Make points pulse in size over time
* return size * (1.0 + 0.5 * sin(millis() * 0.002));
* });
* });
* }
* function draw() {
* background(255);
* shader(myShader);
* strokeWeight(20);
* stroke('blue');
* point(0, 0);
* }
* </code>
* </div>
*/