Skip to content

Commit

Permalink
v-0.8.4 post effects api
Browse files Browse the repository at this point in the history
  • Loading branch information
nakednous committed Mar 19, 2024
1 parent 75653df commit 6a5eae4
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 4 deletions.
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ High-level space transformations [WEBGL](https://p5js.org/reference/#/p5/WEBGL)
- [Handling](#handling)
- [uniformsUI](#uniformsui)
- [Apply shader](#apply-shader)
- [Post-effects](#post-effects)
- [Macros](#macros)
- [Basic matrices](#basic-matrices)
- [Matrix queries](#matrix-queries)
Expand Down Expand Up @@ -138,13 +139,21 @@ These functions manipulate the `uniformsUI`:
- `color`: Specifies the text color for the UI elements' labels.
3. `showUniformsUI(shader)`: Displays the `shader.uniformsUI` elements associated with the `shader`'s uniforms. It attaches necessary event listeners to update the shader uniforms based on user interactions.
4. `hideUniformsUI(shader)`: Hides the `shader.uniformsUI` elements and removes the event listeners, stopping any further updates to the `shader` uniforms from ui interactions.
5. `p5.Shader.setUniformsUI()`: Iterates over the `uniformsUI` map and sets the shader's uniforms based on the current values of the corresponding UI elements. This method should be called within the `draw` loop to ensure the shader uniforms are continuously updated. Note that `applyShader` automatically calls this method.
5. `resetUniformsUI(shader)`: Hides and resets the `shader.uniformsUI` which should be restored with a call to `parseUniformsUI(shader, configUniformsUI)`.
6. `p5.Shader.setUniformsUI()`: Iterates over the `uniformsUI` map and sets the shader's uniforms based on the current values of the corresponding UI elements. This method should be called within the `draw` loop to ensure the shader uniforms are continuously updated. Note that `applyShader` automatically calls this method.

## Apply shader

1. `applyShader(shader, [{ [target], [uniforms], [scene], [options] }])` applies `shader` to the specified `target` (which can be the current context, a [p5.Framebuffer](https://p5js.org/reference/#/p5.Framebuffer) or a [p5.Graphics](https://p5js.org/reference/#/p5.Graphics)), emits the `shader` `uniformsUI` (calling `shader.setUniformsUI()`) and the `uniforms` object (formatted as `{ uniform_1_name: value_1, ..., uniform_n_name: value_n }`), renders geometry by executing `scene(options)` (defaults to an overlaying `quad` if not specified), and returns the `target` for method chaining.
2. `overlay(flip)`: A default rendering method used by `applyShader`, which covers the screen with a [quad](https://p5js.org/reference/#/p5/quad). It can be called independently between [beginHUD and endHUD](#heads-up-display) for a direct screen space application.

## Post-effects

1. `addEffect(key, shader)`: Adds a new effect to the post-effects array, identified by a unique `key` and associated with a `shader`. The `shader` should be an instance of [p5.Shader](https://p5js.org/reference/#/p5.Shader). The effect will be applied in the order it was added when `applyEffects` is called.
2. `resetEffects()`: Clears all the effects from the post-effects array, effectively resetting it to an empty state. This is useful for starting fresh with a new set of effects or clearing out effects that are no longer needed.
3. `effects()`: Returns the current post-effects array. Each effect is an object containing the `key`, `shader`, and a `target` which is a [p5.Framebuffer](https://p5js.org/reference/#/p5.Framebuffer) used to apply the shader.
4. `applyEffects(layer, uniforms, flip)`: Sequentially applies all effects (in the order they were added) to the source `layer`, which can be a [p5.Framebuffer](https://p5js.org/reference/#/p5.Framebuffer), a [p5.Graphics](https://p5js.org/reference/#/p5.Graphics) object, or the current context. The `uniforms` object maps effect keys to functions that return uniform values, with each function accepting the current `sharedLayer` as an argument. These functions dynamically generate uniform values, potentially based on the state of the `sharedLayer` (e.g., its `depth`). The `flip` boolean indicates whether the final image should be vertically flipped. The method sequentially processes each effect, applying its shader with the corresponding uniforms (calling `applyShader`). The final processed layer, now modified by all the effects, is returned.

## Macros

Retrieve image offset, mouse position, pointer position and screen resolution which are common `uniform vec2` variables
Expand Down
56 changes: 53 additions & 3 deletions p5.treegl.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
'use strict';

// TODO's
// i. Should drawing stuff be implemented only for p5.prototype just as overlay is?
// ii. Handling other default uniforms such as uSampler (proof-of-concept found on texture branch)
// blog apps demos docs.
// v-0.9: i. only WEBGL; ii. instance mode tests (drawing); iii. use p5.prototype.map instead of _map
// v-1.0: p5-v2 support
// v-next: handling other default uniforms (e.g., uSampler)
// See:
// https://github.com/processing/p5.js/blob/main/contributor_docs/creating_libraries.md
// https://github.com/processing/p5.js/blob/main/src/core/README.md
Expand All @@ -11,7 +13,7 @@
var Tree = (function (ext) {
const INFO = {
LIBRARY: 'p5.treegl',
VERSION: '0.8.3',
VERSION: '0.8.4',
HOMEPAGE: 'https://github.com/VisualComputing/p5.treegl'
};
Object.freeze(INFO);
Expand Down Expand Up @@ -460,6 +462,7 @@ var Tree = (function (ext) {
return this._renderer._map(...args);
}

// TODO overkill
p5.RendererGL.prototype._map = function (n, start1, stop1, start2, stop2) {
return (n - start1) / (stop1 - start1) * (stop2 - start2) + start2;
}
Expand Down Expand Up @@ -1035,6 +1038,11 @@ void main() {
}
}

p5.prototype.resetUniformsUI = function (shader) {
this.hideUniformsUI(shader);
shader.uniformsUI = undefined;
}

p5.prototype.hideUniformsUI = function (shader) {
if (!shader.uniformsUI) {
console.log('No uniformsUI found for this shader. Call parseUniformsUI(shader) first');
Expand Down Expand Up @@ -1123,6 +1131,46 @@ void main() {
return target || context;
}

p5.prototype._effects = [];

p5.prototype.effects = function () {
return this._effects;
}

p5.prototype.setEffects = function (effects) {
if (Array.isArray(effects)) {
this._effects = effects;
} else {
console.log('effects must be an array');
}
}

p5.prototype.resetEffects = function () {
this._effects = [];
}

p5.prototype.addEffect = function (key, shader) {
this._effects.push({ name: key, shader, target: this.createFramebuffer() });
}

p5.prototype.applyEffects = function (layer, arg2, arg3) {
let sharedLayer = layer;
let uniforms = typeof arg2 === 'object' && !Array.isArray(arg2) ? arg2 : (typeof arg3 === 'object' && !Array.isArray(arg3) ? arg3 : {});
let flip = typeof arg2 === 'boolean' ? arg2 : (typeof arg3 === 'boolean' ? arg3 : true);
this._effects?.forEach(effect => {
const fn = uniforms[effect.name];
if (typeof fn === 'function') {
const uniforms = fn(sharedLayer);
sharedLayer = this.applyShader(effect.shader, {
target: effect.target,
scene: () => overlay(flip),
uniforms,
});
}
});
return sharedLayer;
}

p5.prototype.texOffset = function (image) {
return [1 / image.width, 1 / image.height];
}
Expand Down Expand Up @@ -1425,6 +1473,7 @@ void main() {
this.quad(-1, flip ? 1 : -1, 1, flip ? 1 : -1, 1, flip ? -1 : 1, -1, flip ? -1 : 1);
}
// TODO this._renderer.overlay(...args) gives bug: p5.Geometry.prototype._getFaceNormal: face has colinear sides or a repeated vertex
// key observation: this gets called from a webgl pg!
}

p5.prototype.axes = function (...args) {
Expand Down Expand Up @@ -1629,6 +1678,7 @@ void main() {
this._renderer._circle(...args);
}

// TODO overkill
p5.RendererGL.prototype._circle = function ({ filled = false, x = this.width / 2, y = this.height / 2, radius = 100, detail = 50 } = {}) {
this._rendererState = this.push();
if (filled) {
Expand Down

0 comments on commit 6a5eae4

Please sign in to comment.