|
74 | 74 | dirLight.shadow.mapSize.height = 1024;
|
75 | 75 | scene.add( dirLight );
|
76 | 76 |
|
77 |
| - // ***** Clipping planes: ***** |
| 77 | + // Clipping planes |
78 | 78 |
|
79 |
| - const localPlane = new THREE.Plane( new THREE.Vector3( 0, - 1, 0 ), 0.8 ); |
80 |
| - const localPlane2 = new THREE.Plane( new THREE.Vector3( 0, 0, - 1 ), 0.1 ); |
81 | 79 | const globalPlane = new THREE.Plane( new THREE.Vector3( - 1, 0, 0 ), 0.1 );
|
| 80 | + const localPlane1 = new THREE.Plane( new THREE.Vector3( 0, - 1, 0 ), 0.8 ); |
| 81 | + const localPlane2 = new THREE.Plane( new THREE.Vector3( 0, 0, - 1 ), 0.1 ); |
| 82 | + |
| 83 | + // Clipping Groups |
| 84 | + |
| 85 | + const globalClippingGroup = new THREE.ClippingGroup(); |
| 86 | + globalClippingGroup.clippingPlanes = [ globalPlane ]; |
| 87 | + |
| 88 | + const knotClippingGroup = new THREE.ClippingGroup(); |
| 89 | + knotClippingGroup.clippingPlanes = [ localPlane1, localPlane2 ]; |
| 90 | + knotClippingGroup.clipIntersection = true; |
| 91 | + |
| 92 | + scene.add( globalClippingGroup ); |
| 93 | + globalClippingGroup.add( knotClippingGroup ); |
82 | 94 |
|
83 | 95 | // Geometry
|
84 | 96 |
|
|
88 | 100 | side: THREE.DoubleSide,
|
89 | 101 |
|
90 | 102 | // ***** Clipping setup (material): *****
|
91 |
| - clippingPlanes: [ localPlane, localPlane2 ], |
92 |
| - clipShadows: true, |
93 |
| - alphaToCoverage: true, |
94 |
| - clipIntersection: true |
95 |
| - |
| 103 | + alphaToCoverage: true |
96 | 104 | } );
|
97 | 105 |
|
98 | 106 | const geometry = new THREE.TorusKnotGeometry( 0.4, 0.08, 95, 20 );
|
99 | 107 |
|
100 | 108 | object = new THREE.Mesh( geometry, material );
|
101 | 109 | object.castShadow = true;
|
102 |
| - scene.add( object ); |
| 110 | + knotClippingGroup.add( object ); |
103 | 111 |
|
104 | 112 | const ground = new THREE.Mesh(
|
105 | 113 | new THREE.PlaneGeometry( 9, 9, 1, 1 ),
|
106 |
| - new THREE.MeshPhongNodeMaterial( { color: 0xa0adaf, shininess: 150 } ) |
| 114 | + new THREE.MeshPhongNodeMaterial( { color: 0xa0adaf, shininess: 150, alphaToCoverage: true } ) |
107 | 115 | );
|
108 | 116 |
|
109 | 117 | ground.rotation.x = - Math.PI / 2; // rotates X/Y to X/Z
|
110 | 118 | ground.receiveShadow = true;
|
111 |
| - scene.add( ground ); |
| 119 | + globalClippingGroup.add( ground ); |
112 | 120 |
|
113 | 121 | // Stats
|
114 | 122 |
|
|
125 | 133 | window.addEventListener( 'resize', onWindowResize );
|
126 | 134 | document.body.appendChild( renderer.domElement );
|
127 | 135 |
|
128 |
| - // ***** Clipping setup (renderer): ***** |
129 |
| - const globalPlanes = [ globalPlane ]; |
130 |
| - const Empty = Object.freeze( [] ); |
131 |
| - |
132 |
| - renderer.clippingPlanes = Empty; // GUI sets it to globalPlanes |
133 |
| - renderer.localClippingEnabled = true; |
134 |
| - |
135 | 136 | // Controls
|
| 137 | + |
136 | 138 | const controls = new OrbitControls( camera, renderer.domElement );
|
137 | 139 | controls.target.set( 0, 1, 0 );
|
138 | 140 | controls.update();
|
|
143 | 145 | props = {
|
144 | 146 | alphaToCoverage: true,
|
145 | 147 | },
|
146 |
| - folderLocal = gui.addFolder( 'Local Clipping' ), |
147 |
| - propsLocal = { |
| 148 | + folderKnot = gui.addFolder( 'Knot Clipping Group' ), |
| 149 | + propsKnot = { |
148 | 150 |
|
149 | 151 | get 'Enabled'() {
|
150 | 152 |
|
151 |
| - return renderer.localClippingEnabled; |
| 153 | + return knotClippingGroup.enabled; |
152 | 154 |
|
153 | 155 | },
|
154 | 156 | set 'Enabled'( v ) {
|
155 | 157 |
|
156 |
| - renderer.localClippingEnabled = v; |
| 158 | + knotClippingGroup.enabled = v; |
157 | 159 |
|
158 | 160 | },
|
159 | 161 |
|
160 | 162 | get 'Shadows'() {
|
161 | 163 |
|
162 |
| - return material.clipShadows; |
| 164 | + return knotClippingGroup.clipShadows; |
163 | 165 |
|
164 | 166 | },
|
165 | 167 | set 'Shadows'( v ) {
|
166 | 168 |
|
167 |
| - material.clipShadows = v; |
| 169 | + knotClippingGroup.clipShadows = v; |
168 | 170 |
|
169 | 171 | },
|
170 | 172 |
|
171 | 173 | get 'Intersection'() {
|
172 | 174 |
|
173 |
| - return material.clipIntersection; |
| 175 | + return knotClippingGroup.clipIntersection; |
174 | 176 |
|
175 | 177 | },
|
176 | 178 |
|
177 | 179 | set 'Intersection'( v ) {
|
178 | 180 |
|
179 |
| - material.clipIntersection = v; |
| 181 | + knotClippingGroup.clipIntersection = v; |
180 | 182 |
|
181 | 183 | },
|
182 | 184 |
|
183 | 185 | get 'Plane'() {
|
184 | 186 |
|
185 |
| - return localPlane.constant; |
| 187 | + return localPlane1.constant; |
186 | 188 |
|
187 | 189 | },
|
188 | 190 | set 'Plane'( v ) {
|
189 | 191 |
|
190 |
| - localPlane.constant = v; |
| 192 | + localPlane1.constant = v; |
191 | 193 |
|
192 | 194 | }
|
193 | 195 |
|
194 | 196 | },
|
195 | 197 |
|
196 |
| - folderGlobal = gui.addFolder( 'Global Clipping' ), |
| 198 | + folderGlobal = gui.addFolder( 'Global Clipping Group' ), |
197 | 199 | propsGlobal = {
|
198 | 200 |
|
199 | 201 | get 'Enabled'() {
|
200 | 202 |
|
201 |
| - return renderer.clippingPlanes !== Empty; |
| 203 | + return globalClippingGroup.enabled; |
202 | 204 |
|
203 | 205 | },
|
204 | 206 | set 'Enabled'( v ) {
|
205 | 207 |
|
206 |
| - renderer.clippingPlanes = v ? globalPlanes : Empty; |
| 208 | + globalClippingGroup.enabled = v; |
207 | 209 |
|
208 | 210 | },
|
209 | 211 |
|
|
230 | 232 |
|
231 | 233 | } );
|
232 | 234 |
|
233 |
| - folderLocal.add( propsLocal, 'Enabled' ); |
234 |
| - folderLocal.add( propsLocal, 'Shadows' ); |
235 |
| - folderLocal.add( propsLocal, 'Intersection' ); |
236 |
| - folderLocal.add( propsLocal, 'Plane', 0.3, 1.25 ); |
| 235 | + folderKnot.add( propsKnot, 'Enabled' ); |
| 236 | + folderKnot.add( propsKnot, 'Shadows' ); |
| 237 | + folderKnot.add( propsKnot, 'Intersection' ); |
| 238 | + folderKnot.add( propsKnot, 'Plane', 0.3, 1.25 ); |
237 | 239 |
|
238 | 240 | folderGlobal.add( propsGlobal, 'Enabled' );
|
239 | 241 | folderGlobal.add( propsGlobal, 'Plane', - 0.4, 3 );
|
|
0 commit comments