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 3 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
138 changes: 138 additions & 0 deletions src/webgl/ShaderGenerator.js
Original file line number Diff line number Diff line change
Expand Up @@ -1638,3 +1638,141 @@ export default shadergenerator;
if (typeof p5 !== 'undefined') {
p5.registerAddon(shadergenerator)
}



/* ------------------------------------------------------------- */
/**
* @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 <a href="#/p5/baseMaterialShader">baseMaterialShader()</a>.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:
* - <a href="#/p5/baseMaterialShader">baseMaterialShader()</a>
* - <a href="#/p5/baseNormalShader">baseNormalShader()</a>
* - <a href="#/p5/baseColorShader">baseColorShader()</a>
* - <a href="#/p5/baseStrokeShader">baseStrokeShader()</a>
*
* @param {function} callback
* A callback function which receives a vertex object containing position (vec3), normal (vec3), texCoord (vec2), and color (vec4) properties. The function should return the modified vertex object.
*
* @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 <a href="#/p5/baseMaterialShader">baseMaterialShader()</a>.modify() and similar shader modify calls to control the final color output of a material. The callback receives color components (baseColor, diffuse, ambientColor, ambient, specularColor, specular, emissive, opacity) and returns a vec4 for the final color.
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we describe the input as being an object with the properties baseColor, diffuse, ambientColor, etc? I think it would be important to describe the size of each item (e.g. position/normal are vec3s, texture coordinates are vec2s, color is a vec4) -- although maybe rather than using terms like vec3 we could describe it as "a vector with three components" to avoid referencing the vec3 type, since there aren't user-facing docs for that yet. A bullet list might work if that's too much info to put in one sentence.

One other note is that when we refer to a name of a property/variable/etc in code, such as when listing properties here, we should put the names in backticks so they render as code (baseColor instead of baseColor.)

Copy link
Author

@Abhayaj247 Abhayaj247 Jul 9, 2025

Choose a reason for hiding this comment

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

/**
 * @function combineColors
 * @experimental
 * @description
 * Registers a callback to customize how color components are combined in the fragment shader. This hook can be used inside <a href="#/p5/baseMaterialShader">baseMaterialShader()</a>.modify() and similar shader modify calls to control the final color output of a material. The callback receives an object with the following properties:
 *
 * - `baseColor`: a vector with three components representing the base color (red, green, blue)
 * - `diffuse`: a single number representing the diffuse reflection
 * - `ambientColor`: a vector with three components representing the ambient color
 * - `ambient`: a single number representing the ambient reflection
 * - `specularColor`: a vector with three components representing the specular color
 * - `specular`: a single number representing the specular reflection
 * - `emissive`: a vector with three components representing the emissive color
 * - `opacity`: a single number representing the opacity
 *
 * The callback should return a vector with four components (red, green, blue, alpha) for the final color.
 *
 * 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 the object described above and returns a vector with four components for the final color.
 *
 * @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 r = components.baseColor[0] * components.diffuse +
 *               components.ambientColor[0] * components.ambient +
 *               components.specularColor[0] * components.specular +
 *               components.emissive[0] + 0.2;
 *       let g = components.baseColor[1] * components.diffuse +
 *               components.ambientColor[1] * components.ambient +
 *               components.specularColor[1] * components.specular +
 *               components.emissive[1];
 *       let b = components.baseColor[2] * components.diffuse +
 *               components.ambientColor[2] * components.ambient +
 *               components.specularColor[2] * components.specular +
 *               components.emissive[2];
 *       return [r, g, b, components.opacity];
 *     });
 *   });
 * }
 * function draw() {
 *   background(255);
 *   shader(myShader);
 *   lights();
 *   noStroke();
 *   fill('red');
 *   sphere(50);
 * }
 * </code>
 * </div>
 */
 

@davepagurek Thank you for your feedback! I’ve updated the documentation for combineColors to describe the input as an object with each property listed in a bullet list, using backticks for property names and describing the size of each in plain language. The example now uses array notation for vector properties. Please let me know if you’d like any further adjustments.

*
* 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>
*
* @param {function} callback
* A callback function which receives color components (baseColor, diffuse, ambientColor, ambient, specularColor, specular, emissive, opacity) and returns a vec4 for the final color.
*
* @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 r = components.baseColor.r * components.diffuse.r +
* components.ambientColor.r * components.ambient.r +
* components.specularColor.r * components.specular.r +
* components.emissive.r + 0.2;
* let g = components.baseColor.g * components.diffuse.g +
* components.ambientColor.g * components.ambient.g +
* components.specularColor.g * components.specular.g +
* components.emissive.g;
* let b = components.baseColor.b * components.diffuse.b +
* components.ambientColor.b * components.ambient.b +
* components.specularColor.b * components.specular.b +
* components.emissive.b;
* let a = components.opacity;
* return vec4(r, g, b, a);
* });
* });
* }
* 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 <a href="#/p5/baseMaterialShader">baseMaterialShader()</a>.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:
* - <a href="#/p5/baseMaterialShader">baseMaterialShader()</a>
* - <a href="#/p5/baseNormalShader">baseNormalShader()</a>
* - <a href="#/p5/baseColorShader">baseColorShader()</a>
* - <a href="#/p5/baseStrokeShader">baseStrokeShader()</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>
*/