Skip to content

Adds createFilterShader() and custom shader support to the webGL filter() function #6237

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

Merged
merged 50 commits into from
Aug 2, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
16def01
declare framebuffer usage
wong-justin Jun 23, 2023
c7abb8c
new properties for shader filters
wong-justin Jun 23, 2023
9dbe595
partial shader filter implementation instead of error
wong-justin Jun 23, 2023
a096914
add new filter() signature
wong-justin Jun 23, 2023
87f347a
branch filter() for either webgl mode or 2d mode, not just 2d
wong-justin Jun 23, 2023
e0126bf
revert to p5.Graphics instead of p5.Framebuffer, at least for now
wong-justin Jun 29, 2023
cb1979b
apply shader to secondary graphics, then draw onto main
wong-justin Jun 29, 2023
644e61a
Merge remote-tracking branch 'upstream/main' into shader-filters
wong-justin Jun 29, 2023
628fc18
add manual test for webgl filter()
wong-justin Jun 30, 2023
359d16b
add some automated webgl filter tests
wong-justin Jun 30, 2023
e857d5b
remove confused arguments
wong-justin Jun 30, 2023
a762869
create new shader bound to secondary graphics
wong-justin Jun 30, 2023
2eb64a0
add tests to check sizing
wong-justin Jun 30, 2023
0c5d0ff
docs for filter(shader)
wong-justin Jul 7, 2023
10d85ff
add resizing to secondary graphics
wong-justin Jul 7, 2023
f324437
only create secondary shader once
wong-justin Jul 7, 2023
7f39f69
leave out filter(CONSTANT) test until that feature is added
wong-justin Jul 7, 2023
fc50e52
remove resolution check because pixel density wont change
wong-justin Jul 7, 2023
f3a41e7
remove framebuffer test since framebuffer isnt used for now
wong-justin Jul 7, 2023
7888ad4
fill in empty tests
wong-justin Jul 7, 2023
b52a467
wip: copy uniforms to shader copy
wong-justin Jul 7, 2023
02113bb
add performance visual to filter test page
wong-justin Jul 13, 2023
be7c01c
Merge remote-tracking branch 'upstream/main' into shader-filters
wong-justin Jul 13, 2023
aa1f048
expose the built library
wong-justin Jul 13, 2023
5d50053
rebuild p5.min.js
wong-justin Jul 13, 2023
4e52976
add non-minified library too
wong-justin Jul 13, 2023
590d025
fix parent shader check
wong-justin Jul 13, 2023
f2e69ae
remove tabs and console.log
wong-justin Jul 14, 2023
6e4c04e
add createFilterShader that includes default vertex shader
wong-justin Jul 14, 2023
f23d072
update output lib
wong-justin Jul 14, 2023
034ebb5
clean whitespace
wong-justin Jul 14, 2023
7bfa2f2
stop tracking output libs
wong-justin Jul 14, 2023
f6fbdc2
test for createFilterShader()
wong-justin Jul 14, 2023
86cb79d
mark todos for next PR
wong-justin Jul 14, 2023
bf282f3
fix gitignore
wong-justin Jul 14, 2023
25424c7
document uniforms
wong-justin Jul 21, 2023
d1dd620
refine example fragment shaders
wong-justin Jul 21, 2023
fa178ba
default vertex shader
wong-justin Jul 21, 2023
68ad8ae
rest of createFilterShader docs
wong-justin Jul 21, 2023
c039991
adjust test shaders to match default filter shaders
wong-justin Jul 21, 2023
c476759
add test comparing default vertex shader to a supplied one
wong-justin Jul 21, 2023
4b1e56e
revert pre-flipping the y in the vertex shader
wong-justin Jul 28, 2023
ec76701
add test for edge case of filter shader on graphics context
wong-justin Jul 28, 2023
8220071
move uniform documentation to setUniform
wong-justin Jul 28, 2023
44ad94f
add disclaimers to createFilterShader docs
wong-justin Jul 28, 2023
a532146
Merge remote-tracking branch 'upstream/main' into shader-filters
wong-justin Jul 28, 2023
479aca3
go back to flipping the y
wong-justin Jul 29, 2023
4250399
fix filter() not working on a secondary p5.Graphics
wong-justin Jul 29, 2023
5abd47d
small wording changes in createFilterShader docs
wong-justin Jul 29, 2023
51aa874
remove unused commented code from test
wong-justin Aug 2, 2023
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
51 changes: 33 additions & 18 deletions src/webgl/p5.RendererGL.js
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,7 @@ p5.RendererGL = class RendererGL extends p5.Renderer {

// for post processing step
this.filterShader = undefined;
this.filterFramebuffer = undefined;
this.filterGraphicsLayer = undefined;

this.textureMode = constants.IMAGE;
// default wrap settings
Expand Down Expand Up @@ -879,29 +879,44 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
this.curStrokeJoin = join;
}

filter(...args) {
// Couldn't create filterFramebuffer in RendererGL constructor
// (.framebuffers was still undefined)
filter(userShader) {
// Couldn't create graphics in RendererGL constructor
// (led to infinite loop)
// so it's just created here once on the initial filter call.
if (!this.filterFramebuffer) {
this.filterFramebuffer = new p5.Framebuffer(this._pInst);
if (!this.filterGraphicsLayer) {
this.filterGraphicsLayer =
new p5.Graphics(this.width, this.height, constants.WEBGL, this._pInst);
Copy link
Contributor

Choose a reason for hiding this comment

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

Could it not be working with pgraphics because this._pInst is referring to the main sketch?

}

// TODO:
// TODO, handle different signatures:
// if args[0] is a p5.Shader,
// this.filterShader = args[0]
// else
// this.filterShader = selectFromShaderFilterDefaults(args[0])
// filterOperation = undefined or args[1]
//
// this.filterFramebuffer.begin();
//
// apply shader
// transfer pixels to main canvas
//
// this.filterFramebuffer.end();

p5._friendlyError('webgl filter implementation in progress');
// this.filterShader = map(args[0], {GRAYSCALE: grayscaleShader, ...})
// filterOperationParameter = undefined or args[1]

let pg = this.filterGraphicsLayer;

// not sure why userShader[0] is the actual shader object
// and userShader is Arguments instead
userShader = userShader[0];
// perhaps necessary: bind the shader to the pg renderer, not the main
// let userShaderCopy =
// new p5.Shader(pg._renderer, userShader._vertSrc, userShader._fragSrc);

// apply shader to pg
// TODO: shader isn't being applied properly
pg.shader(userShader);
userShader.setUniform('tex0', this);

// draw pg contents onto main renderer
this._pInst.push();
this._pInst.noStroke(); // don't draw triangles for plane() geometry
this._pInst.texture(pg);
this._pInst.plane(this.width, this.height);
this._pInst.pop();

// p5._friendlyError('webgl filter implementation in progress');
}

blendMode(mode) {
Expand Down
16 changes: 16 additions & 0 deletions test/manual-test-examples/webgl/filter/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="../../styles.css">
<script language="javascript" type="text/javascript" src="../../../../lib/p5.js"></script>
<script language="javascript" type="text/javascript" src="sketch.js"></script>
</head>

<body>
</body>

</html>
44 changes: 44 additions & 0 deletions test/manual-test-examples/webgl/filter/sketch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
function setup() {
createCanvas(100, 100, WEBGL);

let s = createShader(vert, frag);

// check to see if frag shader changes color as intended
// and that vertex shader preserves position, orientation, scale
background('RED');
circle(10,25,30);

filter(s);

// and that there's no side effects after filter()
circle(-35,-35,30);
}

vert = `attribute vec3 aPosition;
attribute vec2 aTexCoord;

varying vec2 vTexCoord;

void main() {
vTexCoord = aTexCoord;
vec4 positionVec4 = vec4(aPosition, 1.0);
positionVec4.xy = positionVec4.xy * 2.0 - 1.0;
gl_Position = positionVec4;
}`;

frag = `precision mediump float;
varying mediump vec2 vTexCoord;

uniform sampler2D tex0;

float luma(vec3 color) {
return dot(color, vec3(0.299, 0.587, 0.114));
}

void main() {
vec2 uv = vTexCoord;
uv.y = 1.0 - uv.y;
vec4 sampledColor = texture2D(tex0, uv);
float gray = luma(sampledColor.rgb);
gl_FragColor = vec4(gray, gray, gray, 1);
}`;
79 changes: 79 additions & 0 deletions test/unit/webgl/p5.RendererGL.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,85 @@ suite('p5.RendererGL', function() {
});
});

suite('filter shader', function() {
setup(function() {
vert = `attribute vec3 aPosition;
attribute vec2 aTexCoord;

varying vec2 vTexCoord;

void main() {
vTexCoord = aTexCoord;
vec4 positionVec4 = vec4(aPosition, 1.0);
positionVec4.xy = positionVec4.xy * 2.0 - 1.0;
gl_Position = positionVec4;
}`;

frag = `precision mediump float;
varying mediump vec2 vTexCoord;

uniform sampler2D tex0;

float luma(vec3 color) {
return dot(color, vec3(0.299, 0.587, 0.114));
}

void main() {
vec2 uv = vTexCoord;
uv.y = 1.0 - uv.y;
vec4 sampledColor = texture2D(tex0, uv);
float gray = luma(sampledColor.rgb);
gl_FragColor = vec4(gray, gray, gray, 1);
}`;
});

teardown(function() {
});

test('filter accepts correct params', function() {
myp5.createCanvas(5, 5, myp5.WEBGL);
let s = myp5.createShader(vert, frag);
myp5.filter(s);
// TODO: myp5.filter(myp5.POSTERIZE, 64)
});

test('secondary graphics layer is instantiated', function() {
let renderer = myp5.createCanvas(5, 5, myp5.WEBGL);
let s = myp5.createShader(vert, frag);
myp5.filter(s);
assert.notStrictEqual(renderer.filterGraphicsLayer, undefined);
});

test('custom shader makes changes to main canvas', function() {
myp5.createCanvas(5, 5, myp5.WEBGL);
let s = myp5.createShader(vert, frag);
myp5.background('RED');
myp5.loadPixels();
let p1 = myp5.pixels.slice(); // copy before pixels is reassigned
myp5.filter(s);
myp5.loadPixels();
let p2 = myp5.pixels;
assert.notDeepEqual(p1, p2);
});

test('default shader makes changes to main canvas', function() {
});

test('create graphics is unaffected after filter', function() {
});

test('framebuffer is unaffected after filter', function() {
});

test('stroke and other settings are unaffected after filter', function() {
});

test('geometries added after filter do not have shader applied', function() {
});


});

suite('text shader', function() {
test('rendering looks the same in WebGL1 and 2', function(done) {
myp5.loadFont('manual-test-examples/p5.Font/Inconsolata-Bold.ttf', function(font) {
Expand Down