@damienmortini/three 0.1.131

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,389 @@
1
+ import {
2
+ AdditiveBlending,
3
+ Box2,
4
+ BufferGeometry,
5
+ ClampToEdgeWrapping,
6
+ Color,
7
+ DataTexture,
8
+ InterleavedBuffer,
9
+ InterleavedBufferAttribute,
10
+ Mesh,
11
+ MeshBasicMaterial,
12
+ NearestFilter,
13
+ RGBFormat,
14
+ RawShaderMaterial,
15
+ Vector2,
16
+ Vector3,
17
+ Vector4
18
+ } from 'three';
19
+
20
+ class Lensflare extends Mesh {
21
+
22
+ constructor() {
23
+
24
+ super( Lensflare.Geometry, new MeshBasicMaterial( { opacity: 0, transparent: true } ) );
25
+
26
+ this.type = 'Lensflare';
27
+ this.frustumCulled = false;
28
+ this.renderOrder = Infinity;
29
+
30
+ //
31
+
32
+ const positionScreen = new Vector3();
33
+ const positionView = new Vector3();
34
+
35
+ // textures
36
+
37
+ const tempMap = new DataTexture( new Uint8Array( 16 * 16 * 3 ), 16, 16, RGBFormat );
38
+ tempMap.minFilter = NearestFilter;
39
+ tempMap.magFilter = NearestFilter;
40
+ tempMap.wrapS = ClampToEdgeWrapping;
41
+ tempMap.wrapT = ClampToEdgeWrapping;
42
+
43
+ const occlusionMap = new DataTexture( new Uint8Array( 16 * 16 * 3 ), 16, 16, RGBFormat );
44
+ occlusionMap.minFilter = NearestFilter;
45
+ occlusionMap.magFilter = NearestFilter;
46
+ occlusionMap.wrapS = ClampToEdgeWrapping;
47
+ occlusionMap.wrapT = ClampToEdgeWrapping;
48
+
49
+ // material
50
+
51
+ const geometry = Lensflare.Geometry;
52
+
53
+ const material1a = new RawShaderMaterial( {
54
+ uniforms: {
55
+ 'scale': { value: null },
56
+ 'screenPosition': { value: null }
57
+ },
58
+ vertexShader: /* glsl */`
59
+
60
+ precision highp float;
61
+
62
+ uniform vec3 screenPosition;
63
+ uniform vec2 scale;
64
+
65
+ attribute vec3 position;
66
+
67
+ void main() {
68
+
69
+ gl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );
70
+
71
+ }`,
72
+
73
+ fragmentShader: /* glsl */`
74
+
75
+ precision highp float;
76
+
77
+ void main() {
78
+
79
+ gl_FragColor = vec4( 1.0, 0.0, 1.0, 1.0 );
80
+
81
+ }`,
82
+ depthTest: true,
83
+ depthWrite: false,
84
+ transparent: false
85
+ } );
86
+
87
+ const material1b = new RawShaderMaterial( {
88
+ uniforms: {
89
+ 'map': { value: tempMap },
90
+ 'scale': { value: null },
91
+ 'screenPosition': { value: null }
92
+ },
93
+ vertexShader: /* glsl */`
94
+
95
+ precision highp float;
96
+
97
+ uniform vec3 screenPosition;
98
+ uniform vec2 scale;
99
+
100
+ attribute vec3 position;
101
+ attribute vec2 uv;
102
+
103
+ varying vec2 vUV;
104
+
105
+ void main() {
106
+
107
+ vUV = uv;
108
+
109
+ gl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );
110
+
111
+ }`,
112
+
113
+ fragmentShader: /* glsl */`
114
+
115
+ precision highp float;
116
+
117
+ uniform sampler2D map;
118
+
119
+ varying vec2 vUV;
120
+
121
+ void main() {
122
+
123
+ gl_FragColor = texture2D( map, vUV );
124
+
125
+ }`,
126
+ depthTest: false,
127
+ depthWrite: false,
128
+ transparent: false
129
+ } );
130
+
131
+ // the following object is used for occlusionMap generation
132
+
133
+ const mesh1 = new Mesh( geometry, material1a );
134
+
135
+ //
136
+
137
+ const elements = [];
138
+
139
+ const shader = LensflareElement.Shader;
140
+
141
+ const material2 = new RawShaderMaterial( {
142
+ uniforms: {
143
+ 'map': { value: null },
144
+ 'occlusionMap': { value: occlusionMap },
145
+ 'color': { value: new Color( 0xffffff ) },
146
+ 'scale': { value: new Vector2() },
147
+ 'screenPosition': { value: new Vector3() }
148
+ },
149
+ vertexShader: shader.vertexShader,
150
+ fragmentShader: shader.fragmentShader,
151
+ blending: AdditiveBlending,
152
+ transparent: true,
153
+ depthWrite: false
154
+ } );
155
+
156
+ const mesh2 = new Mesh( geometry, material2 );
157
+
158
+ this.addElement = function ( element ) {
159
+
160
+ elements.push( element );
161
+
162
+ };
163
+
164
+ //
165
+
166
+ const scale = new Vector2();
167
+ const screenPositionPixels = new Vector2();
168
+ const validArea = new Box2();
169
+ const viewport = new Vector4();
170
+
171
+ this.onBeforeRender = function ( renderer, scene, camera ) {
172
+
173
+ renderer.getCurrentViewport( viewport );
174
+
175
+ const invAspect = viewport.w / viewport.z;
176
+ const halfViewportWidth = viewport.z / 2.0;
177
+ const halfViewportHeight = viewport.w / 2.0;
178
+
179
+ let size = 16 / viewport.w;
180
+ scale.set( size * invAspect, size );
181
+
182
+ validArea.min.set( viewport.x, viewport.y );
183
+ validArea.max.set( viewport.x + ( viewport.z - 16 ), viewport.y + ( viewport.w - 16 ) );
184
+
185
+ // calculate position in screen space
186
+
187
+ positionView.setFromMatrixPosition( this.matrixWorld );
188
+ positionView.applyMatrix4( camera.matrixWorldInverse );
189
+
190
+ if ( positionView.z > 0 ) return; // lensflare is behind the camera
191
+
192
+ positionScreen.copy( positionView ).applyMatrix4( camera.projectionMatrix );
193
+
194
+ // horizontal and vertical coordinate of the lower left corner of the pixels to copy
195
+
196
+ screenPositionPixels.x = viewport.x + ( positionScreen.x * halfViewportWidth ) + halfViewportWidth - 8;
197
+ screenPositionPixels.y = viewport.y + ( positionScreen.y * halfViewportHeight ) + halfViewportHeight - 8;
198
+
199
+ // screen cull
200
+
201
+ if ( validArea.containsPoint( screenPositionPixels ) ) {
202
+
203
+ // save current RGB to temp texture
204
+
205
+ renderer.copyFramebufferToTexture( screenPositionPixels, tempMap );
206
+
207
+ // render pink quad
208
+
209
+ let uniforms = material1a.uniforms;
210
+ uniforms[ 'scale' ].value = scale;
211
+ uniforms[ 'screenPosition' ].value = positionScreen;
212
+
213
+ renderer.renderBufferDirect( camera, null, geometry, material1a, mesh1, null );
214
+
215
+ // copy result to occlusionMap
216
+
217
+ renderer.copyFramebufferToTexture( screenPositionPixels, occlusionMap );
218
+
219
+ // restore graphics
220
+
221
+ uniforms = material1b.uniforms;
222
+ uniforms[ 'scale' ].value = scale;
223
+ uniforms[ 'screenPosition' ].value = positionScreen;
224
+
225
+ renderer.renderBufferDirect( camera, null, geometry, material1b, mesh1, null );
226
+
227
+ // render elements
228
+
229
+ const vecX = - positionScreen.x * 2;
230
+ const vecY = - positionScreen.y * 2;
231
+
232
+ for ( let i = 0, l = elements.length; i < l; i ++ ) {
233
+
234
+ const element = elements[ i ];
235
+
236
+ const uniforms = material2.uniforms;
237
+
238
+ uniforms[ 'color' ].value.copy( element.color );
239
+ uniforms[ 'map' ].value = element.texture;
240
+ uniforms[ 'screenPosition' ].value.x = positionScreen.x + vecX * element.distance;
241
+ uniforms[ 'screenPosition' ].value.y = positionScreen.y + vecY * element.distance;
242
+
243
+ size = element.size / viewport.w;
244
+ const invAspect = viewport.w / viewport.z;
245
+
246
+ uniforms[ 'scale' ].value.set( size * invAspect, size );
247
+
248
+ material2.uniformsNeedUpdate = true;
249
+
250
+ renderer.renderBufferDirect( camera, null, geometry, material2, mesh2, null );
251
+
252
+ }
253
+
254
+ }
255
+
256
+ };
257
+
258
+ this.dispose = function () {
259
+
260
+ material1a.dispose();
261
+ material1b.dispose();
262
+ material2.dispose();
263
+
264
+ tempMap.dispose();
265
+ occlusionMap.dispose();
266
+
267
+ for ( let i = 0, l = elements.length; i < l; i ++ ) {
268
+
269
+ elements[ i ].texture.dispose();
270
+
271
+ }
272
+
273
+ };
274
+
275
+ }
276
+
277
+ }
278
+
279
+ Lensflare.prototype.isLensflare = true;
280
+
281
+ //
282
+
283
+ class LensflareElement {
284
+
285
+ constructor( texture, size = 1, distance = 0, color = new Color( 0xffffff ) ) {
286
+
287
+ this.texture = texture;
288
+ this.size = size;
289
+ this.distance = distance;
290
+ this.color = color;
291
+
292
+ }
293
+
294
+ }
295
+
296
+ LensflareElement.Shader = {
297
+
298
+ uniforms: {
299
+
300
+ 'map': { value: null },
301
+ 'occlusionMap': { value: null },
302
+ 'color': { value: null },
303
+ 'scale': { value: null },
304
+ 'screenPosition': { value: null }
305
+
306
+ },
307
+
308
+ vertexShader: /* glsl */`
309
+
310
+ precision highp float;
311
+
312
+ uniform vec3 screenPosition;
313
+ uniform vec2 scale;
314
+
315
+ uniform sampler2D occlusionMap;
316
+
317
+ attribute vec3 position;
318
+ attribute vec2 uv;
319
+
320
+ varying vec2 vUV;
321
+ varying float vVisibility;
322
+
323
+ void main() {
324
+
325
+ vUV = uv;
326
+
327
+ vec2 pos = position.xy;
328
+
329
+ vec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) );
330
+ visibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) );
331
+ visibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) );
332
+ visibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) );
333
+ visibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) );
334
+ visibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) );
335
+ visibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) );
336
+ visibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) );
337
+ visibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) );
338
+
339
+ vVisibility = visibility.r / 9.0;
340
+ vVisibility *= 1.0 - visibility.g / 9.0;
341
+ vVisibility *= visibility.b / 9.0;
342
+
343
+ gl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );
344
+
345
+ }`,
346
+
347
+ fragmentShader: /* glsl */`
348
+
349
+ precision highp float;
350
+
351
+ uniform sampler2D map;
352
+ uniform vec3 color;
353
+
354
+ varying vec2 vUV;
355
+ varying float vVisibility;
356
+
357
+ void main() {
358
+
359
+ vec4 texture = texture2D( map, vUV );
360
+ texture.a *= vVisibility;
361
+ gl_FragColor = texture;
362
+ gl_FragColor.rgb *= color;
363
+
364
+ }`
365
+
366
+ };
367
+
368
+ Lensflare.Geometry = ( function () {
369
+
370
+ const geometry = new BufferGeometry();
371
+
372
+ const float32Array = new Float32Array( [
373
+ - 1, - 1, 0, 0, 0,
374
+ 1, - 1, 0, 1, 0,
375
+ 1, 1, 0, 1, 1,
376
+ - 1, 1, 0, 0, 1
377
+ ] );
378
+
379
+ const interleavedBuffer = new InterleavedBuffer( float32Array, 5 );
380
+
381
+ geometry.setIndex( [ 0, 1, 2, 0, 2, 3 ] );
382
+ geometry.setAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );
383
+ geometry.setAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );
384
+
385
+ return geometry;
386
+
387
+ } )();
388
+
389
+ export { Lensflare, LensflareElement };