diff --git a/examples/files.json b/examples/files.json
index e67c9ac04f3979..e704fd87b33b47 100644
--- a/examples/files.json
+++ b/examples/files.json
@@ -317,6 +317,7 @@
"webgpu_centroid_sampling",
"webgpu_clearcoat",
"webgpu_clipping",
+ "webgpu_clipping_stencil",
"webgpu_compile_async",
"webgpu_compute_audio",
"webgpu_compute_birds",
diff --git a/examples/screenshots/webgpu_clipping_stencil.jpg b/examples/screenshots/webgpu_clipping_stencil.jpg
new file mode 100644
index 00000000000000..dbe8c4d6bab321
Binary files /dev/null and b/examples/screenshots/webgpu_clipping_stencil.jpg differ
diff --git a/examples/webgpu_clipping_stencil.html b/examples/webgpu_clipping_stencil.html
new file mode 100644
index 00000000000000..a3ff121284a010
--- /dev/null
+++ b/examples/webgpu_clipping_stencil.html
@@ -0,0 +1,321 @@
+
+
+
+ three.js webgpu - clipping stencil
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Solid geometry with clip planes and stencil materials.
+
+
+
+
+
+
+
+
diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js
index a86234d1f0bd53..cf2b0cc6b10162 100644
--- a/src/renderers/WebGLRenderer.js
+++ b/src/renderers/WebGLRenderer.js
@@ -3256,6 +3256,7 @@ class WebGLRenderer {
_gl.bufferData( _gl.PIXEL_PACK_BUFFER, buffer.byteLength, _gl.STREAM_READ );
_gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), 0 );
+ _gl.bindBuffer( _gl.PIXEL_PACK_BUFFER, null );
// reset the frame buffer to the currently set buffer before waiting
const currFramebuffer = _currentRenderTarget !== null ? properties.get( _currentRenderTarget ).__webglFramebuffer : null;
@@ -3271,6 +3272,7 @@ class WebGLRenderer {
// read the data and delete the buffer
_gl.bindBuffer( _gl.PIXEL_PACK_BUFFER, glBuffer );
_gl.getBufferSubData( _gl.PIXEL_PACK_BUFFER, 0, buffer );
+ _gl.bindBuffer( _gl.PIXEL_PACK_BUFFER, null );
_gl.deleteBuffer( glBuffer );
_gl.deleteSync( sync );
diff --git a/src/renderers/common/ClippingContext.js b/src/renderers/common/ClippingContext.js
index 1ed98b973eeb54..d441736f01bfa2 100644
--- a/src/renderers/common/ClippingContext.js
+++ b/src/renderers/common/ClippingContext.js
@@ -5,6 +5,8 @@ import { Vector4 } from '../../math/Vector4.js';
const _plane = /*@__PURE__*/ new Plane();
+let _clippingContextId = 0;
+
/**
* Represents the state that is used to perform clipping via clipping planes.
* There is a default clipping context for each render context. When the
@@ -22,6 +24,14 @@ class ClippingContext {
*/
constructor( parentContext = null ) {
+ /**
+ * The id of the clipping context.
+ *
+ * @type {number}
+ * @readonly
+ */
+ this.id = _clippingContextId ++;
+
/**
* The clipping context's version.
*
@@ -222,7 +232,7 @@ class ClippingContext {
if ( update ) {
this.version ++;
- this.cacheKey = `${ this.intersectionPlanes.length }:${ this.unionPlanes.length }`;
+ this.cacheKey = `${ this.id }:${ this.intersectionPlanes.length }:${ this.unionPlanes.length }`;
}
diff --git a/src/renderers/webgl-fallback/WebGLBackend.js b/src/renderers/webgl-fallback/WebGLBackend.js
index ff4bb212b9407d..00649a36bbe28a 100644
--- a/src/renderers/webgl-fallback/WebGLBackend.js
+++ b/src/renderers/webgl-fallback/WebGLBackend.js
@@ -821,6 +821,7 @@ class WebGLBackend extends Backend {
const clearStencil = renderer.getClearStencil();
if ( depth ) this.state.setDepthMask( true );
+ if ( stencil ) this.state.setStencilMask( 0xffffffff );
if ( descriptor.textures === null ) {
diff --git a/src/renderers/webgl-fallback/utils/WebGLState.js b/src/renderers/webgl-fallback/utils/WebGLState.js
index 1fb2f4fa6ea106..897be18b97d081 100644
--- a/src/renderers/webgl-fallback/utils/WebGLState.js
+++ b/src/renderers/webgl-fallback/utils/WebGLState.js
@@ -959,28 +959,27 @@ class WebGLState {
? this.enable( gl.SAMPLE_ALPHA_TO_COVERAGE )
: this.disable( gl.SAMPLE_ALPHA_TO_COVERAGE );
- if ( hardwareClippingPlanes > 0 ) {
- if ( this.currentClippingPlanes !== hardwareClippingPlanes ) {
+ if ( this.currentClippingPlanes !== hardwareClippingPlanes ) {
- const CLIP_DISTANCE0_WEBGL = 0x3000;
+ const CLIP_DISTANCE0_WEBGL = 0x3000;
- for ( let i = 0; i < 8; i ++ ) {
+ for ( let i = 0; i < 8; i ++ ) {
- if ( i < hardwareClippingPlanes ) {
+ if ( i < hardwareClippingPlanes ) {
- this.enable( CLIP_DISTANCE0_WEBGL + i );
+ this.enable( CLIP_DISTANCE0_WEBGL + i );
- } else {
-
- this.disable( CLIP_DISTANCE0_WEBGL + i );
+ } else {
- }
+ this.disable( CLIP_DISTANCE0_WEBGL + i );
}
}
+ this.currentClippingPlanes = hardwareClippingPlanes;
+
}
}
diff --git a/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js b/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js
index 4387a3f2486550..b9b4f131c69f0d 100644
--- a/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js
+++ b/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js
@@ -1281,6 +1281,7 @@ class WebGLTextureUtils {
backend.state.bindFramebuffer( gl.READ_FRAMEBUFFER, null );
+ gl.deleteBuffer( buffer );
gl.deleteFramebuffer( fb );
return dstBuffer;