Skip to content

Commit c44c4ec

Browse files
authored
WebGPU: Introduce Fat Points (#26930)
* Introduce Fat Points * Introduce FatPointsNodeMaterial * Enable damping * Clean up * Clean up * Clean up * Clean up * Delete FatPointsMaterial * Clean up * Add screenshot * Updated files
1 parent a1bad17 commit c44c4ec

10 files changed

+618
-0
lines changed

examples/files.json

+1
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,7 @@
339339
"webgpu_morphtargets",
340340
"webgpu_occlusion",
341341
"webgpu_particles",
342+
"webgpu_points_fat",
342343
"webgpu_rtt",
343344
"webgpu_sandbox",
344345
"webgpu_shadowmap",

examples/jsm/nodes/Nodes.js

+1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ export { default as BufferNode, buffer } from './accessors/BufferNode.js';
7272
export { default as CameraNode, cameraProjectionMatrix, cameraViewMatrix, cameraNormalMatrix, cameraWorldMatrix, cameraPosition, cameraNear, cameraFar } from './accessors/CameraNode.js';
7373
export { default as CubeTextureNode, cubeTexture } from './accessors/CubeTextureNode.js';
7474
export { default as ExtendedMaterialNode, materialNormal } from './accessors/ExtendedMaterialNode.js';
75+
export { default as FatPointsMaterialNode, materialPointWidth } from './accessors/FatPointsMaterialNode.js';
7576
export { default as InstanceNode, instance } from './accessors/InstanceNode.js';
7677
export { default as LineMaterialNode, materialLineDashSize, materialLineDashOffset, materialLineGapSize, materialLineScale, materialLineWidth } from './accessors/LineMaterialNode.js';
7778
export { default as MaterialNode, materialAlphaTest, materialColor, materialShininess, materialEmissive, materialOpacity, materialSpecularColor, materialReflectivity, materialRoughness, materialMetalness, materialRotation, materialSheen, materialSheenRoughness } from './accessors/MaterialNode.js';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import MaterialNode from './MaterialNode.js';
2+
import { addNodeClass } from '../core/Node.js';
3+
import { nodeImmutable } from '../shadernode/ShaderNode.js';
4+
5+
class FatPointsMaterialNode extends MaterialNode {
6+
7+
setup( /*builder*/ ) {
8+
9+
return this.getFloat( this.scope );
10+
11+
}
12+
13+
}
14+
15+
FatPointsMaterialNode.POINTWIDTH = 'pointWidth';
16+
17+
export default FatPointsMaterialNode;
18+
19+
export const materialPointWidth = nodeImmutable( FatPointsMaterialNode, FatPointsMaterialNode.POINTWIDTH );
20+
21+
addNodeClass( 'FatPointsMaterialNode', FatPointsMaterialNode );

examples/jsm/nodes/core/PropertyNode.js

+1
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,6 @@ export const shininess = nodeImmutable( PropertyNode, 'float', 'Shininess' );
5555
export const output = nodeImmutable( PropertyNode, 'vec4', 'Output' );
5656
export const dashSize = nodeImmutable( PropertyNode, 'float', 'dashSize' );
5757
export const gapSize = nodeImmutable( PropertyNode, 'float', 'gapSize' );
58+
export const pointWidth = nodeImmutable( PropertyNode, 'float', 'pointWidth' );
5859

5960
addNodeClass( 'PropertyNode', PropertyNode );
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
import NodeMaterial, { addNodeMaterial } from './NodeMaterial.js';
2+
import { varying } from '../core/VaryingNode.js';
3+
import { property } from '../core/PropertyNode.js';
4+
import { attribute } from '../core/AttributeNode.js';
5+
import { cameraProjectionMatrix } from '../accessors/CameraNode.js';
6+
import { materialColor } from '../accessors/MaterialNode.js';
7+
import { modelViewMatrix } from '../accessors/ModelNode.js';
8+
import { positionGeometry } from '../accessors/PositionNode.js';
9+
import { smoothstep } from '../math/MathNode.js';
10+
import { tslFn, vec2, vec4 } from '../shadernode/ShaderNode.js';
11+
import { uv } from '../accessors/UVNode.js';
12+
import { materialPointWidth } from '../accessors/FatPointsMaterialNode.js'; // or should this be a property, instead?
13+
import { viewport } from '../display/ViewportNode.js';
14+
import { color } from 'three/nodes';
15+
16+
import { PointsMaterial } from 'three';
17+
18+
const defaultValues = new PointsMaterial();
19+
20+
class FatPointsNodeMaterial extends NodeMaterial {
21+
22+
constructor( params = {} ) {
23+
24+
super();
25+
26+
this.normals = false;
27+
28+
this.lights = false;
29+
30+
this.useAlphaToCoverage = true;
31+
32+
this.useColor = params.vertexColors;
33+
34+
this.pointWidth = 1;
35+
36+
this.pointColorNode = null;
37+
38+
this.setDefaultValues( defaultValues );
39+
40+
this.setupShaders();
41+
42+
this.setValues( params );
43+
44+
}
45+
46+
setupShaders() {
47+
48+
const useAlphaToCoverage = this.alphaToCoverage;
49+
const useColor = this.useColor;
50+
51+
this.vertexNode = tslFn( () => {
52+
53+
//vUv = uv;
54+
varying( vec2(), 'vUv' ).assign( uv() ); // @TODO: Analyze other way to do this
55+
56+
const instancePosition = attribute( 'instancePosition' );
57+
58+
// camera space
59+
const mvPos = property( 'vec4', 'mvPos' );
60+
mvPos.assign( modelViewMatrix.mul( vec4( instancePosition, 1.0 ) ) );
61+
62+
const aspect = viewport.z.div( viewport.w );
63+
64+
// clip space
65+
const clipPos = cameraProjectionMatrix.mul( mvPos );
66+
67+
// offset in ndc space
68+
const offset = property( 'vec2', 'offset' );
69+
offset.assign( positionGeometry.xy );
70+
offset.assign( offset.mul( materialPointWidth ) );
71+
offset.assign( offset.div( viewport.z ) );
72+
offset.y.assign( offset.y.mul( aspect ) );
73+
74+
// back to clip space
75+
offset.assign( offset.mul( clipPos.w ) );
76+
77+
//clipPos.xy += offset;
78+
clipPos.assign( clipPos.add( vec4( offset, 0, 0 ) ) );
79+
80+
return clipPos;
81+
82+
//vec4 mvPosition = mvPos; // this was used for somethihng...
83+
84+
} )();
85+
86+
this.colorNode = tslFn( () => {
87+
88+
const vUv = varying( vec2(), 'vUv' );
89+
90+
// force assignment into correct place in flow
91+
const alpha = property( 'float', 'alpha' );
92+
alpha.assign( 1 );
93+
94+
const a = vUv.x;
95+
const b = vUv.y;
96+
97+
const len2 = a.mul( a ).add( b.mul( b ) );
98+
99+
if ( useAlphaToCoverage ) {
100+
101+
// force assignment out of following 'if' statement - to avoid uniform control flow errors
102+
const dlen = property( 'float', 'dlen' );
103+
dlen.assign( len2.fwidth() );
104+
105+
alpha.assign( smoothstep( dlen.oneMinus(), dlen.add( 1 ), len2 ).oneMinus() );
106+
107+
} else {
108+
109+
len2.greaterThan( 1.0 ).discard();
110+
111+
}
112+
113+
let pointColorNode;
114+
115+
if ( this.pointColorNode ) {
116+
117+
pointColorNode = this.pointColorNode;
118+
119+
} else {
120+
121+
if ( useColor ) {
122+
123+
const instanceColor = attribute( 'instanceColor' );
124+
125+
pointColorNode = color( instanceColor ).mul( color( materialColor ) );
126+
127+
} else {
128+
129+
pointColorNode = materialColor;
130+
131+
}
132+
133+
}
134+
135+
return vec4( pointColorNode, alpha );
136+
137+
} )();
138+
139+
this.needsUpdate = true;
140+
141+
}
142+
143+
get alphaToCoverage() {
144+
145+
return this.useAlphaToCoverage;
146+
147+
}
148+
149+
set alphaToCoverage( value ) {
150+
151+
if ( this.useAlphaToCoverage !== value ) {
152+
153+
this.useAlphaToCoverage = value;
154+
this.setupShaders();
155+
156+
}
157+
158+
}
159+
160+
}
161+
162+
export default FatPointsNodeMaterial;
163+
164+
addNodeMaterial( 'FatPointsNodeMaterial', FatPointsNodeMaterial );

examples/jsm/nodes/materials/Materials.js

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// @TODO: We can simplify "export { default as SomeNode, other, exports } from '...'" to just "export * from '...'" if we will use only named exports
22

33
export { default as NodeMaterial, addNodeMaterial, createNodeMaterialFromType } from './NodeMaterial.js';
4+
export { default as FatPointsNodeMaterial } from './FatPointsNodeMaterial.js';
45
export { default as LineBasicNodeMaterial } from './LineBasicNodeMaterial.js';
56
export { default as LineDashedNodeMaterial } from './LineDashedNodeMaterial.js';
67
export { default as Line2NodeMaterial } from './Line2NodeMaterial.js';

examples/jsm/points/FatPoints.js

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import {
2+
Mesh
3+
} from 'three';
4+
import { FatPointsGeometry } from '../points/FatPointsGeometry.js';
5+
import { FatPointsNodeMaterial } from 'three/nodes';
6+
7+
class FatPoints extends Mesh {
8+
9+
constructor( geometry = new FatPointsGeometry(), material = new FatPointsNodeMaterial() ) {
10+
11+
super( geometry, material );
12+
13+
this.isFatPoints = true;
14+
15+
this.type = 'FatPoints';
16+
17+
}
18+
19+
}
20+
21+
export { FatPoints };

0 commit comments

Comments
 (0)