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

Add shaders for filter() constants, and use them by default in P2D #6324

Merged
merged 56 commits into from Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
568c4ec
mark structure for loading new shader files
wong-justin Aug 3, 2023
9f15a50
destructure args passed to p5.RendererGL.filter
wong-justin Aug 3, 2023
e2f123d
change public filter() signature
wong-justin Aug 3, 2023
bd8dab4
comment overloaded function parameters for clarity
wong-justin Aug 3, 2023
9a02645
whitespace
wong-justin Aug 4, 2023
5bbb980
start adding shaders for filter constants (GRAY)
wong-justin Aug 4, 2023
c1bfee4
fix by creating shaders on secondary graphics layer
wong-justin Aug 10, 2023
ef397a1
use old luminance constants for GRAY
wong-justin Aug 10, 2023
197c905
add texelSize as a default uniform
wong-justin Aug 10, 2023
1e34031
add ERODE
wong-justin Aug 10, 2023
4bf2565
add DILATE
wong-justin Aug 10, 2023
ed40a78
fix comments explaining what DILATE/ERODE do
wong-justin Aug 10, 2023
fc4181e
add BLUR
wong-justin Aug 10, 2023
a94936e
add partial POSTERIZE
wong-justin Aug 10, 2023
586e933
fix filterParameter by moving setUniform after pg.shader() call
wong-justin Aug 11, 2023
1e02d7f
adjust some examples for filter() docs
wong-justin Aug 11, 2023
e0deeeb
adjust wording for filter() docs
wong-justin Aug 11, 2023
5dc1056
fix POSTERIZE to match old output
wong-justin Aug 11, 2023
72f7895
simpler sketch for manual testing
wong-justin Aug 11, 2023
10e0cac
wip, start using shader filters in background of P2D
wong-justin Aug 11, 2023
9ae66c5
add OPAQUE
wong-justin Aug 18, 2023
7b71bc3
add INVERT
wong-justin Aug 18, 2023
2897670
add THRESHOLD
wong-justin Aug 18, 2023
aa1a7e0
add default filter params
wong-justin Aug 18, 2023
4f1b62c
add extra uniform for canvas size
wong-justin Aug 18, 2023
e734106
Merge remote-tracking branch 'upstream/main' into shader-filters
wong-justin Aug 18, 2023
88830eb
keep opacity in THRESHOLD instead of changing it
wong-justin Aug 18, 2023
cb6af67
remove default from inside BLUR shader
wong-justin Aug 18, 2023
89aa499
document new default filter parameters
wong-justin Aug 18, 2023
23c3db5
use min/max() instead of luma() for determining brightness
wong-justin Aug 18, 2023
92c7244
simplify example shader in filter()
wong-justin Aug 18, 2023
41cf4ba
document new uniforms, and slight rephrasing in createFilterShader
wong-justin Aug 18, 2023
6c2e9ce
add some tests
wong-justin Aug 18, 2023
9dc8887
store shaders for filters BLUR, INVERT, etc
wong-justin Aug 18, 2023
b1a76ec
more tests
wong-justin Aug 20, 2023
bafee00
fix feedback effect
wong-justin Aug 20, 2023
3c4afc5
clarify comments
wong-justin Aug 21, 2023
02d187b
support webgl2 fragment shader in createFilterShader()
wong-justin Aug 21, 2023
b5d533c
fix whitespace
wong-justin Aug 21, 2023
ec41c1f
replace single-pass blur with two-pass
wong-justin Aug 22, 2023
8ccfe59
adjust initial blur two-pass by using uniform(tex0, this)
wong-justin Aug 23, 2023
347401b
add variable to reverse flipping effect of previous commit
wong-justin Aug 23, 2023
39def40
remaining steps for blur, including removing extra shader calls
wong-justin Aug 23, 2023
0e6a95b
revise default vertex shader to deal with depth issue #6367
wong-justin Aug 28, 2023
be09142
fix rect() calls
wong-justin Aug 28, 2023
3e22945
update other default vertex shader as well
wong-justin Aug 28, 2023
eca2c76
switch to using main and secondary renderers for blur passes
wong-justin Aug 28, 2023
b0ef928
prevent error when in webgl mode and attempting to use cpu filters
Aug 29, 2023
547578b
testing different manual examples
Aug 29, 2023
44d8f2c
Move blur loop into the shader and use a second temp buffer for rende…
Aug 29, 2023
b7454db
remove unused code
wong-justin Aug 29, 2023
f04ddf8
Merge remote-tracking branch 'ferriss/shader-filters' into shader-fil…
wong-justin Aug 29, 2023
d0a2fe9
fix clear()ing at the right time
wong-justin Aug 30, 2023
b3583f7
remove unused uniform
wong-justin Aug 30, 2023
1bfe9c7
add tests for filter parameters
wong-justin Aug 30, 2023
121137f
Update pixels.js
aferriss Aug 31, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/webgl/p5.RendererGL.js
Expand Up @@ -89,6 +89,8 @@ const filterShaderFrags = {
readFileSync(join(__dirname, '/shaders/filters/dilate.frag'), 'utf-8'),
[constants.BLUR]:
readFileSync(join(__dirname, '/shaders/filters/blur.frag'), 'utf-8'),
[constants.POSTERIZE]:
readFileSync(join(__dirname, '/shaders/filters/posterize.frag'), 'utf-8')
};
const filterShaderVert = readFileSync(join(__dirname, '/shaders/filters/default.vert'), 'utf-8');

Expand Down
34 changes: 34 additions & 0 deletions src/webgl/shaders/filters/posterize.frag
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The POSTERIZE shader mostly works, but it looks a little different (and a little worse imo) compared to the original pixels POSTERIZE.
example sketch with old pixels filter
example sketch with this new shader

Pixels filter code for comparison of implementation details:

p5.js/src/image/filters.js

Lines 289 to 308 in 6d3405f

posterize(canvas, level) {
const pixels = Filters._toPixels(canvas);
if (level < 2 || level > 255) {
throw new Error(
'Level must be greater than 2 and less than 255 for posterize'
);
}
const levels1 = level - 1;
for (let i = 0; i < pixels.length; i += 4) {
const rlevel = pixels[i];
const glevel = pixels[i + 1];
const blevel = pixels[i + 2];
pixels[i] = ((rlevel * level) >> 8) * 255 / levels1;
pixels[i + 1] = ((glevel * level) >> 8) * 255 / levels1;
pixels[i + 2] = ((blevel * level) >> 8) * 255 / levels1;
}
},

  • Not sure how to handle validating the extra filter parameter; here it throws a vanilla error when outside 2-255. But others like BLUR and THRESHOLD just do their own little validation and fail silently if the parameter is invalid. Maybe I should add some extra friendly errors for each case? ('🌸 POSTERIZE only accepts a parameter from 2 to 255; received x', or 'THRESHOLD only accepts a parameter between 0.0 and 1.0; received x')

Copy link
Contributor

Choose a reason for hiding this comment

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

Interesting, I'll take a look and try to suss out whats going on here.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think your round was doing something weird. It should be a floor instead. See: https://editor.p5js.org/aferriss/sketches/mjQKudkIP

@@ -0,0 +1,34 @@
// Limit color space for a stylized cartoon / poster effect

precision highp float;

varying vec2 vTexCoord;

uniform sampler2D tex0;
uniform float filterParameter;

vec3 round(vec3 vals) {
// eg. round(5.5) -> 6.0
return floor(vals + 0.5);
}

vec3 quantize(vec3 color, float n) {
// restrict values to N options/bins
// and round each channel to nearest option
//
// eg. when N = 5, options = 0.0, 0.25, 0.50, 0.75, 1.0
// then posterize (0.1, 0.7, 0.9) -> (0.0, 0.75, 1.0)

color = color * n;
color = round(color);
color = color / (n - 1.0);
return color;
}

void main() {
vec4 color = texture2D(tex0, vTexCoord);

vec3 restrictedColor = quantize(color.rgb, filterParameter);

gl_FragColor = vec4(restrictedColor.rgb, color.a);
}