diff --git a/src/webgl/ShaderGenerator.js b/src/webgl/ShaderGenerator.js index d029ed44ef..94c1674673 100644 --- a/src/webgl/ShaderGenerator.js +++ b/src/webgl/ShaderGenerator.js @@ -1638,3 +1638,480 @@ export default shadergenerator; if (typeof p5 !== 'undefined') { p5.registerAddon(shadergenerator) } + + + +/* ------------------------------------------------------------- */ +/** + * @function getWorldInputs + * @description + * Registers a callback to modify the world-space properties of each vertex in a shader. This hook can be used inside baseColorShader().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: + * - baseMaterialShader() + * - baseNormalShader() + * - baseColorShader() + * - baseStrokeShader() + * + * @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 + *
+ * + * let myShader; + * function setup() { + * createCanvas(200, 200, WEBGL); + * myShader = baseMaterialShader().modify(() => { + * getWorldInputs(inputs => { + * // Move the vertex up and down in a wave in world space + * // In world space, moving the object (e.g., with translate()) will affect these coordinates + * 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); + * } + * + *
+ */ + +/** + * @function combineColors + * @description + * Registers a callback to customize how color components are combined in the fragment shader. This hook can be used inside baseMaterialShader().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: + * - baseMaterialShader() + * + * @param {function} callback + * A callback function which receives the object described above and returns a vector with four components for the final color. + * + * @example + *
+ * + * let myShader; + * function setup() { + * createCanvas(200, 200, WEBGL); + * myShader = baseMaterialShader().modify(() => { + * combineColors(components => { + * // Custom color combination: add a red tint using vector properties + * let r = components.baseColor.r * components.diffuse + + * components.ambientColor.r * components.ambient + + * components.specularColor.r * components.specular + + * components.emissive.r + 0.2; + * let g = components.baseColor.g * components.diffuse + + * components.ambientColor.g * components.ambient + + * components.specularColor.g * components.specular + + * components.emissive.g; + * let b = components.baseColor.b * components.diffuse + + * components.ambientColor.b * components.ambient + + * components.specularColor.b * components.specular + + * components.emissive.b; + * return [r, g, b, components.opacity]; + * }); + * }); + * } + * function draw() { + * background(255); + * shader(myShader); + * lights(); + * noStroke(); + * fill('red'); + * sphere(50); + * } + * + *
+ */ + +/** + * @function beforeVertex + * @description + * Registers a callback to run custom code at the very start of the vertex shader. This hook can be used inside baseColorShader().modify() and similar shader modify calls to set up variables or perform calculations that affect every vertex before processing begins. The callback receives no arguments. + * + * Note: This hook is currently limited to per-vertex operations; storing variables for later use is not supported. + * + * This hook is available in: + * - baseColorShader() + * - baseMaterialShader() + * - baseNormalShader() + * - baseStrokeShader() + * + * @param {function} callback + * A callback function which is called before each vertex is processed. + */ + +/** + * @function afterVertex + * @description + * Registers a callback to run custom code at the very end of the vertex shader. This hook can be used inside baseColorShader().modify() and similar shader modify calls to perform cleanup or final calculations after all vertex processing is done. The callback receives no arguments. + * + * Note: This hook is currently limited to per-vertex operations; storing variables for later use is not supported. + * + * This hook is available in: + * - baseColorShader() + * - baseMaterialShader() + * - baseNormalShader() + * - baseStrokeShader() + * + * @param {function} callback + * A callback function which is called after each vertex is processed. + */ + +/** + * @function beforeFragment + * @description + * Registers a callback to run custom code at the very start of the fragment shader. This hook can be used inside baseColorShader().modify() and similar shader modify calls to set up variables or perform calculations that affect every pixel before color calculations begin. The callback receives no arguments. + * + * This hook is available in: + * - baseColorShader() + * - baseMaterialShader() + * - baseNormalShader() + * - baseStrokeShader() + * + * @param {function} callback + * A callback function which is called before each fragment is processed. + * + * @example + *
+ * + * let myShader; + * function setup() { + * createCanvas(200, 200, WEBGL); + * myShader = baseColorShader().modify(() => { + * beforeFragment(() => { + * // Set a value for use in getFinalColor + * this.brightness = 0.5 + 0.5 * sin(millis() * 0.001); + * }); + * getFinalColor(color => { + * // Use the value set in beforeFragment to tint the color + * color[0] *= this.brightness; // Tint red channel + * return color; + * }); + * }); + * } + * function draw() { + * background(220); + * shader(myShader); + * noStroke(); + * fill('teal'); + * box(100); + * } + * + *
+ */ + +/** + * @function getPixelInputs + * @description + * Registers a callback to modify the properties of each fragment (pixel) before the final color is calculated in the fragment shader. This hook can be used inside baseMaterialShader().modify() and similar shader modify calls to change opacity or other per-pixel properties. The callback receives an object with the following properties: + * - `opacity`: a number between 0 and 1 for the pixel's transparency + * - (Other properties may be available depending on the shader.) + * + * Return the modified object to update the fragment. + * + * This hook is available in: + * - baseMaterialShader() + * - baseStrokeShader() + * + * @param {function} callback + * A callback function which receives the fragment inputs object and should return it after making any changes. + * + * @example + *
+ * + * let myShader; + * function setup() { + * createCanvas(200, 200, WEBGL); + * myShader = baseMaterialShader().modify(() => { + * getPixelInputs(inputs => { + * // Animate opacity based on x position + * inputs.opacity = 0.5 + 0.5 * sin(inputs.texCoord.x * 10.0 + millis() * 0.002); + * return inputs; + * }); + * }); + * } + * function draw() { + * background(240); + * shader(myShader); + * lights(); + * noStroke(); + * fill('purple'); + * sphere(50); + * } + * + *
+ */ + +/** + * @function shouldDiscard + * @description + * Registers a callback to decide whether to discard (skip drawing) a fragment (pixel) in the fragment shader. This hook can be used inside baseStrokeShader().modify() and similar shader modify calls to create effects like round points or custom masking. The callback receives a boolean: + * - `willDiscard`: true if the fragment would be discarded by default + * + * Return true to discard the fragment, or false to keep it. + * + * This hook is available in: + * - baseStrokeShader() + * + * @param {function} callback + * A callback function which receives a boolean and should return a boolean. + * + * @example + *
+ * + * let myShader; + * function setup() { + * createCanvas(200, 200, WEBGL); + * myShader = baseStrokeShader().modify(() => { + * shouldDiscard(willDiscard => { + * // Discard fragments outside a circular region + * return willDiscard || (inputs.position.x * inputs.position.x + inputs.position.y * inputs.position.y > 2500.0); + * }); + * }); + * } + * function draw() { + * background(255); + * strokeShader(myShader); + * strokeWeight(30); + * line(-width/3, 0, width/3, 0); + * } + * + *
+ */ + +/** + * @function getFinalColor + * @description + * Registers a callback to change the final color of each pixel after all lighting and mixing is done in the fragment shader. This hook can be used inside baseColorShader().modify() and similar shader modify calls to adjust the color before it appears on the screen. The callback receives a color array: + * - `[r, g, b, a]`: the current color (red, green, blue, alpha) + * + * Return a new color array to change the output color. + * + * This hook is available in: + * - baseColorShader() + * - baseMaterialShader() + * - baseNormalShader() + * - baseStrokeShader() + * + * @param {function} callback + * A callback function which receives the color array and should return a color array. + * + * @example + *
+ * + * let myShader; + * function setup() { + * createCanvas(200, 200, WEBGL); + * myShader = baseColorShader().modify(() => { + * getFinalColor(color => { + * // Make the output color fully opaque and add a green tint + * color[3] = 1.0; + * color[1] += 0.2; + * return color; + * }); + * }); + * } + * function draw() { + * background(230); + * shader(myShader); + * noStroke(); + * fill('green'); + * circle(0, 0, 100); + * } + * + *
+ */ + +/** + * @function afterFragment + * @description + * Registers a callback to run custom code at the very end of the fragment shader. This hook can be used inside baseColorShader().modify() and similar shader modify calls to perform cleanup or final per-pixel effects after all color calculations are done. The callback receives no arguments. + * + * This hook is available in: + * - baseColorShader() + * - baseMaterialShader() + * - baseNormalShader() + * - baseStrokeShader() + * + * @param {function} callback + * A callback function which is called after each fragment is processed. + * + * @example + *
+ * + * let myShader; + * function setup() { + * createCanvas(200, 200, WEBGL); + * myShader = baseColorShader().modify(() => { + * getFinalColor(color => { + * // Add a purple tint to the color + * color[2] += 0.2; + * return color; + * }); + * afterFragment(() => { + * // This hook runs after the final color is set for each fragment. + * // You could use this for debugging or advanced effects. + * }); + * }); + * } + * function draw() { + * background(240); + * shader(myShader); + * noStroke(); + * fill('purple'); + * sphere(60); + * } + * + *
+ */ + +/** + * @function getColor + * @description + * Registers a callback to set the final color for each pixel in a filter shader. This hook can be used inside baseFilterShader().modify() and similar shader modify calls to control the output color for each pixel. The callback receives the following arguments: + * - `inputs`: an object with properties like `texCoord`, `canvasSize`, `texelSize`, etc. + * - `canvasContent`: a sampler2D texture with the sketch's contents before the filter is applied + * + * Return a color array `[r, g, b, a]` for the pixel. + * + * This hook is available in: + * - baseFilterShader() + * + * @param {function} callback + * A callback function which receives the inputs object and canvasContent, and should return a color array. + * + * @example + *
+ * + * let myShader; + * function setup() { + * createCanvas(200, 200, WEBGL); + * myShader = baseFilterShader().modify(() => { + * getColor((inputs, canvasContent) => { + * // Warp the texture coordinates for a wavy effect + * let warped = [inputs.texCoord.x, inputs.texCoord.y + 0.1 * sin(inputs.texCoord.x * 10.0)]; + * return getTexture(canvasContent, warped); + * }); + * }); + * } + * function draw() { + * background(180); + * // Draw something to the canvas + * fill('yellow'); + * ellipse(0, 0, 150, 150); + * filter(myShader); + * } + * + *
+ */ + +/** + * @function getObjectInputs + * @description + * Registers a callback to modify the properties of each vertex before any transformations are applied in the vertex shader. This hook can be used inside baseColorShader().modify() and similar shader modify calls to move, color, or otherwise modify the raw model data. The callback receives an object with the following properties: + * - `position`: a vector with three components representing the original position of the vertex + * - `normal`: a vector with three components representing the direction the surface is facing + * - `texCoord`: a vector with two components representing the texture coordinates + * - `color`: a vector with four components representing the color of the vertex (red, green, blue, alpha) + * + * Return the modified object to update the vertex. + * + * This hook is available in: + * - baseColorShader() + * - baseMaterialShader() + * - baseNormalShader() + * - baseStrokeShader() + * + * @param {function} callback + * A callback function which receives the vertex object and should return it after making any changes. + * + * @example + *
+ * + * let myShader; + * function setup() { + * createCanvas(200, 200, WEBGL); + * myShader = baseColorShader().modify(() => { + * getObjectInputs(inputs => { + * // Create a sine wave along the x axis in object space + * inputs.position.y += 20 * sin(inputs.position.x * 0.1 + millis() * 0.002); + * return inputs; + * }); + * }); + * } + * function draw() { + * background(220); + * shader(myShader); + * noStroke(); + * fill('orange'); + * box(100); + * } + * + *
+ */ + +/** + * @function getCameraInputs + * @description + * Registers a callback to adjust vertex properties after the model has been transformed by the camera, but before projection, in the vertex shader. This hook can be used inside baseColorShader().modify() and similar shader modify calls to create effects that depend on the camera's view. The callback receives an object with the following properties: + * - `position`: a vector with three components representing the position after camera transformation + * - `normal`: a vector with three components representing the normal after camera transformation + * - `texCoord`: a vector with two components representing the texture coordinates + * - `color`: a vector with four components representing the color of the vertex (red, green, blue, alpha) + * + * Return the modified object to update the vertex. + * + * This hook is available in: + * - baseColorShader() + * - baseMaterialShader() + * - baseNormalShader() + * - baseStrokeShader() + * + * @param {function} callback + * A callback function which receives the vertex object and should return it after making any changes. + * + * @example + *
+ * + * let myShader; + * function setup() { + * createCanvas(200, 200, WEBGL); + * myShader = baseColorShader().modify(() => { + * getCameraInputs(inputs => { + * // Move vertices in camera space based on their x position + * inputs.position.y += 30 * sin(inputs.position.x * 0.05 + millis() * 0.001); + * // Tint all vertices blue + * inputs.color.b = 1.0; + * return inputs; + * }); + * }); + * } + * function draw() { + * background(200); + * shader(myShader); + * noStroke(); + * fill('blue'); + * box(100); + * } + * + *
+ */ \ No newline at end of file