123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- import Node from '../core/Node.js';
- import { nodeObject } from '../shadernode/ShaderNode.js';
- import { positionView } from './PositionNode.js';
- import { diffuseColor, property } from '../core/PropertyNode.js';
- import { tslFn } from '../shadernode/ShaderNode.js';
- import { loop } from '../utils/LoopNode.js';
- import { smoothstep } from '../math/MathNode.js';
- import { uniforms } from './UniformsNode.js';
- class ClippingNode extends Node {
- constructor( scope = ClippingNode.DEFAULT ) {
- super();
- this.scope = scope;
- }
- setup( builder ) {
- super.setup( builder );
- const clippingContext = builder.clippingContext;
- const { localClipIntersection, localClippingCount, globalClippingCount } = clippingContext;
- const numClippingPlanes = globalClippingCount + localClippingCount;
- const numUnionClippingPlanes = localClipIntersection ? numClippingPlanes - localClippingCount : numClippingPlanes;
- if ( this.scope === ClippingNode.ALPHA_TO_COVERAGE ) {
- return this.setupAlphaToCoverage( clippingContext.planes, numClippingPlanes, numUnionClippingPlanes );
- } else {
- return this.setupDefault( clippingContext.planes, numClippingPlanes, numUnionClippingPlanes );
- }
- }
- setupAlphaToCoverage( planes, numClippingPlanes, numUnionClippingPlanes ) {
- return tslFn( () => {
- const clippingPlanes = uniforms( planes );
- const distanceToPlane = property( 'float', 'distanceToPlane' );
- const distanceGradient = property( 'float', 'distanceToGradient' );
- const clipOpacity = property( 'float', 'clipOpacity' );
- clipOpacity.assign( 1 );
- let plane;
- loop( numUnionClippingPlanes, ( { i } ) => {
- plane = clippingPlanes.element( i );
- distanceToPlane.assign( positionView.dot( plane.xyz ).negate().add( plane.w ) );
- distanceGradient.assign( distanceToPlane.fwidth().div( 2.0 ) );
- clipOpacity.mulAssign( smoothstep( distanceGradient.negate(), distanceGradient, distanceToPlane ) );
- clipOpacity.equal( 0.0 ).discard();
- } );
- if ( numUnionClippingPlanes < numClippingPlanes ) {
- const unionClipOpacity = property( 'float', 'unionclipOpacity' );
- unionClipOpacity.assign( 1 );
- loop( { start: numUnionClippingPlanes, end: numClippingPlanes }, ( { i } ) => {
- plane = clippingPlanes.element( i );
- distanceToPlane.assign( positionView.dot( plane.xyz ).negate().add( plane.w ) );
- distanceGradient.assign( distanceToPlane.fwidth().div( 2.0 ) );
- unionClipOpacity.mulAssign( smoothstep( distanceGradient.negate(), distanceGradient, distanceToPlane ).oneMinus() );
- } );
- clipOpacity.mulAssign( unionClipOpacity.oneMinus() );
- }
- diffuseColor.a.mulAssign( clipOpacity );
- diffuseColor.a.equal( 0.0 ).discard();
- } )();
- }
- setupDefault( planes, numClippingPlanes, numUnionClippingPlanes ) {
- return tslFn( () => {
- const clippingPlanes = uniforms( planes );
- let plane;
- loop( numUnionClippingPlanes, ( { i } ) => {
- plane = clippingPlanes.element( i );
- positionView.dot( plane.xyz ).greaterThan( plane.w ).discard();
- } );
- if ( numUnionClippingPlanes < numClippingPlanes ) {
- const clipped = property( 'bool', 'clipped' );
- clipped.assign( true );
- loop( { start: numUnionClippingPlanes, end: numClippingPlanes }, ( { i } ) => {
- plane = clippingPlanes.element( i );
- clipped.assign( positionView.dot( plane.xyz ).greaterThan( plane.w ).and( clipped ) );
- } );
- clipped.discard();
- }
- } )();
- }
- }
- ClippingNode.ALPHA_TO_COVERAGE = 'alphaToCoverage';
- ClippingNode.DEFAULT = 'default';
- export default ClippingNode;
- export const clipping = () => nodeObject( new ClippingNode() );
- export const clippingAlpha = () => nodeObject( new ClippingNode( ClippingNode.ALPHA_TO_COVERAGE ) );
|