Skip to content

Commit f765d87

Browse files
WebGLRenderer: Add WEBGL_clip_cull_distance support. (#27371)
* init WEBGL_clip_cull_distance support * remove unecessary conditions webgl2 * try fix directx * feedbacks * remove unecessary code * Update webgl_clipculldistance.html Style clean up. * Update WebGLExtensions.js * Update webgl_clipculldistance.html * replace material with shader * remove unused time const * Update webgl_clipculldistance.html Simplify example. * Update clipping example. * Revert builds. * ShaderMaterial: Update `extensions` and docs. --------- Co-authored-by: Michael Herzog <[email protected]>
1 parent 7f29595 commit f765d87

File tree

12 files changed

+218
-8
lines changed

12 files changed

+218
-8
lines changed

docs/api/ar/materials/ShaderMaterial.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -327,8 +327,8 @@ <h3>[property:Object extensions]</h3>
327327
derivatives: false, // set to use derivatives
328328
fragDepth: false, // set to use fragment depth values
329329
drawBuffers: false, // set to use draw buffers
330-
shaderTextureLOD: false // set to use
331-
shader texture LOD
330+
shaderTextureLOD: false, // set to use shader texture LOD
331+
clipCullDistance: false // set to use vertex shader clipping
332332
};
333333
</code>
334334
</p>

docs/api/en/materials/ShaderMaterial.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -345,8 +345,8 @@ <h3>[property:Object extensions]</h3>
345345
derivatives: false, // set to use derivatives
346346
fragDepth: false, // set to use fragment depth values
347347
drawBuffers: false, // set to use draw buffers
348-
shaderTextureLOD: false // set to use
349-
shader texture LOD
348+
shaderTextureLOD: false, // set to use shader texture LOD
349+
clipCullDistance: false // set to use vertex shader clipping
350350
};
351351
</code>
352352
</p>

docs/api/fr/materials/ShaderMaterial.html

+2-1
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,8 @@ <h3>[property:Object extensions]</h3>
316316
derivatives: false, // set to use derivatives
317317
fragDepth: false, // set to use fragment depth values
318318
drawBuffers: false, // set to use draw buffers
319-
shaderTextureLOD: false // set to use shader texture LOD
319+
shaderTextureLOD: false, // set to use shader texture LOD
320+
clipCullDistance: false // set to use vertex shader clipping
320321
};
321322
</code>
322323
</p>

docs/api/it/materials/ShaderMaterial.html

+2-1
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,8 @@ <h3>[property:Object extensions]</h3>
321321
derivatives: false, // impostato per utilizzare le direttive
322322
fragDepth: false, // impostato per utilizzare i valori di profondità del frammento
323323
drawBuffers: false, // impostato per utilizzare i buffer di disegno
324-
shaderTextureLOD: false // impostato per utilizzare la texture dello shader LOD
324+
shaderTextureLOD: false, // impostato per utilizzare la texture dello shader LOD
325+
clipCullDistance: false // set to use vertex shader clipping
325326
};
326327
</code>
327328
</p>

docs/api/zh/materials/ShaderMaterial.html

+2-1
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,8 @@ <h3>[property:Object extensions]</h3>
283283
derivatives: false, // set to use derivatives
284284
fragDepth: false, // set to use fragment depth values
285285
drawBuffers: false, // set to use draw buffers
286-
shaderTextureLOD: false // set to use shader texture LOD
286+
shaderTextureLOD: false, // set to use shader texture LOD
287+
clipCullDistance: false // set to use vertex shader clipping
287288
};
288289
</code>
289290
</p>

examples/files.json

+1
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@
299299
"webgl2": [
300300
"webgl2_buffergeometry_attributes_integer",
301301
"webgl2_buffergeometry_attributes_none",
302+
"webgl2_clipculldistance",
302303
"webgl2_materials_texture2darray",
303304
"webgl2_materials_texture3d",
304305
"webgl2_materials_texture3d_partialupdate",
13.7 KB
Loading

examples/webgl2_clipculldistance.html

+189
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<title>three.js WebGL 2 - clip cull distance</title>
5+
<meta charset="utf-8" />
6+
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0" />
7+
<link type="text/css" rel="stylesheet" href="main.css" />
8+
</head>
9+
<body>
10+
<div id="container"></div>
11+
12+
<div id="info">
13+
<a href="https://threejs.org" target="_blank" rel="noopener" >three.js</a> - vertex shader clipping via
14+
<a href="https://registry.khronos.org/webgl/extensions/WEBGL_clip_cull_distance/" target="_blank" rel="noopener" >WEBGL_clip_cull_distance</a>
15+
<div id="notSupported" style="display:none">WEBGL_clip_cull_distance not supported</div>
16+
</div>
17+
18+
<script id="vertexShader" type="x-shader/x-vertex">
19+
20+
uniform float time;
21+
22+
varying vec4 vColor;
23+
24+
void main() {
25+
26+
vColor = color;
27+
28+
#ifdef USE_CLIP_DISTANCE
29+
vec4 worldPosition = modelMatrix * vec4( position, 1.0 );
30+
gl_ClipDistance[ 0 ] = worldPosition.x - sin( time ) * ( 0.5 );
31+
#endif
32+
33+
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
34+
35+
}
36+
37+
</script>
38+
39+
<script id="fragmentShader" type="x-shader/x-fragment">
40+
41+
varying vec4 vColor;
42+
43+
void main() {
44+
45+
gl_FragColor = vColor;
46+
47+
}
48+
49+
</script>
50+
51+
<script type="importmap">
52+
{
53+
"imports": {
54+
"three": "../build/three.module.js",
55+
"three/addons/": "./jsm/"
56+
}
57+
}
58+
</script>
59+
60+
<script type="module">
61+
import * as THREE from 'three';
62+
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
63+
import Stats from 'three/addons/libs/stats.module.js';
64+
65+
let camera, controls, clock, scene, renderer, stats;
66+
67+
let material;
68+
69+
init();
70+
animate();
71+
72+
function init() {
73+
74+
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 10 );
75+
camera.position.z = 2;
76+
77+
scene = new THREE.Scene();
78+
79+
clock = new THREE.Clock();
80+
81+
//
82+
83+
renderer = new THREE.WebGLRenderer( { antialias: true } );
84+
renderer.setPixelRatio( window.devicePixelRatio );
85+
renderer.setSize( window.innerWidth, window.innerHeight );
86+
document.body.appendChild( renderer.domElement );
87+
88+
if ( renderer.extensions.has( 'WEBGL_clip_cull_distance' ) === false ) {
89+
90+
document.getElementById( 'notSupported' ).style.display = '';
91+
return;
92+
93+
}
94+
95+
const ext = renderer
96+
.getContext()
97+
.getExtension( 'WEBGL_clip_cull_distance' );
98+
const gl = renderer.getContext();
99+
100+
gl.enable( ext.CLIP_DISTANCE0_WEBGL );
101+
102+
// geometry
103+
104+
const vertexCount = 200 * 3;
105+
106+
const geometry = new THREE.BufferGeometry();
107+
108+
const positions = [];
109+
const colors = [];
110+
111+
for ( let i = 0; i < vertexCount; i ++ ) {
112+
113+
// adding x,y,z
114+
positions.push( Math.random() - 0.5 );
115+
positions.push( Math.random() - 0.5 );
116+
positions.push( Math.random() - 0.5 );
117+
118+
// adding r,g,b,a
119+
colors.push( Math.random() * 255 );
120+
colors.push( Math.random() * 255 );
121+
colors.push( Math.random() * 255 );
122+
colors.push( Math.random() * 255 );
123+
124+
}
125+
126+
const positionAttribute = new THREE.Float32BufferAttribute( positions, 3 );
127+
const colorAttribute = new THREE.Uint8BufferAttribute( colors, 4 );
128+
colorAttribute.normalized = true;
129+
130+
geometry.setAttribute( 'position', positionAttribute );
131+
geometry.setAttribute( 'color', colorAttribute );
132+
133+
// material
134+
135+
material = new THREE.ShaderMaterial( {
136+
137+
uniforms: {
138+
time: { value: 1.0 }
139+
},
140+
vertexShader: document.getElementById( 'vertexShader' ).textContent,
141+
fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
142+
side: THREE.DoubleSide,
143+
transparent: true,
144+
vertexColors: true
145+
146+
} );
147+
148+
material.extensions.clipCullDistance = true;
149+
150+
const mesh = new THREE.Mesh( geometry, material );
151+
scene.add( mesh );
152+
153+
//
154+
155+
controls = new OrbitControls( camera, renderer.domElement );
156+
157+
//
158+
159+
stats = new Stats();
160+
document.body.appendChild( stats.dom );
161+
162+
window.addEventListener( 'resize', onWindowResize );
163+
164+
}
165+
166+
function onWindowResize() {
167+
168+
camera.aspect = window.innerWidth / window.innerHeight;
169+
camera.updateProjectionMatrix();
170+
171+
renderer.setSize( window.innerWidth, window.innerHeight );
172+
173+
}
174+
175+
function animate() {
176+
177+
requestAnimationFrame( animate );
178+
179+
controls.update();
180+
stats.update();
181+
182+
material.uniforms.time.value = clock.getElapsedTime();
183+
184+
renderer.render( scene, camera );
185+
186+
}
187+
</script>
188+
</body>
189+
</html>

src/materials/ShaderMaterial.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ class ShaderMaterial extends Material {
3636
derivatives: false, // set to use derivatives
3737
fragDepth: false, // set to use fragment depth values
3838
drawBuffers: false, // set to use draw buffers
39-
shaderTextureLOD: false // set to use shader texture LOD
39+
shaderTextureLOD: false, // set to use shader texture LOD
40+
clipCullDistance: false // set to use vertex shader clipping
4041
};
4142

4243
// When rendered geometry doesn't include these attributes but the material does,

src/renderers/webgl/WebGLExtensions.js

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ function WebGLExtensions( gl ) {
5454
if ( capabilities.isWebGL2 ) {
5555

5656
getExtension( 'EXT_color_buffer_float' );
57+
getExtension( 'WEBGL_clip_cull_distance' );
5758

5859
} else {
5960

src/renderers/webgl/WebGLProgram.js

+14
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,16 @@ function generateExtensions( parameters ) {
147147

148148
}
149149

150+
function generateVertexExtensions( parameters ) {
151+
152+
const chunks = [
153+
parameters.extensionClipCullDistance ? '#extension GL_ANGLE_clip_cull_distance : require' : ''
154+
];
155+
156+
return chunks.filter( filterEmptyLine ).join( '\n' );
157+
158+
}
159+
150160
function generateDefines( defines ) {
151161

152162
const chunks = [];
@@ -451,6 +461,8 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
451461

452462
const customExtensions = parameters.isWebGL2 ? '' : generateExtensions( parameters );
453463

464+
const customVertexExtensions = generateVertexExtensions( parameters );
465+
454466
const customDefines = generateDefines( defines );
455467

456468
const program = gl.createProgram();
@@ -503,6 +515,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
503515

504516
customDefines,
505517

518+
parameters.extensionClipCullDistance ? '#define USE_CLIP_DISTANCE' : '',
506519
parameters.batching ? '#define USE_BATCHING' : '',
507520
parameters.instancing ? '#define USE_INSTANCING' : '',
508521
parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '',
@@ -843,6 +856,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
843856
versionString = '#version 300 es\n';
844857

845858
prefixVertex = [
859+
customVertexExtensions,
846860
'precision mediump sampler2DArray;',
847861
'#define attribute in',
848862
'#define varying out',

src/renderers/webgl/WebGLPrograms.js

+1
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities
356356
extensionFragDepth: HAS_EXTENSIONS && material.extensions.fragDepth === true,
357357
extensionDrawBuffers: HAS_EXTENSIONS && material.extensions.drawBuffers === true,
358358
extensionShaderTextureLOD: HAS_EXTENSIONS && material.extensions.shaderTextureLOD === true,
359+
extensionClipCullDistance: HAS_EXTENSIONS && material.extensions.clipCullDistance && extensions.has( 'WEBGL_clip_cull_distance' ),
359360

360361
rendererExtensionFragDepth: IS_WEBGL2 || extensions.has( 'EXT_frag_depth' ),
361362
rendererExtensionDrawBuffers: IS_WEBGL2 || extensions.has( 'WEBGL_draw_buffers' ),

0 commit comments

Comments
 (0)