1 /**
2 * @author supereggbert / http://www.paulbrunt.co.uk/
3 * @author mrdoob / http://mrdoob.com/
4 * @author alteredq / http://alteredqualia.com/
5 * @author szimek / https://github.com/szimek/
6 */
7
8 /**@constructor*/
9 THREE.WebGLRenderer = function ( parameters ) {
10
11 console.log( 'THREE.WebGLRenderer', THREE.REVISION );
12
13 parameters = parameters || {};
14
15 var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElement( 'canvas' ),
16
17 _precision = parameters.precision !== undefined ? parameters.precision : 'highp',
18
19 _alpha = parameters.alpha !== undefined ? parameters.alpha : true,
20 _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
21 _antialias = parameters.antialias !== undefined ? parameters.antialias : false,
22 _stencil = parameters.stencil !== undefined ? parameters.stencil : true,
23 _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,
24
25 _clearColor = parameters.clearColor !== undefined ? new THREE.Color( parameters.clearColor ) : new THREE.Color( 0x000000 ),
26 _clearAlpha = parameters.clearAlpha !== undefined ? parameters.clearAlpha : 0;
27
28 // public properties
29
30 this.domElement = _canvas;
31 this.context = null;
32
33 // clearing
34
35 this.autoClear = true;
36 this.autoClearColor = true;
37 this.autoClearDepth = true;
38 this.autoClearStencil = true;
39
40 // scene graph
41
42 this.sortObjects = true;
43
44 this.autoUpdateObjects = true;
45 this.autoUpdateScene = true;
46
47 // physically based shading
48
49 this.gammaInput = false;
50 this.gammaOutput = false;
51 this.physicallyBasedShading = false;
52
53 // shadow map
54
55 this.shadowMapEnabled = false;
56 this.shadowMapAutoUpdate = true;
57 this.shadowMapSoft = true;
58 this.shadowMapCullFrontFaces = true;
59 this.shadowMapDebug = false;
60 this.shadowMapCascade = false;
61
62 // morphs
63
64 this.maxMorphTargets = 8;
65 this.maxMorphNormals = 4;
66
67 // flags
68
69 this.autoScaleCubemaps = true;
70
71 // custom render plugins
72
73 this.renderPluginsPre = [];
74 this.renderPluginsPost = [];
75
76 // info
77
78 this.info = {
79
80 memory: {
81
82 programs: 0,
83 geometries: 0,
84 textures: 0
85
86 },
87
88 render: {
89
90 calls: 0,
91 vertices: 0,
92 faces: 0,
93 points: 0
94
95 }
96
97 };
98
99 // internal properties
100
101 var _this = this,
102
103 _programs = [],
104 _programs_counter = 0,
105
106 // internal state cache
107
108 _currentProgram = null,
109 _currentFramebuffer = null,
110 _currentMaterialId = -1,
111 _currentGeometryGroupHash = null,
112 _currentCamera = null,
113 _geometryGroupCounter = 0,
114
115 _usedTextureUnits = 0,
116
117 // GL state cache
118
119 _oldDoubleSided = -1,
120 _oldFlipSided = -1,
121
122 _oldBlending = -1,
123
124 _oldBlendEquation = -1,
125 _oldBlendSrc = -1,
126 _oldBlendDst = -1,
127
128 _oldDepthTest = -1,
129 _oldDepthWrite = -1,
130
131 _oldPolygonOffset = null,
132 _oldPolygonOffsetFactor = null,
133 _oldPolygonOffsetUnits = null,
134
135 _oldLineWidth = null,
136
137 _viewportX = 0,
138 _viewportY = 0,
139 _viewportWidth = 0,
140 _viewportHeight = 0,
141 _currentWidth = 0,
142 _currentHeight = 0,
143
144 // frustum
145
146 _frustum = new THREE.Frustum(),
147
148 // camera matrices cache
149
150 _projScreenMatrix = new THREE.Matrix4(),
151 _projScreenMatrixPS = new THREE.Matrix4(),
152
153 _vector3 = new THREE.Vector4(),
154
155 // light arrays cache
156
157 _direction = new THREE.Vector3(),
158
159 _lightsNeedUpdate = true,
160
161 _lights = {
162
163 ambient: [ 0, 0, 0 ],
164 directional: { length: 0, colors: new Array(), positions: new Array() },
165 point: { length: 0, colors: new Array(), positions: new Array(), distances: new Array() },
166 spot: { length: 0, colors: new Array(), positions: new Array(), distances: new Array(), directions: new Array(), anglesCos: new Array(), exponents: new Array() },
167 hemi: { length: 0, skyColors: new Array(), groundColors: new Array(), positions: new Array() }
168
169 };
170
171 // initialize
172
173 var _gl;
174
175 var _glExtensionTextureFloat;
176 var _glExtensionStandardDerivatives;
177 var _glExtensionTextureFilterAnisotropic;
178 var _glExtensionCompressedTextureS3TC;
179
180 initGL();
181
182 setDefaultGLState();
183
184 this.context = _gl;
185
186 // GPU capabilities
187
188 var _maxTextures = _gl.getParameter( _gl.MAX_TEXTURE_IMAGE_UNITS );
189 var _maxVertexTextures = _gl.getParameter( _gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS );
190 var _maxTextureSize = _gl.getParameter( _gl.MAX_TEXTURE_SIZE );
191 var _maxCubemapSize = _gl.getParameter( _gl.MAX_CUBE_MAP_TEXTURE_SIZE );
192
193 var _maxAnisotropy = _glExtensionTextureFilterAnisotropic ? _gl.getParameter( _glExtensionTextureFilterAnisotropic.MAX_TEXTURE_MAX_ANISOTROPY_EXT ) : 0;
194
195 var _supportsVertexTextures = ( _maxVertexTextures > 0 );
196 var _supportsBoneTextures = _supportsVertexTextures && _glExtensionTextureFloat;
197
198 var _compressedTextureFormats = _glExtensionCompressedTextureS3TC ? _gl.getParameter( _gl.COMPRESSED_TEXTURE_FORMATS ) : [];
199
200 // API
201
202 this.getContext = function () {
203
204 return _gl;
205
206 };
207
208 this.supportsVertexTextures = function () {
209
210 return _supportsVertexTextures;
211
212 };
213
214 this.getMaxAnisotropy = function () {
215
216 return _maxAnisotropy;
217
218 };
219
220 this.setSize = function ( width, height ) {
221
222 _canvas.width = width;
223 _canvas.height = height;
224
225 this.setViewport( 0, 0, _canvas.width, _canvas.height );
226
227 };
228
229 this.setViewport = function ( x, y, width, height ) {
230
231 _viewportX = x !== undefined ? x : 0;
232 _viewportY = y !== undefined ? y : 0;
233
234 _viewportWidth = width !== undefined ? width : _canvas.width;
235 _viewportHeight = height !== undefined ? height : _canvas.height;
236
237 _gl.viewport( _viewportX, _viewportY, _viewportWidth, _viewportHeight );
238
239 };
240
241 this.setScissor = function ( x, y, width, height ) {
242
243 _gl.scissor( x, y, width, height );
244
245 };
246
247 this.enableScissorTest = function ( enable ) {
248
249 enable ? _gl.enable( _gl.SCISSOR_TEST ) : _gl.disable( _gl.SCISSOR_TEST );
250
251 };
252
253 // Clearing
254
255 this.setClearColorHex = function ( hex, alpha ) {
256
257 _clearColor.setHex( hex );
258 _clearAlpha = alpha;
259
260 _gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
261
262 };
263
264 this.setClearColor = function ( color, alpha ) {
265
266 _clearColor.copy( color );
267 _clearAlpha = alpha;
268
269 _gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
270
271 };
272
273 this.getClearColor = function () {
274
275 return _clearColor;
276
277 };
278
279 this.getClearAlpha = function () {
280
281 return _clearAlpha;
282
283 };
284
285 this.clear = function ( color, depth, stencil ) {
286
287 var bits = 0;
288
289 if ( color === undefined || color ) bits |= _gl.COLOR_BUFFER_BIT;
290 if ( depth === undefined || depth ) bits |= _gl.DEPTH_BUFFER_BIT;
291 if ( stencil === undefined || stencil ) bits |= _gl.STENCIL_BUFFER_BIT;
292
293 _gl.clear( bits );
294
295 };
296
297 this.clearTarget = function ( renderTarget, color, depth, stencil ) {
298
299 this.setRenderTarget( renderTarget );
300 this.clear( color, depth, stencil );
301
302 };
303
304 // Plugins
305
306 this.addPostPlugin = function ( plugin ) {
307
308 plugin.init( this );
309 this.renderPluginsPost.push( plugin );
310
311 };
312
313 this.addPrePlugin = function ( plugin ) {
314
315 plugin.init( this );
316 this.renderPluginsPre.push( plugin );
317
318 };
319
320 // Deallocation
321
322 this.deallocateObject = function ( object ) {
323
324 if ( ! object.__webglInit ) return;
325
326 object.__webglInit = false;
327
328 delete object._modelViewMatrix;
329 delete object._normalMatrix;
330
331 delete object._normalMatrixArray;
332 delete object._modelViewMatrixArray;
333 delete object._modelMatrixArray;
334
335 if ( object instanceof THREE.Mesh ) {
336
337 for ( var g in object.geometry.geometryGroups ) {
338
339 deleteMeshBuffers( object.geometry.geometryGroups[ g ] );
340
341 }
342
343 } else if ( object instanceof THREE.Ribbon ) {
344
345 deleteRibbonBuffers( object.geometry );
346
347 } else if ( object instanceof THREE.Line ) {
348
349 deleteLineBuffers( object.geometry );
350
351 } else if ( object instanceof THREE.ParticleSystem ) {
352
353 deleteParticleBuffers( object.geometry );
354
355 }
356
357 };
358
359 this.deallocateTexture = function ( texture ) {
360
361 if ( ! texture.__webglInit ) return;
362
363 texture.__webglInit = false;
364 _gl.deleteTexture( texture.__webglTexture );
365
366 _this.info.memory.textures --;
367
368 };
369
370 this.deallocateRenderTarget = function ( renderTarget ) {
371
372 if ( !renderTarget || ! renderTarget.__webglTexture ) return;
373
374 _gl.deleteTexture( renderTarget.__webglTexture );
375
376 if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {
377
378 for ( var i = 0; i < 6; i ++ ) {
379
380 _gl.deleteFramebuffer( renderTarget.__webglFramebuffer[ i ] );
381 _gl.deleteRenderbuffer( renderTarget.__webglRenderbuffer[ i ] );
382
383 }
384
385 } else {
386
387 _gl.deleteFramebuffer( renderTarget.__webglFramebuffer );
388 _gl.deleteRenderbuffer( renderTarget.__webglRenderbuffer );
389
390 }
391
392 };
393
394 this.deallocateMaterial = function ( material ) {
395
396 var program = material.program;
397
398 if ( ! program ) return;
399
400 material.program = undefined;
401
402 // only deallocate GL program if this was the last use of shared program
403 // assumed there is only single copy of any program in the _programs list
404 // (that's how it's constructed)
405
406 var i, il, programInfo;
407 var deleteProgram = false;
408
409 for ( i = 0, il = _programs.length; i < il; i ++ ) {
410
411 programInfo = _programs[ i ];
412
413 if ( programInfo.program === program ) {
414
415 programInfo.usedTimes --;
416
417 if ( programInfo.usedTimes === 0 ) {
418
419 deleteProgram = true;
420
421 }
422
423 break;
424
425 }
426
427 }
428
429 if ( deleteProgram ) {
430
431 // avoid using array.splice, this is costlier than creating new array from scratch
432
433 var newPrograms = [];
434
435 for ( i = 0, il = _programs.length; i < il; i ++ ) {
436
437 programInfo = _programs[ i ];
438
439 if ( programInfo.program !== program ) {
440
441 newPrograms.push( programInfo );
442
443 }
444
445 }
446
447 _programs = newPrograms;
448
449 _gl.deleteProgram( program );
450
451 _this.info.memory.programs --;
452
453 }
454
455 };
456
457 // Rendering
458
459 this.updateShadowMap = function ( scene, camera ) {
460
461 _currentProgram = null;
462 _oldBlending = -1;
463 _oldDepthTest = -1;
464 _oldDepthWrite = -1;
465 _currentGeometryGroupHash = -1;
466 _currentMaterialId = -1;
467 _lightsNeedUpdate = true;
468 _oldDoubleSided = -1;
469 _oldFlipSided = -1;
470
471 this.shadowMapPlugin.update( scene, camera );
472
473 };
474
475 // Internal functions
476
477 // Buffer allocation
478
479 function createParticleBuffers ( geometry ) {
480
481 geometry.__webglVertexBuffer = _gl.createBuffer();
482 geometry.__webglColorBuffer = _gl.createBuffer();
483
484 _this.info.memory.geometries ++;
485
486 };
487
488 function createLineBuffers ( geometry ) {
489
490 geometry.__webglVertexBuffer = _gl.createBuffer();
491 geometry.__webglColorBuffer = _gl.createBuffer();
492 geometry.__webglLineDistanceBuffer = _gl.createBuffer();
493
494 _this.info.memory.geometries ++;
495
496 };
497
498 function createRibbonBuffers ( geometry ) {
499
500 geometry.__webglVertexBuffer = _gl.createBuffer();
501 geometry.__webglColorBuffer = _gl.createBuffer();
502 geometry.__webglNormalBuffer = _gl.createBuffer();
503
504 _this.info.memory.geometries ++;
505
506 };
507
508 function createMeshBuffers ( geometryGroup ) {
509
510 geometryGroup.__webglVertexBuffer = _gl.createBuffer();
511 geometryGroup.__webglNormalBuffer = _gl.createBuffer();
512 geometryGroup.__webglTangentBuffer = _gl.createBuffer();
513 geometryGroup.__webglColorBuffer = _gl.createBuffer();
514 geometryGroup.__webglUVBuffer = _gl.createBuffer();
515 geometryGroup.__webglUV2Buffer = _gl.createBuffer();
516
517 geometryGroup.__webglSkinIndicesBuffer = _gl.createBuffer();
518 geometryGroup.__webglSkinWeightsBuffer = _gl.createBuffer();
519
520 geometryGroup.__webglFaceBuffer = _gl.createBuffer();
521 geometryGroup.__webglLineBuffer = _gl.createBuffer();
522
523 var m, ml;
524
525 if ( geometryGroup.numMorphTargets ) {
526
527 geometryGroup.__webglMorphTargetsBuffers = [];
528
529 for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
530
531 geometryGroup.__webglMorphTargetsBuffers.push( _gl.createBuffer() );
532
533 }
534
535 }
536
537 if ( geometryGroup.numMorphNormals ) {
538
539 geometryGroup.__webglMorphNormalsBuffers = [];
540
541 for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
542
543 geometryGroup.__webglMorphNormalsBuffers.push( _gl.createBuffer() );
544
545 }
546
547 }
548
549 _this.info.memory.geometries ++;
550
551 };
552
553 // Buffer deallocation
554
555 function deleteParticleBuffers ( geometry ) {
556
557 _gl.deleteBuffer( geometry.__webglVertexBuffer );
558 _gl.deleteBuffer( geometry.__webglColorBuffer );
559
560 deleteCustomAttributesBuffers( geometry );
561
562 _this.info.memory.geometries --;
563
564 };
565
566 function deleteLineBuffers ( geometry ) {
567
568 _gl.deleteBuffer( geometry.__webglVertexBuffer );
569 _gl.deleteBuffer( geometry.__webglColorBuffer );
570 _gl.deleteBuffer( geometry.__webglLineDistanceBuffer );
571
572 deleteCustomAttributesBuffers( geometry );
573
574 _this.info.memory.geometries --;
575
576 };
577
578 function deleteRibbonBuffers ( geometry ) {
579
580 _gl.deleteBuffer( geometry.__webglVertexBuffer );
581 _gl.deleteBuffer( geometry.__webglColorBuffer );
582 _gl.deleteBuffer( geometry.__webglNormalBuffer );
583
584 deleteCustomAttributesBuffers( geometry );
585
586 _this.info.memory.geometries --;
587
588 };
589
590 function deleteMeshBuffers ( geometryGroup ) {
591
592 _gl.deleteBuffer( geometryGroup.__webglVertexBuffer );
593 _gl.deleteBuffer( geometryGroup.__webglNormalBuffer );
594 _gl.deleteBuffer( geometryGroup.__webglTangentBuffer );
595 _gl.deleteBuffer( geometryGroup.__webglColorBuffer );
596 _gl.deleteBuffer( geometryGroup.__webglUVBuffer );
597 _gl.deleteBuffer( geometryGroup.__webglUV2Buffer );
598
599 _gl.deleteBuffer( geometryGroup.__webglSkinIndicesBuffer );
600 _gl.deleteBuffer( geometryGroup.__webglSkinWeightsBuffer );
601
602 _gl.deleteBuffer( geometryGroup.__webglFaceBuffer );
603 _gl.deleteBuffer( geometryGroup.__webglLineBuffer );
604
605 var m, ml;
606
607 if ( geometryGroup.numMorphTargets ) {
608
609 for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
610
611 _gl.deleteBuffer( geometryGroup.__webglMorphTargetsBuffers[ m ] );
612
613 }
614
615 }
616
617 if ( geometryGroup.numMorphNormals ) {
618
619 for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
620
621 _gl.deleteBuffer( geometryGroup.__webglMorphNormalsBuffers[ m ] );
622
623 }
624
625 }
626
627 deleteCustomAttributesBuffers( geometryGroup );
628
629 _this.info.memory.geometries --;
630
631 };
632
633 function deleteCustomAttributesBuffers( geometry ) {
634
635 if ( geometry.__webglCustomAttributesList ) {
636
637 for ( var id in geometry.__webglCustomAttributesList ) {
638
639 _gl.deleteBuffer( geometry.__webglCustomAttributesList[ id ].buffer );
640
641 }
642
643 }
644
645 };
646
647 // Buffer initialization
648
649 function initCustomAttributes ( geometry, object ) {
650
651 var nvertices = geometry.vertices.length;
652
653 var material = object.material;
654
655 if ( material.attributes ) {
656
657 if ( geometry.__webglCustomAttributesList === undefined ) {
658
659 geometry.__webglCustomAttributesList = [];
660
661 }
662
663 for ( var a in material.attributes ) {
664
665 var attribute = material.attributes[ a ];
666
667 if ( !attribute.__webglInitialized || attribute.createUniqueBuffers ) {
668
669 attribute.__webglInitialized = true;
670
671 var size = 1; // "f" and "i"
672
673 if ( attribute.type === "v2" ) size = 2;
674 else if ( attribute.type === "v3" ) size = 3;
675 else if ( attribute.type === "v4" ) size = 4;
676 else if ( attribute.type === "c" ) size = 3;
677
678 attribute.size = size;
679
680 attribute.array = new Float32Array( nvertices * size );
681
682 attribute.buffer = _gl.createBuffer();
683 attribute.buffer.belongsToAttribute = a;
684
685 attribute.needsUpdate = true;
686
687 }
688
689 geometry.__webglCustomAttributesList.push( attribute );
690
691 }
692
693 }
694
695 };
696
697 function initParticleBuffers ( geometry, object ) {
698
699 var nvertices = geometry.vertices.length;
700
701 geometry.__vertexArray = new Float32Array( nvertices * 3 );
702 geometry.__colorArray = new Float32Array( nvertices * 3 );
703
704 geometry.__sortArray = [];
705
706 geometry.__webglParticleCount = nvertices;
707
708 initCustomAttributes ( geometry, object );
709
710 };
711
712 function initLineBuffers ( geometry, object ) {
713
714 var nvertices = geometry.vertices.length;
715
716 geometry.__vertexArray = new Float32Array( nvertices * 3 );
717 geometry.__colorArray = new Float32Array( nvertices * 3 );
718 geometry.__lineDistanceArray = new Float32Array( nvertices * 1 );
719
720 geometry.__webglLineCount = nvertices;
721
722 initCustomAttributes ( geometry, object );
723
724 };
725
726 function initRibbonBuffers ( geometry, object ) {
727
728 var nvertices = geometry.vertices.length;
729
730 geometry.__vertexArray = new Float32Array( nvertices * 3 );
731 geometry.__colorArray = new Float32Array( nvertices * 3 );
732 geometry.__normalArray = new Float32Array( nvertices * 3 );
733
734 geometry.__webglVertexCount = nvertices;
735
736 initCustomAttributes ( geometry, object );
737
738 };
739
740 function initMeshBuffers ( geometryGroup, object ) {
741
742 var geometry = object.geometry,
743 faces3 = geometryGroup.faces3,
744 faces4 = geometryGroup.faces4,
745
746 nvertices = faces3.length * 3 + faces4.length * 4,
747 ntris = faces3.length * 1 + faces4.length * 2,
748 nlines = faces3.length * 3 + faces4.length * 4,
749
750 material = getBufferMaterial( object, geometryGroup ),
751
752 uvType = bufferGuessUVType( material ),
753 normalType = bufferGuessNormalType( material ),
754 vertexColorType = bufferGuessVertexColorType( material );
755
756 //console.log( "uvType", uvType, "normalType", normalType, "vertexColorType", vertexColorType, object, geometryGroup, material );
757
758 geometryGroup.__vertexArray = new Float32Array( nvertices * 3 );
759
760 if ( normalType ) {
761
762 geometryGroup.__normalArray = new Float32Array( nvertices * 3 );
763
764 }
765
766 if ( geometry.hasTangents ) {
767
768 geometryGroup.__tangentArray = new Float32Array( nvertices * 4 );
769
770 }
771
772 if ( vertexColorType ) {
773
774 geometryGroup.__colorArray = new Float32Array( nvertices * 3 );
775
776 }
777
778 if ( uvType ) {
779
780 if ( geometry.faceUvs.length > 0 || geometry.faceVertexUvs.length > 0 ) {
781
782 geometryGroup.__uvArray = new Float32Array( nvertices * 2 );
783
784 }
785
786 if ( geometry.faceUvs.length > 1 || geometry.faceVertexUvs.length > 1 ) {
787
788 geometryGroup.__uv2Array = new Float32Array( nvertices * 2 );
789
790 }
791
792 }
793
794 if ( object.geometry.skinWeights.length && object.geometry.skinIndices.length ) {
795
796 geometryGroup.__skinIndexArray = new Float32Array( nvertices * 4 );
797 geometryGroup.__skinWeightArray = new Float32Array( nvertices * 4 );
798
799 }
800
801 geometryGroup.__faceArray = new Uint16Array( ntris * 3 );
802 geometryGroup.__lineArray = new Uint16Array( nlines * 2 );
803
804 var m, ml;
805
806 if ( geometryGroup.numMorphTargets ) {
807
808 geometryGroup.__morphTargetsArrays = [];
809
810 for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
811
812 geometryGroup.__morphTargetsArrays.push( new Float32Array( nvertices * 3 ) );
813
814 }
815
816 }
817
818 if ( geometryGroup.numMorphNormals ) {
819
820 geometryGroup.__morphNormalsArrays = [];
821
822 for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
823
824 geometryGroup.__morphNormalsArrays.push( new Float32Array( nvertices * 3 ) );
825
826 }
827
828 }
829
830 geometryGroup.__webglFaceCount = ntris * 3;
831 geometryGroup.__webglLineCount = nlines * 2;
832
833
834 // custom attributes
835
836 if ( material.attributes ) {
837
838 if ( geometryGroup.__webglCustomAttributesList === undefined ) {
839
840 geometryGroup.__webglCustomAttributesList = [];
841
842 }
843
844 for ( var a in material.attributes ) {
845
846 // Do a shallow copy of the attribute object so different geometryGroup chunks use different
847 // attribute buffers which are correctly indexed in the setMeshBuffers function
848
849 var originalAttribute = material.attributes[ a ];
850
851 var attribute = {};
852
853 for ( var property in originalAttribute ) {
854
855 attribute[ property ] = originalAttribute[ property ];
856
857 }
858
859 if ( !attribute.__webglInitialized || attribute.createUniqueBuffers ) {
860
861 attribute.__webglInitialized = true;
862
863 var size = 1; // "f" and "i"
864
865 if( attribute.type === "v2" ) size = 2;
866 else if( attribute.type === "v3" ) size = 3;
867 else if( attribute.type === "v4" ) size = 4;
868 else if( attribute.type === "c" ) size = 3;
869
870 attribute.size = size;
871
872 attribute.array = new Float32Array( nvertices * size );
873
874 attribute.buffer = _gl.createBuffer();
875 attribute.buffer.belongsToAttribute = a;
876
877 originalAttribute.needsUpdate = true;
878 attribute.__original = originalAttribute;
879
880 }
881
882 geometryGroup.__webglCustomAttributesList.push( attribute );
883
884 }
885
886 }
887
888 geometryGroup.__inittedArrays = true;
889
890 };
891
892 function getBufferMaterial( object, geometryGroup ) {
893
894 return object.material instanceof THREE.MeshFaceMaterial
895 ? object.material.materials[ geometryGroup.materialIndex ]
896 : object.material;
897
898 };
899
900 function materialNeedsSmoothNormals ( material ) {
901
902 return material && material.shading !== undefined && material.shading === THREE.SmoothShading;
903
904 };
905
906 function bufferGuessNormalType ( material ) {
907
908 // only MeshBasicMaterial and MeshDepthMaterial don't need normals
909
910 if ( ( material instanceof THREE.MeshBasicMaterial && !material.envMap ) || material instanceof THREE.MeshDepthMaterial ) {
911
912 return false;
913
914 }
915
916 if ( materialNeedsSmoothNormals( material ) ) {
917
918 return THREE.SmoothShading;
919
920 } else {
921
922 return THREE.FlatShading;
923
924 }
925
926 };
927
928 function bufferGuessVertexColorType ( material ) {
929
930 if ( material.vertexColors ) {
931
932 return material.vertexColors;
933
934 }
935
936 return false;
937
938 };
939
940 function bufferGuessUVType ( material ) {
941
942 // material must use some texture to require uvs
943
944 if ( material.map || material.lightMap || material.bumpMap || material.normalMap || material.specularMap || material instanceof THREE.ShaderMaterial ) {
945
946 return true;
947
948 }
949
950 return false;
951
952 };
953
954 //
955
956 function initDirectBuffers( geometry ) {
957
958 var a, attribute, type;
959
960 for ( a in geometry.attributes ) {
961
962 if ( a === "index" ) {
963
964 type = _gl.ELEMENT_ARRAY_BUFFER;
965
966 } else {
967
968 type = _gl.ARRAY_BUFFER;
969
970 }
971
972 attribute = geometry.attributes[ a ];
973
974 attribute.buffer = _gl.createBuffer();
975
976 _gl.bindBuffer( type, attribute.buffer );
977 _gl.bufferData( type, attribute.array, _gl.STATIC_DRAW );
978
979 }
980
981 };
982
983 // Buffer setting
984
985 function setParticleBuffers ( geometry, hint, object ) {
986
987 var v, c, vertex, offset, index, color,
988
989 vertices = geometry.vertices,
990 vl = vertices.length,
991
992 colors = geometry.colors,
993 cl = colors.length,
994
995 vertexArray = geometry.__vertexArray,
996 colorArray = geometry.__colorArray,
997
998 sortArray = geometry.__sortArray,
999
1000 dirtyVertices = geometry.verticesNeedUpdate,
1001 dirtyElements = geometry.elementsNeedUpdate,
1002 dirtyColors = geometry.colorsNeedUpdate,
1003
1004 customAttributes = geometry.__webglCustomAttributesList,
1005 i, il,
1006 a, ca, cal, value,
1007 customAttribute;
1008
1009 if ( object.sortParticles ) {
1010
1011 _projScreenMatrixPS.copy( _projScreenMatrix );
1012 _projScreenMatrixPS.multiplySelf( object.matrixWorld );
1013
1014 for ( v = 0; v < vl; v ++ ) {
1015
1016 vertex = vertices[ v ];
1017
1018 _vector3.copy( vertex );
1019 _projScreenMatrixPS.multiplyVector3( _vector3 );
1020
1021 sortArray[ v ] = [ _vector3.z, v ];
1022
1023 }
1024
1025 sortArray.sort( function( a, b ) { return b[ 0 ] - a[ 0 ]; } );
1026
1027 for ( v = 0; v < vl; v ++ ) {
1028
1029 vertex = vertices[ sortArray[v][1] ];
1030
1031 offset = v * 3;
1032
1033 vertexArray[ offset ] = vertex.x;
1034 vertexArray[ offset + 1 ] = vertex.y;
1035 vertexArray[ offset + 2 ] = vertex.z;
1036
1037 }
1038
1039 for ( c = 0; c < cl; c ++ ) {
1040
1041 offset = c * 3;
1042
1043 color = colors[ sortArray[c][1] ];
1044
1045 colorArray[ offset ] = color.r;
1046 colorArray[ offset + 1 ] = color.g;
1047 colorArray[ offset + 2 ] = color.b;
1048
1049 }
1050
1051 if ( customAttributes ) {
1052
1053 for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
1054
1055 customAttribute = customAttributes[ i ];
1056
1057 if ( ! ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) ) continue;
1058
1059 offset = 0;
1060
1061 cal = customAttribute.value.length;
1062
1063 if ( customAttribute.size === 1 ) {
1064
1065 for ( ca = 0; ca < cal; ca ++ ) {
1066
1067 index = sortArray[ ca ][ 1 ];
1068
1069 customAttribute.array[ ca ] = customAttribute.value[ index ];
1070
1071 }
1072
1073 } else if ( customAttribute.size === 2 ) {
1074
1075 for ( ca = 0; ca < cal; ca ++ ) {
1076
1077 index = sortArray[ ca ][ 1 ];
1078
1079 value = customAttribute.value[ index ];
1080
1081 customAttribute.array[ offset ] = value.x;
1082 customAttribute.array[ offset + 1 ] = value.y;
1083
1084 offset += 2;
1085
1086 }
1087
1088 } else if ( customAttribute.size === 3 ) {
1089
1090 if ( customAttribute.type === "c" ) {
1091
1092 for ( ca = 0; ca < cal; ca ++ ) {
1093
1094 index = sortArray[ ca ][ 1 ];
1095
1096 value = customAttribute.value[ index ];
1097
1098 customAttribute.array[ offset ] = value.r;
1099 customAttribute.array[ offset + 1 ] = value.g;
1100 customAttribute.array[ offset + 2 ] = value.b;
1101
1102 offset += 3;
1103
1104 }
1105
1106 } else {
1107
1108 for ( ca = 0; ca < cal; ca ++ ) {
1109
1110 index = sortArray[ ca ][ 1 ];
1111
1112 value = customAttribute.value[ index ];
1113
1114 customAttribute.array[ offset ] = value.x;
1115 customAttribute.array[ offset + 1 ] = value.y;
1116 customAttribute.array[ offset + 2 ] = value.z;
1117
1118 offset += 3;
1119
1120 }
1121
1122 }
1123
1124 } else if ( customAttribute.size === 4 ) {
1125
1126 for ( ca = 0; ca < cal; ca ++ ) {
1127
1128 index = sortArray[ ca ][ 1 ];
1129
1130 value = customAttribute.value[ index ];
1131
1132 customAttribute.array[ offset ] = value.x;
1133 customAttribute.array[ offset + 1 ] = value.y;
1134 customAttribute.array[ offset + 2 ] = value.z;
1135 customAttribute.array[ offset + 3 ] = value.w;
1136
1137 offset += 4;
1138
1139 }
1140
1141 }
1142
1143 }
1144
1145 }
1146
1147 } else {
1148
1149 if ( dirtyVertices ) {
1150
1151 for ( v = 0; v < vl; v ++ ) {
1152
1153 vertex = vertices[ v ];
1154
1155 offset = v * 3;
1156
1157 vertexArray[ offset ] = vertex.x;
1158 vertexArray[ offset + 1 ] = vertex.y;
1159 vertexArray[ offset + 2 ] = vertex.z;
1160
1161 }
1162
1163 }
1164
1165 if ( dirtyColors ) {
1166
1167 for ( c = 0; c < cl; c ++ ) {
1168
1169 color = colors[ c ];
1170
1171 offset = c * 3;
1172
1173 colorArray[ offset ] = color.r;
1174 colorArray[ offset + 1 ] = color.g;
1175 colorArray[ offset + 2 ] = color.b;
1176
1177 }
1178
1179 }
1180
1181 if ( customAttributes ) {
1182
1183 for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
1184
1185 customAttribute = customAttributes[ i ];
1186
1187 if ( customAttribute.needsUpdate &&
1188 ( customAttribute.boundTo === undefined ||
1189 customAttribute.boundTo === "vertices") ) {
1190
1191 cal = customAttribute.value.length;
1192
1193 offset = 0;
1194
1195 if ( customAttribute.size === 1 ) {
1196
1197 for ( ca = 0; ca < cal; ca ++ ) {
1198
1199 customAttribute.array[ ca ] = customAttribute.value[ ca ];
1200
1201 }
1202
1203 } else if ( customAttribute.size === 2 ) {
1204
1205 for ( ca = 0; ca < cal; ca ++ ) {
1206
1207 value = customAttribute.value[ ca ];
1208
1209 customAttribute.array[ offset ] = value.x;
1210 customAttribute.array[ offset + 1 ] = value.y;
1211
1212 offset += 2;
1213
1214 }
1215
1216 } else if ( customAttribute.size === 3 ) {
1217
1218 if ( customAttribute.type === "c" ) {
1219
1220 for ( ca = 0; ca < cal; ca ++ ) {
1221
1222 value = customAttribute.value[ ca ];
1223
1224 customAttribute.array[ offset ] = value.r;
1225 customAttribute.array[ offset + 1 ] = value.g;
1226 customAttribute.array[ offset + 2 ] = value.b;
1227
1228 offset += 3;
1229
1230 }
1231
1232 } else {
1233
1234 for ( ca = 0; ca < cal; ca ++ ) {
1235
1236 value = customAttribute.value[ ca ];
1237
1238 customAttribute.array[ offset ] = value.x;
1239 customAttribute.array[ offset + 1 ] = value.y;
1240 customAttribute.array[ offset + 2 ] = value.z;
1241
1242 offset += 3;
1243
1244 }
1245
1246 }
1247
1248 } else if ( customAttribute.size === 4 ) {
1249
1250 for ( ca = 0; ca < cal; ca ++ ) {
1251
1252 value = customAttribute.value[ ca ];
1253
1254 customAttribute.array[ offset ] = value.x;
1255 customAttribute.array[ offset + 1 ] = value.y;
1256 customAttribute.array[ offset + 2 ] = value.z;
1257 customAttribute.array[ offset + 3 ] = value.w;
1258
1259 offset += 4;
1260
1261 }
1262
1263 }
1264
1265 }
1266
1267 }
1268
1269 }
1270
1271 }
1272
1273 if ( dirtyVertices || object.sortParticles ) {
1274
1275 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer );
1276 _gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );
1277
1278 }
1279
1280 if ( dirtyColors || object.sortParticles ) {
1281
1282 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer );
1283 _gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );
1284
1285 }
1286
1287 if ( customAttributes ) {
1288
1289 for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
1290
1291 customAttribute = customAttributes[ i ];
1292
1293 if ( customAttribute.needsUpdate || object.sortParticles ) {
1294
1295 _gl.bindBuffer( _gl.ARRAY_BUFFER, customAttribute.buffer );
1296 _gl.bufferData( _gl.ARRAY_BUFFER, customAttribute.array, hint );
1297
1298 }
1299
1300 }
1301
1302 }
1303
1304
1305 };
1306
1307 function setLineBuffers ( geometry, hint ) {
1308
1309 var v, c, d, vertex, offset, color,
1310
1311 vertices = geometry.vertices,
1312 colors = geometry.colors,
1313 lineDistances = geometry.lineDistances,
1314
1315 vl = vertices.length,
1316 cl = colors.length,
1317 dl = lineDistances.length,
1318
1319 vertexArray = geometry.__vertexArray,
1320 colorArray = geometry.__colorArray,
1321 lineDistanceArray = geometry.__lineDistanceArray,
1322
1323 dirtyVertices = geometry.verticesNeedUpdate,
1324 dirtyColors = geometry.colorsNeedUpdate,
1325 dirtyLineDistances = geometry.lineDistancesNeedUpdate,
1326
1327 customAttributes = geometry.__webglCustomAttributesList,
1328
1329 i, il,
1330 a, ca, cal, value,
1331 customAttribute;
1332
1333 if ( dirtyVertices ) {
1334
1335 for ( v = 0; v < vl; v ++ ) {
1336
1337 vertex = vertices[ v ];
1338
1339 offset = v * 3;
1340
1341 vertexArray[ offset ] = vertex.x;
1342 vertexArray[ offset + 1 ] = vertex.y;
1343 vertexArray[ offset + 2 ] = vertex.z;
1344
1345 }
1346
1347 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer );
1348 _gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );
1349
1350 }
1351
1352 if ( dirtyColors ) {
1353
1354 for ( c = 0; c < cl; c ++ ) {
1355
1356 color = colors[ c ];
1357
1358 offset = c * 3;
1359
1360 colorArray[ offset ] = color.r;
1361 colorArray[ offset + 1 ] = color.g;
1362 colorArray[ offset + 2 ] = color.b;
1363
1364 }
1365
1366 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer );
1367 _gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );
1368
1369 }
1370
1371 if ( dirtyLineDistances ) {
1372
1373 for ( d = 0; d < dl; d ++ ) {
1374
1375 lineDistanceArray[ d ] = lineDistances[ d ];
1376
1377 }
1378
1379 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglLineDistanceBuffer );
1380 _gl.bufferData( _gl.ARRAY_BUFFER, lineDistanceArray, hint );
1381
1382 }
1383
1384 if ( customAttributes ) {
1385
1386 for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
1387
1388 customAttribute = customAttributes[ i ];
1389
1390 if ( customAttribute.needsUpdate &&
1391 ( customAttribute.boundTo === undefined ||
1392 customAttribute.boundTo === "vertices" ) ) {
1393
1394 offset = 0;
1395
1396 cal = customAttribute.value.length;
1397
1398 if ( customAttribute.size === 1 ) {
1399
1400 for ( ca = 0; ca < cal; ca ++ ) {
1401
1402 customAttribute.array[ ca ] = customAttribute.value[ ca ];
1403
1404 }
1405
1406 } else if ( customAttribute.size === 2 ) {
1407
1408 for ( ca = 0; ca < cal; ca ++ ) {
1409
1410 value = customAttribute.value[ ca ];
1411
1412 customAttribute.array[ offset ] = value.x;
1413 customAttribute.array[ offset + 1 ] = value.y;
1414
1415 offset += 2;
1416
1417 }
1418
1419 } else if ( customAttribute.size === 3 ) {
1420
1421 if ( customAttribute.type === "c" ) {
1422
1423 for ( ca = 0; ca < cal; ca ++ ) {
1424
1425 value = customAttribute.value[ ca ];
1426
1427 customAttribute.array[ offset ] = value.r;
1428 customAttribute.array[ offset + 1 ] = value.g;
1429 customAttribute.array[ offset + 2 ] = value.b;
1430
1431 offset += 3;
1432
1433 }
1434
1435 } else {
1436
1437 for ( ca = 0; ca < cal; ca ++ ) {
1438
1439 value = customAttribute.value[ ca ];
1440
1441 customAttribute.array[ offset ] = value.x;
1442 customAttribute.array[ offset + 1 ] = value.y;
1443 customAttribute.array[ offset + 2 ] = value.z;
1444
1445 offset += 3;
1446
1447 }
1448
1449 }
1450
1451 } else if ( customAttribute.size === 4 ) {
1452
1453 for ( ca = 0; ca < cal; ca ++ ) {
1454
1455 value = customAttribute.value[ ca ];
1456
1457 customAttribute.array[ offset ] = value.x;
1458 customAttribute.array[ offset + 1 ] = value.y;
1459 customAttribute.array[ offset + 2 ] = value.z;
1460 customAttribute.array[ offset + 3 ] = value.w;
1461
1462 offset += 4;
1463
1464 }
1465
1466 }
1467
1468 _gl.bindBuffer( _gl.ARRAY_BUFFER, customAttribute.buffer );
1469 _gl.bufferData( _gl.ARRAY_BUFFER, customAttribute.array, hint );
1470
1471 }
1472
1473 }
1474
1475 }
1476
1477 };
1478
1479 function setRibbonBuffers ( geometry, hint ) {
1480
1481 var v, c, n, vertex, offset, color, normal,
1482
1483 i, il, ca, cal, customAttribute, value,
1484
1485 vertices = geometry.vertices,
1486 colors = geometry.colors,
1487 normals = geometry.normals,
1488
1489 vl = vertices.length,
1490 cl = colors.length,
1491 nl = normals.length,
1492
1493 vertexArray = geometry.__vertexArray,
1494 colorArray = geometry.__colorArray,
1495 normalArray = geometry.__normalArray,
1496
1497 dirtyVertices = geometry.verticesNeedUpdate,
1498 dirtyColors = geometry.colorsNeedUpdate,
1499 dirtyNormals = geometry.normalsNeedUpdate,
1500
1501 customAttributes = geometry.__webglCustomAttributesList;
1502
1503 if ( dirtyVertices ) {
1504
1505 for ( v = 0; v < vl; v ++ ) {
1506
1507 vertex = vertices[ v ];
1508
1509 offset = v * 3;
1510
1511 vertexArray[ offset ] = vertex.x;
1512 vertexArray[ offset + 1 ] = vertex.y;
1513 vertexArray[ offset + 2 ] = vertex.z;
1514
1515 }
1516
1517 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer );
1518 _gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );
1519
1520 }
1521
1522 if ( dirtyColors ) {
1523
1524 for ( c = 0; c < cl; c ++ ) {
1525
1526 color = colors[ c ];
1527
1528 offset = c * 3;
1529
1530 colorArray[ offset ] = color.r;
1531 colorArray[ offset + 1 ] = color.g;
1532 colorArray[ offset + 2 ] = color.b;
1533
1534 }
1535
1536 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer );
1537 _gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );
1538
1539 }
1540
1541 if ( dirtyNormals ) {
1542
1543 for ( n = 0; n < nl; n ++ ) {
1544
1545 normal = normals[ n ];
1546
1547 offset = n * 3;
1548
1549 normalArray[ offset ] = normal.x;
1550 normalArray[ offset + 1 ] = normal.y;
1551 normalArray[ offset + 2 ] = normal.z;
1552
1553 }
1554
1555 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglNormalBuffer );
1556 _gl.bufferData( _gl.ARRAY_BUFFER, normalArray, hint );
1557
1558 }
1559
1560 if ( customAttributes ) {
1561
1562 for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
1563
1564 customAttribute = customAttributes[ i ];
1565
1566 if ( customAttribute.needsUpdate &&
1567 ( customAttribute.boundTo === undefined ||
1568 customAttribute.boundTo === "vertices" ) ) {
1569
1570 offset = 0;
1571
1572 cal = customAttribute.value.length;
1573
1574 if ( customAttribute.size === 1 ) {
1575
1576 for ( ca = 0; ca < cal; ca ++ ) {
1577
1578 customAttribute.array[ ca ] = customAttribute.value[ ca ];
1579
1580 }
1581
1582 } else if ( customAttribute.size === 2 ) {
1583
1584 for ( ca = 0; ca < cal; ca ++ ) {
1585
1586 value = customAttribute.value[ ca ];
1587
1588 customAttribute.array[ offset ] = value.x;
1589 customAttribute.array[ offset + 1 ] = value.y;
1590
1591 offset += 2;
1592
1593 }
1594
1595 } else if ( customAttribute.size === 3 ) {
1596
1597 if ( customAttribute.type === "c" ) {
1598
1599 for ( ca = 0; ca < cal; ca ++ ) {
1600
1601 value = customAttribute.value[ ca ];
1602
1603 customAttribute.array[ offset ] = value.r;
1604 customAttribute.array[ offset + 1 ] = value.g;
1605 customAttribute.array[ offset + 2 ] = value.b;
1606
1607 offset += 3;
1608
1609 }
1610
1611 } else {
1612
1613 for ( ca = 0; ca < cal; ca ++ ) {
1614
1615 value = customAttribute.value[ ca ];
1616
1617 customAttribute.array[ offset ] = value.x;
1618 customAttribute.array[ offset + 1 ] = value.y;
1619 customAttribute.array[ offset + 2 ] = value.z;
1620
1621 offset += 3;
1622
1623 }
1624
1625 }
1626
1627 } else if ( customAttribute.size === 4 ) {
1628
1629 for ( ca = 0; ca < cal; ca ++ ) {
1630
1631 value = customAttribute.value[ ca ];
1632
1633 customAttribute.array[ offset ] = value.x;
1634 customAttribute.array[ offset + 1 ] = value.y;
1635 customAttribute.array[ offset + 2 ] = value.z;
1636 customAttribute.array[ offset + 3 ] = value.w;
1637
1638 offset += 4;
1639
1640 }
1641
1642 }
1643
1644 _gl.bindBuffer( _gl.ARRAY_BUFFER, customAttribute.buffer );
1645 _gl.bufferData( _gl.ARRAY_BUFFER, customAttribute.array, hint );
1646
1647 }
1648
1649 }
1650
1651 }
1652
1653 };
1654
1655 function setMeshBuffers( geometryGroup, object, hint, dispose, material ) {
1656
1657 if ( ! geometryGroup.__inittedArrays ) {
1658
1659 return;
1660
1661 }
1662
1663 var normalType = bufferGuessNormalType( material ),
1664 vertexColorType = bufferGuessVertexColorType( material ),
1665 uvType = bufferGuessUVType( material ),
1666
1667 needsSmoothNormals = ( normalType === THREE.SmoothShading );
1668
1669 var f, fl, fi, face,
1670 vertexNormals, faceNormal, normal,
1671 vertexColors, faceColor,
1672 vertexTangents,
1673 uv, uv2, v1, v2, v3, v4, t1, t2, t3, t4, n1, n2, n3, n4,
1674 c1, c2, c3, c4,
1675 sw1, sw2, sw3, sw4,
1676 si1, si2, si3, si4,
1677 sa1, sa2, sa3, sa4,
1678 sb1, sb2, sb3, sb4,
1679 m, ml, i, il,
1680 vn, uvi, uv2i,
1681 vk, vkl, vka,
1682 nka, chf, faceVertexNormals,
1683 a,
1684
1685 vertexIndex = 0,
1686
1687 offset = 0,
1688 offset_uv = 0,
1689 offset_uv2 = 0,
1690 offset_face = 0,
1691 offset_normal = 0,
1692 offset_tangent = 0,
1693 offset_line = 0,
1694 offset_color = 0,
1695 offset_skin = 0,
1696 offset_morphTarget = 0,
1697 offset_custom = 0,
1698 offset_customSrc = 0,
1699
1700 value,
1701
1702 vertexArray = geometryGroup.__vertexArray,
1703 uvArray = geometryGroup.__uvArray,
1704 uv2Array = geometryGroup.__uv2Array,
1705 normalArray = geometryGroup.__normalArray,
1706 tangentArray = geometryGroup.__tangentArray,
1707 colorArray = geometryGroup.__colorArray,
1708
1709 skinIndexArray = geometryGroup.__skinIndexArray,
1710 skinWeightArray = geometryGroup.__skinWeightArray,
1711
1712 morphTargetsArrays = geometryGroup.__morphTargetsArrays,
1713 morphNormalsArrays = geometryGroup.__morphNormalsArrays,
1714
1715 customAttributes = geometryGroup.__webglCustomAttributesList,
1716 customAttribute,
1717
1718 faceArray = geometryGroup.__faceArray,
1719 lineArray = geometryGroup.__lineArray,
1720
1721 geometry = object.geometry, // this is shared for all chunks
1722
1723 dirtyVertices = geometry.verticesNeedUpdate,
1724 dirtyElements = geometry.elementsNeedUpdate,
1725 dirtyUvs = geometry.uvsNeedUpdate,
1726 dirtyNormals = geometry.normalsNeedUpdate,
1727 dirtyTangents = geometry.tangentsNeedUpdate,
1728 dirtyColors = geometry.colorsNeedUpdate,
1729 dirtyMorphTargets = geometry.morphTargetsNeedUpdate,
1730
1731 vertices = geometry.vertices,
1732 chunk_faces3 = geometryGroup.faces3,
1733 chunk_faces4 = geometryGroup.faces4,
1734 obj_faces = geometry.faces,
1735
1736 obj_uvs = geometry.faceVertexUvs[ 0 ],
1737 obj_uvs2 = geometry.faceVertexUvs[ 1 ],
1738
1739 obj_colors = geometry.colors,
1740
1741 obj_skinIndices = geometry.skinIndices,
1742 obj_skinWeights = geometry.skinWeights,
1743
1744 morphTargets = geometry.morphTargets,
1745 morphNormals = geometry.morphNormals;
1746
1747 if ( dirtyVertices ) {
1748
1749 for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
1750
1751 face = obj_faces[ chunk_faces3[ f ] ];
1752
1753 v1 = vertices[ face.a ];
1754 v2 = vertices[ face.b ];
1755 v3 = vertices[ face.c ];
1756
1757 vertexArray[ offset ] = v1.x;
1758 vertexArray[ offset + 1 ] = v1.y;
1759 vertexArray[ offset + 2 ] = v1.z;
1760
1761 vertexArray[ offset + 3 ] = v2.x;
1762 vertexArray[ offset + 4 ] = v2.y;
1763 vertexArray[ offset + 5 ] = v2.z;
1764
1765 vertexArray[ offset + 6 ] = v3.x;
1766 vertexArray[ offset + 7 ] = v3.y;
1767 vertexArray[ offset + 8 ] = v3.z;
1768
1769 offset += 9;
1770
1771 }
1772
1773 for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
1774
1775 face = obj_faces[ chunk_faces4[ f ] ];
1776
1777 v1 = vertices[ face.a ];
1778 v2 = vertices[ face.b ];
1779 v3 = vertices[ face.c ];
1780 v4 = vertices[ face.d ];
1781
1782 vertexArray[ offset ] = v1.x;
1783 vertexArray[ offset + 1 ] = v1.y;
1784 vertexArray[ offset + 2 ] = v1.z;
1785
1786 vertexArray[ offset + 3 ] = v2.x;
1787 vertexArray[ offset + 4 ] = v2.y;
1788 vertexArray[ offset + 5 ] = v2.z;
1789
1790 vertexArray[ offset + 6 ] = v3.x;
1791 vertexArray[ offset + 7 ] = v3.y;
1792 vertexArray[ offset + 8 ] = v3.z;
1793
1794 vertexArray[ offset + 9 ] = v4.x;
1795 vertexArray[ offset + 10 ] = v4.y;
1796 vertexArray[ offset + 11 ] = v4.z;
1797
1798 offset += 12;
1799
1800 }
1801
1802 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer );
1803 _gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );
1804
1805 }
1806
1807 if ( dirtyMorphTargets ) {
1808
1809 for ( vk = 0, vkl = morphTargets.length; vk < vkl; vk ++ ) {
1810
1811 offset_morphTarget = 0;
1812
1813 for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
1814
1815 chf = chunk_faces3[ f ];
1816 face = obj_faces[ chf ];
1817
1818 // morph positions
1819
1820 v1 = morphTargets[ vk ].vertices[ face.a ];
1821 v2 = morphTargets[ vk ].vertices[ face.b ];
1822 v3 = morphTargets[ vk ].vertices[ face.c ];
1823
1824 vka = morphTargetsArrays[ vk ];
1825
1826 vka[ offset_morphTarget ] = v1.x;
1827 vka[ offset_morphTarget + 1 ] = v1.y;
1828 vka[ offset_morphTarget + 2 ] = v1.z;
1829
1830 vka[ offset_morphTarget + 3 ] = v2.x;
1831 vka[ offset_morphTarget + 4 ] = v2.y;
1832 vka[ offset_morphTarget + 5 ] = v2.z;
1833
1834 vka[ offset_morphTarget + 6 ] = v3.x;
1835 vka[ offset_morphTarget + 7 ] = v3.y;
1836 vka[ offset_morphTarget + 8 ] = v3.z;
1837
1838 // morph normals
1839
1840 if ( material.morphNormals ) {
1841
1842 if ( needsSmoothNormals ) {
1843
1844 faceVertexNormals = morphNormals[ vk ].vertexNormals[ chf ];
1845
1846 n1 = faceVertexNormals.a;
1847 n2 = faceVertexNormals.b;
1848 n3 = faceVertexNormals.c;
1849
1850 } else {
1851
1852 n1 = morphNormals[ vk ].faceNormals[ chf ];
1853 n2 = n1;
1854 n3 = n1;
1855
1856 }
1857
1858 nka = morphNormalsArrays[ vk ];
1859
1860 nka[ offset_morphTarget ] = n1.x;
1861 nka[ offset_morphTarget + 1 ] = n1.y;
1862 nka[ offset_morphTarget + 2 ] = n1.z;
1863
1864 nka[ offset_morphTarget + 3 ] = n2.x;
1865 nka[ offset_morphTarget + 4 ] = n2.y;
1866 nka[ offset_morphTarget + 5 ] = n2.z;
1867
1868 nka[ offset_morphTarget + 6 ] = n3.x;
1869 nka[ offset_morphTarget + 7 ] = n3.y;
1870 nka[ offset_morphTarget + 8 ] = n3.z;
1871
1872 }
1873
1874 //
1875
1876 offset_morphTarget += 9;
1877
1878 }
1879
1880 for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
1881
1882 chf = chunk_faces4[ f ];
1883 face = obj_faces[ chf ];
1884
1885 // morph positions
1886
1887 v1 = morphTargets[ vk ].vertices[ face.a ];
1888 v2 = morphTargets[ vk ].vertices[ face.b ];
1889 v3 = morphTargets[ vk ].vertices[ face.c ];
1890 v4 = morphTargets[ vk ].vertices[ face.d ];
1891
1892 vka = morphTargetsArrays[ vk ];
1893
1894 vka[ offset_morphTarget ] = v1.x;
1895 vka[ offset_morphTarget + 1 ] = v1.y;
1896 vka[ offset_morphTarget + 2 ] = v1.z;
1897
1898 vka[ offset_morphTarget + 3 ] = v2.x;
1899 vka[ offset_morphTarget + 4 ] = v2.y;
1900 vka[ offset_morphTarget + 5 ] = v2.z;
1901
1902 vka[ offset_morphTarget + 6 ] = v3.x;
1903 vka[ offset_morphTarget + 7 ] = v3.y;
1904 vka[ offset_morphTarget + 8 ] = v3.z;
1905
1906 vka[ offset_morphTarget + 9 ] = v4.x;
1907 vka[ offset_morphTarget + 10 ] = v4.y;
1908 vka[ offset_morphTarget + 11 ] = v4.z;
1909
1910 // morph normals
1911
1912 if ( material.morphNormals ) {
1913
1914 if ( needsSmoothNormals ) {
1915
1916 faceVertexNormals = morphNormals[ vk ].vertexNormals[ chf ];
1917
1918 n1 = faceVertexNormals.a;
1919 n2 = faceVertexNormals.b;
1920 n3 = faceVertexNormals.c;
1921 n4 = faceVertexNormals.d;
1922
1923 } else {
1924
1925 n1 = morphNormals[ vk ].faceNormals[ chf ];
1926 n2 = n1;
1927 n3 = n1;
1928 n4 = n1;
1929
1930 }
1931
1932 nka = morphNormalsArrays[ vk ];
1933
1934 nka[ offset_morphTarget ] = n1.x;
1935 nka[ offset_morphTarget + 1 ] = n1.y;
1936 nka[ offset_morphTarget + 2 ] = n1.z;
1937
1938 nka[ offset_morphTarget + 3 ] = n2.x;
1939 nka[ offset_morphTarget + 4 ] = n2.y;
1940 nka[ offset_morphTarget + 5 ] = n2.z;
1941
1942 nka[ offset_morphTarget + 6 ] = n3.x;
1943 nka[ offset_morphTarget + 7 ] = n3.y;
1944 nka[ offset_morphTarget + 8 ] = n3.z;
1945
1946 nka[ offset_morphTarget + 9 ] = n4.x;
1947 nka[ offset_morphTarget + 10 ] = n4.y;
1948 nka[ offset_morphTarget + 11 ] = n4.z;
1949
1950 }
1951
1952 //
1953
1954 offset_morphTarget += 12;
1955
1956 }
1957
1958 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ vk ] );
1959 _gl.bufferData( _gl.ARRAY_BUFFER, morphTargetsArrays[ vk ], hint );
1960
1961 if ( material.morphNormals ) {
1962
1963 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphNormalsBuffers[ vk ] );
1964 _gl.bufferData( _gl.ARRAY_BUFFER, morphNormalsArrays[ vk ], hint );
1965
1966 }
1967
1968 }
1969
1970 }
1971
1972 if ( obj_skinWeights.length ) {
1973
1974 for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
1975
1976 face = obj_faces[ chunk_faces3[ f ] ];
1977
1978 // weights
1979
1980 sw1 = obj_skinWeights[ face.a ];
1981 sw2 = obj_skinWeights[ face.b ];
1982 sw3 = obj_skinWeights[ face.c ];
1983
1984 skinWeightArray[ offset_skin ] = sw1.x;
1985 skinWeightArray[ offset_skin + 1 ] = sw1.y;
1986 skinWeightArray[ offset_skin + 2 ] = sw1.z;
1987 skinWeightArray[ offset_skin + 3 ] = sw1.w;
1988
1989 skinWeightArray[ offset_skin + 4 ] = sw2.x;
1990 skinWeightArray[ offset_skin + 5 ] = sw2.y;
1991 skinWeightArray[ offset_skin + 6 ] = sw2.z;
1992 skinWeightArray[ offset_skin + 7 ] = sw2.w;
1993
1994 skinWeightArray[ offset_skin + 8 ] = sw3.x;
1995 skinWeightArray[ offset_skin + 9 ] = sw3.y;
1996 skinWeightArray[ offset_skin + 10 ] = sw3.z;
1997 skinWeightArray[ offset_skin + 11 ] = sw3.w;
1998
1999 // indices
2000
2001 si1 = obj_skinIndices[ face.a ];
2002 si2 = obj_skinIndices[ face.b ];
2003 si3 = obj_skinIndices[ face.c ];
2004
2005 skinIndexArray[ offset_skin ] = si1.x;
2006 skinIndexArray[ offset_skin + 1 ] = si1.y;
2007 skinIndexArray[ offset_skin + 2 ] = si1.z;
2008 skinIndexArray[ offset_skin + 3 ] = si1.w;
2009
2010 skinIndexArray[ offset_skin + 4 ] = si2.x;
2011 skinIndexArray[ offset_skin + 5 ] = si2.y;
2012 skinIndexArray[ offset_skin + 6 ] = si2.z;
2013 skinIndexArray[ offset_skin + 7 ] = si2.w;
2014
2015 skinIndexArray[ offset_skin + 8 ] = si3.x;
2016 skinIndexArray[ offset_skin + 9 ] = si3.y;
2017 skinIndexArray[ offset_skin + 10 ] = si3.z;
2018 skinIndexArray[ offset_skin + 11 ] = si3.w;
2019
2020 offset_skin += 12;
2021
2022 }
2023
2024 for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
2025
2026 face = obj_faces[ chunk_faces4[ f ] ];
2027
2028 // weights
2029
2030 sw1 = obj_skinWeights[ face.a ];
2031 sw2 = obj_skinWeights[ face.b ];
2032 sw3 = obj_skinWeights[ face.c ];
2033 sw4 = obj_skinWeights[ face.d ];
2034
2035 skinWeightArray[ offset_skin ] = sw1.x;
2036 skinWeightArray[ offset_skin + 1 ] = sw1.y;
2037 skinWeightArray[ offset_skin + 2 ] = sw1.z;
2038 skinWeightArray[ offset_skin + 3 ] = sw1.w;
2039
2040 skinWeightArray[ offset_skin + 4 ] = sw2.x;
2041 skinWeightArray[ offset_skin + 5 ] = sw2.y;
2042 skinWeightArray[ offset_skin + 6 ] = sw2.z;
2043 skinWeightArray[ offset_skin + 7 ] = sw2.w;
2044
2045 skinWeightArray[ offset_skin + 8 ] = sw3.x;
2046 skinWeightArray[ offset_skin + 9 ] = sw3.y;
2047 skinWeightArray[ offset_skin + 10 ] = sw3.z;
2048 skinWeightArray[ offset_skin + 11 ] = sw3.w;
2049
2050 skinWeightArray[ offset_skin + 12 ] = sw4.x;
2051 skinWeightArray[ offset_skin + 13 ] = sw4.y;
2052 skinWeightArray[ offset_skin + 14 ] = sw4.z;
2053 skinWeightArray[ offset_skin + 15 ] = sw4.w;
2054
2055 // indices
2056
2057 si1 = obj_skinIndices[ face.a ];
2058 si2 = obj_skinIndices[ face.b ];
2059 si3 = obj_skinIndices[ face.c ];
2060 si4 = obj_skinIndices[ face.d ];
2061
2062 skinIndexArray[ offset_skin ] = si1.x;
2063 skinIndexArray[ offset_skin + 1 ] = si1.y;
2064 skinIndexArray[ offset_skin + 2 ] = si1.z;
2065 skinIndexArray[ offset_skin + 3 ] = si1.w;
2066
2067 skinIndexArray[ offset_skin + 4 ] = si2.x;
2068 skinIndexArray[ offset_skin + 5 ] = si2.y;
2069 skinIndexArray[ offset_skin + 6 ] = si2.z;
2070 skinIndexArray[ offset_skin + 7 ] = si2.w;
2071
2072 skinIndexArray[ offset_skin + 8 ] = si3.x;
2073 skinIndexArray[ offset_skin + 9 ] = si3.y;
2074 skinIndexArray[ offset_skin + 10 ] = si3.z;
2075 skinIndexArray[ offset_skin + 11 ] = si3.w;
2076
2077 skinIndexArray[ offset_skin + 12 ] = si4.x;
2078 skinIndexArray[ offset_skin + 13 ] = si4.y;
2079 skinIndexArray[ offset_skin + 14 ] = si4.z;
2080 skinIndexArray[ offset_skin + 15 ] = si4.w;
2081
2082 offset_skin += 16;
2083
2084 }
2085
2086 if ( offset_skin > 0 ) {
2087
2088 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinIndicesBuffer );
2089 _gl.bufferData( _gl.ARRAY_BUFFER, skinIndexArray, hint );
2090
2091 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinWeightsBuffer );
2092 _gl.bufferData( _gl.ARRAY_BUFFER, skinWeightArray, hint );
2093
2094 }
2095
2096 }
2097
2098 if ( dirtyColors && vertexColorType ) {
2099
2100 for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
2101
2102 face = obj_faces[ chunk_faces3[ f ] ];
2103
2104 vertexColors = face.vertexColors;
2105 faceColor = face.color;
2106
2107 if ( vertexColors.length === 3 && vertexColorType === THREE.VertexColors ) {
2108
2109 c1 = vertexColors[ 0 ];
2110 c2 = vertexColors[ 1 ];
2111 c3 = vertexColors[ 2 ];
2112
2113 } else {
2114
2115 c1 = faceColor;
2116 c2 = faceColor;
2117 c3 = faceColor;
2118
2119 }
2120
2121 colorArray[ offset_color ] = c1.r;
2122 colorArray[ offset_color + 1 ] = c1.g;
2123 colorArray[ offset_color + 2 ] = c1.b;
2124
2125 colorArray[ offset_color + 3 ] = c2.r;
2126 colorArray[ offset_color + 4 ] = c2.g;
2127 colorArray[ offset_color + 5 ] = c2.b;
2128
2129 colorArray[ offset_color + 6 ] = c3.r;
2130 colorArray[ offset_color + 7 ] = c3.g;
2131 colorArray[ offset_color + 8 ] = c3.b;
2132
2133 offset_color += 9;
2134
2135 }
2136
2137 for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
2138
2139 face = obj_faces[ chunk_faces4[ f ] ];
2140
2141 vertexColors = face.vertexColors;
2142 faceColor = face.color;
2143
2144 if ( vertexColors.length === 4 && vertexColorType === THREE.VertexColors ) {
2145
2146 c1 = vertexColors[ 0 ];
2147 c2 = vertexColors[ 1 ];
2148 c3 = vertexColors[ 2 ];
2149 c4 = vertexColors[ 3 ];
2150
2151 } else {
2152
2153 c1 = faceColor;
2154 c2 = faceColor;
2155 c3 = faceColor;
2156 c4 = faceColor;
2157
2158 }
2159
2160 colorArray[ offset_color ] = c1.r;
2161 colorArray[ offset_color + 1 ] = c1.g;
2162 colorArray[ offset_color + 2 ] = c1.b;
2163
2164 colorArray[ offset_color + 3 ] = c2.r;
2165 colorArray[ offset_color + 4 ] = c2.g;
2166 colorArray[ offset_color + 5 ] = c2.b;
2167
2168 colorArray[ offset_color + 6 ] = c3.r;
2169 colorArray[ offset_color + 7 ] = c3.g;
2170 colorArray[ offset_color + 8 ] = c3.b;
2171
2172 colorArray[ offset_color + 9 ] = c4.r;
2173 colorArray[ offset_color + 10 ] = c4.g;
2174 colorArray[ offset_color + 11 ] = c4.b;
2175
2176 offset_color += 12;
2177
2178 }
2179
2180 if ( offset_color > 0 ) {
2181
2182 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglColorBuffer );
2183 _gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );
2184
2185 }
2186
2187 }
2188
2189 if ( dirtyTangents && geometry.hasTangents ) {
2190
2191 for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
2192
2193 face = obj_faces[ chunk_faces3[ f ] ];
2194
2195 vertexTangents = face.vertexTangents;
2196
2197 t1 = vertexTangents[ 0 ];
2198 t2 = vertexTangents[ 1 ];
2199 t3 = vertexTangents[ 2 ];
2200
2201 tangentArray[ offset_tangent ] = t1.x;
2202 tangentArray[ offset_tangent + 1 ] = t1.y;
2203 tangentArray[ offset_tangent + 2 ] = t1.z;
2204 tangentArray[ offset_tangent + 3 ] = t1.w;
2205
2206 tangentArray[ offset_tangent + 4 ] = t2.x;
2207 tangentArray[ offset_tangent + 5 ] = t2.y;
2208 tangentArray[ offset_tangent + 6 ] = t2.z;
2209 tangentArray[ offset_tangent + 7 ] = t2.w;
2210
2211 tangentArray[ offset_tangent + 8 ] = t3.x;
2212 tangentArray[ offset_tangent + 9 ] = t3.y;
2213 tangentArray[ offset_tangent + 10 ] = t3.z;
2214 tangentArray[ offset_tangent + 11 ] = t3.w;
2215
2216 offset_tangent += 12;
2217
2218 }
2219
2220 for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
2221
2222 face = obj_faces[ chunk_faces4[ f ] ];
2223
2224 vertexTangents = face.vertexTangents;
2225
2226 t1 = vertexTangents[ 0 ];
2227 t2 = vertexTangents[ 1 ];
2228 t3 = vertexTangents[ 2 ];
2229 t4 = vertexTangents[ 3 ];
2230
2231 tangentArray[ offset_tangent ] = t1.x;
2232 tangentArray[ offset_tangent + 1 ] = t1.y;
2233 tangentArray[ offset_tangent + 2 ] = t1.z;
2234 tangentArray[ offset_tangent + 3 ] = t1.w;
2235
2236 tangentArray[ offset_tangent + 4 ] = t2.x;
2237 tangentArray[ offset_tangent + 5 ] = t2.y;
2238 tangentArray[ offset_tangent + 6 ] = t2.z;
2239 tangentArray[ offset_tangent + 7 ] = t2.w;
2240
2241 tangentArray[ offset_tangent + 8 ] = t3.x;
2242 tangentArray[ offset_tangent + 9 ] = t3.y;
2243 tangentArray[ offset_tangent + 10 ] = t3.z;
2244 tangentArray[ offset_tangent + 11 ] = t3.w;
2245
2246 tangentArray[ offset_tangent + 12 ] = t4.x;
2247 tangentArray[ offset_tangent + 13 ] = t4.y;
2248 tangentArray[ offset_tangent + 14 ] = t4.z;
2249 tangentArray[ offset_tangent + 15 ] = t4.w;
2250
2251 offset_tangent += 16;
2252
2253 }
2254
2255 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglTangentBuffer );
2256 _gl.bufferData( _gl.ARRAY_BUFFER, tangentArray, hint );
2257
2258 }
2259
2260 if ( dirtyNormals && normalType ) {
2261
2262 for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
2263
2264 face = obj_faces[ chunk_faces3[ f ] ];
2265
2266 vertexNormals = face.vertexNormals;
2267 faceNormal = face.normal;
2268
2269 if ( vertexNormals.length === 3 && needsSmoothNormals ) {
2270
2271 for ( i = 0; i < 3; i ++ ) {
2272
2273 vn = vertexNormals[ i ];
2274
2275 normalArray[ offset_normal ] = vn.x;
2276 normalArray[ offset_normal + 1 ] = vn.y;
2277 normalArray[ offset_normal + 2 ] = vn.z;
2278
2279 offset_normal += 3;
2280
2281 }
2282
2283 } else {
2284
2285 for ( i = 0; i < 3; i ++ ) {
2286
2287 normalArray[ offset_normal ] = faceNormal.x;
2288 normalArray[ offset_normal + 1 ] = faceNormal.y;
2289 normalArray[ offset_normal + 2 ] = faceNormal.z;
2290
2291 offset_normal += 3;
2292
2293 }
2294
2295 }
2296
2297 }
2298
2299 for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
2300
2301 face = obj_faces[ chunk_faces4[ f ] ];
2302
2303 vertexNormals = face.vertexNormals;
2304 faceNormal = face.normal;
2305
2306 if ( vertexNormals.length === 4 && needsSmoothNormals ) {
2307
2308 for ( i = 0; i < 4; i ++ ) {
2309
2310 vn = vertexNormals[ i ];
2311
2312 normalArray[ offset_normal ] = vn.x;
2313 normalArray[ offset_normal + 1 ] = vn.y;
2314 normalArray[ offset_normal + 2 ] = vn.z;
2315
2316 offset_normal += 3;
2317
2318 }
2319
2320 } else {
2321
2322 for ( i = 0; i < 4; i ++ ) {
2323
2324 normalArray[ offset_normal ] = faceNormal.x;
2325 normalArray[ offset_normal + 1 ] = faceNormal.y;
2326 normalArray[ offset_normal + 2 ] = faceNormal.z;
2327
2328 offset_normal += 3;
2329
2330 }
2331
2332 }
2333
2334 }
2335
2336 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglNormalBuffer );
2337 _gl.bufferData( _gl.ARRAY_BUFFER, normalArray, hint );
2338
2339 }
2340
2341 if ( dirtyUvs && obj_uvs && uvType ) {
2342
2343 for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
2344
2345 fi = chunk_faces3[ f ];
2346
2347 uv = obj_uvs[ fi ];
2348
2349 if ( uv === undefined ) continue;
2350
2351 for ( i = 0; i < 3; i ++ ) {
2352
2353 uvi = uv[ i ];
2354
2355 uvArray[ offset_uv ] = uvi.u;
2356 uvArray[ offset_uv + 1 ] = uvi.v;
2357
2358 offset_uv += 2;
2359
2360 }
2361
2362 }
2363
2364 for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
2365
2366 fi = chunk_faces4[ f ];
2367
2368 uv = obj_uvs[ fi ];
2369
2370 if ( uv === undefined ) continue;
2371
2372 for ( i = 0; i < 4; i ++ ) {
2373
2374 uvi = uv[ i ];
2375
2376 uvArray[ offset_uv ] = uvi.u;
2377 uvArray[ offset_uv + 1 ] = uvi.v;
2378
2379 offset_uv += 2;
2380
2381 }
2382
2383 }
2384
2385 if ( offset_uv > 0 ) {
2386
2387 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUVBuffer );
2388 _gl.bufferData( _gl.ARRAY_BUFFER, uvArray, hint );
2389
2390 }
2391
2392 }
2393
2394 if ( dirtyUvs && obj_uvs2 && uvType ) {
2395
2396 for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
2397
2398 fi = chunk_faces3[ f ];
2399
2400 uv2 = obj_uvs2[ fi ];
2401
2402 if ( uv2 === undefined ) continue;
2403
2404 for ( i = 0; i < 3; i ++ ) {
2405
2406 uv2i = uv2[ i ];
2407
2408 uv2Array[ offset_uv2 ] = uv2i.u;
2409 uv2Array[ offset_uv2 + 1 ] = uv2i.v;
2410
2411 offset_uv2 += 2;
2412
2413 }
2414
2415 }
2416
2417 for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
2418
2419 fi = chunk_faces4[ f ];
2420
2421 uv2 = obj_uvs2[ fi ];
2422
2423 if ( uv2 === undefined ) continue;
2424
2425 for ( i = 0; i < 4; i ++ ) {
2426
2427 uv2i = uv2[ i ];
2428
2429 uv2Array[ offset_uv2 ] = uv2i.u;
2430 uv2Array[ offset_uv2 + 1 ] = uv2i.v;
2431
2432 offset_uv2 += 2;
2433
2434 }
2435
2436 }
2437
2438 if ( offset_uv2 > 0 ) {
2439
2440 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUV2Buffer );
2441 _gl.bufferData( _gl.ARRAY_BUFFER, uv2Array, hint );
2442
2443 }
2444
2445 }
2446
2447 if ( dirtyElements ) {
2448
2449 for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
2450
2451 faceArray[ offset_face ] = vertexIndex;
2452 faceArray[ offset_face + 1 ] = vertexIndex + 1;
2453 faceArray[ offset_face + 2 ] = vertexIndex + 2;
2454
2455 offset_face += 3;
2456
2457 lineArray[ offset_line ] = vertexIndex;
2458 lineArray[ offset_line + 1 ] = vertexIndex + 1;
2459
2460 lineArray[ offset_line + 2 ] = vertexIndex;
2461 lineArray[ offset_line + 3 ] = vertexIndex + 2;
2462
2463 lineArray[ offset_line + 4 ] = vertexIndex + 1;
2464 lineArray[ offset_line + 5 ] = vertexIndex + 2;
2465
2466 offset_line += 6;
2467
2468 vertexIndex += 3;
2469
2470 }
2471
2472 for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
2473
2474 faceArray[ offset_face ] = vertexIndex;
2475 faceArray[ offset_face + 1 ] = vertexIndex + 1;
2476 faceArray[ offset_face + 2 ] = vertexIndex + 3;
2477
2478 faceArray[ offset_face + 3 ] = vertexIndex + 1;
2479 faceArray[ offset_face + 4 ] = vertexIndex + 2;
2480 faceArray[ offset_face + 5 ] = vertexIndex + 3;
2481
2482 offset_face += 6;
2483
2484 lineArray[ offset_line ] = vertexIndex;
2485 lineArray[ offset_line + 1 ] = vertexIndex + 1;
2486
2487 lineArray[ offset_line + 2 ] = vertexIndex;
2488 lineArray[ offset_line + 3 ] = vertexIndex + 3;
2489
2490 lineArray[ offset_line + 4 ] = vertexIndex + 1;
2491 lineArray[ offset_line + 5 ] = vertexIndex + 2;
2492
2493 lineArray[ offset_line + 6 ] = vertexIndex + 2;
2494 lineArray[ offset_line + 7 ] = vertexIndex + 3;
2495
2496 offset_line += 8;
2497
2498 vertexIndex += 4;
2499
2500 }
2501
2502 _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglFaceBuffer );
2503 _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, faceArray, hint );
2504
2505 _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglLineBuffer );
2506 _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, lineArray, hint );
2507
2508 }
2509
2510 if ( customAttributes ) {
2511
2512 for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
2513
2514 customAttribute = customAttributes[ i ];
2515
2516 if ( ! customAttribute.__original.needsUpdate ) continue;
2517
2518 offset_custom = 0;
2519 offset_customSrc = 0;
2520
2521 if ( customAttribute.size === 1 ) {
2522
2523 if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
2524
2525 for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
2526
2527 face = obj_faces[ chunk_faces3[ f ] ];
2528
2529 customAttribute.array[ offset_custom ] = customAttribute.value[ face.a ];
2530 customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ face.b ];
2531 customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ face.c ];
2532
2533 offset_custom += 3;
2534
2535 }
2536
2537 for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
2538
2539 face = obj_faces[ chunk_faces4[ f ] ];
2540
2541 customAttribute.array[ offset_custom ] = customAttribute.value[ face.a ];
2542 customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ face.b ];
2543 customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ face.c ];
2544 customAttribute.array[ offset_custom + 3 ] = customAttribute.value[ face.d ];
2545
2546 offset_custom += 4;
2547
2548 }
2549
2550 } else if ( customAttribute.boundTo === "faces" ) {
2551
2552 for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
2553
2554 value = customAttribute.value[ chunk_faces3[ f ] ];
2555
2556 customAttribute.array[ offset_custom ] = value;
2557 customAttribute.array[ offset_custom + 1 ] = value;
2558 customAttribute.array[ offset_custom + 2 ] = value;
2559
2560 offset_custom += 3;
2561
2562 }
2563
2564 for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
2565
2566 value = customAttribute.value[ chunk_faces4[ f ] ];
2567
2568 customAttribute.array[ offset_custom ] = value;
2569 customAttribute.array[ offset_custom + 1 ] = value;
2570 customAttribute.array[ offset_custom + 2 ] = value;
2571 customAttribute.array[ offset_custom + 3 ] = value;
2572
2573 offset_custom += 4;
2574
2575 }
2576
2577 }
2578
2579 } else if ( customAttribute.size === 2 ) {
2580
2581 if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
2582
2583 for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
2584
2585 face = obj_faces[ chunk_faces3[ f ] ];
2586
2587 v1 = customAttribute.value[ face.a ];
2588 v2 = customAttribute.value[ face.b ];
2589 v3 = customAttribute.value[ face.c ];
2590
2591 customAttribute.array[ offset_custom ] = v1.x;
2592 customAttribute.array[ offset_custom + 1 ] = v1.y;
2593
2594 customAttribute.array[ offset_custom + 2 ] = v2.x;
2595 customAttribute.array[ offset_custom + 3 ] = v2.y;
2596
2597 customAttribute.array[ offset_custom + 4 ] = v3.x;
2598 customAttribute.array[ offset_custom + 5 ] = v3.y;
2599
2600 offset_custom += 6;
2601
2602 }
2603
2604 for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
2605
2606 face = obj_faces[ chunk_faces4[ f ] ];
2607
2608 v1 = customAttribute.value[ face.a ];
2609 v2 = customAttribute.value[ face.b ];
2610 v3 = customAttribute.value[ face.c ];
2611 v4 = customAttribute.value[ face.d ];
2612
2613 customAttribute.array[ offset_custom ] = v1.x;
2614 customAttribute.array[ offset_custom + 1 ] = v1.y;
2615
2616 customAttribute.array[ offset_custom + 2 ] = v2.x;
2617 customAttribute.array[ offset_custom + 3 ] = v2.y;
2618
2619 customAttribute.array[ offset_custom + 4 ] = v3.x;
2620 customAttribute.array[ offset_custom + 5 ] = v3.y;
2621
2622 customAttribute.array[ offset_custom + 6 ] = v4.x;
2623 customAttribute.array[ offset_custom + 7 ] = v4.y;
2624
2625 offset_custom += 8;
2626
2627 }
2628
2629 } else if ( customAttribute.boundTo === "faces" ) {
2630
2631 for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
2632
2633 value = customAttribute.value[ chunk_faces3[ f ] ];
2634
2635 v1 = value;
2636 v2 = value;
2637 v3 = value;
2638
2639 customAttribute.array[ offset_custom ] = v1.x;
2640 customAttribute.array[ offset_custom + 1 ] = v1.y;
2641
2642 customAttribute.array[ offset_custom + 2 ] = v2.x;
2643 customAttribute.array[ offset_custom + 3 ] = v2.y;
2644
2645 customAttribute.array[ offset_custom + 4 ] = v3.x;
2646 customAttribute.array[ offset_custom + 5 ] = v3.y;
2647
2648 offset_custom += 6;
2649
2650 }
2651
2652 for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
2653
2654 value = customAttribute.value[ chunk_faces4[ f ] ];
2655
2656 v1 = value;
2657 v2 = value;
2658 v3 = value;
2659 v4 = value;
2660
2661 customAttribute.array[ offset_custom ] = v1.x;
2662 customAttribute.array[ offset_custom + 1 ] = v1.y;
2663
2664 customAttribute.array[ offset_custom + 2 ] = v2.x;
2665 customAttribute.array[ offset_custom + 3 ] = v2.y;
2666
2667 customAttribute.array[ offset_custom + 4 ] = v3.x;
2668 customAttribute.array[ offset_custom + 5 ] = v3.y;
2669
2670 customAttribute.array[ offset_custom + 6 ] = v4.x;
2671 customAttribute.array[ offset_custom + 7 ] = v4.y;
2672
2673 offset_custom += 8;
2674
2675 }
2676
2677 }
2678
2679 } else if ( customAttribute.size === 3 ) {
2680
2681 var pp;
2682
2683 if ( customAttribute.type === "c" ) {
2684
2685 pp = [ "r", "g", "b" ];
2686
2687 } else {
2688
2689 pp = [ "x", "y", "z" ];
2690
2691 }
2692
2693 if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
2694
2695 for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
2696
2697 face = obj_faces[ chunk_faces3[ f ] ];
2698
2699 v1 = customAttribute.value[ face.a ];
2700 v2 = customAttribute.value[ face.b ];
2701 v3 = customAttribute.value[ face.c ];
2702
2703 customAttribute.array[ offset_custom ] = v1[ pp[ 0 ] ];
2704 customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
2705 customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
2706
2707 customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
2708 customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
2709 customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
2710
2711 customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
2712 customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
2713 customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
2714
2715 offset_custom += 9;
2716
2717 }
2718
2719 for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
2720
2721 face = obj_faces[ chunk_faces4[ f ] ];
2722
2723 v1 = customAttribute.value[ face.a ];
2724 v2 = customAttribute.value[ face.b ];
2725 v3 = customAttribute.value[ face.c ];
2726 v4 = customAttribute.value[ face.d ];
2727
2728 customAttribute.array[ offset_custom ] = v1[ pp[ 0 ] ];
2729 customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
2730 customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
2731
2732 customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
2733 customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
2734 customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
2735
2736 customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
2737 customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
2738 customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
2739
2740 customAttribute.array[ offset_custom + 9 ] = v4[ pp[ 0 ] ];
2741 customAttribute.array[ offset_custom + 10 ] = v4[ pp[ 1 ] ];
2742 customAttribute.array[ offset_custom + 11 ] = v4[ pp[ 2 ] ];
2743
2744 offset_custom += 12;
2745
2746 }
2747
2748 } else if ( customAttribute.boundTo === "faces" ) {
2749
2750 for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
2751
2752 value = customAttribute.value[ chunk_faces3[ f ] ];
2753
2754 v1 = value;
2755 v2 = value;
2756 v3 = value;
2757
2758 customAttribute.array[ offset_custom ] = v1[ pp[ 0 ] ];
2759 customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
2760 customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
2761
2762 customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
2763 customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
2764 customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
2765
2766 customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
2767 customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
2768 customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
2769
2770 offset_custom += 9;
2771
2772 }
2773
2774 for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
2775
2776 value = customAttribute.value[ chunk_faces4[ f ] ];
2777
2778 v1 = value;
2779 v2 = value;
2780 v3 = value;
2781 v4 = value;
2782
2783 customAttribute.array[ offset_custom ] = v1[ pp[ 0 ] ];
2784 customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
2785 customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
2786
2787 customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
2788 customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
2789 customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
2790
2791 customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
2792 customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
2793 customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
2794
2795 customAttribute.array[ offset_custom + 9 ] = v4[ pp[ 0 ] ];
2796 customAttribute.array[ offset_custom + 10 ] = v4[ pp[ 1 ] ];
2797 customAttribute.array[ offset_custom + 11 ] = v4[ pp[ 2 ] ];
2798
2799 offset_custom += 12;
2800
2801 }
2802
2803 } else if ( customAttribute.boundTo === "faceVertices" ) {
2804
2805 for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
2806
2807 value = customAttribute.value[ chunk_faces3[ f ] ];
2808
2809 v1 = value[ 0 ];
2810 v2 = value[ 1 ];
2811 v3 = value[ 2 ];
2812
2813 customAttribute.array[ offset_custom ] = v1[ pp[ 0 ] ];
2814 customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
2815 customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
2816
2817 customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
2818 customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
2819 customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
2820
2821 customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
2822 customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
2823 customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
2824
2825 offset_custom += 9;
2826
2827 }
2828
2829 for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
2830
2831 value = customAttribute.value[ chunk_faces4[ f ] ];
2832
2833 v1 = value[ 0 ];
2834 v2 = value[ 1 ];
2835 v3 = value[ 2 ];
2836 v4 = value[ 3 ];
2837
2838 customAttribute.array[ offset_custom ] = v1[ pp[ 0 ] ];
2839 customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
2840 customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
2841
2842 customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
2843 customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
2844 customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
2845
2846 customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
2847 customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
2848 customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
2849
2850 customAttribute.array[ offset_custom + 9 ] = v4[ pp[ 0 ] ];
2851 customAttribute.array[ offset_custom + 10 ] = v4[ pp[ 1 ] ];
2852 customAttribute.array[ offset_custom + 11 ] = v4[ pp[ 2 ] ];
2853
2854 offset_custom += 12;
2855
2856 }
2857
2858 }
2859
2860 } else if ( customAttribute.size === 4 ) {
2861
2862 if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
2863
2864 for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
2865
2866 face = obj_faces[ chunk_faces3[ f ] ];
2867
2868 v1 = customAttribute.value[ face.a ];
2869 v2 = customAttribute.value[ face.b ];
2870 v3 = customAttribute.value[ face.c ];
2871
2872 customAttribute.array[ offset_custom ] = v1.x;
2873 customAttribute.array[ offset_custom + 1 ] = v1.y;
2874 customAttribute.array[ offset_custom + 2 ] = v1.z;
2875 customAttribute.array[ offset_custom + 3 ] = v1.w;
2876
2877 customAttribute.array[ offset_custom + 4 ] = v2.x;
2878 customAttribute.array[ offset_custom + 5 ] = v2.y;
2879 customAttribute.array[ offset_custom + 6 ] = v2.z;
2880 customAttribute.array[ offset_custom + 7 ] = v2.w;
2881
2882 customAttribute.array[ offset_custom + 8 ] = v3.x;
2883 customAttribute.array[ offset_custom + 9 ] = v3.y;
2884 customAttribute.array[ offset_custom + 10 ] = v3.z;
2885 customAttribute.array[ offset_custom + 11 ] = v3.w;
2886
2887 offset_custom += 12;
2888
2889 }
2890
2891 for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
2892
2893 face = obj_faces[ chunk_faces4[ f ] ];
2894
2895 v1 = customAttribute.value[ face.a ];
2896 v2 = customAttribute.value[ face.b ];
2897 v3 = customAttribute.value[ face.c ];
2898 v4 = customAttribute.value[ face.d ];
2899
2900 customAttribute.array[ offset_custom ] = v1.x;
2901 customAttribute.array[ offset_custom + 1 ] = v1.y;
2902 customAttribute.array[ offset_custom + 2 ] = v1.z;
2903 customAttribute.array[ offset_custom + 3 ] = v1.w;
2904
2905 customAttribute.array[ offset_custom + 4 ] = v2.x;
2906 customAttribute.array[ offset_custom + 5 ] = v2.y;
2907 customAttribute.array[ offset_custom + 6 ] = v2.z;
2908 customAttribute.array[ offset_custom + 7 ] = v2.w;
2909
2910 customAttribute.array[ offset_custom + 8 ] = v3.x;
2911 customAttribute.array[ offset_custom + 9 ] = v3.y;
2912 customAttribute.array[ offset_custom + 10 ] = v3.z;
2913 customAttribute.array[ offset_custom + 11 ] = v3.w;
2914
2915 customAttribute.array[ offset_custom + 12 ] = v4.x;
2916 customAttribute.array[ offset_custom + 13 ] = v4.y;
2917 customAttribute.array[ offset_custom + 14 ] = v4.z;
2918 customAttribute.array[ offset_custom + 15 ] = v4.w;
2919
2920 offset_custom += 16;
2921
2922 }
2923
2924 } else if ( customAttribute.boundTo === "faces" ) {
2925
2926 for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
2927
2928 value = customAttribute.value[ chunk_faces3[ f ] ];
2929
2930 v1 = value;
2931 v2 = value;
2932 v3 = value;
2933
2934 customAttribute.array[ offset_custom ] = v1.x;
2935 customAttribute.array[ offset_custom + 1 ] = v1.y;
2936 customAttribute.array[ offset_custom + 2 ] = v1.z;
2937 customAttribute.array[ offset_custom + 3 ] = v1.w;
2938
2939 customAttribute.array[ offset_custom + 4 ] = v2.x;
2940 customAttribute.array[ offset_custom + 5 ] = v2.y;
2941 customAttribute.array[ offset_custom + 6 ] = v2.z;
2942 customAttribute.array[ offset_custom + 7 ] = v2.w;
2943
2944 customAttribute.array[ offset_custom + 8 ] = v3.x;
2945 customAttribute.array[ offset_custom + 9 ] = v3.y;
2946 customAttribute.array[ offset_custom + 10 ] = v3.z;
2947 customAttribute.array[ offset_custom + 11 ] = v3.w;
2948
2949 offset_custom += 12;
2950
2951 }
2952
2953 for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
2954
2955 value = customAttribute.value[ chunk_faces4[ f ] ];
2956
2957 v1 = value;
2958 v2 = value;
2959 v3 = value;
2960 v4 = value;
2961
2962 customAttribute.array[ offset_custom ] = v1.x;
2963 customAttribute.array[ offset_custom + 1 ] = v1.y;
2964 customAttribute.array[ offset_custom + 2 ] = v1.z;
2965 customAttribute.array[ offset_custom + 3 ] = v1.w;
2966
2967 customAttribute.array[ offset_custom + 4 ] = v2.x;
2968 customAttribute.array[ offset_custom + 5 ] = v2.y;
2969 customAttribute.array[ offset_custom + 6 ] = v2.z;
2970 customAttribute.array[ offset_custom + 7 ] = v2.w;
2971
2972 customAttribute.array[ offset_custom + 8 ] = v3.x;
2973 customAttribute.array[ offset_custom + 9 ] = v3.y;
2974 customAttribute.array[ offset_custom + 10 ] = v3.z;
2975 customAttribute.array[ offset_custom + 11 ] = v3.w;
2976
2977 customAttribute.array[ offset_custom + 12 ] = v4.x;
2978 customAttribute.array[ offset_custom + 13 ] = v4.y;
2979 customAttribute.array[ offset_custom + 14 ] = v4.z;
2980 customAttribute.array[ offset_custom + 15 ] = v4.w;
2981
2982 offset_custom += 16;
2983
2984 }
2985
2986 } else if ( customAttribute.boundTo === "faceVertices" ) {
2987
2988 for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
2989
2990 value = customAttribute.value[ chunk_faces3[ f ] ];
2991
2992 v1 = value[ 0 ];
2993 v2 = value[ 1 ];
2994 v3 = value[ 2 ];
2995
2996 customAttribute.array[ offset_custom ] = v1.x;
2997 customAttribute.array[ offset_custom + 1 ] = v1.y;
2998 customAttribute.array[ offset_custom + 2 ] = v1.z;
2999 customAttribute.array[ offset_custom + 3 ] = v1.w;
3000
3001 customAttribute.array[ offset_custom + 4 ] = v2.x;
3002 customAttribute.array[ offset_custom + 5 ] = v2.y;
3003 customAttribute.array[ offset_custom + 6 ] = v2.z;
3004 customAttribute.array[ offset_custom + 7 ] = v2.w;
3005
3006 customAttribute.array[ offset_custom + 8 ] = v3.x;
3007 customAttribute.array[ offset_custom + 9 ] = v3.y;
3008 customAttribute.array[ offset_custom + 10 ] = v3.z;
3009 customAttribute.array[ offset_custom + 11 ] = v3.w;
3010
3011 offset_custom += 12;
3012
3013 }
3014
3015 for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
3016
3017 value = customAttribute.value[ chunk_faces4[ f ] ];
3018
3019 v1 = value[ 0 ];
3020 v2 = value[ 1 ];
3021 v3 = value[ 2 ];
3022 v4 = value[ 3 ];
3023
3024 customAttribute.array[ offset_custom ] = v1.x;
3025 customAttribute.array[ offset_custom + 1 ] = v1.y;
3026 customAttribute.array[ offset_custom + 2 ] = v1.z;
3027 customAttribute.array[ offset_custom + 3 ] = v1.w;
3028
3029 customAttribute.array[ offset_custom + 4 ] = v2.x;
3030 customAttribute.array[ offset_custom + 5 ] = v2.y;
3031 customAttribute.array[ offset_custom + 6 ] = v2.z;
3032 customAttribute.array[ offset_custom + 7 ] = v2.w;
3033
3034 customAttribute.array[ offset_custom + 8 ] = v3.x;
3035 customAttribute.array[ offset_custom + 9 ] = v3.y;
3036 customAttribute.array[ offset_custom + 10 ] = v3.z;
3037 customAttribute.array[ offset_custom + 11 ] = v3.w;
3038
3039 customAttribute.array[ offset_custom + 12 ] = v4.x;
3040 customAttribute.array[ offset_custom + 13 ] = v4.y;
3041 customAttribute.array[ offset_custom + 14 ] = v4.z;
3042 customAttribute.array[ offset_custom + 15 ] = v4.w;
3043
3044 offset_custom += 16;
3045
3046 }
3047
3048 }
3049
3050 }
3051
3052 _gl.bindBuffer( _gl.ARRAY_BUFFER, customAttribute.buffer );
3053 _gl.bufferData( _gl.ARRAY_BUFFER, customAttribute.array, hint );
3054
3055 }
3056
3057 }
3058
3059 if ( dispose ) {
3060
3061 delete geometryGroup.__inittedArrays;
3062 delete geometryGroup.__colorArray;
3063 delete geometryGroup.__normalArray;
3064 delete geometryGroup.__tangentArray;
3065 delete geometryGroup.__uvArray;
3066 delete geometryGroup.__uv2Array;
3067 delete geometryGroup.__faceArray;
3068 delete geometryGroup.__vertexArray;
3069 delete geometryGroup.__lineArray;
3070 delete geometryGroup.__skinIndexArray;
3071 delete geometryGroup.__skinWeightArray;
3072
3073 }
3074
3075 };
3076
3077 function setDirectBuffers ( geometry, hint, dispose ) {
3078
3079 var attributes = geometry.attributes;
3080
3081 var index = attributes[ "index" ];
3082 var position = attributes[ "position" ];
3083 var normal = attributes[ "normal" ];
3084 var uv = attributes[ "uv" ];
3085 var color = attributes[ "color" ];
3086 var tangent = attributes[ "tangent" ];
3087
3088 if ( geometry.elementsNeedUpdate && index !== undefined ) {
3089
3090 _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );
3091 _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, index.array, hint );
3092
3093 }
3094
3095 if ( geometry.verticesNeedUpdate && position !== undefined ) {
3096
3097 _gl.bindBuffer( _gl.ARRAY_BUFFER, position.buffer );
3098 _gl.bufferData( _gl.ARRAY_BUFFER, position.array, hint );
3099
3100 }
3101
3102 if ( geometry.normalsNeedUpdate && normal !== undefined ) {
3103
3104 _gl.bindBuffer( _gl.ARRAY_BUFFER, normal.buffer );
3105 _gl.bufferData( _gl.ARRAY_BUFFER, normal.array, hint );
3106
3107 }
3108
3109 if ( geometry.uvsNeedUpdate && uv !== undefined ) {
3110
3111 _gl.bindBuffer( _gl.ARRAY_BUFFER, uv.buffer );
3112 _gl.bufferData( _gl.ARRAY_BUFFER, uv.array, hint );
3113
3114 }
3115
3116 if ( geometry.colorsNeedUpdate && color !== undefined ) {
3117
3118 _gl.bindBuffer( _gl.ARRAY_BUFFER, color.buffer );
3119 _gl.bufferData( _gl.ARRAY_BUFFER, color.array, hint );
3120
3121 }
3122
3123 if ( geometry.tangentsNeedUpdate && tangent !== undefined ) {
3124
3125 _gl.bindBuffer( _gl.ARRAY_BUFFER, tangent.buffer );
3126 _gl.bufferData( _gl.ARRAY_BUFFER, tangent.array, hint );
3127
3128 }
3129
3130 if ( dispose ) {
3131
3132 for ( var i in geometry.attributes ) {
3133
3134 delete geometry.attributes[ i ].array;
3135
3136 }
3137
3138 }
3139
3140 };
3141
3142 // Buffer rendering
3143
3144 this.renderBufferImmediate = function ( object, program, material ) {
3145
3146 if ( object.hasPositions && ! object.__webglVertexBuffer ) object.__webglVertexBuffer = _gl.createBuffer();
3147 if ( object.hasNormals && ! object.__webglNormalBuffer ) object.__webglNormalBuffer = _gl.createBuffer();
3148 if ( object.hasUvs && ! object.__webglUvBuffer ) object.__webglUvBuffer = _gl.createBuffer();
3149 if ( object.hasColors && ! object.__webglColorBuffer ) object.__webglColorBuffer = _gl.createBuffer();
3150
3151 if ( object.hasPositions ) {
3152
3153 _gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglVertexBuffer );
3154 _gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW );
3155 _gl.enableVertexAttribArray( program.attributes.position );
3156 _gl.vertexAttribPointer( program.attributes.position, 3, _gl.FLOAT, false, 0, 0 );
3157
3158 }
3159
3160 if ( object.hasNormals ) {
3161
3162 _gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglNormalBuffer );
3163
3164 if ( material.shading === THREE.FlatShading ) {
3165
3166 var nx, ny, nz,
3167 nax, nbx, ncx, nay, nby, ncy, naz, nbz, ncz,
3168 normalArray,
3169 i, il = object.count * 3;
3170
3171 for( i = 0; i < il; i += 9 ) {
3172
3173 normalArray = object.normalArray;
3174
3175 nax = normalArray[ i ];
3176 nay = normalArray[ i + 1 ];
3177 naz = normalArray[ i + 2 ];
3178
3179 nbx = normalArray[ i + 3 ];
3180 nby = normalArray[ i + 4 ];
3181 nbz = normalArray[ i + 5 ];
3182
3183 ncx = normalArray[ i + 6 ];
3184 ncy = normalArray[ i + 7 ];
3185 ncz = normalArray[ i + 8 ];
3186
3187 nx = ( nax + nbx + ncx ) / 3;
3188 ny = ( nay + nby + ncy ) / 3;
3189 nz = ( naz + nbz + ncz ) / 3;
3190
3191 normalArray[ i ] = nx;
3192 normalArray[ i + 1 ] = ny;
3193 normalArray[ i + 2 ] = nz;
3194
3195 normalArray[ i + 3 ] = nx;
3196 normalArray[ i + 4 ] = ny;
3197 normalArray[ i + 5 ] = nz;
3198
3199 normalArray[ i + 6 ] = nx;
3200 normalArray[ i + 7 ] = ny;
3201 normalArray[ i + 8 ] = nz;
3202
3203 }
3204
3205 }
3206
3207 _gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW );
3208 _gl.enableVertexAttribArray( program.attributes.normal );
3209 _gl.vertexAttribPointer( program.attributes.normal, 3, _gl.FLOAT, false, 0, 0 );
3210
3211 }
3212
3213 if ( object.hasUvs && material.map ) {
3214
3215 _gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglUvBuffer );
3216 _gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW );
3217 _gl.enableVertexAttribArray( program.attributes.uv );
3218 _gl.vertexAttribPointer( program.attributes.uv, 2, _gl.FLOAT, false, 0, 0 );
3219
3220 }
3221
3222 if ( object.hasColors && material.vertexColors !== THREE.NoColors ) {
3223
3224 _gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglColorBuffer );
3225 _gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW );
3226 _gl.enableVertexAttribArray( program.attributes.color );
3227 _gl.vertexAttribPointer( program.attributes.color, 3, _gl.FLOAT, false, 0, 0 );
3228
3229 }
3230
3231 _gl.drawArrays( _gl.TRIANGLES, 0, object.count );
3232
3233 object.count = 0;
3234
3235 };
3236
3237 this.renderBufferDirect = function ( camera, lights, fog, material, geometry, object ) {
3238
3239 if ( material.visible === false ) return;
3240
3241 var program, attributes, linewidth, primitives, a, attribute;
3242
3243 program = setProgram( camera, lights, fog, material, object );
3244
3245 attributes = program.attributes;
3246
3247 var updateBuffers = false,
3248 wireframeBit = material.wireframe ? 1 : 0,
3249 geometryHash = ( geometry.id * 0xffffff ) + ( program.id * 2 ) + wireframeBit;
3250
3251 if ( geometryHash !== _currentGeometryGroupHash ) {
3252
3253 _currentGeometryGroupHash = geometryHash;
3254 updateBuffers = true;
3255
3256 }
3257
3258 // render mesh
3259
3260 if ( object instanceof THREE.Mesh ) {
3261
3262 var offsets = geometry.offsets;
3263
3264 // if there is more than 1 chunk
3265 // must set attribute pointers to use new offsets for each chunk
3266 // even if geometry and materials didn't change
3267
3268 if ( offsets.length > 1 ) updateBuffers = true;
3269
3270 for ( var i = 0, il = offsets.length; i < il; ++ i ) {
3271
3272 var startIndex = offsets[ i ].index;
3273
3274 if ( updateBuffers ) {
3275
3276 // vertices
3277
3278 var position = geometry.attributes[ "position" ];
3279 var positionSize = position.itemSize;
3280
3281 _gl.bindBuffer( _gl.ARRAY_BUFFER, position.buffer );
3282 _gl.vertexAttribPointer( attributes.position, positionSize, _gl.FLOAT, false, 0, startIndex * positionSize * 4 ); // 4 bytes per Float32
3283
3284 // normals
3285
3286 var normal = geometry.attributes[ "normal" ];
3287
3288 if ( attributes.normal >= 0 && normal ) {
3289
3290 var normalSize = normal.itemSize;
3291
3292 _gl.bindBuffer( _gl.ARRAY_BUFFER, normal.buffer );
3293 _gl.vertexAttribPointer( attributes.normal, normalSize, _gl.FLOAT, false, 0, startIndex * normalSize * 4 );
3294
3295 }
3296
3297 // uvs
3298
3299 var uv = geometry.attributes[ "uv" ];
3300
3301 if ( attributes.uv >= 0 && uv ) {
3302
3303 if ( uv.buffer ) {
3304
3305 var uvSize = uv.itemSize;
3306
3307 _gl.bindBuffer( _gl.ARRAY_BUFFER, uv.buffer );
3308 _gl.vertexAttribPointer( attributes.uv, uvSize, _gl.FLOAT, false, 0, startIndex * uvSize * 4 );
3309
3310 _gl.enableVertexAttribArray( attributes.uv );
3311
3312 } else {
3313
3314 _gl.disableVertexAttribArray( attributes.uv );
3315
3316 }
3317
3318 }
3319
3320 // colors
3321
3322 var color = geometry.attributes[ "color" ];
3323
3324 if ( attributes.color >= 0 && color ) {
3325
3326 var colorSize = color.itemSize;
3327
3328 _gl.bindBuffer( _gl.ARRAY_BUFFER, color.buffer );
3329 _gl.vertexAttribPointer( attributes.color, colorSize, _gl.FLOAT, false, 0, startIndex * colorSize * 4 );
3330
3331 }
3332
3333 // tangents
3334
3335 var tangent = geometry.attributes[ "tangent" ];
3336
3337 if ( attributes.tangent >= 0 && tangent ) {
3338
3339 var tangentSize = tangent.itemSize;
3340
3341 _gl.bindBuffer( _gl.ARRAY_BUFFER, tangent.buffer );
3342 _gl.vertexAttribPointer( attributes.tangent, tangentSize, _gl.FLOAT, false, 0, startIndex * tangentSize * 4 );
3343
3344 }
3345
3346 // indices
3347
3348 var index = geometry.attributes[ "index" ];
3349
3350 _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );
3351
3352 }
3353
3354 // render indexed triangles
3355
3356 _gl.drawElements( _gl.TRIANGLES, offsets[ i ].count, _gl.UNSIGNED_SHORT, offsets[ i ].start * 2 ); // 2 bytes per Uint16
3357
3358 _this.info.render.calls ++;
3359 _this.info.render.vertices += offsets[ i ].count; // not really true, here vertices can be shared
3360 _this.info.render.faces += offsets[ i ].count / 3;
3361
3362 }
3363
3364 // render particles
3365
3366 } else if ( object instanceof THREE.ParticleSystem ) {
3367
3368 if ( updateBuffers ) {
3369
3370 // vertices
3371
3372 var position = geometry.attributes[ "position" ];
3373 var positionSize = position.itemSize;
3374
3375 _gl.bindBuffer( _gl.ARRAY_BUFFER, position.buffer );
3376 _gl.vertexAttribPointer( attributes.position, positionSize, _gl.FLOAT, false, 0, 0 );
3377
3378 // colors
3379
3380 var color = geometry.attributes[ "color" ];
3381
3382 if ( attributes.color >= 0 && color ) {
3383
3384 var colorSize = color.itemSize;
3385
3386 _gl.bindBuffer( _gl.ARRAY_BUFFER, color.buffer );
3387 _gl.vertexAttribPointer( attributes.color, colorSize, _gl.FLOAT, false, 0, 0 );
3388
3389 }
3390
3391 // render particles
3392
3393 _gl.drawArrays( _gl.POINTS, 0, position.numItems / 3 );
3394
3395 _this.info.render.calls ++;
3396 _this.info.render.points += position.numItems / 3;
3397
3398 }
3399
3400 }
3401
3402 };
3403
3404 this.renderBuffer = function ( camera, lights, fog, material, geometryGroup, object ) {
3405
3406 if ( material.visible === false ) return;
3407
3408 var program, attributes, linewidth, primitives, a, attribute, i, il;
3409
3410 program = setProgram( camera, lights, fog, material, object );
3411
3412 attributes = program.attributes;
3413
3414 var updateBuffers = false,
3415 wireframeBit = material.wireframe ? 1 : 0,
3416 geometryGroupHash = ( geometryGroup.id * 0xffffff ) + ( program.id * 2 ) + wireframeBit;
3417
3418 if ( geometryGroupHash !== _currentGeometryGroupHash ) {
3419
3420 _currentGeometryGroupHash = geometryGroupHash;
3421 updateBuffers = true;
3422
3423 }
3424
3425 // vertices
3426
3427 if ( !material.morphTargets && attributes.position >= 0 ) {
3428
3429 if ( updateBuffers ) {
3430
3431 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer );
3432 _gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
3433
3434 }
3435
3436 } else {
3437
3438 if ( object.morphTargetBase ) {
3439
3440 setupMorphTargets( material, geometryGroup, object );
3441
3442 }
3443
3444 }
3445
3446
3447 if ( updateBuffers ) {
3448
3449 // custom attributes
3450
3451 // Use the per-geometryGroup custom attribute arrays which are setup in initMeshBuffers
3452
3453 if ( geometryGroup.__webglCustomAttributesList ) {
3454
3455 for ( i = 0, il = geometryGroup.__webglCustomAttributesList.length; i < il; i ++ ) {
3456
3457 attribute = geometryGroup.__webglCustomAttributesList[ i ];
3458
3459 if ( attributes[ attribute.buffer.belongsToAttribute ] >= 0 ) {
3460
3461 _gl.bindBuffer( _gl.ARRAY_BUFFER, attribute.buffer );
3462 _gl.vertexAttribPointer( attributes[ attribute.buffer.belongsToAttribute ], attribute.size, _gl.FLOAT, false, 0, 0 );
3463
3464 }
3465
3466 }
3467
3468 }
3469
3470
3471 // colors
3472
3473 if ( attributes.color >= 0 ) {
3474
3475 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglColorBuffer );
3476 _gl.vertexAttribPointer( attributes.color, 3, _gl.FLOAT, false, 0, 0 );
3477
3478 }
3479
3480 // normals
3481
3482 if ( attributes.normal >= 0 ) {
3483
3484 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglNormalBuffer );
3485 _gl.vertexAttribPointer( attributes.normal, 3, _gl.FLOAT, false, 0, 0 );
3486
3487 }
3488
3489 // tangents
3490
3491 if ( attributes.tangent >= 0 ) {
3492
3493 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglTangentBuffer );
3494 _gl.vertexAttribPointer( attributes.tangent, 4, _gl.FLOAT, false, 0, 0 );
3495
3496 }
3497
3498 // uvs
3499
3500 if ( attributes.uv >= 0 ) {
3501
3502 if ( geometryGroup.__webglUVBuffer ) {
3503
3504 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUVBuffer );
3505 _gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 0, 0 );
3506
3507 _gl.enableVertexAttribArray( attributes.uv );
3508
3509 } else {
3510
3511 _gl.disableVertexAttribArray( attributes.uv );
3512
3513 }
3514
3515 }
3516
3517 if ( attributes.uv2 >= 0 ) {
3518
3519 if ( geometryGroup.__webglUV2Buffer ) {
3520
3521 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUV2Buffer );
3522 _gl.vertexAttribPointer( attributes.uv2, 2, _gl.FLOAT, false, 0, 0 );
3523
3524 _gl.enableVertexAttribArray( attributes.uv2 );
3525
3526 } else {
3527
3528 _gl.disableVertexAttribArray( attributes.uv2 );
3529
3530 }
3531
3532 }
3533
3534 if ( material.skinning &&
3535 attributes.skinIndex >= 0 && attributes.skinWeight >= 0 ) {
3536
3537 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinIndicesBuffer );
3538 _gl.vertexAttribPointer( attributes.skinIndex, 4, _gl.FLOAT, false, 0, 0 );
3539
3540 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinWeightsBuffer );
3541 _gl.vertexAttribPointer( attributes.skinWeight, 4, _gl.FLOAT, false, 0, 0 );
3542
3543 }
3544
3545 // line distances
3546
3547 if ( attributes.lineDistance >= 0 ) {
3548
3549 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglLineDistanceBuffer );
3550 _gl.vertexAttribPointer( attributes.lineDistance, 1, _gl.FLOAT, false, 0, 0 );
3551
3552 }
3553
3554 }
3555
3556 // render mesh
3557
3558 if ( object instanceof THREE.Mesh ) {
3559
3560 // wireframe
3561
3562 if ( material.wireframe ) {
3563
3564 setLineWidth( material.wireframeLinewidth );
3565
3566 if ( updateBuffers ) _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglLineBuffer );
3567 _gl.drawElements( _gl.LINES, geometryGroup.__webglLineCount, _gl.UNSIGNED_SHORT, 0 );
3568
3569 // triangles
3570
3571 } else {
3572
3573 if ( updateBuffers ) _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglFaceBuffer );
3574 _gl.drawElements( _gl.TRIANGLES, geometryGroup.__webglFaceCount, _gl.UNSIGNED_SHORT, 0 );
3575
3576 }
3577
3578 _this.info.render.calls ++;
3579 _this.info.render.vertices += geometryGroup.__webglFaceCount;
3580 _this.info.render.faces += geometryGroup.__webglFaceCount / 3;
3581
3582 // render lines
3583
3584 } else if ( object instanceof THREE.Line ) {
3585
3586 primitives = ( object.type === THREE.LineStrip ) ? _gl.LINE_STRIP : _gl.LINES;
3587
3588 setLineWidth( material.linewidth );
3589
3590 _gl.drawArrays( primitives, 0, geometryGroup.__webglLineCount );
3591
3592 _this.info.render.calls ++;
3593
3594 // render particles
3595
3596 } else if ( object instanceof THREE.ParticleSystem ) {
3597
3598 _gl.drawArrays( _gl.POINTS, 0, geometryGroup.__webglParticleCount );
3599
3600 _this.info.render.calls ++;
3601 _this.info.render.points += geometryGroup.__webglParticleCount;
3602
3603 // render ribbon
3604
3605 } else if ( object instanceof THREE.Ribbon ) {
3606
3607 _gl.drawArrays( _gl.TRIANGLE_STRIP, 0, geometryGroup.__webglVertexCount );
3608
3609 _this.info.render.calls ++;
3610
3611 }
3612
3613 };
3614
3615 function setupMorphTargets ( material, geometryGroup, object ) {
3616
3617 // set base
3618
3619 var attributes = material.program.attributes;
3620
3621 if ( object.morphTargetBase !== -1 ) {
3622
3623 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ object.morphTargetBase ] );
3624 _gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
3625
3626 } else if ( attributes.position >= 0 ) {
3627
3628 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer );
3629 _gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
3630
3631 }
3632
3633 if ( object.morphTargetForcedOrder.length ) {
3634
3635 // set forced order
3636
3637 var m = 0;
3638 var order = object.morphTargetForcedOrder;
3639 var influences = object.morphTargetInfluences;
3640
3641 while ( m < material.numSupportedMorphTargets && m < order.length ) {
3642
3643 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ order[ m ] ] );
3644 _gl.vertexAttribPointer( attributes[ "morphTarget" + m ], 3, _gl.FLOAT, false, 0, 0 );
3645
3646 if ( material.morphNormals ) {
3647
3648 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphNormalsBuffers[ order[ m ] ] );
3649 _gl.vertexAttribPointer( attributes[ "morphNormal" + m ], 3, _gl.FLOAT, false, 0, 0 );
3650
3651 }
3652
3653 object.__webglMorphTargetInfluences[ m ] = influences[ order[ m ] ];
3654
3655 m ++;
3656 }
3657
3658 } else {
3659
3660 // find the most influencing
3661
3662 var influence, activeInfluenceIndices = [];
3663 var influences = object.morphTargetInfluences;
3664 var i, il = influences.length;
3665
3666 for ( i = 0; i < il; i ++ ) {
3667
3668 influence = influences[ i ];
3669
3670 if ( influence > 0 ) {
3671
3672 activeInfluenceIndices.push( [ i, influence ] );
3673
3674 }
3675
3676 }
3677
3678 if ( activeInfluenceIndices.length > material.numSupportedMorphTargets ) {
3679
3680 activeInfluenceIndices.sort( numericalSort );
3681 activeInfluenceIndices.length = material.numSupportedMorphTargets;
3682
3683 } else if ( activeInfluenceIndices.length > material.numSupportedMorphNormals ) {
3684
3685 activeInfluenceIndices.sort( numericalSort );
3686
3687 } else if ( activeInfluenceIndices.length === 0 ) {
3688
3689 activeInfluenceIndices.push( [ 0, 0 ] );
3690
3691 };
3692
3693 var influenceIndex, m = 0;
3694
3695 while ( m < material.numSupportedMorphTargets ) {
3696
3697 if ( activeInfluenceIndices[ m ] ) {
3698
3699 influenceIndex = activeInfluenceIndices[ m ][ 0 ];
3700
3701 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ influenceIndex ] );
3702
3703 _gl.vertexAttribPointer( attributes[ "morphTarget" + m ], 3, _gl.FLOAT, false, 0, 0 );
3704
3705 if ( material.morphNormals ) {
3706
3707 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphNormalsBuffers[ influenceIndex ] );
3708 _gl.vertexAttribPointer( attributes[ "morphNormal" + m ], 3, _gl.FLOAT, false, 0, 0 );
3709
3710 }
3711
3712 object.__webglMorphTargetInfluences[ m ] = influences[ influenceIndex ];
3713
3714 } else {
3715
3716 _gl.vertexAttribPointer( attributes[ "morphTarget" + m ], 3, _gl.FLOAT, false, 0, 0 );
3717
3718 if ( material.morphNormals ) {
3719
3720 _gl.vertexAttribPointer( attributes[ "morphNormal" + m ], 3, _gl.FLOAT, false, 0, 0 );
3721
3722 }
3723
3724 object.__webglMorphTargetInfluences[ m ] = 0;
3725
3726 }
3727
3728 m ++;
3729
3730 }
3731
3732 }
3733
3734 // load updated influences uniform
3735
3736 if ( material.program.uniforms.morphTargetInfluences !== null ) {
3737
3738 _gl.uniform1fv( material.program.uniforms.morphTargetInfluences, object.__webglMorphTargetInfluences );
3739
3740 }
3741
3742 };
3743
3744 // Sorting
3745
3746 function painterSortStable ( a, b ) {
3747
3748 if ( a.z !== b.z ) {
3749
3750 return b.z - a.z;
3751
3752 } else {
3753
3754 return b.id - a.id;
3755
3756 }
3757
3758 };
3759
3760 function numericalSort ( a, b ) {
3761
3762 return b[ 1 ] - a[ 1 ];
3763
3764 };
3765
3766
3767 // Rendering
3768
3769 this.render = function ( scene, camera, renderTarget, forceClear ) {
3770
3771 if ( camera instanceof THREE.Camera === false ) {
3772
3773 console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
3774 return;
3775
3776 }
3777
3778 var i, il,
3779
3780 webglObject, object,
3781 renderList,
3782
3783 lights = scene.__lights,
3784 fog = scene.fog;
3785
3786 // reset caching for this frame
3787
3788 _currentMaterialId = -1;
3789 _lightsNeedUpdate = true;
3790
3791 // update scene graph
3792
3793 if ( this.autoUpdateScene ) scene.updateMatrixWorld();
3794
3795 // update camera matrices and frustum
3796
3797 if ( camera.parent === undefined ) camera.updateMatrixWorld();
3798
3799 if ( ! camera._viewMatrixArray ) camera._viewMatrixArray = new Float32Array( 16 );
3800 if ( ! camera._projectionMatrixArray ) camera._projectionMatrixArray = new Float32Array( 16 );
3801
3802 camera.matrixWorldInverse.getInverse( camera.matrixWorld );
3803
3804 camera.matrixWorldInverse.flattenToArray( camera._viewMatrixArray );
3805 camera.projectionMatrix.flattenToArray( camera._projectionMatrixArray );
3806
3807 _projScreenMatrix.multiply( camera.projectionMatrix, camera.matrixWorldInverse );
3808 _frustum.setFromMatrix( _projScreenMatrix );
3809
3810 // update WebGL objects
3811
3812 if ( this.autoUpdateObjects ) this.initWebGLObjects( scene );
3813
3814 // custom render plugins (pre pass)
3815
3816 renderPlugins( this.renderPluginsPre, scene, camera );
3817
3818 //
3819
3820 _this.info.render.calls = 0;
3821 _this.info.render.vertices = 0;
3822 _this.info.render.faces = 0;
3823 _this.info.render.points = 0;
3824
3825 this.setRenderTarget( renderTarget );
3826
3827 if ( this.autoClear || forceClear ) {
3828
3829 this.clear( this.autoClearColor, this.autoClearDepth, this.autoClearStencil );
3830
3831 }
3832
3833 // set matrices for regular objects (frustum culled)
3834
3835 renderList = scene.__webglObjects;
3836
3837 for ( i = 0, il = renderList.length; i < il; i ++ ) {
3838
3839 webglObject = renderList[ i ];
3840 object = webglObject.object;
3841
3842 webglObject.render = false;
3843
3844 if ( object.visible ) {
3845
3846 if ( ! ( object instanceof THREE.Mesh || object instanceof THREE.ParticleSystem ) || ! ( object.frustumCulled ) || _frustum.contains( object ) ) {
3847
3848 //object.matrixWorld.flattenToArray( object._modelMatrixArray );
3849
3850 setupMatrices( object, camera );
3851
3852 unrollBufferMaterial( webglObject );
3853
3854 webglObject.render = true;
3855
3856 if ( this.sortObjects === true ) {
3857
3858 if ( object.renderDepth !== null ) {
3859
3860 webglObject.z = object.renderDepth;
3861
3862 } else {
3863
3864 _vector3.copy( object.matrixWorld.getPosition() );
3865 _projScreenMatrix.multiplyVector3( _vector3 );
3866
3867 webglObject.z = _vector3.z;
3868
3869 }
3870
3871 webglObject.id = object.id;
3872
3873 }
3874
3875 }
3876
3877 }
3878
3879 }
3880
3881 if ( this.sortObjects ) {
3882
3883 renderList.sort( painterSortStable );
3884
3885 }
3886
3887 // set matrices for immediate objects
3888
3889 renderList = scene.__webglObjectsImmediate;
3890
3891 for ( i = 0, il = renderList.length; i < il; i ++ ) {
3892
3893 webglObject = renderList[ i ];
3894 object = webglObject.object;
3895
3896 if ( object.visible ) {
3897
3898 /*
3899 if ( object.matrixAutoUpdate ) {
3900
3901 object.matrixWorld.flattenToArray( object._modelMatrixArray );
3902
3903 }
3904 */
3905
3906 setupMatrices( object, camera );
3907
3908 unrollImmediateBufferMaterial( webglObject );
3909
3910 }
3911
3912 }
3913
3914 if ( scene.overrideMaterial ) {
3915
3916 var material = scene.overrideMaterial;
3917
3918 this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
3919 this.setDepthTest( material.depthTest );
3920 this.setDepthWrite( material.depthWrite );
3921 setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
3922
3923 renderObjects( scene.__webglObjects, false, "", camera, lights, fog, true, material );
3924 renderObjectsImmediate( scene.__webglObjectsImmediate, "", camera, lights, fog, false, material );
3925
3926 } else {
3927
3928 // opaque pass (front-to-back order)
3929
3930 this.setBlending( THREE.NormalBlending );
3931
3932 renderObjects( scene.__webglObjects, true, "opaque", camera, lights, fog, false );
3933 renderObjectsImmediate( scene.__webglObjectsImmediate, "opaque", camera, lights, fog, false );
3934
3935 // transparent pass (back-to-front order)
3936
3937 renderObjects( scene.__webglObjects, false, "transparent", camera, lights, fog, true );
3938 renderObjectsImmediate( scene.__webglObjectsImmediate, "transparent", camera, lights, fog, true );
3939
3940 }
3941
3942 // custom render plugins (post pass)
3943
3944 renderPlugins( this.renderPluginsPost, scene, camera );
3945
3946
3947 // Generate mipmap if we're using any kind of mipmap filtering
3948
3949 if ( renderTarget && renderTarget.generateMipmaps && renderTarget.minFilter !== THREE.NearestFilter && renderTarget.minFilter !== THREE.LinearFilter ) {
3950
3951 updateRenderTargetMipmap( renderTarget );
3952
3953 }
3954
3955 // Ensure depth buffer writing is enabled so it can be cleared on next render
3956
3957 this.setDepthTest( true );
3958 this.setDepthWrite( true );
3959
3960 // _gl.finish();
3961
3962 };
3963
3964 function renderPlugins( plugins, scene, camera ) {
3965
3966 if ( ! plugins.length ) return;
3967
3968 for ( var i = 0, il = plugins.length; i < il; i ++ ) {
3969
3970 // reset state for plugin (to start from clean slate)
3971
3972 _currentProgram = null;
3973 _currentCamera = null;
3974
3975 _oldBlending = -1;
3976 _oldDepthTest = -1;
3977 _oldDepthWrite = -1;
3978 _oldDoubleSided = -1;
3979 _oldFlipSided = -1;
3980 _currentGeometryGroupHash = -1;
3981 _currentMaterialId = -1;
3982
3983 _lightsNeedUpdate = true;
3984
3985 plugins[ i ].render( scene, camera, _currentWidth, _currentHeight );
3986
3987 // reset state after plugin (anything could have changed)
3988
3989 _currentProgram = null;
3990 _currentCamera = null;
3991
3992 _oldBlending = -1;
3993 _oldDepthTest = -1;
3994 _oldDepthWrite = -1;
3995 _oldDoubleSided = -1;
3996 _oldFlipSided = -1;
3997 _currentGeometryGroupHash = -1;
3998 _currentMaterialId = -1;
3999
4000 _lightsNeedUpdate = true;
4001
4002 }
4003
4004 };
4005
4006 function renderObjects ( renderList, reverse, materialType, camera, lights, fog, useBlending, overrideMaterial ) {
4007
4008 var webglObject, object, buffer, material, start, end, delta;
4009
4010 if ( reverse ) {
4011
4012 start = renderList.length - 1;
4013 end = -1;
4014 delta = -1;
4015
4016 } else {
4017
4018 start = 0;
4019 end = renderList.length;
4020 delta = 1;
4021 }
4022
4023 for ( var i = start; i !== end; i += delta ) {
4024
4025 webglObject = renderList[ i ];
4026
4027 if ( webglObject.render ) {
4028
4029 object = webglObject.object;
4030 buffer = webglObject.buffer;
4031
4032 if ( overrideMaterial ) {
4033
4034 material = overrideMaterial;
4035
4036 } else {
4037
4038 material = webglObject[ materialType ];
4039
4040 if ( ! material ) continue;
4041
4042 if ( useBlending ) _this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
4043
4044 _this.setDepthTest( material.depthTest );
4045 _this.setDepthWrite( material.depthWrite );
4046 setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
4047
4048 }
4049
4050 _this.setMaterialFaces( material );
4051
4052 if ( buffer instanceof THREE.BufferGeometry ) {
4053
4054 _this.renderBufferDirect( camera, lights, fog, material, buffer, object );
4055
4056 } else {
4057
4058 _this.renderBuffer( camera, lights, fog, material, buffer, object );
4059
4060 }
4061
4062 }
4063
4064 }
4065
4066 };
4067
4068 function renderObjectsImmediate ( renderList, materialType, camera, lights, fog, useBlending, overrideMaterial ) {
4069
4070 var webglObject, object, material, program;
4071
4072 for ( var i = 0, il = renderList.length; i < il; i ++ ) {
4073
4074 webglObject = renderList[ i ];
4075 object = webglObject.object;
4076
4077 if ( object.visible ) {
4078
4079 if ( overrideMaterial ) {
4080
4081 material = overrideMaterial;
4082
4083 } else {
4084
4085 material = webglObject[ materialType ];
4086
4087 if ( ! material ) continue;
4088
4089 if ( useBlending ) _this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
4090
4091 _this.setDepthTest( material.depthTest );
4092 _this.setDepthWrite( material.depthWrite );
4093 setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
4094
4095 }
4096
4097 _this.renderImmediateObject( camera, lights, fog, material, object );
4098
4099 }
4100
4101 }
4102
4103 };
4104
4105 this.renderImmediateObject = function ( camera, lights, fog, material, object ) {
4106
4107 var program = setProgram( camera, lights, fog, material, object );
4108
4109 _currentGeometryGroupHash = -1;
4110
4111 _this.setMaterialFaces( material );
4112
4113 if ( object.immediateRenderCallback ) {
4114
4115 object.immediateRenderCallback( program, _gl, _frustum );
4116
4117 } else {
4118
4119 object.render( function( object ) { _this.renderBufferImmediate( object, program, material ); } );
4120
4121 }
4122
4123 };
4124
4125 function unrollImmediateBufferMaterial ( globject ) {
4126
4127 var object = globject.object,
4128 material = object.material;
4129
4130 if ( material.transparent ) {
4131
4132 globject.transparent = material;
4133 globject.opaque = null;
4134
4135 } else {
4136
4137 globject.opaque = material;
4138 globject.transparent = null;
4139
4140 }
4141
4142 };
4143
4144 function unrollBufferMaterial ( globject ) {
4145
4146 var object = globject.object,
4147 buffer = globject.buffer,
4148 material, materialIndex, meshMaterial;
4149
4150 meshMaterial = object.material;
4151
4152 if ( meshMaterial instanceof THREE.MeshFaceMaterial ) {
4153
4154 materialIndex = buffer.materialIndex;
4155
4156 if ( materialIndex >= 0 ) {
4157
4158 material = meshMaterial.materials[ materialIndex ];
4159
4160 if ( material.transparent ) {
4161
4162 globject.transparent = material;
4163 globject.opaque = null;
4164
4165 } else {
4166
4167 globject.opaque = material;
4168 globject.transparent = null;
4169
4170 }
4171
4172 }
4173
4174 } else {
4175
4176 material = meshMaterial;
4177
4178 if ( material ) {
4179
4180 if ( material.transparent ) {
4181
4182 globject.transparent = material;
4183 globject.opaque = null;
4184
4185 } else {
4186
4187 globject.opaque = material;
4188 globject.transparent = null;
4189
4190 }
4191
4192 }
4193
4194 }
4195
4196 };
4197
4198 // Geometry splitting
4199
4200 function sortFacesByMaterial ( geometry, material ) {
4201
4202 var f, fl, face, materialIndex, vertices,
4203 materialHash, groupHash,
4204 hash_map = {};
4205
4206 var numMorphTargets = geometry.morphTargets.length;
4207 var numMorphNormals = geometry.morphNormals.length;
4208
4209 var usesFaceMaterial = material instanceof THREE.MeshFaceMaterial;
4210
4211 geometry.geometryGroups = {};
4212
4213 for ( f = 0, fl = geometry.faces.length; f < fl; f ++ ) {
4214
4215 face = geometry.faces[ f ];
4216 materialIndex = usesFaceMaterial ? face.materialIndex : undefined;
4217
4218 materialHash = ( materialIndex !== undefined ) ? materialIndex : -1;
4219
4220 if ( hash_map[ materialHash ] === undefined ) {
4221
4222 hash_map[ materialHash ] = { 'hash': materialHash, 'counter': 0 };
4223
4224 }
4225
4226 groupHash = hash_map[ materialHash ].hash + '_' + hash_map[ materialHash ].counter;
4227
4228 if ( geometry.geometryGroups[ groupHash ] === undefined ) {
4229
4230 geometry.geometryGroups[ groupHash ] = { 'faces3': [], 'faces4': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
4231
4232 }
4233
4234 vertices = face instanceof THREE.Face3 ? 3 : 4;
4235
4236 if ( geometry.geometryGroups[ groupHash ].vertices + vertices > 65535 ) {
4237
4238 hash_map[ materialHash ].counter += 1;
4239 groupHash = hash_map[ materialHash ].hash + '_' + hash_map[ materialHash ].counter;
4240
4241 if ( geometry.geometryGroups[ groupHash ] === undefined ) {
4242
4243 geometry.geometryGroups[ groupHash ] = { 'faces3': [], 'faces4': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
4244
4245 }
4246
4247 }
4248
4249 if ( face instanceof THREE.Face3 ) {
4250
4251 geometry.geometryGroups[ groupHash ].faces3.push( f );
4252
4253 } else {
4254
4255 geometry.geometryGroups[ groupHash ].faces4.push( f );
4256
4257 }
4258
4259 geometry.geometryGroups[ groupHash ].vertices += vertices;
4260
4261 }
4262
4263 geometry.geometryGroupsList = [];
4264
4265 for ( var g in geometry.geometryGroups ) {
4266
4267 geometry.geometryGroups[ g ].id = _geometryGroupCounter ++;
4268
4269 geometry.geometryGroupsList.push( geometry.geometryGroups[ g ] );
4270
4271 }
4272
4273 };
4274
4275 // Objects refresh
4276
4277 this.initWebGLObjects = function ( scene ) {
4278
4279 if ( !scene.__webglObjects ) {
4280
4281 scene.__webglObjects = [];
4282 scene.__webglObjectsImmediate = [];
4283 scene.__webglSprites = [];
4284 scene.__webglFlares = [];
4285
4286 }
4287
4288 while ( scene.__objectsAdded.length ) {
4289
4290 addObject( scene.__objectsAdded[ 0 ], scene );
4291 scene.__objectsAdded.splice( 0, 1 );
4292
4293 }
4294
4295 while ( scene.__objectsRemoved.length ) {
4296
4297 removeObject( scene.__objectsRemoved[ 0 ], scene );
4298 scene.__objectsRemoved.splice( 0, 1 );
4299
4300 }
4301
4302 // update must be called after objects adding / removal
4303
4304 for ( var o = 0, ol = scene.__webglObjects.length; o < ol; o ++ ) {
4305
4306 updateObject( scene.__webglObjects[ o ].object );
4307
4308 }
4309
4310 };
4311
4312 // Objects adding
4313
4314 function addObject ( object, scene ) {
4315
4316 var g, geometry, material, geometryGroup;
4317
4318 if ( ! object.__webglInit ) {
4319
4320 object.__webglInit = true;
4321
4322 object._modelViewMatrix = new THREE.Matrix4();
4323 object._normalMatrix = new THREE.Matrix3();
4324
4325 if ( object instanceof THREE.Mesh ) {
4326
4327 geometry = object.geometry;
4328 material = object.material;
4329
4330 if ( geometry instanceof THREE.Geometry ) {
4331
4332 if ( geometry.geometryGroups === undefined ) {
4333
4334 sortFacesByMaterial( geometry, material );
4335
4336 }
4337
4338 // create separate VBOs per geometry chunk
4339
4340 for ( g in geometry.geometryGroups ) {
4341
4342 geometryGroup = geometry.geometryGroups[ g ];
4343
4344 // initialise VBO on the first access
4345
4346 if ( ! geometryGroup.__webglVertexBuffer ) {
4347
4348 createMeshBuffers( geometryGroup );
4349 initMeshBuffers( geometryGroup, object );
4350
4351 geometry.verticesNeedUpdate = true;
4352 geometry.morphTargetsNeedUpdate = true;
4353 geometry.elementsNeedUpdate = true;
4354 geometry.uvsNeedUpdate = true;
4355 geometry.normalsNeedUpdate = true;
4356 geometry.tangentsNeedUpdate = true;
4357 geometry.colorsNeedUpdate = true;
4358
4359 }
4360
4361 }
4362
4363 } else if ( geometry instanceof THREE.BufferGeometry ) {
4364
4365 initDirectBuffers( geometry );
4366
4367 }
4368
4369 } else if ( object instanceof THREE.Ribbon ) {
4370
4371 geometry = object.geometry;
4372
4373 if ( ! geometry.__webglVertexBuffer ) {
4374
4375 createRibbonBuffers( geometry );
4376 initRibbonBuffers( geometry, object );
4377
4378 geometry.verticesNeedUpdate = true;
4379 geometry.colorsNeedUpdate = true;
4380 geometry.normalsNeedUpdate = true;
4381
4382 }
4383
4384 } else if ( object instanceof THREE.Line ) {
4385
4386 geometry = object.geometry;
4387
4388 if ( ! geometry.__webglVertexBuffer ) {
4389
4390 createLineBuffers( geometry );
4391 initLineBuffers( geometry, object );
4392
4393 geometry.verticesNeedUpdate = true;
4394 geometry.colorsNeedUpdate = true;
4395 geometry.lineDistancesNeedUpdate = true;
4396
4397 }
4398
4399 } else if ( object instanceof THREE.ParticleSystem ) {
4400
4401 geometry = object.geometry;
4402
4403 if ( ! geometry.__webglVertexBuffer ) {
4404
4405 if ( geometry instanceof THREE.Geometry ) {
4406
4407 createParticleBuffers( geometry );
4408 initParticleBuffers( geometry, object );
4409
4410 geometry.verticesNeedUpdate = true;
4411 geometry.colorsNeedUpdate = true;
4412
4413 } else if ( geometry instanceof THREE.BufferGeometry ) {
4414
4415 initDirectBuffers( geometry );
4416
4417 }
4418
4419
4420 }
4421
4422 }
4423
4424 }
4425
4426 if ( ! object.__webglActive ) {
4427
4428 if ( object instanceof THREE.Mesh ) {
4429
4430 geometry = object.geometry;
4431
4432 if ( geometry instanceof THREE.BufferGeometry ) {
4433
4434 addBuffer( scene.__webglObjects, geometry, object );
4435
4436 } else {
4437
4438 for ( g in geometry.geometryGroups ) {
4439
4440 geometryGroup = geometry.geometryGroups[ g ];
4441
4442 addBuffer( scene.__webglObjects, geometryGroup, object );
4443
4444 }
4445
4446 }
4447
4448 } else if ( object instanceof THREE.Ribbon ||
4449 object instanceof THREE.Line ||
4450 object instanceof THREE.ParticleSystem ) {
4451
4452 geometry = object.geometry;
4453 addBuffer( scene.__webglObjects, geometry, object );
4454
4455 } else if ( object instanceof THREE.ImmediateRenderObject || object.immediateRenderCallback ) {
4456
4457 addBufferImmediate( scene.__webglObjectsImmediate, object );
4458
4459 } else if ( object instanceof THREE.Sprite ) {
4460
4461 scene.__webglSprites.push( object );
4462
4463 } else if ( object instanceof THREE.LensFlare ) {
4464
4465 scene.__webglFlares.push( object );
4466
4467 }
4468
4469 object.__webglActive = true;
4470
4471 }
4472
4473 };
4474
4475 function addBuffer ( objlist, buffer, object ) {
4476
4477 objlist.push(
4478 {
4479 buffer: buffer,
4480 object: object,
4481 opaque: null,
4482 transparent: null
4483 }
4484 );
4485
4486 };
4487
4488 function addBufferImmediate ( objlist, object ) {
4489
4490 objlist.push(
4491 {
4492 object: object,
4493 opaque: null,
4494 transparent: null
4495 }
4496 );
4497
4498 };
4499
4500 // Objects updates
4501
4502 function updateObject ( object ) {
4503
4504 var geometry = object.geometry,
4505 geometryGroup, customAttributesDirty, material;
4506
4507 if ( object instanceof THREE.Mesh ) {
4508
4509 if ( geometry instanceof THREE.BufferGeometry ) {
4510
4511 if ( geometry.verticesNeedUpdate || geometry.elementsNeedUpdate ||
4512 geometry.uvsNeedUpdate || geometry.normalsNeedUpdate ||
4513 geometry.colorsNeedUpdate || geometry.tangentsNeedUpdate ) {
4514
4515 setDirectBuffers( geometry, _gl.DYNAMIC_DRAW, !geometry.dynamic );
4516
4517 }
4518
4519 geometry.verticesNeedUpdate = false;
4520 geometry.elementsNeedUpdate = false;
4521 geometry.uvsNeedUpdate = false;
4522 geometry.normalsNeedUpdate = false;
4523 geometry.colorsNeedUpdate = false;
4524 geometry.tangentsNeedUpdate = false;
4525
4526 } else {
4527
4528 // check all geometry groups
4529
4530 for( var i = 0, il = geometry.geometryGroupsList.length; i < il; i ++ ) {
4531
4532 geometryGroup = geometry.geometryGroupsList[ i ];
4533
4534 material = getBufferMaterial( object, geometryGroup );
4535
4536 if ( geometry.buffersNeedUpdate ) {
4537
4538 initMeshBuffers( geometryGroup, object );
4539
4540 }
4541
4542 customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
4543
4544 if ( geometry.verticesNeedUpdate || geometry.morphTargetsNeedUpdate || geometry.elementsNeedUpdate ||
4545 geometry.uvsNeedUpdate || geometry.normalsNeedUpdate ||
4546 geometry.colorsNeedUpdate || geometry.tangentsNeedUpdate || customAttributesDirty ) {
4547
4548 setMeshBuffers( geometryGroup, object, _gl.DYNAMIC_DRAW, !geometry.dynamic, material );
4549
4550 }
4551
4552 }
4553
4554 geometry.verticesNeedUpdate = false;
4555 geometry.morphTargetsNeedUpdate = false;
4556 geometry.elementsNeedUpdate = false;
4557 geometry.uvsNeedUpdate = false;
4558 geometry.normalsNeedUpdate = false;
4559 geometry.colorsNeedUpdate = false;
4560 geometry.tangentsNeedUpdate = false;
4561
4562 geometry.buffersNeedUpdate = false;
4563
4564 material.attributes && clearCustomAttributes( material );
4565
4566 }
4567
4568 } else if ( object instanceof THREE.Ribbon ) {
4569
4570 material = getBufferMaterial( object, geometry );
4571
4572 customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
4573
4574 if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || geometry.normalsNeedUpdate || customAttributesDirty ) {
4575
4576 setRibbonBuffers( geometry, _gl.DYNAMIC_DRAW );
4577
4578 }
4579
4580 geometry.verticesNeedUpdate = false;
4581 geometry.colorsNeedUpdate = false;
4582 geometry.normalsNeedUpdate = false;
4583
4584 material.attributes && clearCustomAttributes( material );
4585
4586 } else if ( object instanceof THREE.Line ) {
4587
4588 material = getBufferMaterial( object, geometry );
4589
4590 customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
4591
4592 if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || geometry.lineDistancesNeedUpdate || customAttributesDirty ) {
4593
4594 setLineBuffers( geometry, _gl.DYNAMIC_DRAW );
4595
4596 }
4597
4598 geometry.verticesNeedUpdate = false;
4599 geometry.colorsNeedUpdate = false;
4600 geometry.lineDistancesNeedUpdate = false;
4601
4602 material.attributes && clearCustomAttributes( material );
4603
4604 } else if ( object instanceof THREE.ParticleSystem ) {
4605
4606 if ( geometry instanceof THREE.BufferGeometry ) {
4607
4608 if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate ) {
4609
4610 setDirectBuffers( geometry, _gl.DYNAMIC_DRAW, !geometry.dynamic );
4611
4612 }
4613
4614 geometry.verticesNeedUpdate = false;
4615 geometry.colorsNeedUpdate = false;
4616
4617 } else {
4618
4619 material = getBufferMaterial( object, geometry );
4620
4621 customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
4622
4623 if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || object.sortParticles || customAttributesDirty ) {
4624
4625 setParticleBuffers( geometry, _gl.DYNAMIC_DRAW, object );
4626
4627 }
4628
4629 geometry.verticesNeedUpdate = false;
4630 geometry.colorsNeedUpdate = false;
4631
4632 material.attributes && clearCustomAttributes( material );
4633
4634 }
4635
4636 }
4637
4638 };
4639
4640 // Objects updates - custom attributes check
4641
4642 function areCustomAttributesDirty ( material ) {
4643
4644 for ( var a in material.attributes ) {
4645
4646 if ( material.attributes[ a ].needsUpdate ) return true;
4647
4648 }
4649
4650 return false;
4651
4652 };
4653
4654 function clearCustomAttributes ( material ) {
4655
4656 for ( var a in material.attributes ) {
4657
4658 material.attributes[ a ].needsUpdate = false;
4659
4660 }
4661
4662 };
4663
4664 // Objects removal
4665
4666 function removeObject ( object, scene ) {
4667
4668 if ( object instanceof THREE.Mesh ||
4669 object instanceof THREE.ParticleSystem ||
4670 object instanceof THREE.Ribbon ||
4671 object instanceof THREE.Line ) {
4672
4673 removeInstances( scene.__webglObjects, object );
4674
4675 } else if ( object instanceof THREE.Sprite ) {
4676
4677 removeInstancesDirect( scene.__webglSprites, object );
4678
4679 } else if ( object instanceof THREE.LensFlare ) {
4680
4681 removeInstancesDirect( scene.__webglFlares, object );
4682
4683 } else if ( object instanceof THREE.ImmediateRenderObject || object.immediateRenderCallback ) {
4684
4685 removeInstances( scene.__webglObjectsImmediate, object );
4686
4687 }
4688
4689 object.__webglActive = false;
4690
4691 };
4692
4693 function removeInstances ( objlist, object ) {
4694
4695 for ( var o = objlist.length - 1; o >= 0; o -- ) {
4696
4697 if ( objlist[ o ].object === object ) {
4698
4699 objlist.splice( o, 1 );
4700
4701 }
4702
4703 }
4704
4705 };
4706
4707 function removeInstancesDirect ( objlist, object ) {
4708
4709 for ( var o = objlist.length - 1; o >= 0; o -- ) {
4710
4711 if ( objlist[ o ] === object ) {
4712
4713 objlist.splice( o, 1 );
4714
4715 }
4716
4717 }
4718
4719 };
4720
4721 // Materials
4722
4723 this.initMaterial = function ( material, lights, fog, object ) {
4724
4725 var u, a, identifiers, i, parameters, maxLightCount, maxBones, maxShadows, shaderID;
4726
4727 if ( material instanceof THREE.MeshDepthMaterial ) {
4728
4729 shaderID = 'depth';
4730
4731 } else if ( material instanceof THREE.MeshNormalMaterial ) {
4732
4733 shaderID = 'normal';
4734
4735 } else if ( material instanceof THREE.MeshBasicMaterial ) {
4736
4737 shaderID = 'basic';
4738
4739 } else if ( material instanceof THREE.MeshLambertMaterial ) {
4740
4741 shaderID = 'lambert';
4742
4743 } else if ( material instanceof THREE.MeshPhongMaterial ) {
4744
4745 shaderID = 'phong';
4746
4747 } else if ( material instanceof THREE.LineBasicMaterial ) {
4748
4749 shaderID = 'basic';
4750
4751 } else if ( material instanceof THREE.LineDashedMaterial ) {
4752
4753 shaderID = 'dashed';
4754
4755 } else if ( material instanceof THREE.ParticleBasicMaterial ) {
4756
4757 shaderID = 'particle_basic';
4758
4759 }
4760
4761 if ( shaderID ) {
4762
4763 setMaterialShaders( material, THREE.ShaderLib[ shaderID ] );
4764
4765 }
4766
4767 // heuristics to create shader parameters according to lights in the scene
4768 // (not to blow over maxLights budget)
4769
4770 maxLightCount = allocateLights( lights );
4771
4772 maxShadows = allocateShadows( lights );
4773
4774 maxBones = allocateBones( object );
4775
4776 parameters = {
4777
4778 map: !!material.map,
4779 envMap: !!material.envMap,
4780 lightMap: !!material.lightMap,
4781 bumpMap: !!material.bumpMap,
4782 normalMap: !!material.normalMap,
4783 specularMap: !!material.specularMap,
4784
4785 vertexColors: material.vertexColors,
4786
4787 fog: fog,
4788 useFog: material.fog,
4789 fogExp: fog instanceof THREE.FogExp2,
4790
4791 sizeAttenuation: material.sizeAttenuation,
4792
4793 skinning: material.skinning,
4794 maxBones: maxBones,
4795 useVertexTexture: _supportsBoneTextures && object && object.useVertexTexture,
4796 boneTextureWidth: object && object.boneTextureWidth,
4797 boneTextureHeight: object && object.boneTextureHeight,
4798
4799 morphTargets: material.morphTargets,
4800 morphNormals: material.morphNormals,
4801 maxMorphTargets: this.maxMorphTargets,
4802 maxMorphNormals: this.maxMorphNormals,
4803
4804 maxDirLights: maxLightCount.directional,
4805 maxPointLights: maxLightCount.point,
4806 maxSpotLights: maxLightCount.spot,
4807 maxHemiLights: maxLightCount.hemi,
4808
4809 maxShadows: maxShadows,
4810 shadowMapEnabled: this.shadowMapEnabled && object.receiveShadow,
4811 shadowMapSoft: this.shadowMapSoft,
4812 shadowMapDebug: this.shadowMapDebug,
4813 shadowMapCascade: this.shadowMapCascade,
4814
4815 alphaTest: material.alphaTest,
4816 metal: material.metal,
4817 perPixel: material.perPixel,
4818 wrapAround: material.wrapAround,
4819 doubleSided: material.side === THREE.DoubleSide,
4820 flipSided: material.side === THREE.BackSide
4821
4822 };
4823
4824 material.program = buildProgram( shaderID, material.fragmentShader, material.vertexShader, material.uniforms, material.attributes, material.defines, parameters );
4825
4826 var attributes = material.program.attributes;
4827
4828 if ( attributes.position >= 0 ) _gl.enableVertexAttribArray( attributes.position );
4829 if ( attributes.color >= 0 ) _gl.enableVertexAttribArray( attributes.color );
4830 if ( attributes.normal >= 0 ) _gl.enableVertexAttribArray( attributes.normal );
4831 if ( attributes.tangent >= 0 ) _gl.enableVertexAttribArray( attributes.tangent );
4832 if ( attributes.lineDistance >= 0 ) _gl.enableVertexAttribArray( attributes.lineDistance );
4833
4834 if ( material.skinning &&
4835 attributes.skinIndex >= 0 && attributes.skinWeight >= 0 ) {
4836
4837 _gl.enableVertexAttribArray( attributes.skinIndex );
4838 _gl.enableVertexAttribArray( attributes.skinWeight );
4839
4840 }
4841
4842 if ( material.attributes ) {
4843
4844 for ( a in material.attributes ) {
4845
4846 if ( attributes[ a ] !== undefined && attributes[ a ] >= 0 ) _gl.enableVertexAttribArray( attributes[ a ] );
4847
4848 }
4849
4850 }
4851
4852 if ( material.morphTargets ) {
4853
4854 material.numSupportedMorphTargets = 0;
4855
4856 var id, base = "morphTarget";
4857
4858 for ( i = 0; i < this.maxMorphTargets; i ++ ) {
4859
4860 id = base + i;
4861
4862 if ( attributes[ id ] >= 0 ) {
4863
4864 _gl.enableVertexAttribArray( attributes[ id ] );
4865 material.numSupportedMorphTargets ++;
4866
4867 }
4868
4869 }
4870
4871 }
4872
4873 if ( material.morphNormals ) {
4874
4875 material.numSupportedMorphNormals = 0;
4876
4877 var id, base = "morphNormal";
4878
4879 for ( i = 0; i < this.maxMorphNormals; i ++ ) {
4880
4881 id = base + i;
4882
4883 if ( attributes[ id ] >= 0 ) {
4884
4885 _gl.enableVertexAttribArray( attributes[ id ] );
4886 material.numSupportedMorphNormals ++;
4887
4888 }
4889
4890 }
4891
4892 }
4893
4894 material.uniformsList = [];
4895
4896 for ( u in material.uniforms ) {
4897
4898 material.uniformsList.push( [ material.uniforms[ u ], u ] );
4899
4900 }
4901
4902 };
4903
4904 function setMaterialShaders( material, shaders ) {
4905
4906 material.uniforms = THREE.UniformsUtils.clone( shaders.uniforms );
4907 material.vertexShader = shaders.vertexShader;
4908 material.fragmentShader = shaders.fragmentShader;
4909
4910 };
4911
4912 function setProgram( camera, lights, fog, material, object ) {
4913
4914 _usedTextureUnits = 0;
4915
4916 if ( material.needsUpdate ) {
4917
4918 if ( material.program ) _this.deallocateMaterial( material );
4919
4920 _this.initMaterial( material, lights, fog, object );
4921 material.needsUpdate = false;
4922
4923 }
4924
4925 if ( material.morphTargets ) {
4926
4927 if ( ! object.__webglMorphTargetInfluences ) {
4928
4929 object.__webglMorphTargetInfluences = new Float32Array( _this.maxMorphTargets );
4930
4931 }
4932
4933 }
4934
4935 var refreshMaterial = false;
4936
4937 var program = material.program,
4938 p_uniforms = program.uniforms,
4939 m_uniforms = material.uniforms;
4940
4941 if ( program !== _currentProgram ) {
4942
4943 _gl.useProgram( program );
4944 _currentProgram = program;
4945
4946 refreshMaterial = true;
4947
4948 }
4949
4950 if ( material.id !== _currentMaterialId ) {
4951
4952 _currentMaterialId = material.id;
4953 refreshMaterial = true;
4954
4955 }
4956
4957 if ( refreshMaterial || camera !== _currentCamera ) {
4958
4959 _gl.uniformMatrix4fv( p_uniforms.projectionMatrix, false, camera._projectionMatrixArray );
4960
4961 if ( camera !== _currentCamera ) _currentCamera = camera;
4962
4963 }
4964
4965 // skinning uniforms must be set even if material didn't change
4966 // auto-setting of texture unit for bone texture must go before other textures
4967 // not sure why, but otherwise weird things happen
4968
4969 if ( material.skinning ) {
4970
4971 if ( _supportsBoneTextures && object.useVertexTexture ) {
4972
4973 if ( p_uniforms.boneTexture !== null ) {
4974
4975 var textureUnit = getTextureUnit();
4976
4977 _gl.uniform1i( p_uniforms.boneTexture, textureUnit );
4978 _this.setTexture( object.boneTexture, textureUnit );
4979
4980 }
4981
4982 } else {
4983
4984 if ( p_uniforms.boneGlobalMatrices !== null ) {
4985
4986 _gl.uniformMatrix4fv( p_uniforms.boneGlobalMatrices, false, object.boneMatrices );
4987
4988 }
4989
4990 }
4991
4992 }
4993
4994 if ( refreshMaterial ) {
4995
4996 // refresh uniforms common to several materials
4997
4998 if ( fog && material.fog ) {
4999
5000 refreshUniformsFog( m_uniforms, fog );
5001
5002 }
5003
5004 if ( material instanceof THREE.MeshPhongMaterial ||
5005 material instanceof THREE.MeshLambertMaterial ||
5006 material.lights ) {
5007
5008 if ( _lightsNeedUpdate ) {
5009
5010 setupLights( program, lights );
5011 _lightsNeedUpdate = false;
5012
5013 }
5014
5015 refreshUniformsLights( m_uniforms, _lights );
5016
5017 }
5018
5019 if ( material instanceof THREE.MeshBasicMaterial ||
5020 material instanceof THREE.MeshLambertMaterial ||
5021 material instanceof THREE.MeshPhongMaterial ) {
5022
5023 refreshUniformsCommon( m_uniforms, material );
5024
5025 }
5026
5027 // refresh single material specific uniforms
5028
5029 if ( material instanceof THREE.LineBasicMaterial ) {
5030
5031 refreshUniformsLine( m_uniforms, material );
5032
5033 } else if ( material instanceof THREE.LineDashedMaterial ) {
5034
5035 refreshUniformsLine( m_uniforms, material );
5036 refreshUniformsDash( m_uniforms, material );
5037
5038 } else if ( material instanceof THREE.ParticleBasicMaterial ) {
5039
5040 refreshUniformsParticle( m_uniforms, material );
5041
5042 } else if ( material instanceof THREE.MeshPhongMaterial ) {
5043
5044 refreshUniformsPhong( m_uniforms, material );
5045
5046 } else if ( material instanceof THREE.MeshLambertMaterial ) {
5047
5048 refreshUniformsLambert( m_uniforms, material );
5049
5050 } else if ( material instanceof THREE.MeshDepthMaterial ) {
5051
5052 m_uniforms.mNear.value = camera.near;
5053 m_uniforms.mFar.value = camera.far;
5054 m_uniforms.opacity.value = material.opacity;
5055
5056 } else if ( material instanceof THREE.MeshNormalMaterial ) {
5057
5058 m_uniforms.opacity.value = material.opacity;
5059
5060 }
5061
5062 if ( object.receiveShadow && ! material._shadowPass ) {
5063
5064 refreshUniformsShadow( m_uniforms, lights );
5065
5066 }
5067
5068 // load common uniforms
5069
5070 loadUniformsGeneric( program, material.uniformsList );
5071
5072 // load material specific uniforms
5073 // (shader material also gets them for the sake of genericity)
5074
5075 if ( material instanceof THREE.ShaderMaterial ||
5076 material instanceof THREE.MeshPhongMaterial ||
5077 material.envMap ) {
5078
5079 if ( p_uniforms.cameraPosition !== null ) {
5080
5081 var position = camera.matrixWorld.getPosition();
5082 _gl.uniform3f( p_uniforms.cameraPosition, position.x, position.y, position.z );
5083
5084 }
5085
5086 }
5087
5088 if ( material instanceof THREE.MeshPhongMaterial ||
5089 material instanceof THREE.MeshLambertMaterial ||
5090 material instanceof THREE.ShaderMaterial ||
5091 material.skinning ) {
5092
5093 if ( p_uniforms.viewMatrix !== null ) {
5094
5095 _gl.uniformMatrix4fv( p_uniforms.viewMatrix, false, camera._viewMatrixArray );
5096
5097 }
5098
5099 }
5100
5101 }
5102
5103 loadUniformsMatrices( p_uniforms, object );
5104
5105 if ( p_uniforms.modelMatrix !== null ) {
5106
5107 _gl.uniformMatrix4fv( p_uniforms.modelMatrix, false, object.matrixWorld.elements );
5108
5109 }
5110
5111 return program;
5112
5113 };
5114
5115 // Uniforms (refresh uniforms objects)
5116
5117 function refreshUniformsCommon ( uniforms, material ) {
5118
5119 uniforms.opacity.value = material.opacity;
5120
5121 if ( _this.gammaInput ) {
5122
5123 uniforms.diffuse.value.copyGammaToLinear( material.color );
5124
5125 } else {
5126
5127 uniforms.diffuse.value = material.color;
5128
5129 }
5130
5131 uniforms.map.value = material.map;
5132 uniforms.lightMap.value = material.lightMap;
5133 uniforms.specularMap.value = material.specularMap;
5134
5135 if ( material.bumpMap ) {
5136
5137 uniforms.bumpMap.value = material.bumpMap;
5138 uniforms.bumpScale.value = material.bumpScale;
5139
5140 }
5141
5142 if ( material.normalMap ) {
5143
5144 uniforms.normalMap.value = material.normalMap;
5145 uniforms.normalScale.value.copy( material.normalScale );
5146
5147 }
5148
5149 // uv repeat and offset setting priorities
5150 // 1. color map
5151 // 2. specular map
5152 // 3. normal map
5153 // 4. bump map
5154
5155 var uvScaleMap;
5156
5157 if ( material.map ) {
5158
5159 uvScaleMap = material.map;
5160
5161 } else if ( material.specularMap ) {
5162
5163 uvScaleMap = material.specularMap;
5164
5165 } else if ( material.normalMap ) {
5166
5167 uvScaleMap = material.normalMap;
5168
5169 } else if ( material.bumpMap ) {
5170
5171 uvScaleMap = material.bumpMap;
5172
5173 }
5174
5175 if ( uvScaleMap !== undefined ) {
5176
5177 var offset = uvScaleMap.offset;
5178 var repeat = uvScaleMap.repeat;
5179
5180 uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y );
5181
5182 }
5183
5184 uniforms.envMap.value = material.envMap;
5185 uniforms.flipEnvMap.value = ( material.envMap instanceof THREE.WebGLRenderTargetCube ) ? 1 : -1;
5186
5187 if ( _this.gammaInput ) {
5188
5189 //uniforms.reflectivity.value = material.reflectivity * material.reflectivity;
5190 uniforms.reflectivity.value = material.reflectivity;
5191
5192 } else {
5193
5194 uniforms.reflectivity.value = material.reflectivity;
5195
5196 }
5197
5198 uniforms.refractionRatio.value = material.refractionRatio;
5199 uniforms.combine.value = material.combine;
5200 uniforms.useRefract.value = material.envMap && material.envMap.mapping instanceof THREE.CubeRefractionMapping;
5201
5202 };
5203
5204 function refreshUniformsLine ( uniforms, material ) {
5205
5206 uniforms.diffuse.value = material.color;
5207 uniforms.opacity.value = material.opacity;
5208
5209 };
5210
5211 function refreshUniformsDash ( uniforms, material ) {
5212
5213 uniforms.dashSize.value = material.dashSize;
5214 uniforms.totalSize.value = material.dashSize + material.gapSize;
5215 uniforms.scale.value = material.scale;
5216
5217 };
5218
5219 function refreshUniformsParticle ( uniforms, material ) {
5220
5221 uniforms.psColor.value = material.color;
5222 uniforms.opacity.value = material.opacity;
5223 uniforms.size.value = material.size;
5224 uniforms.scale.value = _canvas.height / 2.0; // TODO: Cache this.
5225
5226 uniforms.map.value = material.map;
5227
5228 };
5229
5230 function refreshUniformsFog ( uniforms, fog ) {
5231
5232 uniforms.fogColor.value = fog.color;
5233
5234 if ( fog instanceof THREE.Fog ) {
5235
5236 uniforms.fogNear.value = fog.near;
5237 uniforms.fogFar.value = fog.far;
5238
5239 } else if ( fog instanceof THREE.FogExp2 ) {
5240
5241 uniforms.fogDensity.value = fog.density;
5242
5243 }
5244
5245 };
5246
5247 function refreshUniformsPhong ( uniforms, material ) {
5248
5249 uniforms.shininess.value = material.shininess;
5250
5251 if ( _this.gammaInput ) {
5252
5253 uniforms.ambient.value.copyGammaToLinear( material.ambient );
5254 uniforms.emissive.value.copyGammaToLinear( material.emissive );
5255 uniforms.specular.value.copyGammaToLinear( material.specular );
5256
5257 } else {
5258
5259 uniforms.ambient.value = material.ambient;
5260 uniforms.emissive.value = material.emissive;
5261 uniforms.specular.value = material.specular;
5262
5263 }
5264
5265 if ( material.wrapAround ) {
5266
5267 uniforms.wrapRGB.value.copy( material.wrapRGB );
5268
5269 }
5270
5271 };
5272
5273 function refreshUniformsLambert ( uniforms, material ) {
5274
5275 if ( _this.gammaInput ) {
5276
5277 uniforms.ambient.value.copyGammaToLinear( material.ambient );
5278 uniforms.emissive.value.copyGammaToLinear( material.emissive );
5279
5280 } else {
5281
5282 uniforms.ambient.value = material.ambient;
5283 uniforms.emissive.value = material.emissive;
5284
5285 }
5286
5287 if ( material.wrapAround ) {
5288
5289 uniforms.wrapRGB.value.copy( material.wrapRGB );
5290
5291 }
5292
5293 };
5294
5295 function refreshUniformsLights ( uniforms, lights ) {
5296
5297 uniforms.ambientLightColor.value = lights.ambient;
5298
5299 uniforms.directionalLightColor.value = lights.directional.colors;
5300 uniforms.directionalLightDirection.value = lights.directional.positions;
5301
5302 uniforms.pointLightColor.value = lights.point.colors;
5303 uniforms.pointLightPosition.value = lights.point.positions;
5304 uniforms.pointLightDistance.value = lights.point.distances;
5305
5306 uniforms.spotLightColor.value = lights.spot.colors;
5307 uniforms.spotLightPosition.value = lights.spot.positions;
5308 uniforms.spotLightDistance.value = lights.spot.distances;
5309 uniforms.spotLightDirection.value = lights.spot.directions;
5310 uniforms.spotLightAngleCos.value = lights.spot.anglesCos;
5311 uniforms.spotLightExponent.value = lights.spot.exponents;
5312
5313 uniforms.hemisphereLightSkyColor.value = lights.hemi.skyColors;
5314 uniforms.hemisphereLightGroundColor.value = lights.hemi.groundColors;
5315 uniforms.hemisphereLightDirection.value = lights.hemi.positions;
5316
5317 };
5318
5319 function refreshUniformsShadow ( uniforms, lights ) {
5320
5321 if ( uniforms.shadowMatrix ) {
5322
5323 var j = 0;
5324
5325 for ( var i = 0, il = lights.length; i < il; i ++ ) {
5326
5327 var light = lights[ i ];
5328
5329 if ( ! light.castShadow ) continue;
5330
5331 if ( light instanceof THREE.SpotLight || ( light instanceof THREE.DirectionalLight && ! light.shadowCascade ) ) {
5332
5333 uniforms.shadowMap.value[ j ] = light.shadowMap;
5334 uniforms.shadowMapSize.value[ j ] = light.shadowMapSize;
5335
5336 uniforms.shadowMatrix.value[ j ] = light.shadowMatrix;
5337
5338 uniforms.shadowDarkness.value[ j ] = light.shadowDarkness;
5339 uniforms.shadowBias.value[ j ] = light.shadowBias;
5340
5341 j ++;
5342
5343 }
5344
5345 }
5346
5347 }
5348
5349 };
5350
5351 // Uniforms (load to GPU)
5352
5353 function loadUniformsMatrices ( uniforms, object ) {
5354
5355 _gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, object._modelViewMatrix.elements );
5356
5357 if ( uniforms.normalMatrix ) {
5358
5359 _gl.uniformMatrix3fv( uniforms.normalMatrix, false, object._normalMatrix.elements );
5360
5361 }
5362
5363 };
5364
5365 function getTextureUnit() {
5366
5367 var textureUnit = _usedTextureUnits;
5368
5369 if ( textureUnit >= _maxTextures ) {
5370
5371 console.warn( "Trying to use " + textureUnit + " texture units while this GPU supports only " + _maxTextures );
5372
5373 }
5374
5375 _usedTextureUnits += 1;
5376
5377 return textureUnit;
5378
5379 };
5380
5381 function loadUniformsGeneric ( program, uniforms ) {
5382
5383 var uniform, value, type, location, texture, textureUnit, i, il, j, jl, offset;
5384
5385 for ( j = 0, jl = uniforms.length; j < jl; j ++ ) {
5386
5387 location = program.uniforms[ uniforms[ j ][ 1 ] ];
5388 if ( !location ) continue;
5389
5390 uniform = uniforms[ j ][ 0 ];
5391
5392 type = uniform.type;
5393 value = uniform.value;
5394
5395 if ( type === "i" ) { // single integer
5396
5397 _gl.uniform1i( location, value );
5398
5399 } else if ( type === "f" ) { // single float
5400
5401 _gl.uniform1f( location, value );
5402
5403 } else if ( type === "v2" ) { // single THREE.Vector2
5404
5405 _gl.uniform2f( location, value.x, value.y );
5406
5407 } else if ( type === "v3" ) { // single THREE.Vector3
5408
5409 _gl.uniform3f( location, value.x, value.y, value.z );
5410
5411 } else if ( type === "v4" ) { // single THREE.Vector4
5412
5413 _gl.uniform4f( location, value.x, value.y, value.z, value.w );
5414
5415 } else if ( type === "c" ) { // single THREE.Color
5416
5417 _gl.uniform3f( location, value.r, value.g, value.b );
5418
5419 } else if ( type === "iv1" ) { // flat array of integers (JS or typed array)
5420
5421 _gl.uniform1iv( location, value );
5422
5423 } else if ( type === "iv" ) { // flat array of integers with 3 x N size (JS or typed array)
5424
5425 _gl.uniform3iv( location, value );
5426
5427 } else if ( type === "fv1" ) { // flat array of floats (JS or typed array)
5428
5429 _gl.uniform1fv( location, value );
5430
5431 } else if ( type === "fv" ) { // flat array of floats with 3 x N size (JS or typed array)
5432
5433 _gl.uniform3fv( location, value );
5434
5435 } else if ( type === "v2v" ) { // array of THREE.Vector2
5436
5437 if ( uniform._array === undefined ) {
5438
5439 uniform._array = new Float32Array( 2 * value.length );
5440
5441 }
5442
5443 for ( i = 0, il = value.length; i < il; i ++ ) {
5444
5445 offset = i * 2;
5446
5447 uniform._array[ offset ] = value[ i ].x;
5448 uniform._array[ offset + 1 ] = value[ i ].y;
5449
5450 }
5451
5452 _gl.uniform2fv( location, uniform._array );
5453
5454 } else if ( type === "v3v" ) { // array of THREE.Vector3
5455
5456 if ( uniform._array === undefined ) {
5457
5458 uniform._array = new Float32Array( 3 * value.length );
5459
5460 }
5461
5462 for ( i = 0, il = value.length; i < il; i ++ ) {
5463
5464 offset = i * 3;
5465
5466 uniform._array[ offset ] = value[ i ].x;
5467 uniform._array[ offset + 1 ] = value[ i ].y;
5468 uniform._array[ offset + 2 ] = value[ i ].z;
5469
5470 }
5471
5472 _gl.uniform3fv( location, uniform._array );
5473
5474 } else if ( type === "v4v" ) { // array of THREE.Vector4
5475
5476 if ( uniform._array === undefined ) {
5477
5478 uniform._array = new Float32Array( 4 * value.length );
5479
5480 }
5481
5482 for ( i = 0, il = value.length; i < il; i ++ ) {
5483
5484 offset = i * 4;
5485
5486 uniform._array[ offset ] = value[ i ].x;
5487 uniform._array[ offset + 1 ] = value[ i ].y;
5488 uniform._array[ offset + 2 ] = value[ i ].z;
5489 uniform._array[ offset + 3 ] = value[ i ].w;
5490
5491 }
5492
5493 _gl.uniform4fv( location, uniform._array );
5494
5495 } else if ( type === "m4") { // single THREE.Matrix4
5496
5497 if ( uniform._array === undefined ) {
5498
5499 uniform._array = new Float32Array( 16 );
5500
5501 }
5502
5503 value.flattenToArray( uniform._array );
5504 _gl.uniformMatrix4fv( location, false, uniform._array );
5505
5506 } else if ( type === "m4v" ) { // array of THREE.Matrix4
5507
5508 if ( uniform._array === undefined ) {
5509
5510 uniform._array = new Float32Array( 16 * value.length );
5511
5512 }
5513
5514 for ( i = 0, il = value.length; i < il; i ++ ) {
5515
5516 value[ i ].flattenToArrayOffset( uniform._array, i * 16 );
5517
5518 }
5519
5520 _gl.uniformMatrix4fv( location, false, uniform._array );
5521
5522 } else if ( type === "t" ) { // single THREE.Texture (2d or cube)
5523
5524 texture = value;
5525 textureUnit = getTextureUnit();
5526
5527 _gl.uniform1i( location, textureUnit );
5528
5529 if ( !texture ) continue;
5530
5531 if ( texture.image instanceof Array && texture.image.length === 6 ) {
5532
5533 setCubeTexture( texture, textureUnit );
5534
5535 } else if ( texture instanceof THREE.WebGLRenderTargetCube ) {
5536
5537 setCubeTextureDynamic( texture, textureUnit );
5538
5539 } else {
5540
5541 _this.setTexture( texture, textureUnit );
5542
5543 }
5544
5545 } else if ( type === "tv" ) { // array of THREE.Texture (2d)
5546
5547 if ( uniform._array === undefined ) {
5548
5549 uniform._array = [];
5550
5551 }
5552
5553 for( i = 0, il = uniform.value.length; i < il; i ++ ) {
5554
5555 uniform._array[ i ] = getTextureUnit();
5556
5557 }
5558
5559 _gl.uniform1iv( location, uniform._array );
5560
5561 for( i = 0, il = uniform.value.length; i < il; i ++ ) {
5562
5563 texture = uniform.value[ i ];
5564 textureUnit = uniform._array[ i ];
5565
5566 if ( !texture ) continue;
5567
5568 _this.setTexture( texture, textureUnit );
5569
5570 }
5571
5572 }
5573
5574 }
5575
5576 };
5577
5578 function setupMatrices ( object, camera ) {
5579
5580 object._modelViewMatrix.multiply( camera.matrixWorldInverse, object.matrixWorld );
5581
5582 object._normalMatrix.getInverse( object._modelViewMatrix );
5583 object._normalMatrix.transpose();
5584
5585 };
5586
5587 //
5588
5589 function setColorGamma( array, offset, color, intensitySq ) {
5590
5591 array[ offset ] = color.r * color.r * intensitySq;
5592 array[ offset + 1 ] = color.g * color.g * intensitySq;
5593 array[ offset + 2 ] = color.b * color.b * intensitySq;
5594
5595 };
5596
5597 function setColorLinear( array, offset, color, intensity ) {
5598
5599 array[ offset ] = color.r * intensity;
5600 array[ offset + 1 ] = color.g * intensity;
5601 array[ offset + 2 ] = color.b * intensity;
5602
5603 };
5604
5605 function setupLights ( program, lights ) {
5606
5607 var l, ll, light, n,
5608 r = 0, g = 0, b = 0,
5609 color, skyColor, groundColor,
5610 intensity, intensitySq,
5611 position,
5612 distance,
5613
5614 zlights = _lights,
5615
5616 dirColors = zlights.directional.colors,
5617 dirPositions = zlights.directional.positions,
5618
5619 pointColors = zlights.point.colors,
5620 pointPositions = zlights.point.positions,
5621 pointDistances = zlights.point.distances,
5622
5623 spotColors = zlights.spot.colors,
5624 spotPositions = zlights.spot.positions,
5625 spotDistances = zlights.spot.distances,
5626 spotDirections = zlights.spot.directions,
5627 spotAnglesCos = zlights.spot.anglesCos,
5628 spotExponents = zlights.spot.exponents,
5629
5630 hemiSkyColors = zlights.hemi.skyColors,
5631 hemiGroundColors = zlights.hemi.groundColors,
5632 hemiPositions = zlights.hemi.positions,
5633
5634 dirLength = 0,
5635 pointLength = 0,
5636 spotLength = 0,
5637 hemiLength = 0,
5638
5639 dirCount = 0,
5640 pointCount = 0,
5641 spotCount = 0,
5642 hemiCount = 0,
5643
5644 dirOffset = 0,
5645 pointOffset = 0,
5646 spotOffset = 0,
5647 hemiOffset = 0;
5648
5649 for ( l = 0, ll = lights.length; l < ll; l ++ ) {
5650
5651 light = lights[ l ];
5652
5653 if ( light.onlyShadow ) continue;
5654
5655 color = light.color;
5656 intensity = light.intensity;
5657 distance = light.distance;
5658
5659 if ( light instanceof THREE.AmbientLight ) {
5660
5661 if ( ! light.visible ) continue;
5662
5663 if ( _this.gammaInput ) {
5664
5665 r += color.r * color.r;
5666 g += color.g * color.g;
5667 b += color.b * color.b;
5668
5669 } else {
5670
5671 r += color.r;
5672 g += color.g;
5673 b += color.b;
5674
5675 }
5676
5677 } else if ( light instanceof THREE.DirectionalLight ) {
5678
5679 dirCount += 1;
5680
5681 if ( ! light.visible ) continue;
5682
5683 dirOffset = dirLength * 3;
5684
5685 if ( _this.gammaInput ) {
5686
5687 setColorGamma( dirColors, dirOffset, color, intensity * intensity );
5688
5689 } else {
5690
5691 setColorLinear( dirColors, dirOffset, color, intensity );
5692
5693 }
5694
5695 _direction.copy( light.matrixWorld.getPosition() );
5696 _direction.subSelf( light.target.matrixWorld.getPosition() );
5697 _direction.normalize();
5698
5699 dirPositions[ dirOffset ] = _direction.x;
5700 dirPositions[ dirOffset + 1 ] = _direction.y;
5701 dirPositions[ dirOffset + 2 ] = _direction.z;
5702
5703 dirLength += 1;
5704
5705 } else if ( light instanceof THREE.PointLight ) {
5706
5707 pointCount += 1;
5708
5709 if ( ! light.visible ) continue;
5710
5711 pointOffset = pointLength * 3;
5712
5713 if ( _this.gammaInput ) {
5714
5715 setColorGamma( pointColors, pointOffset, color, intensity * intensity );
5716
5717 } else {
5718
5719 setColorLinear( pointColors, pointOffset, color, intensity );
5720
5721 }
5722
5723 position = light.matrixWorld.getPosition();
5724
5725 pointPositions[ pointOffset ] = position.x;
5726 pointPositions[ pointOffset + 1 ] = position.y;
5727 pointPositions[ pointOffset + 2 ] = position.z;
5728
5729 pointDistances[ pointLength ] = distance;
5730
5731 pointLength += 1;
5732
5733 } else if ( light instanceof THREE.SpotLight ) {
5734
5735 spotCount += 1;
5736
5737 if ( ! light.visible ) continue;
5738
5739 spotOffset = spotLength * 3;
5740
5741 if ( _this.gammaInput ) {
5742
5743 setColorGamma( spotColors, spotOffset, color, intensity * intensity );
5744
5745 } else {
5746
5747 setColorLinear( spotColors, spotOffset, color, intensity );
5748
5749 }
5750
5751 position = light.matrixWorld.getPosition();
5752
5753 spotPositions[ spotOffset ] = position.x;
5754 spotPositions[ spotOffset + 1 ] = position.y;
5755 spotPositions[ spotOffset + 2 ] = position.z;
5756
5757 spotDistances[ spotLength ] = distance;
5758
5759 _direction.copy( position );
5760 _direction.subSelf( light.target.matrixWorld.getPosition() );
5761 _direction.normalize();
5762
5763 spotDirections[ spotOffset ] = _direction.x;
5764 spotDirections[ spotOffset + 1 ] = _direction.y;
5765 spotDirections[ spotOffset + 2 ] = _direction.z;
5766
5767 spotAnglesCos[ spotLength ] = Math.cos( light.angle );
5768 spotExponents[ spotLength ] = light.exponent;
5769
5770 spotLength += 1;
5771
5772 } else if ( light instanceof THREE.HemisphereLight ) {
5773
5774 hemiCount += 1;
5775
5776 if ( ! light.visible ) continue;
5777
5778 skyColor = light.color;
5779 groundColor = light.groundColor;
5780
5781 hemiOffset = hemiLength * 3;
5782
5783 if ( _this.gammaInput ) {
5784
5785 intensitySq = intensity * intensity;
5786
5787 setColorGamma( hemiSkyColors, hemiOffset, skyColor, intensitySq );
5788 setColorGamma( hemiGroundColors, hemiOffset, groundColor, intensitySq );
5789
5790 } else {
5791
5792 setColorLinear( hemiSkyColors, hemiOffset, skyColor, intensity );
5793 setColorLinear( hemiGroundColors, hemiOffset, groundColor, intensity );
5794
5795 }
5796
5797 _direction.copy( light.matrixWorld.getPosition() );
5798 _direction.normalize();
5799
5800 hemiPositions[ hemiOffset ] = _direction.x;
5801 hemiPositions[ hemiOffset + 1 ] = _direction.y;
5802 hemiPositions[ hemiOffset + 2 ] = _direction.z;
5803
5804 hemiLength += 1;
5805
5806 }
5807
5808 }
5809
5810 // null eventual remains from removed lights
5811 // (this is to avoid if in shader)
5812
5813 for ( l = dirLength * 3, ll = Math.max( dirColors.length, dirCount * 3 ); l < ll; l ++ ) dirColors[ l ] = 0.0;
5814 for ( l = dirLength * 3, ll = Math.max( dirPositions.length, dirCount * 3 ); l < ll; l ++ ) dirPositions[ l ] = 0.0;
5815
5816 for ( l = pointLength * 3, ll = Math.max( pointColors.length, pointCount * 3 ); l < ll; l ++ ) pointColors[ l ] = 0.0;
5817 for ( l = pointLength * 3, ll = Math.max( pointPositions.length, pointCount * 3 ); l < ll; l ++ ) pointPositions[ l ] = 0.0;
5818 for ( l = pointLength, ll = Math.max( pointDistances.length, pointCount ); l < ll; l ++ ) pointDistances[ l ] = 0.0;
5819
5820 for ( l = spotLength * 3, ll = Math.max( spotColors.length, spotCount * 3 ); l < ll; l ++ ) spotColors[ l ] = 0.0;
5821 for ( l = spotLength * 3, ll = Math.max( spotPositions.length, spotCount * 3 ); l < ll; l ++ ) spotPositions[ l ] = 0.0;
5822 for ( l = spotLength * 3, ll = Math.max( spotDirections.length, spotCount * 3 ); l < ll; l ++ ) spotDirections[ l ] = 0.0;
5823 for ( l = spotLength, ll = Math.max( spotAnglesCos.length, spotCount ); l < ll; l ++ ) spotAnglesCos[ l ] = 0.0;
5824 for ( l = spotLength, ll = Math.max( spotExponents.length, spotCount ); l < ll; l ++ ) spotExponents[ l ] = 0.0;
5825 for ( l = spotLength, ll = Math.max( spotDistances.length, spotCount ); l < ll; l ++ ) spotDistances[ l ] = 0.0;
5826
5827 for ( l = hemiLength * 3, ll = Math.max( hemiSkyColors.length, hemiCount * 3 ); l < ll; l ++ ) hemiSkyColors[ l ] = 0.0;
5828 for ( l = hemiLength * 3, ll = Math.max( hemiGroundColors.length, hemiCount * 3 ); l < ll; l ++ ) hemiGroundColors[ l ] = 0.0;
5829 for ( l = hemiLength * 3, ll = Math.max( hemiPositions.length, hemiCount * 3 ); l < ll; l ++ ) hemiPositions[ l ] = 0.0;
5830
5831 zlights.directional.length = dirLength;
5832 zlights.point.length = pointLength;
5833 zlights.spot.length = spotLength;
5834 zlights.hemi.length = hemiLength;
5835
5836 zlights.ambient[ 0 ] = r;
5837 zlights.ambient[ 1 ] = g;
5838 zlights.ambient[ 2 ] = b;
5839
5840 };
5841
5842 // GL state setting
5843
5844 this.setFaceCulling = function ( cullFace, frontFace ) {
5845
5846 if ( cullFace ) {
5847
5848 if ( !frontFace || frontFace === "ccw" ) {
5849
5850 _gl.frontFace( _gl.CCW );
5851
5852 } else {
5853
5854 _gl.frontFace( _gl.CW );
5855
5856 }
5857
5858 if( cullFace === "back" ) {
5859
5860 _gl.cullFace( _gl.BACK );
5861
5862 } else if( cullFace === "front" ) {
5863
5864 _gl.cullFace( _gl.FRONT );
5865
5866 } else {
5867
5868 _gl.cullFace( _gl.FRONT_AND_BACK );
5869
5870 }
5871
5872 _gl.enable( _gl.CULL_FACE );
5873
5874 } else {
5875
5876 _gl.disable( _gl.CULL_FACE );
5877
5878 }
5879
5880 };
5881
5882 this.setMaterialFaces = function ( material ) {
5883
5884 var doubleSided = material.side === THREE.DoubleSide;
5885 var flipSided = material.side === THREE.BackSide;
5886
5887 if ( _oldDoubleSided !== doubleSided ) {
5888
5889 if ( doubleSided ) {
5890
5891 _gl.disable( _gl.CULL_FACE );
5892
5893 } else {
5894
5895 _gl.enable( _gl.CULL_FACE );
5896
5897 }
5898
5899 _oldDoubleSided = doubleSided;
5900
5901 }
5902
5903 if ( _oldFlipSided !== flipSided ) {
5904
5905 if ( flipSided ) {
5906
5907 _gl.frontFace( _gl.CW );
5908
5909 } else {
5910
5911 _gl.frontFace( _gl.CCW );
5912
5913 }
5914
5915 _oldFlipSided = flipSided;
5916
5917 }
5918
5919 };
5920
5921 this.setDepthTest = function ( depthTest ) {
5922
5923 if ( _oldDepthTest !== depthTest ) {
5924
5925 if ( depthTest ) {
5926
5927 _gl.enable( _gl.DEPTH_TEST );
5928
5929 } else {
5930
5931 _gl.disable( _gl.DEPTH_TEST );
5932
5933 }
5934
5935 _oldDepthTest = depthTest;
5936
5937 }
5938
5939 };
5940
5941 this.setDepthWrite = function ( depthWrite ) {
5942
5943 if ( _oldDepthWrite !== depthWrite ) {
5944
5945 _gl.depthMask( depthWrite );
5946 _oldDepthWrite = depthWrite;
5947
5948 }
5949
5950 };
5951
5952 function setLineWidth ( width ) {
5953
5954 if ( width !== _oldLineWidth ) {
5955
5956 _gl.lineWidth( width );
5957
5958 _oldLineWidth = width;
5959
5960 }
5961
5962 };
5963
5964 function setPolygonOffset ( polygonoffset, factor, units ) {
5965
5966 if ( _oldPolygonOffset !== polygonoffset ) {
5967
5968 if ( polygonoffset ) {
5969
5970 _gl.enable( _gl.POLYGON_OFFSET_FILL );
5971
5972 } else {
5973
5974 _gl.disable( _gl.POLYGON_OFFSET_FILL );
5975
5976 }
5977
5978 _oldPolygonOffset = polygonoffset;
5979
5980 }
5981
5982 if ( polygonoffset && ( _oldPolygonOffsetFactor !== factor || _oldPolygonOffsetUnits !== units ) ) {
5983
5984 _gl.polygonOffset( factor, units );
5985
5986 _oldPolygonOffsetFactor = factor;
5987 _oldPolygonOffsetUnits = units;
5988
5989 }
5990
5991 };
5992
5993 this.setBlending = function ( blending, blendEquation, blendSrc, blendDst ) {
5994
5995 if ( blending !== _oldBlending ) {
5996
5997 if ( blending === THREE.NoBlending ) {
5998
5999 _gl.disable( _gl.BLEND );
6000
6001 } else if ( blending === THREE.AdditiveBlending ) {
6002
6003 _gl.enable( _gl.BLEND );
6004 _gl.blendEquation( _gl.FUNC_ADD );
6005 _gl.blendFunc( _gl.SRC_ALPHA, _gl.ONE );
6006
6007 } else if ( blending === THREE.SubtractiveBlending ) {
6008
6009 // TODO: Find blendFuncSeparate() combination
6010 _gl.enable( _gl.BLEND );
6011 _gl.blendEquation( _gl.FUNC_ADD );
6012 _gl.blendFunc( _gl.ZERO, _gl.ONE_MINUS_SRC_COLOR );
6013
6014 } else if ( blending === THREE.MultiplyBlending ) {
6015
6016 // TODO: Find blendFuncSeparate() combination
6017 _gl.enable( _gl.BLEND );
6018 _gl.blendEquation( _gl.FUNC_ADD );
6019 _gl.blendFunc( _gl.ZERO, _gl.SRC_COLOR );
6020
6021 } else if ( blending === THREE.CustomBlending ) {
6022
6023 _gl.enable( _gl.BLEND );
6024
6025 } else {
6026
6027 _gl.enable( _gl.BLEND );
6028 _gl.blendEquationSeparate( _gl.FUNC_ADD, _gl.FUNC_ADD );
6029 _gl.blendFuncSeparate( _gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA, _gl.ONE, _gl.ONE_MINUS_SRC_ALPHA );
6030
6031 }
6032
6033 _oldBlending = blending;
6034
6035 }
6036
6037 if ( blending === THREE.CustomBlending ) {
6038
6039 if ( blendEquation !== _oldBlendEquation ) {
6040
6041 _gl.blendEquation( paramThreeToGL( blendEquation ) );
6042
6043 _oldBlendEquation = blendEquation;
6044
6045 }
6046
6047 if ( blendSrc !== _oldBlendSrc || blendDst !== _oldBlendDst ) {
6048
6049 _gl.blendFunc( paramThreeToGL( blendSrc ), paramThreeToGL( blendDst ) );
6050
6051 _oldBlendSrc = blendSrc;
6052 _oldBlendDst = blendDst;
6053
6054 }
6055
6056 } else {
6057
6058 _oldBlendEquation = null;
6059 _oldBlendSrc = null;
6060 _oldBlendDst = null;
6061
6062 }
6063
6064 };
6065
6066 // Defines
6067
6068 function generateDefines ( defines ) {
6069
6070 var value, chunk, chunks = [];
6071
6072 for ( var d in defines ) {
6073
6074 value = defines[ d ];
6075 if ( value === false ) continue;
6076
6077 chunk = "#define " + d + " " + value;
6078 chunks.push( chunk );
6079
6080 }
6081
6082 return chunks.join( "\n" );
6083
6084 };
6085
6086 // Shaders
6087
6088 function buildProgram ( shaderID, fragmentShader, vertexShader, uniforms, attributes, defines, parameters ) {
6089
6090 var p, pl, d, program, code;
6091 var chunks = [];
6092
6093 // Generate code
6094
6095 if ( shaderID ) {
6096
6097 chunks.push( shaderID );
6098
6099 } else {
6100
6101 chunks.push( fragmentShader );
6102 chunks.push( vertexShader );
6103
6104 }
6105
6106 for ( d in defines ) {
6107
6108 chunks.push( d );
6109 chunks.push( defines[ d ] );
6110
6111 }
6112
6113 for ( p in parameters ) {
6114
6115 chunks.push( p );
6116 chunks.push( parameters[ p ] );
6117
6118 }
6119
6120 code = chunks.join();
6121
6122 // Check if code has been already compiled
6123
6124 for ( p = 0, pl = _programs.length; p < pl; p ++ ) {
6125
6126 var programInfo = _programs[ p ];
6127
6128 if ( programInfo.code === code ) {
6129
6130 //console.log( "Code already compiled." /*: \n\n" + code*/ );
6131
6132 programInfo.usedTimes ++;
6133
6134 return programInfo.program;
6135
6136 }
6137
6138 }
6139
6140 //console.log( "building new program " );
6141
6142 //
6143
6144 var customDefines = generateDefines( defines );
6145
6146 //
6147
6148 program = _gl.createProgram();
6149
6150 var prefix_vertex = [
6151
6152 "precision " + _precision + " float;",
6153
6154 customDefines,
6155
6156 _supportsVertexTextures ? "#define VERTEX_TEXTURES" : "",
6157
6158 _this.gammaInput ? "#define GAMMA_INPUT" : "",
6159 _this.gammaOutput ? "#define GAMMA_OUTPUT" : "",
6160 _this.physicallyBasedShading ? "#define PHYSICALLY_BASED_SHADING" : "",
6161
6162 "#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
6163 "#define MAX_POINT_LIGHTS " + parameters.maxPointLights,
6164 "#define MAX_SPOT_LIGHTS " + parameters.maxSpotLights,
6165 "#define MAX_HEMI_LIGHTS " + parameters.maxHemiLights,
6166
6167 "#define MAX_SHADOWS " + parameters.maxShadows,
6168
6169 "#define MAX_BONES " + parameters.maxBones,
6170
6171 parameters.map ? "#define USE_MAP" : "",
6172 parameters.envMap ? "#define USE_ENVMAP" : "",
6173 parameters.lightMap ? "#define USE_LIGHTMAP" : "",
6174 parameters.bumpMap ? "#define USE_BUMPMAP" : "",
6175 parameters.normalMap ? "#define USE_NORMALMAP" : "",
6176 parameters.specularMap ? "#define USE_SPECULARMAP" : "",
6177 parameters.vertexColors ? "#define USE_COLOR" : "",
6178
6179 parameters.skinning ? "#define USE_SKINNING" : "",
6180 parameters.useVertexTexture ? "#define BONE_TEXTURE" : "",
6181 parameters.boneTextureWidth ? "#define N_BONE_PIXEL_X " + parameters.boneTextureWidth.toFixed( 1 ) : "",
6182 parameters.boneTextureHeight ? "#define N_BONE_PIXEL_Y " + parameters.boneTextureHeight.toFixed( 1 ) : "",
6183
6184 parameters.morphTargets ? "#define USE_MORPHTARGETS" : "",
6185 parameters.morphNormals ? "#define USE_MORPHNORMALS" : "",
6186 parameters.perPixel ? "#define PHONG_PER_PIXEL" : "",
6187 parameters.wrapAround ? "#define WRAP_AROUND" : "",
6188 parameters.doubleSided ? "#define DOUBLE_SIDED" : "",
6189 parameters.flipSided ? "#define FLIP_SIDED" : "",
6190
6191 parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
6192 parameters.shadowMapSoft ? "#define SHADOWMAP_SOFT" : "",
6193 parameters.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "",
6194 parameters.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "",
6195
6196 parameters.sizeAttenuation ? "#define USE_SIZEATTENUATION" : "",
6197
6198 "uniform mat4 modelMatrix;",
6199 "uniform mat4 modelViewMatrix;",
6200 "uniform mat4 projectionMatrix;",
6201 "uniform mat4 viewMatrix;",
6202 "uniform mat3 normalMatrix;",
6203 "uniform vec3 cameraPosition;",
6204
6205 "attribute vec3 position;",
6206 "attribute vec3 normal;",
6207 "attribute vec2 uv;",
6208 "attribute vec2 uv2;",
6209
6210 "#ifdef USE_COLOR",
6211
6212 "attribute vec3 color;",
6213
6214 "#endif",
6215
6216 "#ifdef USE_MORPHTARGETS",
6217
6218 "attribute vec3 morphTarget0;",
6219 "attribute vec3 morphTarget1;",
6220 "attribute vec3 morphTarget2;",
6221 "attribute vec3 morphTarget3;",
6222
6223 "#ifdef USE_MORPHNORMALS",
6224
6225 "attribute vec3 morphNormal0;",
6226 "attribute vec3 morphNormal1;",
6227 "attribute vec3 morphNormal2;",
6228 "attribute vec3 morphNormal3;",
6229
6230 "#else",
6231
6232 "attribute vec3 morphTarget4;",
6233 "attribute vec3 morphTarget5;",
6234 "attribute vec3 morphTarget6;",
6235 "attribute vec3 morphTarget7;",
6236
6237 "#endif",
6238
6239 "#endif",
6240
6241 "#ifdef USE_SKINNING",
6242
6243 "attribute vec4 skinIndex;",
6244 "attribute vec4 skinWeight;",
6245
6246 "#endif",
6247
6248 ""
6249
6250 ].join("\n");
6251
6252 var prefix_fragment = [
6253
6254 "precision " + _precision + " float;",
6255
6256 ( parameters.bumpMap || parameters.normalMap ) ? "#extension GL_OES_standard_derivatives : enable" : "",
6257
6258 customDefines,
6259
6260 "#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
6261 "#define MAX_POINT_LIGHTS " + parameters.maxPointLights,
6262 "#define MAX_SPOT_LIGHTS " + parameters.maxSpotLights,
6263 "#define MAX_HEMI_LIGHTS " + parameters.maxHemiLights,
6264
6265 "#define MAX_SHADOWS " + parameters.maxShadows,
6266
6267 parameters.alphaTest ? "#define ALPHATEST " + parameters.alphaTest: "",
6268
6269 _this.gammaInput ? "#define GAMMA_INPUT" : "",
6270 _this.gammaOutput ? "#define GAMMA_OUTPUT" : "",
6271 _this.physicallyBasedShading ? "#define PHYSICALLY_BASED_SHADING" : "",
6272
6273 ( parameters.useFog && parameters.fog ) ? "#define USE_FOG" : "",
6274 ( parameters.useFog && parameters.fogExp ) ? "#define FOG_EXP2" : "",
6275
6276 parameters.map ? "#define USE_MAP" : "",
6277 parameters.envMap ? "#define USE_ENVMAP" : "",
6278 parameters.lightMap ? "#define USE_LIGHTMAP" : "",
6279 parameters.bumpMap ? "#define USE_BUMPMAP" : "",
6280 parameters.normalMap ? "#define USE_NORMALMAP" : "",
6281 parameters.specularMap ? "#define USE_SPECULARMAP" : "",
6282 parameters.vertexColors ? "#define USE_COLOR" : "",
6283
6284 parameters.metal ? "#define METAL" : "",
6285 parameters.perPixel ? "#define PHONG_PER_PIXEL" : "",
6286 parameters.wrapAround ? "#define WRAP_AROUND" : "",
6287 parameters.doubleSided ? "#define DOUBLE_SIDED" : "",
6288 parameters.flipSided ? "#define FLIP_SIDED" : "",
6289
6290 parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
6291 parameters.shadowMapSoft ? "#define SHADOWMAP_SOFT" : "",
6292 parameters.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "",
6293 parameters.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "",
6294
6295 "uniform mat4 viewMatrix;",
6296 "uniform vec3 cameraPosition;",
6297 ""
6298
6299 ].join("\n");
6300
6301 var glFragmentShader = getShader( "fragment", prefix_fragment + fragmentShader );
6302 var glVertexShader = getShader( "vertex", prefix_vertex + vertexShader );
6303
6304 _gl.attachShader( program, glVertexShader );
6305 _gl.attachShader( program, glFragmentShader );
6306
6307 _gl.linkProgram( program );
6308
6309 if ( !_gl.getProgramParameter( program, _gl.LINK_STATUS ) ) {
6310
6311 console.error( "Could not initialise shader\n" + "VALIDATE_STATUS: " + _gl.getProgramParameter( program, _gl.VALIDATE_STATUS ) + ", gl error [" + _gl.getError() + "]" );
6312
6313 }
6314
6315 // clean up
6316
6317 _gl.deleteShader( glFragmentShader );
6318 _gl.deleteShader( glVertexShader );
6319
6320 //console.log( prefix_fragment + fragmentShader );
6321 //console.log( prefix_vertex + vertexShader );
6322
6323 program.uniforms = {};
6324 program.attributes = {};
6325
6326 var identifiers, u, a, i;
6327
6328 // cache uniform locations
6329
6330 identifiers = [
6331
6332 'viewMatrix', 'modelViewMatrix', 'projectionMatrix', 'normalMatrix', 'modelMatrix', 'cameraPosition',
6333 'morphTargetInfluences'
6334
6335 ];
6336
6337 if ( parameters.useVertexTexture ) {
6338
6339 identifiers.push( 'boneTexture' );
6340
6341 } else {
6342
6343 identifiers.push( 'boneGlobalMatrices' );
6344
6345 }
6346
6347 for ( u in uniforms ) {
6348
6349 identifiers.push( u );
6350
6351 }
6352
6353 cacheUniformLocations( program, identifiers );
6354
6355 // cache attributes locations
6356
6357 identifiers = [
6358
6359 "position", "normal", "uv", "uv2", "tangent", "color",
6360 "skinIndex", "skinWeight", "lineDistance"
6361
6362 ];
6363
6364 for ( i = 0; i < parameters.maxMorphTargets; i ++ ) {
6365
6366 identifiers.push( "morphTarget" + i );
6367
6368 }
6369
6370 for ( i = 0; i < parameters.maxMorphNormals; i ++ ) {
6371
6372 identifiers.push( "morphNormal" + i );
6373
6374 }
6375
6376 for ( a in attributes ) {
6377
6378 identifiers.push( a );
6379
6380 }
6381
6382 cacheAttributeLocations( program, identifiers );
6383
6384 program.id = _programs_counter ++;
6385
6386 _programs.push( { program: program, code: code, usedTimes: 1 } );
6387
6388 _this.info.memory.programs = _programs.length;
6389
6390 return program;
6391
6392 };
6393
6394 // Shader parameters cache
6395
6396 function cacheUniformLocations ( program, identifiers ) {
6397
6398 var i, l, id;
6399
6400 for( i = 0, l = identifiers.length; i < l; i ++ ) {
6401
6402 id = identifiers[ i ];
6403 program.uniforms[ id ] = _gl.getUniformLocation( program, id );
6404
6405 }
6406
6407 };
6408
6409 function cacheAttributeLocations ( program, identifiers ) {
6410
6411 var i, l, id;
6412
6413 for( i = 0, l = identifiers.length; i < l; i ++ ) {
6414
6415 id = identifiers[ i ];
6416 program.attributes[ id ] = _gl.getAttribLocation( program, id );
6417
6418 }
6419
6420 };
6421
6422 function addLineNumbers ( string ) {
6423
6424 var chunks = string.split( "\n" );
6425
6426 for ( var i = 0, il = chunks.length; i < il; i ++ ) {
6427
6428 // Chrome reports shader errors on lines
6429 // starting counting from 1
6430
6431 chunks[ i ] = ( i + 1 ) + ": " + chunks[ i ];
6432
6433 }
6434
6435 return chunks.join( "\n" );
6436
6437 };
6438
6439 function getShader ( type, string ) {
6440
6441 var shader;
6442
6443 if ( type === "fragment" ) {
6444
6445 shader = _gl.createShader( _gl.FRAGMENT_SHADER );
6446
6447 } else if ( type === "vertex" ) {
6448
6449 shader = _gl.createShader( _gl.VERTEX_SHADER );
6450
6451 }
6452
6453 _gl.shaderSource( shader, string );
6454 _gl.compileShader( shader );
6455
6456 if ( !_gl.getShaderParameter( shader, _gl.COMPILE_STATUS ) ) {
6457
6458 console.error( _gl.getShaderInfoLog( shader ) );
6459 console.error( addLineNumbers( string ) );
6460 return null;
6461
6462 }
6463
6464 return shader;
6465
6466 };
6467
6468 // Textures
6469
6470
6471 function isPowerOfTwo ( value ) {
6472
6473 return ( value & ( value - 1 ) ) === 0;
6474
6475 };
6476
6477 function setTextureParameters ( textureType, texture, isImagePowerOfTwo ) {
6478
6479 if ( isImagePowerOfTwo ) {
6480
6481 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, paramThreeToGL( texture.wrapS ) );
6482 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, paramThreeToGL( texture.wrapT ) );
6483
6484 _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, paramThreeToGL( texture.magFilter ) );
6485 _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, paramThreeToGL( texture.minFilter ) );
6486
6487 } else {
6488
6489 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
6490 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
6491
6492 _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) );
6493 _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) );
6494
6495 }
6496
6497 if ( _glExtensionTextureFilterAnisotropic && texture.type !== THREE.FloatType ) {
6498
6499 if ( texture.anisotropy > 1 || texture.__oldAnisotropy ) {
6500
6501 _gl.texParameterf( textureType, _glExtensionTextureFilterAnisotropic.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, _maxAnisotropy ) );
6502 texture.__oldAnisotropy = texture.anisotropy;
6503
6504 }
6505
6506 }
6507
6508 };
6509
6510 this.setTexture = function ( texture, slot ) {
6511
6512 if ( texture.needsUpdate ) {
6513
6514 if ( ! texture.__webglInit ) {
6515
6516 texture.__webglInit = true;
6517 texture.__webglTexture = _gl.createTexture();
6518
6519 _this.info.memory.textures ++;
6520
6521 }
6522
6523 _gl.activeTexture( _gl.TEXTURE0 + slot );
6524 _gl.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture );
6525
6526 _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
6527 _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
6528
6529 var image = texture.image,
6530 isImagePowerOfTwo = isPowerOfTwo( image.width ) && isPowerOfTwo( image.height ),
6531 glFormat = paramThreeToGL( texture.format ),
6532 glType = paramThreeToGL( texture.type );
6533
6534 setTextureParameters( _gl.TEXTURE_2D, texture, isImagePowerOfTwo );
6535
6536 if ( texture instanceof THREE.CompressedTexture ) {
6537
6538 var mipmap, mipmaps = texture.mipmaps;
6539
6540 for( var i = 0, il = mipmaps.length; i < il; i ++ ) {
6541
6542 mipmap = mipmaps[ i ];
6543 _gl.compressedTexImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
6544
6545 }
6546
6547 } else if ( texture instanceof THREE.DataTexture ) {
6548
6549 _gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data );
6550
6551 } else {
6552
6553 _gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, texture.image );
6554
6555 }
6556
6557 if ( texture.generateMipmaps && isImagePowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );
6558
6559 texture.needsUpdate = false;
6560
6561 if ( texture.onUpdate ) texture.onUpdate();
6562
6563 } else {
6564
6565 _gl.activeTexture( _gl.TEXTURE0 + slot );
6566 _gl.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture );
6567
6568 }
6569
6570 };
6571
6572 function clampToMaxSize ( image, maxSize ) {
6573
6574 if ( image.width <= maxSize && image.height <= maxSize ) {
6575
6576 return image;
6577
6578 }
6579
6580 // Warning: Scaling through the canvas will only work with images that use
6581 // premultiplied alpha.
6582
6583 var maxDimension = Math.max( image.width, image.height );
6584 var newWidth = Math.floor( image.width * maxSize / maxDimension );
6585 var newHeight = Math.floor( image.height * maxSize / maxDimension );
6586
6587 var canvas = document.createElement( 'canvas' );
6588 canvas.width = newWidth;
6589 canvas.height = newHeight;
6590
6591 var ctx = canvas.getContext( "2d" );
6592 ctx.drawImage( image, 0, 0, image.width, image.height, 0, 0, newWidth, newHeight );
6593
6594 return canvas;
6595
6596 }
6597
6598 function setCubeTexture ( texture, slot ) {
6599
6600 if ( texture.image.length === 6 ) {
6601
6602 if ( texture.needsUpdate ) {
6603
6604 if ( ! texture.image.__webglTextureCube ) {
6605
6606 texture.image.__webglTextureCube = _gl.createTexture();
6607
6608 }
6609
6610 _gl.activeTexture( _gl.TEXTURE0 + slot );
6611 _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube );
6612
6613 _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
6614
6615 var isCompressed = texture instanceof THREE.CompressedTexture;
6616
6617 var cubeImage = [];
6618
6619 for ( var i = 0; i < 6; i ++ ) {
6620
6621 if ( _this.autoScaleCubemaps && ! isCompressed ) {
6622
6623 cubeImage[ i ] = clampToMaxSize( texture.image[ i ], _maxCubemapSize );
6624
6625 } else {
6626
6627 cubeImage[ i ] = texture.image[ i ];
6628
6629 }
6630
6631 }
6632
6633 var image = cubeImage[ 0 ],
6634 isImagePowerOfTwo = isPowerOfTwo( image.width ) && isPowerOfTwo( image.height ),
6635 glFormat = paramThreeToGL( texture.format ),
6636 glType = paramThreeToGL( texture.type );
6637
6638 setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isImagePowerOfTwo );
6639
6640 for ( var i = 0; i < 6; i ++ ) {
6641
6642 if ( isCompressed ) {
6643
6644 var mipmap, mipmaps = cubeImage[ i ].mipmaps;
6645
6646 for( var j = 0, jl = mipmaps.length; j < jl; j ++ ) {
6647
6648 mipmap = mipmaps[ j ];
6649 _gl.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
6650
6651 }
6652
6653 } else {
6654
6655 _gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] );
6656
6657 }
6658
6659 }
6660
6661 if ( texture.generateMipmaps && isImagePowerOfTwo ) {
6662
6663 _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
6664
6665 }
6666
6667 texture.needsUpdate = false;
6668
6669 if ( texture.onUpdate ) texture.onUpdate();
6670
6671 } else {
6672
6673 _gl.activeTexture( _gl.TEXTURE0 + slot );
6674 _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube );
6675
6676 }
6677
6678 }
6679
6680 };
6681
6682 function setCubeTextureDynamic ( texture, slot ) {
6683
6684 _gl.activeTexture( _gl.TEXTURE0 + slot );
6685 _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.__webglTexture );
6686
6687 };
6688
6689 // Render targets
6690
6691 function setupFrameBuffer ( framebuffer, renderTarget, textureTarget ) {
6692
6693 _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
6694 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureTarget, renderTarget.__webglTexture, 0 );
6695
6696 };
6697
6698 function setupRenderBuffer ( renderbuffer, renderTarget ) {
6699
6700 _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer );
6701
6702 if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
6703
6704 _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTarget.width, renderTarget.height );
6705 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
6706
6707 /* For some reason this is not working. Defaulting to RGBA4.
6708 } else if( ! renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
6709
6710 _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.STENCIL_INDEX8, renderTarget.width, renderTarget.height );
6711 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
6712 */
6713 } else if( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
6714
6715 _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height );
6716 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
6717
6718 } else {
6719
6720 _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.RGBA4, renderTarget.width, renderTarget.height );
6721
6722 }
6723
6724 };
6725
6726 this.setRenderTarget = function ( renderTarget ) {
6727
6728 var isCube = ( renderTarget instanceof THREE.WebGLRenderTargetCube );
6729
6730 if ( renderTarget && ! renderTarget.__webglFramebuffer ) {
6731
6732 if ( renderTarget.depthBuffer === undefined ) renderTarget.depthBuffer = true;
6733 if ( renderTarget.stencilBuffer === undefined ) renderTarget.stencilBuffer = true;
6734
6735 renderTarget.__webglTexture = _gl.createTexture();
6736
6737 // Setup texture, create render and frame buffers
6738
6739 var isTargetPowerOfTwo = isPowerOfTwo( renderTarget.width ) && isPowerOfTwo( renderTarget.height ),
6740 glFormat = paramThreeToGL( renderTarget.format ),
6741 glType = paramThreeToGL( renderTarget.type );
6742
6743 if ( isCube ) {
6744
6745 renderTarget.__webglFramebuffer = [];
6746 renderTarget.__webglRenderbuffer = [];
6747
6748 _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, renderTarget.__webglTexture );
6749 setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget, isTargetPowerOfTwo );
6750
6751 for ( var i = 0; i < 6; i ++ ) {
6752
6753 renderTarget.__webglFramebuffer[ i ] = _gl.createFramebuffer();
6754 renderTarget.__webglRenderbuffer[ i ] = _gl.createRenderbuffer();
6755
6756 _gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
6757
6758 setupFrameBuffer( renderTarget.__webglFramebuffer[ i ], renderTarget, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i );
6759 setupRenderBuffer( renderTarget.__webglRenderbuffer[ i ], renderTarget );
6760
6761 }
6762
6763 if ( isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
6764
6765 } else {
6766
6767 renderTarget.__webglFramebuffer = _gl.createFramebuffer();
6768 renderTarget.__webglRenderbuffer = _gl.createRenderbuffer();
6769
6770 _gl.bindTexture( _gl.TEXTURE_2D, renderTarget.__webglTexture );
6771 setTextureParameters( _gl.TEXTURE_2D, renderTarget, isTargetPowerOfTwo );
6772
6773 _gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
6774
6775 setupFrameBuffer( renderTarget.__webglFramebuffer, renderTarget, _gl.TEXTURE_2D );
6776 setupRenderBuffer( renderTarget.__webglRenderbuffer, renderTarget );
6777
6778 if ( isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );
6779
6780 }
6781
6782 // Release everything
6783
6784 if ( isCube ) {
6785
6786 _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
6787
6788 } else {
6789
6790 _gl.bindTexture( _gl.TEXTURE_2D, null );
6791
6792 }
6793
6794 _gl.bindRenderbuffer( _gl.RENDERBUFFER, null );
6795 _gl.bindFramebuffer( _gl.FRAMEBUFFER, null);
6796
6797 }
6798
6799 var framebuffer, width, height, vx, vy;
6800
6801 if ( renderTarget ) {
6802
6803 if ( isCube ) {
6804
6805 framebuffer = renderTarget.__webglFramebuffer[ renderTarget.activeCubeFace ];
6806
6807 } else {
6808
6809 framebuffer = renderTarget.__webglFramebuffer;
6810
6811 }
6812
6813 width = renderTarget.width;
6814 height = renderTarget.height;
6815
6816 vx = 0;
6817 vy = 0;
6818
6819 } else {
6820
6821 framebuffer = null;
6822
6823 width = _viewportWidth;
6824 height = _viewportHeight;
6825
6826 vx = _viewportX;
6827 vy = _viewportY;
6828
6829 }
6830
6831 if ( framebuffer !== _currentFramebuffer ) {
6832
6833 _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
6834 _gl.viewport( vx, vy, width, height );
6835
6836 _currentFramebuffer = framebuffer;
6837
6838 }
6839
6840 _currentWidth = width;
6841 _currentHeight = height;
6842
6843 };
6844
6845 function updateRenderTargetMipmap ( renderTarget ) {
6846
6847 if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {
6848
6849 _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, renderTarget.__webglTexture );
6850 _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
6851 _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
6852
6853 } else {
6854
6855 _gl.bindTexture( _gl.TEXTURE_2D, renderTarget.__webglTexture );
6856 _gl.generateMipmap( _gl.TEXTURE_2D );
6857 _gl.bindTexture( _gl.TEXTURE_2D, null );
6858
6859 }
6860
6861 };
6862
6863 // Fallback filters for non-power-of-2 textures
6864
6865 function filterFallback ( f ) {
6866
6867 if ( f === THREE.NearestFilter || f === THREE.NearestMipMapNearestFilter || f === THREE.NearestMipMapLinearFilter ) {
6868
6869 return _gl.NEAREST;
6870
6871 }
6872
6873 return _gl.LINEAR;
6874
6875 };
6876
6877 // Map three.js constants to WebGL constants
6878
6879 function paramThreeToGL ( p ) {
6880
6881 if ( p === THREE.RepeatWrapping ) return _gl.REPEAT;
6882 if ( p === THREE.ClampToEdgeWrapping ) return _gl.CLAMP_TO_EDGE;
6883 if ( p === THREE.MirroredRepeatWrapping ) return _gl.MIRRORED_REPEAT;
6884
6885 if ( p === THREE.NearestFilter ) return _gl.NEAREST;
6886 if ( p === THREE.NearestMipMapNearestFilter ) return _gl.NEAREST_MIPMAP_NEAREST;
6887 if ( p === THREE.NearestMipMapLinearFilter ) return _gl.NEAREST_MIPMAP_LINEAR;
6888
6889 if ( p === THREE.LinearFilter ) return _gl.LINEAR;
6890 if ( p === THREE.LinearMipMapNearestFilter ) return _gl.LINEAR_MIPMAP_NEAREST;
6891 if ( p === THREE.LinearMipMapLinearFilter ) return _gl.LINEAR_MIPMAP_LINEAR;
6892
6893 if ( p === THREE.UnsignedByteType ) return _gl.UNSIGNED_BYTE;
6894 if ( p === THREE.UnsignedShort4444Type ) return _gl.UNSIGNED_SHORT_4_4_4_4;
6895 if ( p === THREE.UnsignedShort5551Type ) return _gl.UNSIGNED_SHORT_5_5_5_1;
6896 if ( p === THREE.UnsignedShort565Type ) return _gl.UNSIGNED_SHORT_5_6_5;
6897
6898 if ( p === THREE.ByteType ) return _gl.BYTE;
6899 if ( p === THREE.ShortType ) return _gl.SHORT;
6900 if ( p === THREE.UnsignedShortType ) return _gl.UNSIGNED_SHORT;
6901 if ( p === THREE.IntType ) return _gl.INT;
6902 if ( p === THREE.UnsignedIntType ) return _gl.UNSIGNED_INT;
6903 if ( p === THREE.FloatType ) return _gl.FLOAT;
6904
6905 if ( p === THREE.AlphaFormat ) return _gl.ALPHA;
6906 if ( p === THREE.RGBFormat ) return _gl.RGB;
6907 if ( p === THREE.RGBAFormat ) return _gl.RGBA;
6908 if ( p === THREE.LuminanceFormat ) return _gl.LUMINANCE;
6909 if ( p === THREE.LuminanceAlphaFormat ) return _gl.LUMINANCE_ALPHA;
6910
6911 if ( p === THREE.AddEquation ) return _gl.FUNC_ADD;
6912 if ( p === THREE.SubtractEquation ) return _gl.FUNC_SUBTRACT;
6913 if ( p === THREE.ReverseSubtractEquation ) return _gl.FUNC_REVERSE_SUBTRACT;
6914
6915 if ( p === THREE.ZeroFactor ) return _gl.ZERO;
6916 if ( p === THREE.OneFactor ) return _gl.ONE;
6917 if ( p === THREE.SrcColorFactor ) return _gl.SRC_COLOR;
6918 if ( p === THREE.OneMinusSrcColorFactor ) return _gl.ONE_MINUS_SRC_COLOR;
6919 if ( p === THREE.SrcAlphaFactor ) return _gl.SRC_ALPHA;
6920 if ( p === THREE.OneMinusSrcAlphaFactor ) return _gl.ONE_MINUS_SRC_ALPHA;
6921 if ( p === THREE.DstAlphaFactor ) return _gl.DST_ALPHA;
6922 if ( p === THREE.OneMinusDstAlphaFactor ) return _gl.ONE_MINUS_DST_ALPHA;
6923
6924 if ( p === THREE.DstColorFactor ) return _gl.DST_COLOR;
6925 if ( p === THREE.OneMinusDstColorFactor ) return _gl.ONE_MINUS_DST_COLOR;
6926 if ( p === THREE.SrcAlphaSaturateFactor ) return _gl.SRC_ALPHA_SATURATE;
6927
6928 if ( _glExtensionCompressedTextureS3TC !== undefined ) {
6929
6930 if ( p === THREE.RGB_S3TC_DXT1_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGB_S3TC_DXT1_EXT;
6931 if ( p === THREE.RGBA_S3TC_DXT1_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT1_EXT;
6932 if ( p === THREE.RGBA_S3TC_DXT3_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT3_EXT;
6933 if ( p === THREE.RGBA_S3TC_DXT5_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT5_EXT;
6934
6935 }
6936
6937 return 0;
6938
6939 };
6940
6941 // Allocations
6942
6943 function allocateBones ( object ) {
6944
6945 if ( _supportsBoneTextures && object && object.useVertexTexture ) {
6946
6947 return 1024;
6948
6949 } else {
6950
6951 // default for when object is not specified
6952 // ( for example when prebuilding shader
6953 // to be used with multiple objects )
6954 //
6955 // - leave some extra space for other uniforms
6956 // - limit here is ANGLE's 254 max uniform vectors
6957 // (up to 54 should be safe)
6958
6959 var nVertexUniforms = _gl.getParameter( _gl.MAX_VERTEX_UNIFORM_VECTORS );
6960 var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
6961
6962 var maxBones = nVertexMatrices;
6963
6964 if ( object !== undefined && object instanceof THREE.SkinnedMesh ) {
6965
6966 maxBones = Math.min( object.bones.length, maxBones );
6967
6968 if ( maxBones < object.bones.length ) {
6969
6970 console.warn( "WebGLRenderer: too many bones - " + object.bones.length + ", this GPU supports just " + maxBones + " (try OpenGL instead of ANGLE)" );
6971
6972 }
6973
6974 }
6975
6976 return maxBones;
6977
6978 }
6979
6980 };
6981
6982 function allocateLights ( lights ) {
6983
6984 var l, ll, light, dirLights, pointLights, spotLights, hemiLights;
6985
6986 dirLights = pointLights = spotLights = hemiLights = 0;
6987
6988 for ( l = 0, ll = lights.length; l < ll; l ++ ) {
6989
6990 light = lights[ l ];
6991
6992 if ( light.onlyShadow ) continue;
6993
6994 if ( light instanceof THREE.DirectionalLight ) dirLights ++;
6995 if ( light instanceof THREE.PointLight ) pointLights ++;
6996 if ( light instanceof THREE.SpotLight ) spotLights ++;
6997 if ( light instanceof THREE.HemisphereLight ) hemiLights ++;
6998
6999 }
7000
7001 return { 'directional' : dirLights, 'point' : pointLights, 'spot': spotLights, 'hemi': hemiLights };
7002
7003 };
7004
7005 function allocateShadows ( lights ) {
7006
7007 var l, ll, light, maxShadows = 0;
7008
7009 for ( l = 0, ll = lights.length; l < ll; l++ ) {
7010
7011 light = lights[ l ];
7012
7013 if ( ! light.castShadow ) continue;
7014
7015 if ( light instanceof THREE.SpotLight ) maxShadows ++;
7016 if ( light instanceof THREE.DirectionalLight && ! light.shadowCascade ) maxShadows ++;
7017
7018 }
7019
7020 return maxShadows;
7021
7022 };
7023
7024 // Initialization
7025
7026 function initGL () {
7027
7028 try {
7029
7030 if ( ! ( _gl = _canvas.getContext( 'experimental-webgl', { alpha: _alpha, premultipliedAlpha: _premultipliedAlpha, antialias: _antialias, stencil: _stencil, preserveDrawingBuffer: _preserveDrawingBuffer } ) ) ) {
7031
7032 throw 'Error creating WebGL context.';
7033
7034 }
7035
7036 } catch ( error ) {
7037
7038 console.error( error );
7039
7040 }
7041
7042 _glExtensionTextureFloat = _gl.getExtension( 'OES_texture_float' );
7043 _glExtensionStandardDerivatives = _gl.getExtension( 'OES_standard_derivatives' );
7044
7045 _glExtensionTextureFilterAnisotropic = _gl.getExtension( 'EXT_texture_filter_anisotropic' ) ||
7046 _gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) ||
7047 _gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
7048
7049
7050 _glExtensionCompressedTextureS3TC = _gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) ||
7051 _gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) ||
7052 _gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
7053
7054 if ( ! _glExtensionTextureFloat ) {
7055
7056 console.log( 'THREE.WebGLRenderer: Float textures not supported.' );
7057
7058 }
7059
7060 if ( ! _glExtensionStandardDerivatives ) {
7061
7062 console.log( 'THREE.WebGLRenderer: Standard derivatives not supported.' );
7063
7064 }
7065
7066 if ( ! _glExtensionTextureFilterAnisotropic ) {
7067
7068 console.log( 'THREE.WebGLRenderer: Anisotropic texture filtering not supported.' );
7069
7070 }
7071
7072 if ( ! _glExtensionCompressedTextureS3TC ) {
7073
7074 console.log( 'THREE.WebGLRenderer: S3TC compressed textures not supported.' );
7075
7076 }
7077
7078 };
7079
7080 function setDefaultGLState () {
7081
7082 _gl.clearColor( 0, 0, 0, 1 );
7083 _gl.clearDepth( 1 );
7084 _gl.clearStencil( 0 );
7085
7086 _gl.enable( _gl.DEPTH_TEST );
7087 _gl.depthFunc( _gl.LEQUAL );
7088
7089 _gl.frontFace( _gl.CCW );
7090 _gl.cullFace( _gl.BACK );
7091 _gl.enable( _gl.CULL_FACE );
7092
7093 _gl.enable( _gl.BLEND );
7094 _gl.blendEquation( _gl.FUNC_ADD );
7095 _gl.blendFunc( _gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA );
7096
7097 _gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
7098
7099 };
7100
7101 // default plugins (order is important)
7102
7103 this.shadowMapPlugin = new THREE.ShadowMapPlugin();
7104 this.addPrePlugin( this.shadowMapPlugin );
7105
7106 this.addPostPlugin( new THREE.SpritePlugin() );
7107 this.addPostPlugin( new THREE.LensFlarePlugin() );
7108
7109 };
7110
nike free rn
new balance hombre baratas
cinturones gucci
ugg rebajas
cinturon gucci
ray ban baratas
nike cortez
peuterey mujer
christian louboutin madrid
mbt zapatos
gafas ray ban baratas
mbt ofertas
air max blancas
mbt barcelona
nike air max 90
woolrich barcelona
nike mujer
botas ugg
gafas de sol carrera aratas
air max 2016 baratas
oakley baratas
nike air max 2016