Skip to content
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

Created basic WebGL feedback example #1246

Merged
merged 6 commits into from
Oct 14, 2023
Merged
Changes from all 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
56 changes: 56 additions & 0 deletions src/data/examples/en/20_3D/12_simple_feedback.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* @name Simple Feedback
* @arialabel An example of a simple feedback effect using two buffers.
Copy link
Member

Choose a reason for hiding this comment

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

Here, I think it would be good to expand on this description to motivate why two buffers are required and why WebGL specifically is needed to make this work.

* @description A simple feedback effect that is achieved by using two WebGL graphics buffers.
* This effect works by drawing the previous frame to a second
* createGraphics() buffer, which can be blended with the current frame. This
* takes advantage of texture mapping in WebGL.
*/

let pg, swap;

function setup() {
createCanvas(710, 400);

// this will hold the previous frame
aceslowman marked this conversation as resolved.
Show resolved Hide resolved
pg = createGraphics(710, 400, WEBGL);
// this will hold our main graphic
swap = createGraphics(710, 400, WEBGL);

describe(
'a slowly oscillating, radiating white sphere that fades into a dark gray background through a feedback visual effect'
);
}

function draw() {
// clears and resets the p5.Graphics so that 3D objects draw correctly
pg.reset();

// draw the previous frame
pg.texture(swap);
Copy link
Contributor

@davepagurek davepagurek Jul 25, 2022

Choose a reason for hiding this comment

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

I notice that a number of people who use WebGL p5.Graphics objects run into issues at first when they don't call reset(), possibly because there aren't many examples that use it. For this example it doesn't matter if you reset or not, but if e.g. you used sphere instead of ellipse then you would see the sphere peeking out through the plane. How would you feel about using reset and sphere just so that people are aware of that method? It might be trying to do too much in one example, let me know what you think!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That sounds great, I have pushed a new commit using sphere() and reset(). How would you explain reset() to the user? I have added 'p5.Graphics sometimes requires us to use reset() before drawing', but that doesn't feel like it does enough to explain why.

Copy link
Contributor

@davepagurek davepagurek Jul 28, 2022

Choose a reason for hiding this comment

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

I guess the main thing that reset does is that it clears the depth buffer, so you can draw new things without the old things going in front. Kind of like ensuring everything from before just becomes background colours instead of 3D content. It also does some other stuff like resets lights though so best practice is probably to do it first thing. Maybe we can move it to the top with a comment like: "Keep the colors from before but reset all 3D information so new shapes always go on top of the existing colors"? Or a more succinct version of that if you can think of something!

Copy link
Member

@kjhollen kjhollen Aug 2, 2022

Choose a reason for hiding this comment

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

I think it's also worthwhile to comment why reset() isn't used for the swap object.

Generally, maybe it would be worthwhile to think of the simplest possible example using createGraphics that would motivate calling reset(). We do have an example here, but it's not linked from the main reference page: https://p5js.org/reference/#/p5.Graphics/reset (you first have to open the p5.Graphics reference). A good first step could be to add this simple example to createGraphics directly?

Another way I've seen this show up in teaching with a WebGL buffer is that students still expect the matrix transform to be reset with draw(). Could be a more succinct way to explain the concept on its own.

pg.noStroke();
pg.plane(width, height);

// draw our sphere on top
pg.push();
// slowly move the sphere in a circle
pg.translate(sin(millis() / 200) * 5, cos(millis() / 200) * 5, 0);
pg.fill(255);
pg.sphere(90);
pg.pop();

// draw a slightly scaled up copy of the texture
swap.push();
swap.scale(1.1, 1.1);
swap.texture(pg);
swap.noStroke();
swap.plane(width, height);
swap.pop();

// an opaque rectangle is drawn over top to control the feedback decay
swap.fill(0, 50);
swap.rect(-width / 2, -height / 2, width, height);

// draw the output to the screen
image(swap, 0, 0);
}