Skip to content

Commit 65440c1

Browse files
committed
fix: preserve user-set uSampler for custom shaders
Don't override uSampler in _setFillUniforms when the user has explicitly set it via setUniform on their custom shader. Track user-set uniforms per shader instance and reset each frame. Fixes #8200
1 parent 012b46e commit 65440c1

3 files changed

Lines changed: 40 additions & 1 deletion

File tree

src/core/p5.Renderer3D.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,13 @@ export class Renderer3D extends Renderer {
729729

730730
//Clear depth every frame
731731
this._resetBuffersBeforeDraw();
732+
733+
if (this.states.userFillShader) {
734+
this.states.userFillShader._userSetUniforms?.clear();
735+
}
736+
if (this.states.userImageShader) {
737+
this.states.userImageShader._userSetUniforms?.clear();
738+
}
732739
}
733740

734741
background(...args) {
@@ -1493,6 +1500,7 @@ export class Renderer3D extends Renderer {
14931500
}
14941501

14951502
// TODO: optimize
1503+
fillShader._isInternalSetUniform = true;
14961504
fillShader.setUniform("uUseVertexColor", this._useVertexColor);
14971505
fillShader.setUniform("uMaterialColor", this.states.curFillColor);
14981506
fillShader.setUniform("isTexture", !!this.states._tex);
@@ -1501,7 +1509,9 @@ export class Renderer3D extends Renderer {
15011509
// the next time a shader is used. However, the texture() function
15021510
// works differently and is global p5 state. If the p5 state has
15031511
// been cleared, we also need to clear the value in uSampler to match.
1504-
fillShader.setUniform("uSampler", this.states._tex || empty);
1512+
if (!fillShader._userSetUniforms.has('uSampler')) {
1513+
fillShader.setUniform("uSampler", this.states._tex || empty);
1514+
}
15051515
fillShader.setUniform(
15061516
"uTint",
15071517
this.states.tint?._getRGBA([255, 255, 255, 255]) ?? [255, 255, 255, 255]
@@ -1594,6 +1604,7 @@ export class Renderer3D extends Renderer {
15941604
"uQuadraticAttenuation",
15951605
this.states.quadraticAttenuation
15961606
);
1607+
fillShader._isInternalSetUniform = false;
15971608
}
15981609

15991610
// getting called from _setFillUniforms

src/webgl/p5.Shader.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class Shader {
3939
this.attributes = {};
4040
this._loadedUniforms = false;
4141
this.uniforms = {};
42+
this._userSetUniforms = new Set();
4243
this._bound = false;
4344
this.samplers = [];
4445
this.hooks = {
@@ -1103,6 +1104,10 @@ class Shader {
11031104
return;
11041105
}
11051106

1107+
if (!this._isInternalSetUniform) {
1108+
this._userSetUniforms.add(uniformName);
1109+
}
1110+
11061111
// In p5.strands-related code, where some of the code may be in
11071112
// p5.webgpu.js instead of the main p5.js build, we generally use
11081113
// duck typing instead of instanceof to avoid accidentally importing

test/unit/webgl/p5.RendererGL.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,29 @@ suite('p5.RendererGL', function() {
208208
expect(uSampler.texture.isFramebufferTexture).toBeFalsy();
209209
myp5.pop();
210210
});
211+
212+
test('user-set uSampler on custom shader is not overridden', function() {
213+
myp5.createCanvas(10, 10, myp5.WEBGL);
214+
215+
const myShader = myp5.createFilterShader(`precision highp float;
216+
uniform sampler2D uSampler;
217+
varying vec2 vTexCoord;
218+
void main() {
219+
gl_FragColor = texture2D(uSampler, vTexCoord);
220+
}`);
221+
222+
const fbo = myp5.createFramebuffer();
223+
fbo.draw(() => myp5.background('red'));
224+
225+
myp5.shader(myShader);
226+
myp5.noStroke();
227+
myShader.setUniform('uSampler', fbo);
228+
229+
myp5.plane(myp5.width, myp5.height);
230+
231+
const pixel = myp5.get(5, 5);
232+
assert.deepEqual(pixel, [255, 0, 0, 255]);
233+
});
211234
});
212235

213236
suite('default stroke shader', function() {

0 commit comments

Comments
 (0)