|
|
@@ -6,6 +6,7 @@ import { diffuseColor } from '../core/PropertyNode.js';
|
|
|
import { Loop } from '../utils/LoopNode.js';
|
|
|
import { smoothstep } from '../math/MathNode.js';
|
|
|
import { uniformArray } from './UniformArrayNode.js';
|
|
|
+import { builtin } from './BuiltinNode.js';
|
|
|
|
|
|
class ClippingNode extends Node {
|
|
|
|
|
|
@@ -30,11 +31,16 @@ class ClippingNode extends Node {
|
|
|
const clippingContext = builder.clippingContext;
|
|
|
const { intersectionPlanes, unionPlanes } = clippingContext;
|
|
|
|
|
|
+ this.hardwareClipping = builder.material.hardwareClipping;
|
|
|
|
|
|
if ( this.scope === ClippingNode.ALPHA_TO_COVERAGE ) {
|
|
|
|
|
|
return this.setupAlphaToCoverage( intersectionPlanes, unionPlanes );
|
|
|
|
|
|
+ } else if ( this.scope === ClippingNode.HARDWARE ) {
|
|
|
+
|
|
|
+ return this.setupHardwareClipping( unionPlanes, builder );
|
|
|
+
|
|
|
} else {
|
|
|
|
|
|
return this.setupDefault( intersectionPlanes, unionPlanes );
|
|
|
@@ -54,15 +60,13 @@ class ClippingNode extends Node {
|
|
|
|
|
|
const numUnionPlanes = unionPlanes.length;
|
|
|
|
|
|
- if ( numUnionPlanes > 0 ) {
|
|
|
+ if ( ! this.hardwareClipping && numUnionPlanes > 0 ) {
|
|
|
|
|
|
const clippingPlanes = uniformArray( unionPlanes );
|
|
|
|
|
|
- let plane;
|
|
|
-
|
|
|
Loop( numUnionPlanes, ( { i } ) => {
|
|
|
|
|
|
- plane = clippingPlanes.element( i );
|
|
|
+ const plane = clippingPlanes.element( i );
|
|
|
|
|
|
distanceToPlane.assign( positionView.dot( plane.xyz ).negate().add( plane.w ) );
|
|
|
distanceGradient.assign( distanceToPlane.fwidth().div( 2.0 ) );
|
|
|
@@ -80,11 +84,9 @@ class ClippingNode extends Node {
|
|
|
const clippingPlanes = uniformArray( intersectionPlanes );
|
|
|
const intersectionClipOpacity = float( 1 ).toVar( 'intersectionClipOpacity' );
|
|
|
|
|
|
- let plane;
|
|
|
-
|
|
|
Loop( numIntersectionPlanes, ( { i } ) => {
|
|
|
|
|
|
- plane = clippingPlanes.element( i );
|
|
|
+ const plane = clippingPlanes.element( i );
|
|
|
|
|
|
distanceToPlane.assign( positionView.dot( plane.xyz ).negate().add( plane.w ) );
|
|
|
distanceGradient.assign( distanceToPlane.fwidth().div( 2.0 ) );
|
|
|
@@ -111,15 +113,13 @@ class ClippingNode extends Node {
|
|
|
|
|
|
const numUnionPlanes = unionPlanes.length;
|
|
|
|
|
|
- if ( numUnionPlanes > 0 ) {
|
|
|
+ if ( ! this.hardwareClipping && numUnionPlanes > 0 ) {
|
|
|
|
|
|
const clippingPlanes = uniformArray( unionPlanes );
|
|
|
|
|
|
- let plane;
|
|
|
-
|
|
|
Loop( numUnionPlanes, ( { i } ) => {
|
|
|
|
|
|
- plane = clippingPlanes.element( i );
|
|
|
+ const plane = clippingPlanes.element( i );
|
|
|
positionView.dot( plane.xyz ).greaterThan( plane.w ).discard();
|
|
|
|
|
|
} );
|
|
|
@@ -133,11 +133,9 @@ class ClippingNode extends Node {
|
|
|
const clippingPlanes = uniformArray( intersectionPlanes );
|
|
|
const clipped = bool( true ).toVar( 'clipped' );
|
|
|
|
|
|
- let plane;
|
|
|
-
|
|
|
Loop( numIntersectionPlanes, ( { i } ) => {
|
|
|
|
|
|
- plane = clippingPlanes.element( i );
|
|
|
+ const plane = clippingPlanes.element( i );
|
|
|
clipped.assign( positionView.dot( plane.xyz ).greaterThan( plane.w ).and( clipped ) );
|
|
|
|
|
|
} );
|
|
|
@@ -150,13 +148,38 @@ class ClippingNode extends Node {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ setupHardwareClipping( unionPlanes, builder ) {
|
|
|
+
|
|
|
+ const numUnionPlanes = unionPlanes.length;
|
|
|
+
|
|
|
+ builder.enableHardwareClipping( numUnionPlanes );
|
|
|
+
|
|
|
+ return Fn( () => {
|
|
|
+
|
|
|
+ const clippingPlanes = uniformArray( unionPlanes );
|
|
|
+ const hw_clip_distances = builtin( builder.getClipDistance() );
|
|
|
+
|
|
|
+ Loop( numUnionPlanes, ( { i } ) => {
|
|
|
+
|
|
|
+ const plane = clippingPlanes.element( i );
|
|
|
+
|
|
|
+ const distance = positionView.dot( plane.xyz ).sub( plane.w ).negate();
|
|
|
+ hw_clip_distances.element( i ).assign( distance );
|
|
|
+
|
|
|
+ } );
|
|
|
+
|
|
|
+ } )();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
|
|
|
ClippingNode.ALPHA_TO_COVERAGE = 'alphaToCoverage';
|
|
|
ClippingNode.DEFAULT = 'default';
|
|
|
+ClippingNode.HARDWARE = 'hardware';
|
|
|
|
|
|
export default ClippingNode;
|
|
|
|
|
|
export const clipping = () => nodeObject( new ClippingNode() );
|
|
|
-
|
|
|
export const clippingAlpha = () => nodeObject( new ClippingNode( ClippingNode.ALPHA_TO_COVERAGE ) );
|
|
|
+export const hardwareClipping = () => nodeObject( new ClippingNode( ClippingNode.HARDWARE ) );
|