Skip to content

Commit 0842096

Browse files
authored
Merge pull request #7578 from Vaivaswat2244/stencil_test
Updated Stencil Test Case to prevent it from disable after every draw
2 parents 3cb5e8e + 08537ab commit 0842096

File tree

2 files changed

+141
-4
lines changed

2 files changed

+141
-4
lines changed

src/webgl/p5.RendererGL.js

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,29 @@ class RendererGL extends Renderer {
432432
this.drawShapeCount = 1;
433433

434434
this.scratchMat3 = new Matrix(3);
435+
436+
this._userEnabledStencil = false;
437+
// Store original methods for internal use
438+
this._internalEnable = this.drawingContext.enable;
439+
this._internalDisable = this.drawingContext.disable;
440+
441+
// Override WebGL enable function
442+
this.drawingContext.enable = (key) => {
443+
if (key === this.drawingContext.STENCIL_TEST) {
444+
if (!this._clipping) {
445+
this._userEnabledStencil = true;
446+
}
447+
}
448+
return this._internalEnable.call(this.drawingContext, key);
449+
};
450+
451+
// Override WebGL disable function
452+
this.drawingContext.disable = (key) => {
453+
if (key === this.drawingContext.STENCIL_TEST) {
454+
this._userEnabledStencil = false;
455+
}
456+
return this._internalDisable.call(this.drawingContext, key);
457+
};
435458
}
436459

437460
//////////////////////////////////////////////
@@ -1010,7 +1033,10 @@ class RendererGL extends Renderer {
10101033
//Clear depth every frame
10111034
this.GL.clearStencil(0);
10121035
this.GL.clear(this.GL.DEPTH_BUFFER_BIT | this.GL.STENCIL_BUFFER_BIT);
1013-
this.GL.disable(this.GL.STENCIL_TEST);
1036+
if (!this._userEnabledStencil) {
1037+
this._internalDisable.call(this.GL, this.GL.STENCIL_TEST);
1038+
}
1039+
10141040
}
10151041

10161042
/**
@@ -1402,7 +1428,7 @@ class RendererGL extends Renderer {
14021428
const gl = this.GL;
14031429
gl.clearStencil(0);
14041430
gl.clear(gl.STENCIL_BUFFER_BIT);
1405-
gl.enable(gl.STENCIL_TEST);
1431+
this._internalEnable.call(gl, gl.STENCIL_TEST);
14061432
this._stencilTestOn = true;
14071433
gl.stencilFunc(
14081434
gl.ALWAYS, // the test
@@ -1752,6 +1778,12 @@ class RendererGL extends Renderer {
17521778
this._pushPopDepth === this._clipDepths[this._clipDepths.length - 1]
17531779
) {
17541780
this._clearClip();
1781+
if (!this._userEnabledStencil) {
1782+
this._internalDisable.call(this.GL, this.GL.STENCIL_TEST);
1783+
}
1784+
1785+
// Reset saved state
1786+
// this._userEnabledStencil = this._savedStencilTestState;
17551787
}
17561788
super.pop(...args);
17571789
this._applyStencilTestIfClipping();
@@ -1760,10 +1792,12 @@ class RendererGL extends Renderer {
17601792
const drawTarget = this.drawTarget();
17611793
if (drawTarget._isClipApplied !== this._stencilTestOn) {
17621794
if (drawTarget._isClipApplied) {
1763-
this.GL.enable(this.GL.STENCIL_TEST);
1795+
this._internalEnable.call(this.GL, this.GL.STENCIL_TEST);
17641796
this._stencilTestOn = true;
17651797
} else {
1766-
this.GL.disable(this.GL.STENCIL_TEST);
1798+
if (!this._userEnabledStencil) {
1799+
this._internalDisable.call(this.GL, this.GL.STENCIL_TEST);
1800+
}
17671801
this._stencilTestOn = false;
17681802
}
17691803
}

test/unit/webgl/p5.RendererGL.js

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { suite } from 'vitest';
12
import p5 from '../../../src/app.js';
23
import '../../js/chai_helpers';
34
const toArray = (typedArray) => Array.from(typedArray);
@@ -2704,6 +2705,108 @@ suite('p5.RendererGL', function() {
27042705
);
27052706
});
27062707

2708+
suite('Stencil Test Tracking', function() {
2709+
test('Stencil test is disabled by default',
2710+
function() {
2711+
myp5.createCanvas(50, 50, myp5.WEBGL);
2712+
const gl = myp5._renderer.GL;
2713+
const isEnabled = gl.isEnabled(gl.STENCIL_TEST);
2714+
2715+
assert.equal(isEnabled, false);
2716+
assert.equal(myp5._renderer._userEnabledStencil, false);
2717+
}
2718+
);
2719+
2720+
test('Tracks when user manually enables stencil test',
2721+
function() {
2722+
myp5.createCanvas(50, 50, myp5.WEBGL);
2723+
const gl = myp5._renderer.GL;
2724+
2725+
gl.enable(gl.STENCIL_TEST);
2726+
assert.equal(myp5._renderer._userEnabledStencil, true);
2727+
assert.equal(gl.isEnabled(gl.STENCIL_TEST), true);
2728+
}
2729+
);
2730+
2731+
test('Tracks when user manually disables stencil test',
2732+
function() {
2733+
myp5.createCanvas(50, 50, myp5.WEBGL);
2734+
const gl = myp5._renderer.GL;
2735+
2736+
gl.enable(gl.STENCIL_TEST);
2737+
gl.disable(gl.STENCIL_TEST);
2738+
2739+
assert.equal(myp5._renderer._userEnabledStencil, false);
2740+
assert.equal(gl.isEnabled(gl.STENCIL_TEST), false);
2741+
}
2742+
);
2743+
2744+
test('Maintains stencil test state across draw cycles when user enabled',
2745+
function() {
2746+
let drawCalled = false;
2747+
2748+
myp5.createCanvas(50, 50, myp5.WEBGL);
2749+
const originalDraw = myp5.draw;
2750+
2751+
myp5.draw = function() {
2752+
drawCalled = true;
2753+
if (originalDraw) originalDraw.call(myp5);
2754+
};
2755+
2756+
const gl = myp5._renderer.GL;
2757+
gl.enable(gl.STENCIL_TEST);
2758+
assert.equal(gl.isEnabled(gl.STENCIL_TEST), true)
2759+
myp5.redraw();
2760+
2761+
assert.equal(gl.isEnabled(gl.STENCIL_TEST), true);
2762+
assert.equal(myp5._renderer._userEnabledStencil, true);
2763+
2764+
myp5.draw = originalDraw;
2765+
}
2766+
);
2767+
2768+
test('Internal clip operations preserve user stencil test setting',
2769+
function() {
2770+
myp5.createCanvas(50, 50, myp5.WEBGL);
2771+
const gl = myp5._renderer.GL;
2772+
2773+
gl.enable(gl.STENCIL_TEST);
2774+
2775+
myp5.push();
2776+
myp5.clip(() => {
2777+
myp5.rect(0, 0, 10, 10);
2778+
});
2779+
assert.equal(gl.isEnabled(gl.STENCIL_TEST), true)
2780+
myp5.pop();
2781+
2782+
assert.equal(myp5._renderer._userEnabledStencil, true);
2783+
assert.equal(gl.isEnabled(gl.STENCIL_TEST), true);
2784+
}
2785+
);
2786+
2787+
test('Internal clip operations do not enable stencil test for future draw cycles',
2788+
function() {
2789+
myp5.createCanvas(50, 50, myp5.WEBGL);
2790+
const gl = myp5._renderer.GL;
2791+
2792+
gl.disable(gl.STENCIL_TEST);
2793+
assert.equal(myp5._renderer._userEnabledStencil, false);
2794+
2795+
myp5.push();
2796+
myp5.clip(() => {
2797+
myp5.rect(0, 0, 10, 10);
2798+
});
2799+
assert.equal(gl.isEnabled(gl.STENCIL_TEST), true)
2800+
myp5.pop();
2801+
2802+
myp5.redraw();
2803+
2804+
assert.equal(myp5._renderer._userEnabledStencil, false);
2805+
assert.equal(gl.isEnabled(gl.STENCIL_TEST), false);
2806+
}
2807+
);
2808+
});
2809+
27072810
suite('Matrix getters', function() {
27082811
test('uModelMatrix', function() {
27092812
p5.registerAddon(function (p5, fn) {

0 commit comments

Comments
 (0)