163 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			163 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
								 | 
							
								import NodeMaterial, { addNodeMaterial } from './NodeMaterial.js';
							 | 
						||
| 
								 | 
							
								import { varying } from '../core/VaryingNode.js';
							 | 
						||
| 
								 | 
							
								import { property } from '../core/PropertyNode.js';
							 | 
						||
| 
								 | 
							
								import { attribute } from '../core/AttributeNode.js';
							 | 
						||
| 
								 | 
							
								import { cameraProjectionMatrix } from '../accessors/CameraNode.js';
							 | 
						||
| 
								 | 
							
								import { materialColor, materialPointWidth } from '../accessors/MaterialNode.js'; // or should this be a property, instead?
							 | 
						||
| 
								 | 
							
								import { modelViewMatrix } from '../accessors/ModelNode.js';
							 | 
						||
| 
								 | 
							
								import { positionGeometry } from '../accessors/PositionNode.js';
							 | 
						||
| 
								 | 
							
								import { smoothstep } from '../math/MathNode.js';
							 | 
						||
| 
								 | 
							
								import { tslFn, vec2, vec4 } from '../shadernode/ShaderNode.js';
							 | 
						||
| 
								 | 
							
								import { uv } from '../accessors/UVNode.js';
							 | 
						||
| 
								 | 
							
								import { viewport } from '../display/ViewportNode.js';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import { PointsMaterial } from 'three';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const defaultValues = new PointsMaterial();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class InstancedPointsNodeMaterial extends NodeMaterial {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									constructor( params = {} ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										super();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.normals = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.lights = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.useAlphaToCoverage = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.useColor = params.vertexColors;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.pointWidth = 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.pointColorNode = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.setDefaultValues( defaultValues );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.setupShaders();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.setValues( params );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									setupShaders() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const useAlphaToCoverage = this.alphaToCoverage;
							 | 
						||
| 
								 | 
							
										const useColor = this.useColor;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.vertexNode = tslFn( () => {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											//vUv = uv;
							 | 
						||
| 
								 | 
							
											varying( vec2(), 'vUv' ).assign( uv() ); // @TODO: Analyze other way to do this
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											const instancePosition = attribute( 'instancePosition' );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// camera space
							 | 
						||
| 
								 | 
							
											const mvPos = property( 'vec4', 'mvPos' );
							 | 
						||
| 
								 | 
							
											mvPos.assign( modelViewMatrix.mul( vec4( instancePosition, 1.0 ) ) );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											const aspect = viewport.z.div( viewport.w );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// clip space
							 | 
						||
| 
								 | 
							
											const clipPos = cameraProjectionMatrix.mul( mvPos );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// offset in ndc space
							 | 
						||
| 
								 | 
							
											const offset = property( 'vec2', 'offset' );
							 | 
						||
| 
								 | 
							
											offset.assign( positionGeometry.xy );
							 | 
						||
| 
								 | 
							
											offset.assign( offset.mul( materialPointWidth ) );
							 | 
						||
| 
								 | 
							
											offset.assign( offset.div( viewport.z ) );
							 | 
						||
| 
								 | 
							
											offset.y.assign( offset.y.mul( aspect ) );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// back to clip space
							 | 
						||
| 
								 | 
							
											offset.assign( offset.mul( clipPos.w ) );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											//clipPos.xy += offset;
							 | 
						||
| 
								 | 
							
											clipPos.assign( clipPos.add( vec4( offset, 0, 0 ) ) );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											return clipPos;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											//vec4 mvPosition = mvPos; // this was used for somethihng...
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										} )();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.fragmentNode = tslFn( () => {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											const vUv = varying( vec2(), 'vUv' );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// force assignment into correct place in flow
							 | 
						||
| 
								 | 
							
											const alpha = property( 'float', 'alpha' );
							 | 
						||
| 
								 | 
							
											alpha.assign( 1 );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											const a = vUv.x;
							 | 
						||
| 
								 | 
							
											const b = vUv.y;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											const len2 = a.mul( a ).add( b.mul( b ) );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( useAlphaToCoverage ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// force assignment out of following 'if' statement - to avoid uniform control flow errors
							 | 
						||
| 
								 | 
							
												const dlen = property( 'float', 'dlen' );
							 | 
						||
| 
								 | 
							
												dlen.assign( len2.fwidth() );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												alpha.assign( smoothstep( dlen.oneMinus(), dlen.add( 1 ), len2 ).oneMinus() );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												len2.greaterThan( 1.0 ).discard();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											let pointColorNode;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( this.pointColorNode ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												pointColorNode = this.pointColorNode;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if ( useColor ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													const instanceColor = attribute( 'instanceColor' );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													pointColorNode = instanceColor.mul( materialColor );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												} else {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													pointColorNode = materialColor;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											return vec4( pointColorNode, alpha );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										} )();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.needsUpdate = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									get alphaToCoverage() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return this.useAlphaToCoverage;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									set alphaToCoverage( value ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( this.useAlphaToCoverage !== value ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											this.useAlphaToCoverage = value;
							 | 
						||
| 
								 | 
							
											this.setupShaders();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export default InstancedPointsNodeMaterial;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								addNodeMaterial( 'InstancedPointsNodeMaterial', InstancedPointsNodeMaterial );
							 |