Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
3 changes: 2 additions & 1 deletion src/image/pixels.js
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,8 @@ p5.prototype.filter = function(...args) {
// dest coords
-this.width/2, -this.height/2, this.width, this.height
);

//clearing the main canvas
this._renderer.clear();
// filter it with shaders
this.filterGraphicsLayer.filter(operation, value);
Copy link
Contributor

@davepagurek davepagurek Nov 5, 2023

Choose a reason for hiding this comment

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

I think we might still need to put the image() call below in between a push(), resetMatrix(), and pop() similar to what we do for WebGL, since it looks like it still has an offset here.

Edit: ignore me, I was testing on the wrong p5 build!

Copy link
Collaborator Author

@perminder-17 perminder-17 Nov 5, 2023

Choose a reason for hiding this comment

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

Okay. No problem


Expand Down
86 changes: 50 additions & 36 deletions src/webgl/p5.RendererGL.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ const defaultShaders = {
lineDefs + readFileSync(join(__dirname, '/shaders/line.frag'), 'utf-8'),
pointVert: readFileSync(join(__dirname, '/shaders/point.vert'), 'utf-8'),
pointFrag: readFileSync(join(__dirname, '/shaders/point.frag'), 'utf-8'),
imageLightVert : readFileSync(join(__dirname, '/shaders/imageLight.vert'), 'utf-8'),
imageLightDiffusedFrag : readFileSync(join(__dirname, '/shaders/imageLightDiffused.frag'), 'utf-8'),
imageLightSpecularFrag : readFileSync(join(__dirname, '/shaders/imageLightSpecular.frag'), 'utf-8')
imageLightVert: readFileSync(join(__dirname, '/shaders/imageLight.vert'), 'utf-8'),
imageLightDiffusedFrag: readFileSync(join(__dirname, '/shaders/imageLightDiffused.frag'), 'utf-8'),
imageLightSpecularFrag: readFileSync(join(__dirname, '/shaders/imageLightSpecular.frag'), 'utf-8')
};
for (const key in defaultShaders) {
defaultShaders[key] = webgl2CompatibilityShader + defaultShaders[key];
Expand Down Expand Up @@ -538,6 +538,10 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
this._curCamera._computeCameraDefaultSettings();
this._curCamera._setDefaultCamera();

// FilterCamera
this.filterCamera = new p5.Camera(this);
this.filterCamera._computeCameraDefaultSettings();
this.filterCamera._setDefaultCamera();
// Information about the previous frame's touch object
// for executing orbitControl()
this.prevTouches = [];
Expand Down Expand Up @@ -1078,7 +1082,7 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
// Create and store shader for constants once on initial filter call.
// Need to store multiple in case user calls different filters,
// eg. filter(BLUR) then filter(GRAY)
if ( !(operation in this.defaultFilterShaders) ) {
if (!(operation in this.defaultFilterShaders)) {
this.defaultFilterShaders[operation] = new p5.Shader(
pg._renderer,
filterShaderVert,
Expand Down Expand Up @@ -1109,7 +1113,7 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
this._pInst.noStroke();

// draw main to temp buffer
tmp.image(this, -this.width/2, -this.height/2);
tmp.image(this, -this.width / 2, -this.height / 2);

pg.shader(this.filterShader);
this.filterShader.setUniform('texelSize', texelSize);
Expand All @@ -1119,15 +1123,18 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
// horiz pass
this.filterShader.setUniform('direction', [1, 0]);
this.filterShader.setUniform('tex0', tmp);
pg.rect(-this.width/2, -this.height/2, this.width, this.height);
pg.clear();
pg.rect(-this.width / 2, -this.height / 2, this.width, this.height);

// read back to temp buffer
tmp.image(pg, -this.width/2, -this.height/2);
tmp.clear();
tmp.image(pg, -this.width / 2, -this.height / 2);

// vert pass
this.filterShader.setUniform('direction', [0, 1]);
this.filterShader.setUniform('tex0', tmp);
pg.rect(-this.width/2, -this.height/2, this.width, this.height);
pg.clear();
pg.rect(-this.width / 2, -this.height / 2, this.width, this.height);

this._pInst.pop();
}
Expand All @@ -1140,15 +1147,22 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
// filterParameter uniform only used for POSTERIZE, and THRESHOLD
// but shouldn't hurt to always set
this.filterShader.setUniform('filterParameter', filterParameter);
pg.rect(-this.width/2, -this.height/2, this.width, this.height);
pg.rect(-this.width / 2, -this.height / 2, this.width, this.height);

}
// draw pg contents onto main renderer
this._pInst.push();
pg._pInst.resetMatrix();
this._pInst.noStroke();
this._pInst.image(pg, -this.width/2, -this.height/2,
pg._pInst.imageMode(constants.CORNER);
pg._pInst.blendMode(constants.BLEND);
this.clear();
this._pInst.push();
pg._pInst.setCamera(this.filterCamera);
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 this one should be this._pInst.setCamera(...), since we're using it for the this._pInst.image call below.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

WhatsApp.Video.2023-11-03.at.21.06.48_d5719e17.mp4

this is the output.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

let me use this._pInst.setCamera()

this._pInst.image(pg, -this.width / 2, -this.height / 2,
this.width, this.height);
this._pInst.pop();
this._pInst.pop();
}

blendMode(mode) {
Expand Down Expand Up @@ -1762,17 +1776,17 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
this._defaultLightShader = new p5.Shader(
this,
this._webGL2CompatibilityPrefix('vert', 'highp') +
defaultShaders.phongVert,
defaultShaders.phongVert,
this._webGL2CompatibilityPrefix('frag', 'highp') +
defaultShaders.phongFrag
defaultShaders.phongFrag
);
} else {
this._defaultLightShader = new p5.Shader(
this,
this._webGL2CompatibilityPrefix('vert', 'highp') +
defaultShaders.lightVert,
defaultShaders.lightVert,
this._webGL2CompatibilityPrefix('frag', 'highp') +
defaultShaders.lightTextureFrag
defaultShaders.lightTextureFrag
);
}
}
Expand All @@ -1785,9 +1799,9 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
this._defaultImmediateModeShader = new p5.Shader(
this,
this._webGL2CompatibilityPrefix('vert', 'mediump') +
defaultShaders.immediateVert,
defaultShaders.immediateVert,
this._webGL2CompatibilityPrefix('frag', 'mediump') +
defaultShaders.vertexColorFrag
defaultShaders.vertexColorFrag
);
}

Expand All @@ -1799,9 +1813,9 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
this._defaultNormalShader = new p5.Shader(
this,
this._webGL2CompatibilityPrefix('vert', 'mediump') +
defaultShaders.normalVert,
defaultShaders.normalVert,
this._webGL2CompatibilityPrefix('frag', 'mediump') +
defaultShaders.normalFrag
defaultShaders.normalFrag
);
}

Expand All @@ -1813,9 +1827,9 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
this._defaultColorShader = new p5.Shader(
this,
this._webGL2CompatibilityPrefix('vert', 'mediump') +
defaultShaders.normalVert,
defaultShaders.normalVert,
this._webGL2CompatibilityPrefix('frag', 'mediump') +
defaultShaders.basicFrag
defaultShaders.basicFrag
);
}

Expand All @@ -1827,9 +1841,9 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
this._defaultPointShader = new p5.Shader(
this,
this._webGL2CompatibilityPrefix('vert', 'mediump') +
defaultShaders.pointVert,
defaultShaders.pointVert,
this._webGL2CompatibilityPrefix('frag', 'mediump') +
defaultShaders.pointFrag
defaultShaders.pointFrag
);
}
return this._defaultPointShader;
Expand All @@ -1840,9 +1854,9 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
this._defaultLineShader = new p5.Shader(
this,
this._webGL2CompatibilityPrefix('vert', 'mediump') +
defaultShaders.lineVert,
defaultShaders.lineVert,
this._webGL2CompatibilityPrefix('frag', 'mediump') +
defaultShaders.lineFrag
defaultShaders.lineFrag
);
}

Expand Down Expand Up @@ -1916,9 +1930,9 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
* Returns the blurry image
* maps a p5.Image used by imageLight() to a p5.Graphics
*/
getDiffusedTexture(input){
getDiffusedTexture(input) {
// if one already exists for a given input image
if(this.diffusedTextures.get(input)!=null){
if (this.diffusedTextures.get(input) != null) {
return this.diffusedTextures.get(input);
}
// if not, only then create one
Expand Down Expand Up @@ -1952,18 +1966,18 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
* Storing the texture for input image in map called `specularTextures`
* maps the input p5.Image to a p5.MipmapTexture
*/
getSpecularTexture(input){
getSpecularTexture(input) {
// check if already exits (there are tex of diff resolution so which one to check)
// currently doing the whole array
if(this.specularTextures.get(input)!=null){
if (this.specularTextures.get(input) != null) {
return this.specularTextures.get(input);
}
// Hardcoded size
const size = 512;
let tex;
const levels = [];
const graphic = this._pInst.createGraphics(size, size, constants.WEBGL);
let count = Math.log(size)/Math.log(2);
let count = Math.log(size) / Math.log(2);
graphic.pixelDensity(1);
// currently only 8 levels
// This loop calculates 8 graphics of varying size of canvas
Expand All @@ -1972,8 +1986,8 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
// because rougher surfaces have less detailed/more blurry reflections.
for (let w = size; w >= 1; w /= 2) {
graphic.resizeCanvas(w, w);
let currCount = Math.log(w)/Math.log(2);
let roughness = 1-currCount/count;
let currCount = Math.log(w) / Math.log(2);
let roughness = 1 - currCount / count;
let myShader = graphic.createShader(
defaultShaders.imageLightVert,
defaultShaders.imageLightSpecularFrag
Expand All @@ -1988,7 +2002,7 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
}
graphic.remove();
tex = new MipmapTexture(this, levels, {});
this.specularTextures.set(input,tex);
this.specularTextures.set(input, tex);
return tex;
}

Expand Down Expand Up @@ -2090,9 +2104,9 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
}

// getting called from _setFillUniforms
_setImageLightUniforms(shader){
_setImageLightUniforms(shader) {
//set uniform values
shader.setUniform('uUseImageLight', this.activeImageLight != null );
shader.setUniform('uUseImageLight', this.activeImageLight != null);
// true
if (this.activeImageLight) {
// this.activeImageLight has image as a key
Expand All @@ -2106,8 +2120,8 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
// only calculated 8 different levels of roughness
// The factor of 20 is just to spread up this range so that,
// [1, max] of shininess is converted to [0,160] of roughness
let roughness = 20/this._useShininess;
shader.setUniform('levelOfDetail', roughness*8);
let roughness = 20 / this._useShininess;
shader.setUniform('levelOfDetail', roughness * 8);
shader.setUniform('environmentMapSpecular', specularLight);
}
}
Expand Down
9 changes: 7 additions & 2 deletions src/webgl/shaders/filters/invert.frag
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ uniform sampler2D tex0;

void main() {
vec4 color = texture2D(tex0, vTexCoord);
vec3 invertedColor = 1.0 - color.rgb;
gl_FragColor = vec4(invertedColor, color.a);
vec3 invertedColor = vec3(1.0) - color.rgb; // Declare and calculate invertedColor
//checking if pixel is opaque
if (color.a == 1.0) {
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 this will still break for colors that are semitransparent, since they'll go through the else branch.

To explain a bit about what's happening, the colors here are premultiplied, meaning color.r is actually the original r value multiplied by color.a.

So if we want to invert just the original colors but keep the alpha, maybe we need:

vec3 origColor = color.rgb / color.a;
vec3 invertedColor = vec3(1.0) - origColor;
gl_FragColor = vec4(invertedColor * color.a, color.a);

gl_FragColor = vec4(invertedColor, color.a);
} else {
gl_FragColor = color;
}
}