@@ -6,6 +6,30 @@ import { InterleavedBufferAttribute } from '../../core/InterleavedBufferAttribut
6
6
import { InterleavedBuffer } from '../../core/InterleavedBuffer.js' ;
7
7
import { StaticDrawUsage , DynamicDrawUsage } from '../../constants.js' ;
8
8
9
+ /** @module BufferAttributeNode **/
10
+
11
+ /**
12
+ * In earlier `three.js` versions it was only possible to define attribute data
13
+ * on geometry level. With `BufferAttributeNode`, it is also possible to do this
14
+ * on the node level.
15
+ * ```js
16
+ * const geometry = new THREE.PlaneGeometry();
17
+ * const positionAttribute = geometry.getAttribute( 'position' );
18
+ *
19
+ * const colors = [];
20
+ * for ( let i = 0; i < position.count; i ++ ) {
21
+ * colors.push( 1, 0, 0 );
22
+ * }
23
+ *
24
+ * material.colorNode = bufferAttribute( new THREE.Float32BufferAttribute( colors, 3 ) );
25
+ * ```
26
+ * This new approach is especially interesting when geometry data are generated via
27
+ * compute shaders. The below line converts a storage buffer into an attribute.
28
+ * ```js
29
+ * material.positionNode = positionBuffer.toAttribute();
30
+ * ```
31
+ * @augments InputNode
32
+ */
9
33
class BufferAttributeNode extends InputNode {
10
34
11
35
static get type ( ) {
@@ -14,21 +38,82 @@ class BufferAttributeNode extends InputNode {
14
38
15
39
}
16
40
41
+ /**
42
+ * Constructs a new buffer attribute node.
43
+ *
44
+ * @param {BufferAttribute|InterleavedBuffer|TypedArray } value - The attribute data.
45
+ * @param {String? } [bufferType=null] - The buffer type (e.g. `'vec3'`).
46
+ * @param {Number } [bufferStride=0] - The buffer stride.
47
+ * @param {Number } [bufferOffset=0] - The buffer offset.
48
+ */
17
49
constructor ( value , bufferType = null , bufferStride = 0 , bufferOffset = 0 ) {
18
50
19
51
super ( value , bufferType ) ;
20
52
53
+ /**
54
+ * This flag can be used for type testing.
55
+ *
56
+ * @type {Boolean }
57
+ * @readonly
58
+ * @default true
59
+ */
21
60
this . isBufferNode = true ;
22
61
62
+ /**
63
+ * The buffer type (e.g. `'vec3'`).
64
+ *
65
+ * @type {String }
66
+ * @default null
67
+ */
23
68
this . bufferType = bufferType ;
69
+
70
+ /**
71
+ * The buffer stride.
72
+ *
73
+ * @type {Number }
74
+ * @default 0
75
+ */
24
76
this . bufferStride = bufferStride ;
77
+
78
+ /**
79
+ * The buffer offset.
80
+ *
81
+ * @type {Number }
82
+ * @default 0
83
+ */
25
84
this . bufferOffset = bufferOffset ;
26
85
86
+ /**
87
+ * The usage property. Set this to `THREE.DynamicDrawUsage` via `.setUsage()`,
88
+ * if you are planning to update the attribute data per frame.
89
+ *
90
+ * @type {Number }
91
+ * @default StaticDrawUsage
92
+ */
27
93
this . usage = StaticDrawUsage ;
94
+
95
+ /**
96
+ * Whether the attribute is instanced or not.
97
+ *
98
+ * @type {Boolean }
99
+ * @default false
100
+ */
28
101
this . instanced = false ;
29
102
103
+ /**
104
+ * A reference to the buffer attribute.
105
+ *
106
+ * @type {BufferAttribute? }
107
+ * @default null
108
+ */
30
109
this . attribute = null ;
31
110
111
+ /**
112
+ * `BufferAttributeNode` sets this property to `true` by default.
113
+ *
114
+ * @type {Boolean }
115
+ * @default true
116
+ */
32
117
this . global = true ;
33
118
34
119
if ( value && value . isBufferAttribute === true ) {
@@ -41,6 +126,13 @@ class BufferAttributeNode extends InputNode {
41
126
42
127
}
43
128
129
+ /**
130
+ * This method is overwritten since the attribute data might be shared
131
+ * and thus the hash should be shared as well.
132
+ *
133
+ * @param {NodeBuilder } builder - The current node builder.
134
+ * @return {String } The hash.
135
+ */
44
136
getHash ( builder ) {
45
137
46
138
if ( this . bufferStride === 0 && this . bufferOffset === 0 ) {
@@ -65,6 +157,13 @@ class BufferAttributeNode extends InputNode {
65
157
66
158
}
67
159
160
+ /**
161
+ * This method is overwritten since the node type is inferred from
162
+ * the buffer attribute.
163
+ *
164
+ * @param {NodeBuilder } builder - The current node builder.
165
+ * @return {String } The node type.
166
+ */
68
167
getNodeType ( builder ) {
69
168
70
169
if ( this . bufferType === null ) {
@@ -77,6 +176,13 @@ class BufferAttributeNode extends InputNode {
77
176
78
177
}
79
178
179
+ /**
180
+ * Depending on which value was passed to the node, `setup()` behaves
181
+ * differently. If no instance of `BufferAttribute` was passed, the method
182
+ * creates an internal attribute and configures it respectively.
183
+ *
184
+ * @param {NodeBuilder } builder - The current node builder.
185
+ */
80
186
setup ( builder ) {
81
187
82
188
if ( this . attribute !== null ) return ;
@@ -97,6 +203,12 @@ class BufferAttributeNode extends InputNode {
97
203
98
204
}
99
205
206
+ /**
207
+ * Generates the code snippet of the buffer attribute node.
208
+ *
209
+ * @param {NodeBuilder } builder - The current node builder.
210
+ * @return {String } The generated code snippet.
211
+ */
100
212
generate ( builder ) {
101
213
102
214
const nodeType = this . getNodeType ( builder ) ;
@@ -124,12 +236,24 @@ class BufferAttributeNode extends InputNode {
124
236
125
237
}
126
238
239
+ /**
240
+ * Overwrites the default implementation to return a fixed value `'bufferAttribute'`.
241
+ *
242
+ * @param {NodeBuilder } builder - The current node builder.
243
+ * @return {String } The input type.
244
+ */
127
245
getInputType ( /*builder*/ ) {
128
246
129
247
return 'bufferAttribute' ;
130
248
131
249
}
132
250
251
+ /**
252
+ * Sets the `usage` property to the given value.
253
+ *
254
+ * @param {Number } value - The usage to set.
255
+ * @return {BufferAttributeNode } A reference to this node.
256
+ */
133
257
setUsage ( value ) {
134
258
135
259
this . usage = value ;
@@ -144,6 +268,12 @@ class BufferAttributeNode extends InputNode {
144
268
145
269
}
146
270
271
+ /**
272
+ * Sets the `instanced` property to the given value.
273
+ *
274
+ * @param {Number } value - The value to set.
275
+ * @return {BufferAttributeNode } A reference to this node.
276
+ */
147
277
setInstanced ( value ) {
148
278
149
279
this . instanced = value ;
@@ -156,10 +286,53 @@ class BufferAttributeNode extends InputNode {
156
286
157
287
export default BufferAttributeNode ;
158
288
159
- export const bufferAttribute = ( array , type , stride , offset ) => nodeObject ( new BufferAttributeNode ( array , type , stride , offset ) ) ;
160
- export const dynamicBufferAttribute = ( array , type , stride , offset ) => bufferAttribute ( array , type , stride , offset ) . setUsage ( DynamicDrawUsage ) ;
161
-
162
- export const instancedBufferAttribute = ( array , type , stride , offset ) => bufferAttribute ( array , type , stride , offset ) . setInstanced ( true ) ;
163
- export const instancedDynamicBufferAttribute = ( array , type , stride , offset ) => dynamicBufferAttribute ( array , type , stride , offset ) . setInstanced ( true ) ;
289
+ /**
290
+ * TSL function for creating a buffer attribute node.
291
+ *
292
+ * @function
293
+ * @param {BufferAttribute|InterleavedBuffer|TypedArray } array - The attribute data.
294
+ * @param {String? } [type=null] - The buffer type (e.g. `'vec3'`).
295
+ * @param {Number } [stride=0] - The buffer stride.
296
+ * @param {Number } [offset=0] - The buffer offset.
297
+ * @returns {BufferAttributeNode }
298
+ */
299
+ export const bufferAttribute = ( array , type = null , stride = 0 , offset = 0 ) => nodeObject ( new BufferAttributeNode ( array , type , stride , offset ) ) ;
300
+
301
+ /**
302
+ * TSL function for creating a buffer attribute node but with dynamic draw usage.
303
+ * Use this function if attribute data are updated per frame.
304
+ *
305
+ * @function
306
+ * @param {BufferAttribute|InterleavedBuffer|TypedArray } array - The attribute data.
307
+ * @param {String? } [type=null] - The buffer type (e.g. `'vec3'`).
308
+ * @param {Number } [stride=0] - The buffer stride.
309
+ * @param {Number } [offset=0] - The buffer offset.
310
+ * @returns {BufferAttributeNode }
311
+ */
312
+ export const dynamicBufferAttribute = ( array , type = null , stride = 0 , offset = 0 ) => bufferAttribute ( array , type , stride , offset ) . setUsage ( DynamicDrawUsage ) ;
313
+
314
+ /**
315
+ * TSL function for creating a buffer attribute node but with enabled instancing
316
+ *
317
+ * @function
318
+ * @param {BufferAttribute|InterleavedBuffer|TypedArray } array - The attribute data.
319
+ * @param {String? } [type=null] - The buffer type (e.g. `'vec3'`).
320
+ * @param {Number } [stride=0] - The buffer stride.
321
+ * @param {Number } [offset=0] - The buffer offset.
322
+ * @returns {BufferAttributeNode }
323
+ */
324
+ export const instancedBufferAttribute = ( array , type = null , stride = 0 , offset = 0 ) => bufferAttribute ( array , type , stride , offset ) . setInstanced ( true ) ;
325
+
326
+ /**
327
+ * TSL function for creating a buffer attribute node but with dynamic draw usage and enabled instancing
328
+ *
329
+ * @function
330
+ * @param {BufferAttribute|InterleavedBuffer|TypedArray } array - The attribute data.
331
+ * @param {String? } [type=null] - The buffer type (e.g. `'vec3'`).
332
+ * @param {Number } [stride=0] - The buffer stride.
333
+ * @param {Number } [offset=0] - The buffer offset.
334
+ * @returns {BufferAttributeNode }
335
+ */
336
+ export const instancedDynamicBufferAttribute = ( array , type = null , stride = 0 , offset = 0 ) => dynamicBufferAttribute ( array , type , stride , offset ) . setInstanced ( true ) ;
164
337
165
338
addMethodChaining ( 'toAttribute' , ( bufferNode ) => bufferAttribute ( bufferNode . value ) ) ;
0 commit comments