From 5f00840f734fd7bf4a9d221dbac93cbe9559d048 Mon Sep 17 00:00:00 2001 From: Perminder Singh Date: Thu, 30 Nov 2023 01:55:15 +0530 Subject: [PATCH 1/2] Improved imageLight performance by implementing framebuffer instead of graphics --- src/webgl/light.js | 1 + src/webgl/p5.RendererGL.js | 82 +++++++++++++++++++++----------------- 2 files changed, 47 insertions(+), 36 deletions(-) diff --git a/src/webgl/light.js b/src/webgl/light.js index e8c8079248..fcfd9e60d5 100644 --- a/src/webgl/light.js +++ b/src/webgl/light.js @@ -1144,6 +1144,7 @@ p5.prototype.noLights = function(...args) { this._assert3d('noLights'); p5._validateParameters('noLights', args); + this._renderer.activeImageLight = null; this._renderer._enableLighting = false; this._renderer.ambientLightColors.length = 0; diff --git a/src/webgl/p5.RendererGL.js b/src/webgl/p5.RendererGL.js index 3c4aa212fc..29f8c3f6f6 100644 --- a/src/webgl/p5.RendererGL.js +++ b/src/webgl/p5.RendererGL.js @@ -480,10 +480,10 @@ p5.RendererGL = class RendererGL extends p5.Renderer { this.activeImageLight = null; // If activeImageLight property is Null, diffusedTextures, // specularTextures are Empty. - // Else, it maps a p5.Image used by imageLight() to a p5.Graphics. - // p5.Graphics for this are calculated in getDiffusedTexture function + // Else, it maps a p5.Image used by imageLight() to a p5.framebuffer. + // p5.framebuffer for this are calculated in getDiffusedTexture function this.diffusedTextures = new Map(); - // p5.Graphics for this are calculated in getSpecularTexture function + // p5.framebuffer for this are calculated in getSpecularTexture function this.specularTextures = new Map(); this.drawMode = constants.FILL; @@ -553,6 +553,7 @@ p5.RendererGL = class RendererGL extends p5.Renderer { this.executeZoom = false; this.executeRotateAndMove = false; + this.specularShader = undefined; this._defaultLightShader = undefined; this._defaultImmediateModeShader = undefined; this._defaultNormalShader = undefined; @@ -1914,7 +1915,7 @@ p5.RendererGL = class RendererGL extends p5.Renderer { * To create a blurry image from the input non blurry img, if it doesn't already exist * Add it to the diffusedTexture map, * Returns the blurry image - * maps a p5.Image used by imageLight() to a p5.Graphics + * maps a p5.Image used by imageLight() to a p5.Framebuffer */ getDiffusedTexture(input) { // if one already exists for a given input image @@ -1922,25 +1923,28 @@ p5.RendererGL = class RendererGL extends p5.Renderer { return this.diffusedTextures.get(input); } // if not, only then create one - let newGraphic; // maybe switch to framebuffer + let newFramebuffer; // hardcoded to 200px, because it's going to be blurry and smooth let smallWidth = 200; let width = smallWidth; let height = Math.floor(smallWidth * (input.height / input.width)); - newGraphic = this._pInst.createGraphics(width, height, constants.WEBGL); - // create graphics is like making a new sketch, all functions on main - // sketch it would be available on graphics - let irradiance = newGraphic.createShader( - defaultShaders.imageLightVert, - defaultShaders.imageLightDiffusedFrag - ); - newGraphic.shader(irradiance); - irradiance.setUniform('environmentMap', input); - newGraphic.noStroke(); - newGraphic.rectMode(newGraphic.CENTER); - newGraphic.rect(0, 0, newGraphic.width, newGraphic.height); - this.diffusedTextures.set(input, newGraphic); - return newGraphic; + newFramebuffer = this._pInst.createFramebuffer(); + // create framebuffer is like making a new sketch, all functions on main + // sketch it would be available on framebuffer + newFramebuffer.draw(() => { + let irradiance = this._pInst.createShader( + defaultShaders.imageLightVert, + defaultShaders.imageLightDiffusedFrag + ); + this._pInst.shader(irradiance); + irradiance.setUniform('environmentMap', input); + this._pInst.noStroke(); + this._pInst.rectMode(constants.CENTER); + this._pInst.noLights(); + this._pInst.rect(0, 0, width, height); + }); + this.diffusedTextures.set(input, newFramebuffer); + return newFramebuffer; } /* @@ -1962,31 +1966,37 @@ p5.RendererGL = class RendererGL extends p5.Renderer { const size = 512; let tex; const levels = []; - const graphic = this._pInst.createGraphics(size, size, constants.WEBGL); + const framebuffer = this._pInst.createFramebuffer(); let count = Math.log(size) / Math.log(2); - graphic.pixelDensity(1); + framebuffer.pixelDensity(1); + if (!this.specularShader) { + this.specularShader = this._pInst.createShader( + defaultShaders.imageLightVert, + defaultShaders.imageLightSpecularFrag + ); + } // currently only 8 levels - // This loop calculates 8 graphics of varying size of canvas + // This loop calculates 8 framebuffers of varying size of canvas // and corresponding different roughness levels. // Roughness increases with the decrease in canvas size, // because rougher surfaces have less detailed/more blurry reflections. for (let w = size; w >= 1; w /= 2) { - graphic.resizeCanvas(w, w); + framebuffer.resize(w, w); let currCount = Math.log(w) / Math.log(2); let roughness = 1 - currCount / count; - let myShader = graphic.createShader( - defaultShaders.imageLightVert, - defaultShaders.imageLightSpecularFrag - ); - graphic.shader(myShader); - graphic.clear(); - myShader.setUniform('environmentMap', input); - myShader.setUniform('roughness', roughness); - graphic.noStroke(); - graphic.plane(w, w); - levels.push(graphic.get().drawingContext.getImageData(0, 0, w, w)); - } - graphic.remove(); + framebuffer.draw(() => { + this._pInst.shader(this.specularShader); + this._pInst.clear(); + this.specularShader.setUniform('environmentMap', input); + this.specularShader.setUniform('roughness', roughness); + this._pInst.noStroke(); + this._pInst.noLights(); + this._pInst.plane(w, w); + }); + levels.push(framebuffer.get().drawingContext.getImageData(0, 0, w, w)); + } + // Free the Framebuffer + framebuffer.remove(); tex = new MipmapTexture(this, levels, {}); this.specularTextures.set(input, tex); return tex; From 12d67f0cac2f1d64d07dd62e2490688db3343b40 Mon Sep 17 00:00:00 2001 From: Perminder Singh <127239756+perminder-17@users.noreply.github.com> Date: Thu, 30 Nov 2023 23:42:42 +0530 Subject: [PATCH 2/2] fixes.js --- src/webgl/p5.RendererGL.js | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/webgl/p5.RendererGL.js b/src/webgl/p5.RendererGL.js index 29f8c3f6f6..ac76ac23d0 100644 --- a/src/webgl/p5.RendererGL.js +++ b/src/webgl/p5.RendererGL.js @@ -554,6 +554,7 @@ p5.RendererGL = class RendererGL extends p5.Renderer { this.executeRotateAndMove = false; this.specularShader = undefined; + this.diffusedShader = undefined; this._defaultLightShader = undefined; this._defaultImmediateModeShader = undefined; this._defaultNormalShader = undefined; @@ -1928,16 +1929,20 @@ p5.RendererGL = class RendererGL extends p5.Renderer { let smallWidth = 200; let width = smallWidth; let height = Math.floor(smallWidth * (input.height / input.width)); - newFramebuffer = this._pInst.createFramebuffer(); + newFramebuffer = this._pInst.createFramebuffer({ + width, height, density: 1 + }); // create framebuffer is like making a new sketch, all functions on main // sketch it would be available on framebuffer - newFramebuffer.draw(() => { - let irradiance = this._pInst.createShader( + if (!this.diffusedShader) { + this.diffusedShader = this._pInst.createShader( defaultShaders.imageLightVert, defaultShaders.imageLightDiffusedFrag ); - this._pInst.shader(irradiance); - irradiance.setUniform('environmentMap', input); + } + newFramebuffer.draw(() => { + this._pInst.shader(this.diffusedShader); + this.diffusedShader.setUniform('environmentMap', input); this._pInst.noStroke(); this._pInst.rectMode(constants.CENTER); this._pInst.noLights(); @@ -1966,9 +1971,10 @@ p5.RendererGL = class RendererGL extends p5.Renderer { const size = 512; let tex; const levels = []; - const framebuffer = this._pInst.createFramebuffer(); + const framebuffer = this._pInst.createFramebuffer({ + width: size, height: size, density: 1 + }); let count = Math.log(size) / Math.log(2); - framebuffer.pixelDensity(1); if (!this.specularShader) { this.specularShader = this._pInst.createShader( defaultShaders.imageLightVert,