Skip to content

Commit 4744428

Browse files
committed
Write out struct members as bullets
1 parent b9e89d6 commit 4744428

File tree

2 files changed

+109
-25
lines changed

2 files changed

+109
-25
lines changed

src/webgl/material.js

Lines changed: 77 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -191,12 +191,45 @@ p5.prototype.loadShader = function (
191191
* The second parameter, `fragSrc`, sets the fragment shader. It’s a string
192192
* that contains the fragment shader program written in GLSL.
193193
*
194+
* A shader can optionally describe *hooks,* which are functions in GLSL that
195+
* users may choose to provide to customize the behavior of the shader using the
196+
* <a href="#/p5.Shader/modify">`modify()`</a> method of `p5.Shader`. These are added by
197+
* describing the hooks in a third parameter, `options`, and referencing the hooks in
198+
* your `vertSrc` or `fragSrc`. Hooks for the vertex or fragment shader are described under
199+
* the `vertex` and `fragment` keys of `options`. Each one is an object. where each key is
200+
* the type and name of a hook function, and each value is a string with the
201+
* parameter list and default implementation of the hook. For example, to let users
202+
* optionally run code at the start of the vertex shader, the options object could
203+
* include:
204+
*
205+
* ```js
206+
* {
207+
* vertex: {
208+
* 'void beforeVertex': '() {}'
209+
* }
210+
* }
211+
* ```
212+
*
213+
* Then, in your vertex shader source, you can run a hook by calling a function
214+
* with the same name prefixed by `HOOK_`:
215+
*
216+
* ```glsl
217+
* void main() {
218+
* HOOK_beforeVertex();
219+
* // Add the rest ofy our shader code here!
220+
* }
221+
* ```
222+
*
194223
* Note: Only filter shaders can be used in 2D mode. All shaders can be used
195224
* in WebGL mode.
196225
*
197226
* @method createShader
198227
* @param {String} vertSrc source code for the vertex shader.
199228
* @param {String} fragSrc source code for the fragment shader.
229+
* @param {Object} [options] An optional object describing how this shader can
230+
* be augmented with hooks. It can include:
231+
* - `vertex`: An object describing the available vertex shader hooks.
232+
* - `fragment`: An object describing the available frament shader hooks.
200233
* @returns {p5.Shader} new shader object created from the
201234
* vertex and fragment shaders.
202235
*
@@ -785,10 +818,26 @@ p5.prototype.shader = function (s) {
785818
* - `vec4 getVertexColor`: Update the color of each vertex. It takes in a `vec4 color` and must return a modified version.
786819
* - `void afterVertex`: Called at the end of the vertex shader.
787820
* - `void beforeFragment`: Called at the start of the fragment shader.
788-
* - `Inputs getPixelInputs`: Update the per-pixel inputs of the material. It takes in an `Inputs` struct, which includes `vec3 normal`, `vec2 texCoord`, `vec3 ambientColor`, `vec4 color`, `vec3 ambientMaterial`, `vec3 specularMaterial`, `vec3 emissiveMaterial`, `float shininess`, and `vec3 ambientLight`. The struct can be modified and returned.
821+
* - `Inputs getPixelInputs`: Update the per-pixel inputs of the material. It takes in an `Inputs` struct, which includes:
822+
* - `vec3 normal`, the direction pointing out of the surface
823+
* - `vec2 texCoord`, a vector where `x` and `y` are between 0 and 1 describing the spot on a texture the pixel is mapped to, as a fraction of the texture size
824+
* - `vec3 ambientLight`, the ambient light color on the vertex
825+
* - `vec4 color`, the base material color of the pixel
826+
* - `vec3 ambientMaterial`, the color of the pixel when affected by ambient light
827+
* - `vec3 specularMaterial`, the color of the pixel when reflecting specular highlights
828+
* - `vec3 emissiveMaterial`, the light color emitted by the pixel
829+
* - `float shininess`, a number representing how sharp specular reflections should be
830+
The struct can be modified and returned.
789831
* - `vec4 combineColors`: Take in a `ColorComponents` struct containing all the different components of light, and combining them into
790-
* a single final color. The struct contains `vec3 baseColor`, `float opacity`, `vec3 ambientColor`, `vec3 specularColor`,
791-
* `vec3 diffuse`, `vec3 ambientLight`, `vec3 specular`, and `vec3 emissive`.
832+
* a single final color. The struct contains:
833+
* - `vec3 baseColor`, the base color of the pixel
834+
* - `float opacity`, the opacity between 0 and 1 that it should be drawn at
835+
* - `vec3 ambientColor`, the color of the pixel when affected by ambient light
836+
* - `vec3 specularColor`, the color of the pixel when affected by specular reflections
837+
* - `vec3 diffuse`, the amount of diffused light hitting the pixel
838+
* - `vec3 ambient`, the amount of ambient light hitting the pixel
839+
* - `vec3 specular`, the amount of specular reflection hitting the pixel
840+
* - `vec3 emissive`, the amount of light emitted by the pixel
792841
* - `vec4 getFinalColor`: Update the final color after mixing. It takes in a `vec4 color` and must return a modified version.
793842
* - `void afterFragment`: Called at the end of the fragment shader.
794843
*
@@ -834,18 +883,21 @@ p5.prototype.shader = function (s) {
834883
* function setup() {
835884
* createCanvas(200, 200, WEBGL);
836885
* myShader = materialShader().modify({
837-
* vertexDeclarations: 'out vec2 myUV;',
838-
* fragmentDeclarations: 'in vec2 myUV;',
839-
* 'vec2 getUV': `(vec2 uv) {
840-
* // Store and return
841-
* myUV = uv;
842-
* return myUV;
843-
* }`,
844886
* 'Inputs getPixelInputs': `(Inputs inputs) {
845887
* vec3 newNormal = inputs.normal;
846888
* // Simple bump mapping: adjust the normal based on position
847-
* newNormal.x += 0.05 * sin(inputs.texCoord.y * ${TWO_PI} * 15.0);
848-
* newNormal.y += 0.05 * sin(inputs.texCoord.x * ${TWO_PI} * 15.0);
889+
* newNormal.x += 0.2 * sin(
890+
* sin(
891+
* inputs.texCoord.y * ${TWO_PI} * 10.0 +
892+
* inputs.texCoord.x * ${TWO_PI} * 25.0
893+
* )
894+
* );
895+
* newNormal.y += 0.2 * sin(
896+
* sin(
897+
* inputs.texCoord.x * ${TWO_PI} * 10.0 +
898+
* inputs.texCoord.y * ${TWO_PI} * 25.0
899+
* )
900+
* );
849901
* inputs.normal = normalize(newNormal);
850902
* return inputs;
851903
* }`
@@ -855,7 +907,7 @@ p5.prototype.shader = function (s) {
855907
* function draw() {
856908
* background(255);
857909
* shader(myShader);
858-
* ambientLight(50);
910+
* ambientLight(150);
859911
* pointLight(
860912
* 255, 255, 255,
861913
* 100*cos(frameCount*0.04), -50, 100*sin(frameCount*0.04)
@@ -1030,7 +1082,12 @@ p5.prototype.colorShader = function() {
10301082
* - `vec4 getVertexColor`: Update the color of each vertex. It takes in a `vec4 color` and must return a modified version.
10311083
* - `void afterVertex`: Called at the end of the vertex shader.
10321084
* - `void beforeFragment`: Called at the start of the fragment shader.
1033-
* - `Inputs getPixelInputs`: Update the inputs to the shader. It takes in a struct `Inputs inputs`, which includes `vec4 color`, `vec2 tangent`, `vec2 center`, `vec2 position`, and `float strokeWeight`.
1085+
* - `Inputs getPixelInputs`: Update the inputs to the shader. It takes in a struct `Inputs inputs`, which includes:
1086+
* - `vec4 color`, the color of the stroke
1087+
* - `vec2 tangent`, the direction of the stroke in screen space
1088+
* - `vec2 center`, the coordinate of the center of the stroke in screen space p5.js pixels
1089+
* - `vec2 position`, the coordinate of the current pixel in screen space p5.js pixels
1090+
* - `float strokeWeight`, the thickness of the stroke in p5.js pixels
10341091
* - `bool shouldDiscard`: Caps and joins are made by discarded pixels in the fragment shader to carve away unwanted areas. Use this to change this logic. It takes in a `bool willDiscard` and must return a modified version.
10351092
* - `vec4 getFinalColor`: Update the final color after mixing. It takes in a `vec4 color` and must return a modified version.
10361093
* - `void afterFragment`: Called at the end of the fragment shader.
@@ -1052,11 +1109,6 @@ p5.prototype.colorShader = function() {
10521109
* fragmentDeclarations: `
10531110
* vec2 myCenter;
10541111
* vec2 myPosition;
1055-
* float random(vec2 p) {
1056-
* vec3 p3 = fract(vec3(p.xyx) * .1031);
1057-
* p3 += dot(p3, p3.yzx + 33.33);
1058-
* return fract((p3.x + p3.y) * p3.z);
1059-
* }
10601112
* `,
10611113
* 'Inputs getPixelInputs': `(Inputs inputs) {
10621114
* // Store a copy, then return unchanged
@@ -1065,10 +1117,12 @@ p5.prototype.colorShader = function() {
10651117
* return inputs;
10661118
* }`,
10671119
* 'vec4 getFinalColor': `(vec4 c) {
1068-
* if (length(myPosition - myCenter) + random(gl_FragCoord.xy)*10. > 15.) {
1069-
* return vec4(0.0, 0.0, 0.0, 0.0);
1070-
* }
1071-
* return c;
1120+
* float opacity = 1.0 - smoothstep(
1121+
* 0.0,
1122+
* 15.0,
1123+
* length(myPosition - myCenter)
1124+
* );
1125+
* return c * opacity;
10721126
* }`
10731127
* });
10741128
* }

src/webgl/p5.Shader.js

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,32 @@ import p5 from '../core/main';
2424
* created, it can be used with the <a href="#/p5/shader">shader()</a>
2525
* function, as in `shader(myShader)`.
2626
*
27+
* A shader can optionally describe *hooks,* which are functions in GLSL that
28+
* users may choose to provide to customize the behavior of the shader. For the
29+
* vertex or the fragment shader, users can pass in an object where each key is
30+
* the type and name of a hook function, and each value is a string with the
31+
* parameter list and default implementation of the hook. For example, to let users
32+
* optionally run code at the start of the vertex shader, the options object could
33+
* include:
34+
*
35+
* ```js
36+
* {
37+
* vertex: {
38+
* 'void beforeVertex': '() {}'
39+
* }
40+
* }
41+
* ```
42+
*
43+
* Then, in your vertex shader source, you can run a hook by calling a function
44+
* with the same name prefixed by `HOOK_`:
45+
*
46+
* ```glsl
47+
* void main() {
48+
* HOOK_beforeVertex();
49+
* // Add the rest ofy our shader code here!
50+
* }
51+
* ```
52+
*
2753
* Note: <a href="#/p5/createShader">createShader()</a>,
2854
* <a href="#/p5/createFilterShader">createFilterShader()</a>, and
2955
* <a href="#/p5/loadShader">loadShader()</a> are the recommended ways to
@@ -34,7 +60,10 @@ import p5 from '../core/main';
3460
* @param {p5.RendererGL} renderer WebGL context for this shader.
3561
* @param {String} vertSrc source code for the vertex shader program.
3662
* @param {String} fragSrc source code for the fragment shader program.
37-
* @param {Object} [options] TODO
63+
* @param {Object} [options] An optional object describing how this shader can
64+
* be augmented with hooks. It can include:
65+
* - `vertex`: An object describing the available vertex shader hooks.
66+
* - `fragment`: An object describing the available frament shader hooks.
3867
*
3968
* @example
4069
* <div>
@@ -141,7 +170,8 @@ p5.Shader = class {
141170
this._bound = false;
142171
this.samplers = [];
143172
this.hooks = {
144-
// Stores uniform declarations
173+
// Stores uniform declarations. This should be passed in by
174+
// `.modify()` instead of being manualy passed in.
145175
declarations: options.declarations,
146176

147177
// Stores the hook implementations

0 commit comments

Comments
 (0)