PageSourceSearch

https://tommyos.vercel.app/System/ShaderToy/CoastalLandscape/piLibs.js

js tommyos.vercel.app collected 2026-10-03 07:56:20 UTC 142,758 bytes, 2,934 lines download raw bytes

1"use strict"
2
3//==============================================================================
4//
5// piLibs 2015-2017 - http://www.iquilezles.org/www/material/piLibs/piLibs.htm
6//
7// piCamera
8//
9//==============================================================================
10
11function piCamera()
12{
13    var mMatrix = setIdentity();
14    var mMatrixInv = setIdentity();
15
16    var mPosition = [0.0,0.0,0.0];
17    var mXRotation = 0.0;
18    var mYRotation = 0.0;
19
20    var mPositionTarget = [0.0,0.0,0.0];
21    var mXRotationTarget = 0.0;
22    var mYRotationTarget = 0.0;
23
24    var me = {};
25
26    me.SetPos = function(pos)
27                {
28                    mPosition = pos;
29                };
30
31    me.LocalMove = function( dis )
32                    {
33                        dis = matMulvec( setRotationY(-mYRotation), dis);
34                        mPositionTarget = sub(mPositionTarget,dis)
35                    };
36
37    me.RotateXY = function( x, y)
38                  {
39                    mXRotationTarget -= x;
40                    mYRotationTarget -= y;
41                    mXRotationTarget = Math.min( Math.max( mXRotationTarget, -Math.PI/2), Math.PI/2 );
42                  };
43
44
45    me.CameraExectue = function( dt )
46    {
47        // smooth position
48        mXRotation += (mXRotationTarget-mXRotation) * 12.0*dt;
49        mYRotation += (mYRotationTarget-mYRotation) * 12.0*dt;
50        mPosition = add(mPosition, mul( sub(mPositionTarget, mPosition), 12.0*dt));
51
52        // Make Camera matrix
53        mMatrix = matMul( matMul(setRotationX(mXRotation),
54                                 setRotationY(mYRotation)),
55                                 setTranslation(mPosition));
56        mMatrixInv = invertFast(mMatrix);
57
58    }
59
60    me.GetMatrix = function() { return mMatrix; };
61    me.GetMatrixInverse = function() { return mMatrixInv; };
62    me.SetMatrix = function( mat )
63                    {
64                        mMatrix = mat;
65                        mMatrixInv = invertFast(mMatrix);
66
67                        mPosition = getXYZ(matMulpoint(mat, [0.0,0.0,0.0]));
68                        mPositionTarget = mPosition;
69                    };
70
71    me.GetPos = function() { return getXYZ(matMulpoint(mMatrixInv, [0.0,0.0,0.0])); }
72    me.GetDir = function() { return getXYZ(normalize(matMulvec(mMatrixInv, [0.0,0.0,-1.0]))); }
73
74    return me;
75}
76//==============================================================================
77//
78// piLibs 2015-2017 - http://www.iquilezles.org/www/material/piLibs/piLibs.htm
79//
80// piFile
81//
82//==============================================================================
83
84function piFile( binaryDataArrayBuffer )
85{
86    // private
87    var mDataView = binaryDataArrayBuffer;
88    var mOffset = 0;
89
90    // public members
91    var me = {};
92    me.mDummy = 0;
93
94    me.Seek = function( off ) { mOffset = off; };
95    me.ReadUInt8  = function()  { var res = (new Uint8Array(mDataView,mOffset))[0]; mOffset+=1; return res; };
96    me.ReadUInt16 = function()  { var res = (new Uint16Array(mDataView,mOffset))[0]; mOffset+=2; return res; };
97    me.ReadUInt32 = function()  { var res = (new Uint32Array(mDataView,mOffset))[0]; mOffset+=4; return res; };
98    me.ReadUInt64 = function()  { return me.ReadUInt32() + (me.ReadUInt32()<<32); };
99    me.ReadFloat32 = function() { var res = (new Float32Array(mDataView,mOffset))[0]; mOffset+=4; return res; };
100    me.ReadFloat32Array = function(n)
101                          {
102                              var src = new Float32Array(mDataView, mOffset);
103                              var res = [];  for( var i=0; i<n; i++ ) { res[i] = src[i]; }
104                              mOffset += 4*n;
105                              return res;
106                          };
107    me.ReadFloat32ArrayNative = function(n) { var src = new Float32Array(mDataView, mOffset); mOffset += 4*n; return src; };
108    return me;
109}
110//==============================================================================
111//
112// piLibs 2015-2017 - http://www.iquilezles.org/www/material/piLibs/piLibs.htm
113//
114// piMesh
115//
116//==============================================================================
117
118function piMesh()
119{
120    this.mChunks = [];
121    this.mPrimitiveType = 0;
122    this.mVertexFormat = null;
123}
124
125piMesh.prototype.createCube = function(renderer)
126{
127    this.mPrimitiveType = 0;
128
129    this.mChunks[0] = { mVerts : new Float32Array([ -1.0, -1.0, -1.0,
130                                       1.0, -1.0, -1.0,
131                                      -1.0,  1.0, -1.0,
132                                       1.0,  1.0, -1.0,
133                                      -1.0, -1.0,  1.0,
134                                       1.0, -1.0,  1.0,
135                                      -1.0,  1.0,  1.0,
136                                       1.0,  1.0,  1.0 ]),
137
138                        mIndices : new Uint16Array([ 0, 2, 1,   1, 2, 3,   5, 1, 3,   5, 3, 7,   4, 5, 7,   4, 7, 6,   4, 6, 2,   4, 2, 0,   6, 7, 3,   6, 3, 2,   4, 0, 1,   4, 1, 5 ]),
139                        mNumVertices : 8,
140                        mNumFaces : 12,
141                        mTransform : setIdentity(),
142                        mVBO : null,
143                        mIBO : null };
144
145    this.mVertexFormat = { mStride:12, mChannels:[ { mNumComponents:3, mType: renderer.TYPE.FLOAT32, mNormalize: false } ] };
146
147    return true;
148}
149
150piMesh.prototype.createCubeSharp = function (renderer)
151{
152    this.mPrimitiveType = 0;
153
154    this.mChunks[0] = { mVerts : new Float32Array([-1.0, 1.0,-1.0,   0.0, 1.0, 0.0,   0.0, 0.0,
155                                    -1.0, 1.0, 1.0,   0.0, 1.0, 0.0,   0.0, 1.0,
156                                     1.0, 1.0, 1.0,   0.0, 1.0, 0.0,   1.0, 1.0,
157                                     1.0, 1.0,-1.0,   0.0, 1.0, 0.0,   1.0, 0.0,
158
159                                    -1.0,-1.0, 1.0,   0.0, 0.0, 1.0,   0.0, 0.0,
160                                     1.0,-1.0, 1.0,   0.0, 0.0, 1.0,   0.0, 1.0,
161                                     1.0, 1.0, 1.0,   0.0, 0.0, 1.0,   1.0, 1.0,
162                                    -1.0, 1.0, 1.0,   0.0, 0.0, 1.0,   1.0, 0.0,
163
164                                     1.0, 1.0, 1.0,   1.0, 0.0, 0.0,   0.0, 0.0,
165                                     1.0,-1.0, 1.0,   1.0, 0.0, 0.0,   0.0, 1.0,
166                                     1.0,-1.0,-1.0,   1.0, 0.0, 0.0,   1.0, 1.0,
167                                     1.0, 1.0,-1.0,   1.0, 0.0, 0.0,   1.0, 0.0,
168
169                                     1.0,-1.0,-1.0,   0.0, 0.0,-1.0,   0.0, 0.0,
170                                    -1.0,-1.0,-1.0,   0.0, 0.0,-1.0,   0.0, 1.0,
171                                    -1.0, 1.0,-1.0,   0.0, 0.0,-1.0,   1.0, 1.0,
172                                     1.0, 1.0,-1.0,   0.0, 0.0,-1.0,   1.0, 0.0,
173
174                                    -1.0,-1.0, 1.0,   0.0,-1.0, 0.0,   0.0, 0.0,
175                                    -1.0,-1.0,-1.0,   0.0,-1.0, 0.0,   0.0, 1.0,
176                                     1.0,-1.0,-1.0,   0.0,-1.0, 0.0,   1.0, 1.0,
177                                     1.0,-1.0, 1.0,   0.0,-1.0, 0.0,   1.0, 0.0,
178
179                                    -1.0, 1.0, 1.0,  -1.0, 0.0, 0.0,   0.0, 0.0,
180                                    -1.0, 1.0,-1.0,  -1.0, 0.0, 0.0,   0.0, 1.0,
181                                    -1.0,-1.0,-1.0,  -1.0, 0.0, 0.0,   1.0, 1.0,
182                                    -1.0,-1.0, 1.0,  -1.0, 0.0, 0.0,   1.0, 0.0 ]),
183
184                        mIndices : new Uint16Array([0,1,2, 0,2,3,   4,5,6, 4,6,7,    8,9,10,8,10,11,   12,13,14,12,14,15,   16,17,18,16,18,19,   20,21,22,20,22,23]),
185                        mNumVertices : 24,
186                        mNumFaces : 12,
187                        mTransform : setIdentity(),
188                        mVBO : null,
189                        mIBO : null };
190
191
192    this.mVertexFormat = { mStride:32, mChannels:[ { mNumComponents:3, mType: renderer.TYPE.FLOAT32, mNormalize: false },
193                                                   { mNumComponents:3, mType: renderer.TYPE.FLOAT32, mNormalize: false },
194                                                   { mNumComponents:2, mType: renderer.TYPE.FLOAT32, mNormalize: false } ] };
195
196    return true;
197}
198
199
200piMesh.prototype.createUnitQuad = function (renderer)
201{
202    this.mPrimitiveType = 0;
203    this.mVertexFormat = { mStride:8, mChannels: [ {mNumComponents:2, mType: renderer.TYPE.FLOAT32, mNormalize: false} ] };
204
205    this.mChunks[0] = { mVerts : new Float32Array([-1.0, -1.0, 1.0, -1.0, -1.0,  1.0, 1.0,  1.0]),
206                        mIndices : new Uint16Array([0, 2, 1, 1, 2, 3]),
207                        mNumVertices : 4,
208                        mNumFaces : 2,
209                        mTransform : setIdentity(),
210                        mVBO : null,
211                        mIBO : null };
212
213    return true;
214}
215
216
217
218
219piMesh.prototype.destroy = function()
220{ }
221
222piMesh.prototype.scale = function (x, y, z)
223{
224    var stride = this.mVertexFormat.mStride/4;
225    for( var j=0; j<this.mChunks.length; j++ )
226    {
227        var nv = this.mChunks[j].mNumVertices;
228        for (var i = 0; i < nv; i++)
229        {
230            this.mChunks[j].mVerts[stride * i + 0] *= x;
231            this.mChunks[j].mVerts[stride * i + 1] *= y;
232            this.mChunks[j].mVerts[stride * i + 2] *= z;
233        }
234    }
235}
236
237piMesh.prototype.translate = function (x, y, z)
238{
239    var stride = this.mVertexFormat.mStride/4;
240    for( var j=0; j<this.mChunks.length; j++ )
241    {
242        var nv = this.mChunks[j].mNumVertices;
243        for (var i = 0; i < nv; i++)
244        {
245            this.mChunks[j].mVerts[stride * i + 0] += x;
246            this.mChunks[j].mVerts[stride * i + 1] += y;
247            this.mChunks[j].mVerts[stride * i + 2] += z;
248        }
249    }
250}
251
252piMesh.prototype.GPULoad = function (renderer)
253{
254    for( var i=0; i<this.mChunks.length; i++ )
255    {
256        var vbo = renderer.CreateVertexArray(this.mChunks[i].mVerts, renderer.BUFTYPE.STATIC );
257        if (vbo == null)
258            return false;
259
260        var ibo = renderer.CreateIndexArray(this.mChunks[i].mIndices, renderer.BUFTYPE.STATIC);
261        if (ibo == null)
262            return false;
263
264        this.mChunks[i].mVBO = vbo;
265        this.mChunks[i].mIBO = ibo;
266    }
267    return true;
268}
269
270piMesh.prototype.GPURender = function (renderer, positions )//, matPrj, matCam )
271{
272    var num = this.mChunks.length;
273    for( var i=0; i<num; i++ )
274    {
275        renderer.AttachVertexArray(this.mChunks[i].mVBO, this.mVertexFormat, positions );
276        renderer.AttachIndexArray(this.mChunks[i].mIBO );
277        renderer.DrawPrimitive(renderer.PRIMTYPE.TRIANGLES, this.mChunks[i].mNumFaces * 3, true, 1);
278        renderer.DetachIndexArray(this.mChunks[i].mIBO);
279        renderer.DetachVertexArray(this.mChunks[i].mVBO, this.mVertexFormat );
280    }
281}
282//==============================================================================
283//
284// piLibs 2014-2017 - http://www.iquilezles.org/www/material/piLibs/piLibs.htm
285//
286// piRenderer
287//
288//==============================================================================
289
290function piRenderer()
291{
292    // private members
293
294    var mGL = null;
295    var mBindedShader = null;
296    var mIs20 = false;
297    var mFloat32Textures;
298    var mFloat32Filter;
299    var mFloat16Textures;
300    var mDrawBuffers;
301    var mDepthTextures;
302    var mDerivatives;
303    var mFloat16Filter;
304    var mShaderTextureLOD;
305    var mAnisotropic;
306    var mRenderToFloat32F;
307    var mDebugShader;
308    var mAsynchCompile;
309
310    var mVBO_Quad = null;
311    var mVBO_Tri = null;
312    var mVBO_CubePosNor = null;
313    var mVBO_CubePos = null;
314    var mShaderHeader = ["",""];
315    var mShaderHeaderLines = [0,0];
316
317    // public members
318    var me = {};
319
320    me.CLEAR      = { Color: 1, Zbuffer : 2, Stencil : 4 };
321    me.TEXFMT     = { C4I8 : 0, C1I8 : 1, C1F16 : 2, C4F16 : 3, C1F32 : 4, C4F32 : 5, Z16 : 6, Z24 : 7, Z32 : 8, C3F32:9 };
322    me.TEXWRP     = { CLAMP : 0, REPEAT : 1 };
323    me.BUFTYPE    = { STATIC : 0, DYNAMIC : 1 };
324    me.PRIMTYPE   = { POINTS : 0, LINES : 1, LINE_LOOP : 2, LINE_STRIP : 3, TRIANGLES : 4, TRIANGLE_STRIP : 5 };
325    me.RENDSTGATE = { WIREFRAME : 0, FRONT_FACE : 1, CULL_FACE : 2, DEPTH_TEST : 3, ALPHA_TO_COVERAGE : 4 };
326    me.TEXTYPE    = { T2D : 0, T3D : 1, CUBEMAP : 2 };
327    me.FILTER     = { NONE : 0, LINEAR : 1, MIPMAP : 2, NONE_MIPMAP : 3 };
328    me.TYPE       = { UINT8 : 0, UINT16 : 1, UINT32 : 2, FLOAT16: 3, FLOAT32 : 4, FLOAT64: 5 };
329
330    // private functions
331
332    var iFormatPI2GL = function( format )
333    {
334        if( mIs20 )
335        {
336             if (format === me.TEXFMT.C4I8)  return { mGLFormat: mGL.RGBA8,           mGLExternal: mGL.RGBA,             mGLType: mGL.UNSIGNED_BYTE }
337        else if (format === me.TEXFMT.C1I8)  return { mGLFormat: mGL.R8,              mGLExternal: mGL.RED,              mGLType: mGL.UNSIGNED_BYTE }
338        else if (format === me.TEXFMT.C1F16) return { mGLFormat: mGL.R16F,            mGLExternal: mGL.RED,              mGLType: mGL.FLOAT }
339        else if (format === me.TEXFMT.C4F16) return { mGLFormat: mGL.RGBA16F,         mGLExternal: mGL.RGBA,             mGLType: mGL.FLOAT }
340        else if (format === me.TEXFMT.C1F32) return { mGLFormat: mGL.R32F,            mGLExternal: mGL.RED,              mGLType: mGL.FLOAT }
341        else if (format === me.TEXFMT.C4F32) return { mGLFormat: mGL.RGBA32F,         mGLExternal: mGL.RGBA,             mGLType: mGL.FLOAT }
342        else if (format === me.TEXFMT.C3F32) return { mGLFormat: mGL.RGB32F,          mGLExternal: mGL.RGB,              mGLType: mGL.FLOAT }
343        else if (format === me.TEXFMT.Z16)   return { mGLFormat: mGL.DEPTH_COMPONENT16, mGLExternal: mGL.DEPTH_COMPONENT,  mGLType: mGL.UNSIGNED_SHORT }
344        else if (format === me.TEXFMT.Z24)   return { mGLFormat: mGL.DEPTH_COMPONENT24, mGLExternal: mGL.DEPTH_COMPONENT,  mGLType: mGL.UNSIGNED_SHORT }
345        else if (format === me.TEXFMT.Z32)   return { mGLFormat: mGL.DEPTH_COMPONENT32F, mGLExternal: mGL.DEPTH_COMPONENT,  mGLType: mGL.UNSIGNED_SHORT }
346        }
347        else
348        {
349             if (format === me.TEXFMT.C4I8)  return { mGLFormat: mGL.RGBA,            mGLExternal: mGL.RGBA,            mGLType: mGL.UNSIGNED_BYTE }
350        else if (format === me.TEXFMT.C1I8)  return { mGLFormat: mGL.LUMINANCE,       mGLExternal: mGL.LUMINANCE,       mGLType: mGL.UNSIGNED_BYTE }
351        else if (format === me.TEXFMT.C1F16) return { mGLFormat: mGL.LUMINANCE,       mGLExternal: mGL.LUMINANCE,       mGLType: mGL.FLOAT }
352        else if (format === me.TEXFMT.C4F16) return { mGLFormat: mGL.RGBA,            mGLExternal: mGL.RGBA,            mGLType: mGL.FLOAT }
353        else if (format === me.TEXFMT.C1F32) return { mGLFormat: mGL.LUMINANCE,       mGLExternal: mGL.RED,             mGLType: mGL.FLOAT }
354        else if (format === me.TEXFMT.C4F32) return { mGLFormat: mGL.RGBA,            mGLExternal: mGL.RGBA,            mGLType: mGL.FLOAT }
355        else if (format === me.TEXFMT.Z16)   return { mGLFormat: mGL.DEPTH_COMPONENT, mGLExternal: mGL.DEPTH_COMPONENT, mGLType: mGL.UNSIGNED_SHORT }
356        }
357
358        return null;
359     }
360
361    // public functions
362
363    me.Initialize = function( gl )
364                    {
365                        mGL = gl;
366
367                        mIs20 = !(gl instanceof WebGLRenderingContext);
368
369                        if( mIs20 )
370                        {
371                            mFloat32Textures  = true;
372                            mFloat32Filter    = mGL.getExtension( 'OES_texture_float_linear');
373                            mFloat16Textures  = true;
374                            mFloat16Filter    = mGL.getExtension( 'OES_texture_half_float_linear' );
375                            mDerivatives      = true;
376                            mDrawBuffers      = true;
377                            mDepthTextures    = true;
378                            mShaderTextureLOD = true;
379                            mAnisotropic = mGL.getExtension( 'EXT_texture_filter_anisotropic' );
380                            mRenderToFloat32F = mGL.getExtension( 'EXT_color_buffer_float');
381                            mDebugShader = mGL.getExtension('WEBGL_debug_shaders');
382                            mAsynchCompile = mGL.getExtension('KHR_parallel_shader_compile');
383
384							mGL.hint( mGL.FRAGMENT_SHADER_DERIVATIVE_HINT, mGL.NICEST);
385                        }
386                        else
387                        {
388                            mFloat32Textures  = mGL.getExtension( 'OES_texture_float' );
389                            mFloat32Filter    = mGL.getExtension( 'OES_texture_float_linear');
390                            mFloat16Textures  = mGL.getExtension( 'OES_texture_half_float' );
391                            mFloat16Filter    = mGL.getExtension( 'OES_texture_half_float_linear' );
392                            mDerivatives      = mGL.getExtension( 'OES_standard_derivatives' );
393                            mDrawBuffers      = mGL.getExtension( 'WEBGL_draw_buffers' );
394                            mDepthTextures    = mGL.getExtension( 'WEBGL_depth_texture' );
395                            mShaderTextureLOD = mGL.getExtension( 'EXT_shader_texture_lod' );
396                            mAnisotropic      = mGL.getExtension( 'EXT_texture_filter_anisotropic' );
397                            mRenderToFloat32F = mFloat32Textures;
398                            mDebugShader      = null;
399                            mAsynchCompile    = null;
400
401							if( mDerivatives !== null) mGL.hint( mDerivatives.FRAGMENT_SHADER_DERIVATIVE_HINT_OES, mGL.NICEST);
402                        }
403
404
405                        var maxTexSize = mGL.getParameter( mGL.MAX_TEXTURE_SIZE );
406                        var maxCubeSize = mGL.getParameter( mGL.MAX_CUBE_MAP_TEXTURE_SIZE );
407                        var maxRenderbufferSize = mGL.getParameter( mGL.MAX_RENDERBUFFER_SIZE );
408                        var extensions = mGL.getSupportedExtensions();
409                        var textureUnits = mGL.getParameter( mGL.MAX_TEXTURE_IMAGE_UNITS );
410                        console.log("WebGL (2.0=" + mIs20 + "):" +
411                                    " Asynch Compile: "  + ((mAsynchCompile !==null) ? "yes" : "no") +
412                                    ", Textures: F32 ["   + ((mFloat32Textures !==null) ? "yes" : "no") +
413                                    "], F16 ["   + ((mFloat16Textures !==null) ? "yes" : "no") +
414                                    "], Depth [" + ((mDepthTextures   !==null) ? "yes" : "no") +
415                                    "], LOD ["    + ((mShaderTextureLOD!==null) ? "yes" : "no") +
416                                    "], Aniso ["   + ((mAnisotropic     !==null) ? "yes" : "no") +
417                                    "], Units [" + textureUnits +
418                                    "], Max Size [" + maxTexSize +
419                                    "], Cube Max Size [" + maxCubeSize +
420                                    "], Targets: MRT ["            + ((mDrawBuffers     !==null) ? "yes" : "no") +
421                                    "], F32 ["     + ((mRenderToFloat32F!==null) ? "yes" : "no") +
422                                    "], Max Size [" + maxRenderbufferSize + "]");
423
424                        // create a 2D quad Vertex Buffer
425                        var vertices = new Float32Array( [ -1.0, -1.0,   1.0, -1.0,    -1.0,  1.0,     1.0, -1.0,    1.0,  1.0,    -1.0,  1.0] );
426                        mVBO_Quad = mGL.createBuffer();
427                        mGL.bindBuffer( mGL.ARRAY_BUFFER, mVBO_Quad );
428                        mGL.bufferData( mGL.ARRAY_BUFFER, vertices, mGL.STATIC_DRAW );
429                        mGL.bindBuffer( mGL.ARRAY_BUFFER, null );
430
431                        // create a 2D triangle Vertex Buffer
432                        mVBO_Tri = mGL.createBuffer();
433                        mGL.bindBuffer( mGL.ARRAY_BUFFER, mVBO_Tri );
434                        mGL.bufferData( mGL.ARRAY_BUFFER, new Float32Array( [ -1.0, -1.0,   3.0, -1.0,    -1.0,  3.0] ), mGL.STATIC_DRAW );
435                        mGL.bindBuffer( mGL.ARRAY_BUFFER, null );
436
437                        // create a 3D cube Vertex Buffer
438                        mVBO_CubePosNor = mGL.createBuffer();
439                        mGL.bindBuffer( mGL.ARRAY_BUFFER, mVBO_CubePosNor );
440                        mGL.bufferData( mGL.ARRAY_BUFFER, new Float32Array( [ -1.0, -1.0, -1.0,  -1.0,  0.0,  0.0,
441                                                                              -1.0, -1.0,  1.0,  -1.0,  0.0,  0.0,
442                                                                              -1.0,  1.0, -1.0,  -1.0,  0.0,  0.0,
443                                                                              -1.0,  1.0,  1.0,  -1.0,  0.0,  0.0,
444                                                                               1.0,  1.0, -1.0,   1.0,  0.0,  0.0,
445                                                                               1.0,  1.0,  1.0,   1.0,  0.0,  0.0,
446                                                                               1.0, -1.0, -1.0,   1.0,  0.0,  0.0,
447                                                                               1.0, -1.0,  1.0,   1.0,  0.0,  0.0,
448                                                                               1.0,  1.0,  1.0,   0.0,  1.0,  0.0,
449                                                                               1.0,  1.0, -1.0,   0.0,  1.0,  0.0,
450                                                                              -1.0,  1.0,  1.0,   0.0,  1.0,  0.0,
451                                                                              -1.0,  1.0, -1.0,   0.0,  1.0,  0.0,
452                                                                               1.0, -1.0, -1.0,   0.0, -1.0,  0.0,
453                                                                               1.0, -1.0,  1.0,   0.0, -1.0,  0.0,
454                                                                              -1.0, -1.0, -1.0,   0.0, -1.0,  0.0,
455                                                                              -1.0, -1.0,  1.0,   0.0, -1.0,  0.0,
456                                                                              -1.0,  1.0,  1.0,   0.0,  0.0,  1.0,
457                                                                              -1.0, -1.0,  1.0,   0.0,  0.0,  1.0,
458                                                                               1.0,  1.0,  1.0,   0.0,  0.0,  1.0,
459                                                                               1.0, -1.0,  1.0,   0.0,  0.0,  1.0,
460                                                                              -1.0, -1.0, -1.0,   0.0,  0.0, -1.0,
461                                                                              -1.0,  1.0, -1.0,   0.0,  0.0, -1.0,
462                                                                               1.0, -1.0, -1.0,   0.0,  0.0, -1.0,
463                                                                               1.0,  1.0, -1.0,   0.0,  0.0, -1.0 ] ), mGL.STATIC_DRAW );
464                        mGL.bindBuffer( mGL.ARRAY_BUFFER, null );
465
466                        // create a 3D cube Vertex Buffer
467                        mVBO_CubePos = mGL.createBuffer();
468                        mGL.bindBuffer( mGL.ARRAY_BUFFER, mVBO_CubePos );
469                        mGL.bufferData( mGL.ARRAY_BUFFER, new Float32Array( [ -1.0, -1.0, -1.0,
470                                                                              -1.0, -1.0,  1.0,
471                                                                              -1.0,  1.0, -1.0,
472                                                                              -1.0,  1.0,  1.0,
473                                                                               1.0,  1.0, -1.0,
474                                                                               1.0,  1.0,  1.0,
475                                                                               1.0, -1.0, -1.0,
476                                                                               1.0, -1.0,  1.0,
477                                                                               1.0,  1.0,  1.0,
478                                                                               1.0,  1.0, -1.0,
479                                                                              -1.0,  1.0,  1.0,
480                                                                              -1.0,  1.0, -1.0,
481                                                                               1.0, -1.0, -1.0,
482                                                                               1.0, -1.0,  1.0,
483                                                                              -1.0, -1.0, -1.0,
484                                                                              -1.0, -1.0,  1.0,
485                                                                              -1.0,  1.0,  1.0,
486                                                                              -1.0, -1.0,  1.0,
487                                                                               1.0,  1.0,  1.0,
488                                                                               1.0, -1.0,  1.0,
489                                                                              -1.0, -1.0, -1.0,
490                                                                              -1.0,  1.0, -1.0,
491                                                                               1.0, -1.0, -1.0,
492                                                                               1.0,  1.0, -1.0 ] ), mGL.STATIC_DRAW );
493                        mGL.bindBuffer( mGL.ARRAY_BUFFER, null );
494
495                        //-------------------------------------------------------------------
496
497                        mShaderHeader[0] = "";
498                        mShaderHeaderLines[0] = 0;
499                        if( mIs20 )
500                        {
501                            mShaderHeader[0] += "#version 300 es\n" +
502                                                "#ifdef GL_ES\n"+
503                                                "precision highp float;\n" +
504                                                "precision highp int;\n"+
505                                                "precision mediump sampler3D;\n"+
506                                                "#endif\n";
507                            mShaderHeaderLines[0] += 6;
508                        }
509                        else
510                        {
511                            mShaderHeader[0] += "#ifdef GL_ES\n"+
512                                                "precision highp float;\n" +
513                                                "precision highp int;\n"+
514                                                "#endif\n"+
515                                                "float round( float x ) { return floor(x+0.5); }\n"+
516                                                "vec2 round(vec2 x) { return floor(x + 0.5); }\n"+
517                                                "vec3 round(vec3 x) { return floor(x + 0.5); }\n"+
518                                                "vec4 round(vec4 x) { return floor(x + 0.5); }\n"+
519                                                "float trunc( float x, float n ) { return floor(x*n)/n; }\n"+
520                                                "mat3 transpose(mat3 m) { return mat3(m[0].x, m[1].x, m[2].x, m[0].y, m[1].y, m[2].y, m[0].z, m[1].z, m[2].z); }\n"+
521                                                "float determinant( in mat2 m ) { return m[0][0]*m[1][1] - m[0][1]*m[1][0]; }\n"+
522                                                "float determinant( mat4 m ) { float b00 = m[0][0] * m[1][1] - m[0][1] * m[1][0], b01 = m[0][0] * m[1][2] - m[0][2] * m[1][0], b02 = m[0][0] * m[1][3] - m[0][3] * m[1][0], b03 = m[0][1] * m[1][2] - m[0][2] * m[1][1], b04 = m[0][1] * m[1][3] - m[0][3] * m[1][1], b05 = m[0][2] * m[1][3] - m[0][3] * m[1][2], b06 = m[2][0] * m[3][1] - m[2][1] * m[3][0], b07 = m[2][0] * m[3][2] - m[2][2] * m[3][0], b08 = m[2][0] * m[3][3] - m[2][3] * m[3][0], b09 = m[2][1] * m[3][2] - m[2][2] * m[3][1], b10 = m[2][1] * m[3][3] - m[2][3] * m[3][1], b11 = m[2][2] * m[3][3] - m[2][3] * m[3][2];  return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;}\n"+
523                                                "mat2 inverse(mat2 m) { float det = determinant(m); return mat2(m[1][1], -m[0][1], -m[1][0], m[0][0]) / det; }\n"+
524                                                "mat4 inverse(mat4 m ) { float inv0 = m[1].y*m[2].z*m[3].w - m[1].y*m[2].w*m[3].z - m[2].y*m[1].z*m[3].w + m[2].y*m[1].w*m[3].z + m[3].y*m[1].z*m[2].w - m[3].y*m[1].w*m[2].z; float inv4 = -m[1].x*m[2].z*m[3].w + m[1].x*m[2].w*m[3].z + m[2].x*m[1].z*m[3].w - m[2].x*m[1].w*m[3].z - m[3].x*m[1].z*m[2].w + m[3].x*m[1].w*m[2].z; float inv8 = m[1].x*m[2].y*m[3].w - m[1].x*m[2].w*m[3].y - m[2].x  * m[1].y * m[3].w + m[2].x  * m[1].w * m[3].y + m[3].x * m[1].y * m[2].w - m[3].x * m[1].w * m[2].y; float inv12 = -m[1].x  * m[2].y * m[3].z + m[1].x  * m[2].z * m[3].y +m[2].x  * m[1].y * m[3].z - m[2].x  * m[1].z * m[3].y - m[3].x * m[1].y * m[2].z + m[3].x * m[1].z * m[2].y; float inv1 = -m[0].y*m[2].z * m[3].w + m[0].y*m[2].w * m[3].z + m[2].y  * m[0].z * m[3].w - m[2].y  * m[0].w * m[3].z - m[3].y * m[0].z * m[2].w + m[3].y * m[0].w * m[2].z; float inv5 = m[0].x  * m[2].z * m[3].w - m[0].x  * m[2].w * m[3].z - m[2].x  * m[0].z * m[3].w + m[2].x  * m[0].w * m[3].z + m[3].x * m[0].z * m[2].w - m[3].x * m[0].w * m[2].z; float inv9 = -m[0].x  * m[2].y * m[3].w +  m[0].x  * m[2].w * m[3].y + m[2].x  * m[0].y * m[3].w - m[2].x  * m[0].w * m[3].y - m[3].x * m[0].y * m[2].w + m[3].x * m[0].w * m[2].y; float inv13 = m[0].x  * m[2].y * m[3].z - m[0].x  * m[2].z * m[3].y - m[2].x  * m[0].y * m[3].z + m[2].x  * m[0].z * m[3].y + m[3].x * m[0].y * m[2].z - m[3].x * m[0].z * m[2].y; float inv2 = m[0].y  * m[1].z * m[3].w - m[0].y  * m[1].w * m[3].z - m[1].y  * m[0].z * m[3].w + m[1].y  * m[0].w * m[3].z + m[3].y * m[0].z * m[1].w - m[3].y * m[0].w * m[1].z; float inv6 = -m[0].x  * m[1].z * m[3].w + m[0].x  * m[1].w * m[3].z + m[1].x  * m[0].z * m[3].w - m[1].x  * m[0].w * m[3].z - m[3].x * m[0].z * m[1].w + m[3].x * m[0].w * m[1].z; float inv10 = m[0].x  * m[1].y * m[3].w - m[0].x  * m[1].w * m[3].y - m[1].x  * m[0].y * m[3].w + m[1].x  * m[0].w * m[3].y + m[3].x * m[0].y * m[1].w - m[3].x * m[0].w * m[1].y; float inv14 = -m[0].x  * m[1].y * m[3].z + m[0].x  * m[1].z * m[3].y + m[1].x  * m[0].y * m[3].z - m[1].x  * m[0].z * m[3].y - m[3].x * m[0].y * m[1].z + m[3].x * m[0].z * m[1].y; float inv3 = -m[0].y * m[1].z * m[2].w + m[0].y * m[1].w * m[2].z + m[1].y * m[0].z * m[2].w - m[1].y * m[0].w * m[2].z - m[2].y * m[0].z * m[1].w + m[2].y * m[0].w * m[1].z; float inv7 = m[0].x * m[1].z * m[2].w - m[0].x * m[1].w * m[2].z - m[1].x * m[0].z * m[2].w + m[1].x * m[0].w * m[2].z + m[2].x * m[0].z * m[1].w - m[2].x * m[0].w * m[1].z; float inv11 = -m[0].x * m[1].y * m[2].w + m[0].x * m[1].w * m[2].y + m[1].x * m[0].y * m[2].w - m[1].x * m[0].w * m[2].y - m[2].x * m[0].y * m[1].w + m[2].x * m[0].w * m[1].y; float inv15 = m[0].x * m[1].y * m[2].z - m[0].x * m[1].z * m[2].y - m[1].x * m[0].y * m[2].z + m[1].x * m[0].z * m[2].y + m[2].x * m[0].y * m[1].z - m[2].x * m[0].z * m[1].y;
524 float det = m[0].x * inv0 + m[0].y * inv4 + m[0].z * inv8 + m[0].w * inv12; det = 1.0 / det; return det*mat4( inv0, inv1, inv2, inv3,inv4, inv5, inv6, inv7,inv8, inv9, inv10, inv11,inv12, inv13, inv14, inv15);}\n"+
525                                                "float sinh(float x)  { return (exp(x)-exp(-x))/2.; }\n"+
526                                                "float cosh(float x)  { return (exp(x)+exp(-x))/2.; }\n"+
527                                                "float tanh(float x)  { return sinh(x)/cosh(x); }\n"+
528                                                "float coth(float x)  { return cosh(x)/sinh(x); }\n"+
529                                                "float sech(float x)  { return 1./cosh(x); }\n"+
530                                                "float csch(float x)  { return 1./sinh(x); }\n"+
531                                                "float asinh(float x) { return    log(x+sqrt(x*x+1.)); }\n"+
532                                                "float acosh(float x) { return    log(x+sqrt(x*x-1.)); }\n"+
533                                                "float atanh(float x) { return .5*log((1.+x)/(1.-x)); }\n"+
534                                                "float acoth(float x) { return .5*log((x+1.)/(x-1.)); }\n"+
535                                                "float asech(float x) { return    log((1.+sqrt(1.-x*x))/x); }\n"+
536                                                "float acsch(float x) { return    log((1.+sqrt(1.+x*x))/x); }\n";
537                            mShaderHeaderLines[0] += 26;
538                        }
539
540                        //-------------------------------------------------------
541
542                        mShaderHeader[1] = "";
543                        mShaderHeaderLines[1] = 0;
544                        if( mIs20 )
545                        {
546                            mShaderHeader[1] += "#version 300 es\n"+
547                                                "#ifdef GL_ES\n"+
548                                                "precision highp float;\n"+
549                                                "precision highp int;\n"+
550                                                "precision mediump sampler3D;\n"+
551                                                "#endif\n";
552                            mShaderHeaderLines[1] += 6;
553                        }
554                        else
555                        {
556                            if( mDerivatives ) { mShaderHeader[1] += "#ifdef GL_OES_standard_derivatives\n#extension GL_OES_standard_derivatives : enable\n#endif\n"; mShaderHeaderLines[1]+=3; }
557                            if( mShaderTextureLOD  ) { mShaderHeader[1] += "#extension GL_EXT_shader_texture_lod : enable\n"; mShaderHeaderLines[1]++; }
558                            mShaderHeader[1] += "#ifdef GL_ES\n"+
559                                                "precision highp float;\n"+
560                                                "precision highp int;\n"+
561                                                "#endif\n"+
562                                                "vec4 texture(     sampler2D   s, vec2 c)                   { return texture2D(s,c); }\n"+
563                                                "vec4 texture(     sampler2D   s, vec2 c, float b)          { return texture2D(s,c,b); }\n"+
564                                                "vec4 texture(     samplerCube s, vec3 c )                  { return textureCube(s,c); }\n"+
565                                                "vec4 texture(     samplerCube s, vec3 c, float b)          { return textureCube(s,c,b); }\n"+
566                                                "float round( float x ) { return floor(x+0.5); }\n"+
567                                                "vec2 round(vec2 x) { return floor(x + 0.5); }\n"+
568                                                "vec3 round(vec3 x) { return floor(x + 0.5); }\n"+
569                                                "vec4 round(vec4 x) { return floor(x + 0.5); }\n"+
570                                                "float trunc( float x, float n ) { return floor(x*n)/n; }\n"+
571                                                "mat3 transpose(mat3 m) { return mat3(m[0].x, m[1].x, m[2].x, m[0].y, m[1].y, m[2].y, m[0].z, m[1].z, m[2].z); }\n"+
572                                                "float determinant( in mat2 m ) { return m[0][0]*m[1][1] - m[0][1]*m[1][0]; }\n"+
573                                                "float determinant( mat4 m ) { float b00 = m[0][0] * m[1][1] - m[0][1] * m[1][0], b01 = m[0][0] * m[1][2] - m[0][2] * m[1][0], b02 = m[0][0] * m[1][3] - m[0][3] * m[1][0], b03 = m[0][1] * m[1][2] - m[0][2] * m[1][1], b04 = m[0][1] * m[1][3] - m[0][3] * m[1][1], b05 = m[0][2] * m[1][3] - m[0][3] * m[1][2], b06 = m[2][0] * m[3][1] - m[2][1] * m[3][0], b07 = m[2][0] * m[3][2] - m[2][2] * m[3][0], b08 = m[2][0] * m[3][3] - m[2][3] * m[3][0], b09 = m[2][1] * m[3][2] - m[2][2] * m[3][1], b10 = m[2][1] * m[3][3] - m[2][3] * m[3][1], b11 = m[2][2] * m[3][3] - m[2][3] * m[3][2];  return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;}\n"+
574                                                "mat2 inverse(mat2 m) { float det = determinant(m); return mat2(m[1][1], -m[0][1], -m[1][0], m[0][0]) / det; }\n"+
575                                                "mat4 inverse(mat4 m ) { float inv0 = m[1].y*m[2].z*m[3].w - m[1].y*m[2].w*m[3].z - m[2].y*m[1].z*m[3].w + m[2].y*m[1].w*m[3].z + m[3].y*m[1].z*m[2].w - m[3].y*m[1].w*m[2].z; float inv4 = -m[1].x*m[2].z*m[3].w + m[1].x*m[2].w*m[3].z + m[2].x*m[1].z*m[3].w - m[2].x*m[1].w*m[3].z - m[3].x*m[1].z*m[2].w + m[3].x*m[1].w*m[2].z; float inv8 = m[1].x*m[2].y*m[3].w - m[1].x*m[2].w*m[3].y - m[2].x  * m[1].y * m[3].w + m[2].x  * m[1].w * m[3].y + m[3].x * m[1].y * m[2].w - m[3].x * m[1].w * m[2].y; float inv12 = -m[1].x  * m[2].y * m[3].z + m[1].x  * m[2].z * m[3].y +m[2].x  * m[1].y * m[3].z - m[2].x  * m[1].z * m[3].y - m[3].x * m[1].y * m[2].z + m[3].x * m[1].z * m[2].y;
575 float inv1 = -m[0].y*m[2].z * m[3].w + m[0].y*m[2].w * m[3].z + m[2].y  * m[0].z * m[3].w - m[2].y  * m[0].w * m[3].z - m[3].y * m[0].z * m[2].w + m[3].y * m[0].w * m[2].z; float inv5 = m[0].x  * m[2].z * m[3].w - m[0].x  * m[2].w * m[3].z - m[2].x  * m[0].z * m[3].w + m[2].x  * m[0].w * m[3].z + m[3].x * m[0].z * m[2].w - m[3].x * m[0].w * m[2].z; float inv9 = -m[0].x  * m[2].y * m[3].w +  m[0].x  * m[2].w * m[3].y + m[2].x  * m[0].y * m[3].w - m[2].x  * m[0].w * m[3].y - m[3].x * m[0].y * m[2].w + m[3].x * m[0].w * m[2].y; float inv13 = m[0].x  * m[2].y * m[3].z - m[0].x  * m[2].z * m[3].y - m[2].x  * m[0].y * m[3].z + m[2].x  * m[0].z * m[3].y + m[3].x * m[0].y * m[2].z - m[3].x * m[0].z * m[2].y; float inv2 = m[0].y  * m[1].z * m[3].w - m[0].y  * m[1].w * m[3].z - m[1].y  * m[0].z * m[3].w + m[1].y  * m[0].w * m[3].z + m[3].y * m[0].z * m[1].w - m[3].y * m[0].w * m[1].z; float inv6 = -m[0].x  * m[1].z * m[3].w + m[0].x  * m[1].w * m[3].z + m[1].x  * m[0].z * m[3].w - m[1].x  * m[0].w * m[3].z - m[3].x * m[0].z * m[1].w + m[3].x * m[0].w * m[1].z; float inv10 = m[0].x  * m[1].y * m[3].w - m[0].x  * m[1].w * m[3].y - m[1].x  * m[0].y * m[3].w + m[1].x  * m[0].w * m[3].y + m[3].x * m[0].y * m[1].w - m[3].x * m[0].w * m[1].y; float inv14 = -m[0].x  * m[1].y * m[3].z + m[0].x  * m[1].z * m[3].y + m[1].x  * m[0].y * m[3].z - m[1].x  * m[0].z * m[3].y - m[3].x * m[0].y * m[1].z + m[3].x * m[0].z * m[1].y; float inv3 = -m[0].y * m[1].z * m[2].w + m[0].y * m[1].w * m[2].z + m[1].y * m[0].z * m[2].w - m[1].y * m[0].w * m[2].z - m[2].y * m[0].z * m[1].w + m[2].y * m[0].w * m[1].z; float inv7 = m[0].x * m[1].z * m[2].w - m[0].x * m[1].w * m[2].z - m[1].x * m[0].z * m[2].w + m[1].x * m[0].w * m[2].z + m[2].x * m[0].z * m[1].w - m[2].x * m[0].w * m[1].z; float inv11 = -m[0].x * m[1].y * m[2].w + m[0].x * m[1].w * m[2].y + m[1].x * m[0].y * m[2].w - m[1].x * m[0].w * m[2].y - m[2].x * m[0].y * m[1].w + m[2].x * m[0].w * m[1].y; float inv15 = m[0].x * m[1].y * m[2].z - m[0].x * m[1].z * m[2].y - m[1].x * m[0].y * m[2].z + m[1].x * m[0].z * m[2].y + m[2].x * m[0].y * m[1].z - m[2].x * m[0].z * m[1].y; float det = m[0].x * inv0 + m[0].y * inv4 + m[0].z * inv8 + m[0].w * inv12; det = 1.0 / det; return det*mat4( inv0, inv1, inv2, inv3,inv4, inv5, inv6, inv7,inv8, inv9, inv10, inv11,inv12, inv13, inv14, inv15);}\n"+
576                                                "float sinh(float x)  { return (exp(x)-exp(-x))/2.; }\n"+
577                                                "float cosh(float x)  { return (exp(x)+exp(-x))/2.; }\n"+
578                                                "float tanh(float x)  { return sinh(x)/cosh(x); }\n"+
579                                                "float coth(float x)  { return cosh(x)/sinh(x); }\n"+
580                                                "float sech(float x)  { return 1./cosh(x); }\n"+
581                                                "float csch(float x)  { return 1./sinh(x); }\n"+
582                                                "float asinh(float x) { return    log(x+sqrt(x*x+1.)); }\n"+
583                                                "float acosh(float x) { return    log(x+sqrt(x*x-1.)); }\n"+
584                                                "float atanh(float x) { return .5*log((1.+x)/(1.-x)); }\n"+
585                                                "float acoth(float x) { return .5*log((x+1.)/(x-1.)); }\n"+
586                                                "float asech(float x) { return    log((1.+sqrt(1.-x*x))/x); }\n"+
587                                                "float acsch(float x) { return    log((1.+sqrt(1.+x*x))/x); }\n";
588                            mShaderHeaderLines[1] += 30;
589                            if( mShaderTextureLOD )
590                            {
591                            mShaderHeader[1] += "vec4 textureLod(  sampler2D   s, vec2 c, float b)          { return texture2DLodEXT(s,c,b); }\n";
592                            mShaderHeader[1] += "vec4 textureGrad( sampler2D   s, vec2 c, vec2 dx, vec2 dy) { return texture2DGradEXT(s,c,dx,dy); }\n";
593                            mShaderHeaderLines[1] += 2;
594
595                            //mShaderHeader[1] += "vec4 texelFetch( sampler2D s, ivec2 c, int l) { return texture2DLodEXT(s,(vec2(c)+0.5)/vec2(800,450),float(l)); }\n";
596                            //mShaderHeaderLines[1] += 1;
597                            }
598                        }
599
600                        return true;
601                    };
602
603        me.GetCaps =    function ()
604                        {
605                            return { mIsGL20 : mIs20,
606                                     mFloat32Textures: mFloat32Textures != null,
607                                     mFloat16Textures: mFloat16Textures != null,
608                                     mDrawBuffers: mDrawBuffers != null,
609                                     mDepthTextures: mDepthTextures != null,
610                                     mDerivatives: mDerivatives != null,
611                                     mShaderTextureLOD: mShaderTextureLOD != null };
612                        };
613
614        me.GetShaderHeaderLines = function (shaderType)
615                        {
616                            return mShaderHeaderLines[shaderType];
617                        };
618
619        me.CheckErrors = function()
620                         {
621                                var error = mGL.getError();
622                                if( error != mGL.NO_ERROR )
623                                {
624                                    for( var prop in mGL )
625                                    {
626                                        if( typeof mGL[prop] == 'number' )
627                                        {
628                                            if( mGL[prop] == error )
629                                            {
630                                                console.log( "GL Error " + error + ": " + prop );
631                                                break;
632                                            }
633                                        }
634                                    }
635                                }
636                         };
637
638        me.Clear =  function( flags, ccolor, cdepth, cstencil )
639                    {
640                        var mode = 0;
641                        if( flags & 1 ) { mode |= mGL.COLOR_BUFFER_BIT;   mGL.clearColor( ccolor[0], ccolor[1], ccolor[2], ccolor[3] ); }
642                        if( flags & 2 ) { mode |= mGL.DEPTH_BUFFER_BIT;   mGL.clearDepth( cdepth ); }
643                        if( flags & 4 ) { mode |= mGL.STENCIL_BUFFER_BIT; mGL.clearStencil( cstencil ); }
644                        mGL.clear( mode );
645                    };
646
647
648        me.CreateTexture = function ( type, xres, yres, format, filter, wrap, buffer)
649                           {
650                                if( mGL===null ) return null;
651
652                                var id = mGL.createTexture();
653
654                                var glFoTy = iFormatPI2GL( format );
655                                var glWrap = mGL.REPEAT; if (wrap === me.TEXWRP.CLAMP) glWrap = mGL.CLAMP_TO_EDGE;
656
657                                if( type===me.TEXTYPE.T2D )
658                                {
659                                    mGL.bindTexture( mGL.TEXTURE_2D, id );
660
661                                    mGL.texImage2D( mGL.TEXTURE_2D, 0, glFoTy.mGLFormat, xres, yres, 0, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
662                                    mGL.texParameteri( mGL.TEXTURE_2D, mGL.TEXTURE_WRAP_S, glWrap );
663                                    mGL.texParameteri( mGL.TEXTURE_2D, mGL.TEXTURE_WRAP_T, glWrap );
664
665                                    if (filter === me.FILTER.NONE)
666                                    {
667                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
668                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST);
669                                    }
670                                    else if (filter === me.FILTER.LINEAR)
671                                    {
672                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
673                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR);
674                                    }
675                                    else if (filter === me.FILTER.MIPMAP)
676                                    {
677                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
678                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR_MIPMAP_LINEAR);
679                                        mGL.generateMipmap(mGL.TEXTURE_2D);
680                                    }
681                                    else
682                                    {
683                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
684                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST_MIPMAP_LINEAR);
685                                        mGL.generateMipmap(mGL.TEXTURE_2D);
686                                    }
687
688                                    mGL.bindTexture( mGL.TEXTURE_2D, null );
689                                }
690                                else if( type===me.TEXTYPE.T3D )
691                                {
692                                    if( mIs20 )
693                                    {
694                                        mGL.bindTexture( mGL.TEXTURE_3D, id );
695                                        mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_BASE_LEVEL, 0);
696                                        mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAX_LEVEL, Math.log2(xres));
697                                        if (filter === me.FILTER.NONE)
698                                        {
699                                            mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
700                                            mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST);
701                                        }
702                                        else if (filter === me.FILTER.LINEAR)
703                                        {
704                                            mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
705                                            mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR);
706                                        }
707                                        else if (filter === me.FILTER.MIPMAP)
708                                        {
709                                            mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
710                                            mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR_MIPMAP_LINEAR);
711                                        }
712                                        else
713                                        {
714                                            mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
715                                            mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST_MIPMAP_LINEAR);
716                                            mGL.generateMipmap(mGL.TEXTURE_3D);
717                                        }
718                                        mGL.texImage3D( mGL.TEXTURE_3D, 0, glFoTy.mGLFormat, xres, yres, yres, 0, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
719
720                                        mGL.texParameteri( mGL.TEXTURE_3D, mGL.TEXTURE_WRAP_R, glWrap );
721                                        mGL.texParameteri( mGL.TEXTURE_3D, mGL.TEXTURE_WRAP_S, glWrap );
722                                        mGL.texParameteri( mGL.TEXTURE_3D, mGL.TEXTURE_WRAP_T, glWrap );
723
724                                        if (filter === me.FILTER.MIPMAP)
725                                            mGL.generateMipmap( mGL.TEXTURE_3D );
726                                        mGL.bindTexture( mGL.TEXTURE_3D, null );
727                                    }
728                                    else
729                                    {
730                                        return null;
731                                    }
732                                }
733                                else
734                                {
735                                    mGL.bindTexture( mGL.TEXTURE_CUBE_MAP, id );
736
737                                    mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glFoTy.mGLFormat, xres, yres, 0, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
738                                    mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glFoTy.mGLFormat, xres, yres, 0, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
739                                    mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glFoTy.mGLFormat, xres, yres, 0, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
740                                    mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glFoTy.mGLFormat, xres, yres, 0, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
741                                    mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glFoTy.mGLFormat, xres, yres, 0, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
742                                    mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glFoTy.mGLFormat, xres, yres, 0, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
743
744                                    if( filter === me.FILTER.NONE)
745                                    {
746                                        mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
747                                        mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST);
748                                    }
749                                    else if (filter === me.FILTER.LINEAR)
750                                    {
751                                        mGL.texParameteri( mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR );
752                                        mGL.texParameteri( mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR );
753                                    }
754                                    else if (filter === me.FILTER.MIPMAP)
755                                    {
756                                        mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
757                                        mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR_MIPMAP_LINEAR);
758                                    }
759
760                                    if (filter === me.FILTER.MIPMAP)
761                                        mGL.generateMipmap( mGL.TEXTURE_CUBE_MAP );
762
763                                    mGL.bindTexture( mGL.TEXTURE_CUBE_MAP, null );
764                                }
765                        return { mObjectID: id, mXres: xres, mYres: yres, mFormat: format, mType: type, mFilter: filter, mWrap: wrap, mVFlip:false };
766                        };
767
768        me.CreateTextureFromImage = function ( type, image, format, filter, wrap, flipY)
769                                {
770                                    if( mGL===null ) return null;
771
772                                    var id = mGL.createTexture();
773
774                                    var glFoTy = iFormatPI2GL( format );
775
776                                    var glWrap = mGL.REPEAT; if (wrap === me.TEXWRP.CLAMP) glWrap = mGL.CLAMP_TO_EDGE;
777
778                                    if( type===me.TEXTYPE.T2D )
779                                    {
780                                        mGL.bindTexture(mGL.TEXTURE_2D, id);
781
782                                        mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, flipY);
783                                        mGL.pixelStorei(mGL.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
784                                        if( mIs20 ) mGL.pixelStorei(mGL.UNPACK_COLORSPACE_CONVERSION_WEBGL, mGL.NONE );
785
786                     
786                   mGL.texImage2D(mGL.TEXTURE_2D, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image);
787
788                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_WRAP_S, glWrap);
789                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_WRAP_T, glWrap);
790
791                                        if (filter === me.FILTER.NONE)
792                                        {
793                                            mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
794                                            mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST);
795                                        }
796                                        else if (filter === me.FILTER.LINEAR)
797                                        {
798                                            mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
799                                            mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR);
800                                        }
801                                        else if( filter === me.FILTER.MIPMAP)
802                                        {
803                                            mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
804                                            mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR_MIPMAP_LINEAR);
805                                            mGL.generateMipmap(mGL.TEXTURE_2D);
806                                        }
807                                        else
808                                        {
809                                            mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
810                                            mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST_MIPMAP_LINEAR);
811                                            mGL.generateMipmap(mGL.TEXTURE_2D);
812                                        }
813                                        mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, false);
814                                        mGL.bindTexture(mGL.TEXTURE_2D, null);
815                                    }
816                                    else if( type===me.TEXTYPE.T3D )
817                                    {
818                                        return null;
819                                    }
820                                    else
821                                    {
822                                        mGL.bindTexture( mGL.TEXTURE_CUBE_MAP, id );
823                                        mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, flipY);
824                                        mGL.activeTexture( mGL.TEXTURE0 );
825                                        mGL.texImage2D(  mGL.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image[0] );
826                                        mGL.texImage2D(  mGL.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image[1] );
827                                        mGL.texImage2D(  mGL.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, (flipY ? image[3] : image[2]) );
828                                        mGL.texImage2D(  mGL.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, (flipY ? image[2] : image[3]) );
829                                        mGL.texImage2D(  mGL.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image[4] );
830                                        mGL.texImage2D(  mGL.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image[5] );
831
832                                        if( filter === me.FILTER.NONE)
833                                        {
834                                            mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
835                                            mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST);
836                                        }
837                                        else if (filter === me.FILTER.LINEAR)
838                                        {
839                                            mGL.texParameteri( mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR );
840                                            mGL.texParameteri( mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR );
841                                        }
842                                        else if (filter === me.FILTER.MIPMAP)
843                                        {
844                                            mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
845                                            mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR_MIPMAP_LINEAR);
846                                            mGL.generateMipmap( mGL.TEXTURE_CUBE_MAP );
847                                        }
848                                        mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, false);
849                                        mGL.bindTexture( mGL.TEXTURE_CUBE_MAP, null );
850                                    }
851                                    return { mObjectID: id, mXres: image.width, mYres: image.height, mFormat: format, mType: type, mFilter: filter, mWrap:wrap, mVFlip:flipY };
852                                };
853
854        me.SetSamplerFilter = function (te, filter, doGenerateMipsIfNeeded)
855                            {
856                                if (te.mFilter === filter) return;
857
858                                if (te.mType === me.TEXTYPE.T2D)
859                                {
860                                    mGL.bindTexture(mGL.TEXTURE_2D, te.mObjectID);
861
862                                    if (filter === me.FILTER.NONE)
863                                    {
864                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
865                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST);
866                                    }
867                                    else if (filter === me.FILTER.LINEAR)
868                                    {
869                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
870                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR);
871                                    }
872                                    else if (filter === me.FILTER.MIPMAP)
873                                    {
874                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
875                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR_MIPMAP_LINEAR);
876                                        if( doGenerateMipsIfNeeded ) mGL.generateMipmap(mGL.TEXTURE_2D);
877                                    }
878                                    else
879                                    {
880                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
881                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST_MIPMAP_LINEAR);
882                                        if( doGenerateMipsIfNeeded ) mGL.generateMipmap(mGL.TEXTURE_2D);
883                                    }
884
885                                    mGL.bindTexture(mGL.TEXTURE_2D, null);
886
887                                }
888                                else if (te.mType === me.TEXTYPE.T3D)
889                                {
890                                    mGL.bindTexture(mGL.TEXTURE_3D, te.mObjectID);
891
892                                    if (filter === me.FILTER.NONE)
893                                    {
894                                        mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
895                                        mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST);
896                                    }
897                                    else if (filter === me.FILTER.LINEAR)
898                                    {
899                                        mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
900                                        mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR);
901                                    }
902                                    else if (filter === me.FILTER.MIPMAP)
903                                    {
904                                        mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
905                                        mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR_MIPMAP_LINEAR);
906                                        if( doGenerateMipsIfNeeded ) mGL.generateMipmap(mGL.TEXTURE_3D);
907                                    }
908                                    else
909                                    {
910                                        mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
911                                        mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST_MIPMAP_LINEAR);
912                                        if( doGenerateMipsIfNeeded ) mGL.generateMipmap(mGL.TEXTURE_3D);
913                                    }
914
915                                    mGL.bindTexture(mGL.TEXTURE_3D, null);
916
917                                }
918                                else
919                                {
920                                    mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, te.mObjectID);
921
922                                    if (filter === me.FILTER.NONE)
923                                    {
924                                        mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
925                                        mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST);
926                                    }
927                                    else if (filter === me.FILTER.LINEAR)
928                                    {
929                                        mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
930                                        mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR);
931                                    }
932                                    else if (filter === me.FILTER.MIPMAP)
933                                    {
934                                        mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
935                                        mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR_MIPMAP_LINEAR);
936                                        if( doGenerateMipsIfNeeded ) mGL.generateMipmap(mGL.TEXTURE_CUBE_MAP);
937                                    }
938                                    else
939                                    {
940                                        mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
941                                        mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST_MIPMAP_LINEAR);
942                                        if( doGenerateMipsIfNeeded ) mGL.generateMipmap(mGL.TEXTURE_CUBE_MAP);
943                                    }
944
945                                    mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, null);
946                                }
947
948
949                                te.mFilter = filter;
950                            };
951
952        me.SetSamplerWrap = function (te, wrap)
953                            {
954                                if (te.mWrap === wrap) return;
955
956                                var glWrap = mGL.REPEAT; if (wrap === me.TEXWRP.CLAMP) glWrap = mGL.CLAMP_TO_EDGE;
957
958                                var id = te.mObjectID;
959
960                                if (te.mType === me.TEXTYPE.T2D)
961                                {
962                                    mGL.bindTexture(mGL.TEXTURE_2D, id);
963                                    mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_WRAP_S, glWrap);
964                                    mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_WRAP_T, glWrap);
965                                    mGL.bindTexture(mGL.TEXTURE_2D, null);
966
967                                }
968                                else if (te.mType === me.TEXTYPE.T3D)
969                                {
970                                    mGL.bindTexture(mGL.TEXTURE_3D, id);
971                                    mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_WRAP_R, glWrap);
972                                    mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_WRAP_S, glWrap);
973                                    mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_WRAP_T, glWrap);
974                                    mGL.bindTexture(mGL.TEXTURE_3D, null);
975                                }
976
977                                te.mWrap = wrap;
978                            };
979
980        me.SetSamplerVFlip = function (te, vflip, image)
981                            {
982                                if (te.mVFlip === vflip) return;
983
984                                var id = te.mObjectID;
985
986                                if (te.mType === me.TEXTYPE.T2D)
987                                {
988                                    if( image != null)
989                                    {
990                                        mGL.activeTexture( mGL.TEXTURE0 );
991                                        mGL.bindTexture(mGL.TEXTURE_2D, id);
992                                        mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, vflip);
993                                        var glFoTy = iFormatPI2GL( te.mFormat );
994                                        mGL.texImage2D(mGL.TEXTURE_2D, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image);
995                                        mGL.bindTexture(mGL.TEXTURE_2D, null);
996                                        mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, false);
997                                    }
998                                }
999                                else if (te.mType === me.TEXTYPE.CUBEMAP)
1000                                {
1001                                    if( image != null)
1002                                    {
1003                                        var glFoTy = iFormatPI2GL( te.mFormat );
1004                                        mGL.activeTexture( mGL.TEXTURE0 );
1005                                        mGL.bindTexture( mGL.TEXTURE_CUBE_MAP, id );
1006                                        mGL.pixelStorei( mGL.UNPACK_FLIP_Y_WEBGL, vflip);
1007                                        mGL.texImage2D(  mGL.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image[0] );
1008                                        mGL.texImage2D(  mGL.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image[1] );
1009                                        mGL.texImage2D(  mGL.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, (vflip ? image[3] : image[2]) );
1010                                        mGL.texImage2D(  mGL.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, (vflip ? image[2] : image[3]) );
1011                                        mGL.texImage2D(  mGL.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image[4] );
1012                                        mGL.texImage2D(  mGL.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image[5] );
1013                                        mGL.bindTexture( mGL.TEXTURE_CUBE_MAP, null );
1014                                        mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, false);
1015                                    }
1016
1017                                }
1018
1019                                te.mVFlip = vflip;
1020                            };
1021
1022        me.CreateMipmaps =  function (te)
1023                            {
1024                                if( te.mType===me.TEXTYPE.T2D )
1025                                {
1026                                    mGL.activeTexture(mGL.TEXTURE0);
1027                                    mGL.bindTexture(mGL.TEXTURE_2D, te.mObjectID);
1028                                    mGL.generateMipmap(mGL.TEXTURE_2D);
1029                                    mGL.bindTexture(mGL.TEXTURE_2D, null);
1030                                }
1031                                else if( te.mType===me.TEXTYPE.CUBEMAP )
1032                                {
1033                                    mGL.activeTexture(mGL.TEXTURE0);
1034                                    mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, te.mObjectID);
1035                                    mGL.generateMipmap( mGL.TEXTURE_CUBE_MAP );
1036                                    mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, null);
1037                                }
1038                            };
1039
1040        me.UpdateTexture =  function( tex, x0, y0, xres, yres, buffer )
1041                            {
1042                                var glFoTy = iFormatPI2GL( tex.mFormat );
1043                                if( tex.mType===me.TEXTYPE.T2D )
1044                                {
1045                                    mGL.activeTexture( mGL.TEXTURE0);
1046                                    mGL.bindTexture( mGL.TEXTURE_2D, tex.mObjectID );
1047                                    mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, tex.mVFlip );
1048                                    mGL.texSubImage2D( mGL.TEXTURE_2D, 0, x0, y0, xres, yres, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
1049                                    mGL.bindTexture( mGL.TEXTURE_2D, null );
1050                                    mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, false);
1051                                }
1052                            };
1053
1054        me.UpdateTextureFromImage = function( tex, image )
1055                                {
1056                                    var glFoTy = iFormatPI2GL( tex.mFormat );
1057                                    if( tex.mType===me.TEXTYPE.T2D )
1058                                    {
1059                                        mGL.activeTexture( mGL.TEXTURE0 );
1060                                        mGL.bindTexture( mGL.TEXTURE_2D, tex.mObjectID );
1061                                        mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, tex.mVFlip );
1062                                        mGL.texImage2D(  mGL.TEXTURE_2D, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image );
1063                                        mGL.bindTexture( mGL.TEXTURE_2D, null );
1064                                        mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, false);
1065                                    }
1066                                };
1067
1068        me.DestroyTexture = function( te )
1069                            {
1070                                 mGL.deleteTexture( te.mObjectID );
1071                            };
1072
1073        me.AttachTextures = function (num, t0, t1, t2, t3)
1074                            {
1075                                if (num > 0 && t0 != null)
1076                                {
1077                                    mGL.activeTexture(mGL.TEXTURE0);
1078                                         if (t0.mType === me.TEXTYPE.T2D) mGL.bindTexture(mGL.TEXTURE_2D, t0.mObjectID);
1079                                    else if (t0.mType === me.TEXTYPE.T3D) mGL.bindTexture(mGL.TEXTURE_3D, t0.mObjectID);
1080                                    else if (t0.mType === me.TEXTYPE.CUBEMAP) mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, t0.mObjectID);
1081                                }
1082
1083                                if (num > 1 && t1 != null)
1084                                {
1085                                    mGL.activeTexture(mGL.TEXTURE1);
1086                                         if (t1.mType === me.TEXTYPE.T2D) mGL.bindTexture(mGL.TEXTURE_2D, t1.mObjectID);
1087                                    else if (t1.mType === me.TEXTYPE.T3D) mGL.bindTexture(mGL.TEXTURE_3D, t1.mObjectID);
1088                                    else if (t1.mType === me.TEXTYPE.CUBEMAP) mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, t1.mObjectID);
1089                                }
1090
1091                                if (num > 2 && t2 != null)
1092                                {
1093                                    mGL.activeTexture(mGL.TEXTURE2);
1094                                         if (t2.mType === me.TEXTYPE.T2D) mGL.bindTexture(mGL.TEXTURE_2D, t2.mObjectID);
1095                                    else if (t2.mType === me.TEXTYPE.T3D) mGL.bindTexture(mGL.TEXTURE_3D, t2.mObjectID);
1096                                    else if (t2.mType === me.TEXTYPE.CUBEMAP) mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, t2.mObjectID);
1097                                }
1098
1099                                if (num > 3 && t3 != null)
1100                                {
1101                                    mGL.activeTexture(mGL.TEXTURE3);
1102                                         if (t3.mType === me.TEXTYPE.T2D) mGL.bindTexture(mGL.TEXTURE_2D, t3.mObjectID);
1103                                    else if (t3.mType === me.TEXTYPE.T3D) mGL.bindTexture(mGL.TEXTURE_3D, t3.mObjectID);
1104                                    else if (t3.mType === me.TEXTYPE.CUBEMAP) mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, t3.mObjectID);
1105                                }
1106                            };
1107
1108        me.DettachTextures = function()
1109                             {
1110                                mGL.activeTexture(mGL.TEXTURE0);
1111                                mGL.bindTexture(mGL.TEXTURE_2D, null);
1112                                mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, null);
1113
1114                                mGL.activeTexture(mGL.TEXTURE1);
1115                                mGL.bindTexture(mGL.TEXTURE_2D, null);
1116                                mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, null);
1117
1118                                mGL.activeTexture(mGL.TEXTURE2);
1119                                mGL.bindTexture(mGL.TEXTURE_2D, null);
1120                                mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, null);
1121
1122                                mGL.activeTexture(mGL.TEXTURE3);
1123                                mGL.bindTexture(mGL.TEXTURE_2D, null);
1124                                mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, null);
1125                             };
1126
1127        me.CreateRenderTarget = function ( color0, color1, color2, color3, depth, wantZbuffer )
1128                                {
1129                                    var id =  mGL.createFramebuffer();
1130                                    mGL.bindFramebuffer(mGL.FRAMEBUFFER, id);
1131
1132                                    if (depth === null)
1133                                    {
1134                                        if( wantZbuffer===true )
1135                                        {
1136                                            var zb = mGL.createRenderbuffer();
1137                                            mGL.bindRenderbuffer(mGL.RENDERBUFFER, zb);
1138                                            mGL.renderbufferStorage(mGL.RENDERBUFFER, mGL.DEPTH_COMPONENT16, color0.mXres, color0.mYres);
1139
1140                                            mGL.framebufferRenderbuffer(mGL.FRAMEBUFFER, mGL.DEPTH_ATTACHMENT, mGL.RENDERBUFFER, zb);
1141                                        }
1142                                    }
1143                                    else
1144                                    {
1145                                        mGL.framebufferTexture2D(mGL.FRAMEBUFFER, mGL.DEPTH_ATTACHMENT, mGL.TEXTURE_2D, depth.mOb
1145jectID, 0);
1146                                    }
1147
1148                                    if( color0 !=null ) mGL.framebufferTexture2D(mGL.FRAMEBUFFER, mGL.COLOR_ATTACHMENT0, mGL.TEXTURE_2D, color0.mObjectID, 0);
1149
1150                                    if (mGL.checkFramebufferStatus(mGL.FRAMEBUFFER) != mGL.FRAMEBUFFER_COMPLETE)
1151                                        return null;
1152
1153                                    mGL.bindRenderbuffer(mGL.RENDERBUFFER, null);
1154                                    mGL.bindFramebuffer(mGL.FRAMEBUFFER, null);
1155                                    return { mObjectID: id, mTex0: color0 };
1156                                };
1157
1158        me.DestroyRenderTarget = function ( tex )
1159                                 {
1160                                     mGL.deleteFramebuffer(tex.mObjectID);
1161                                 };
1162
1163        me.SetRenderTarget = function (tex)
1164                             {
1165                                if( tex===null )
1166                                    mGL.bindFramebuffer(mGL.FRAMEBUFFER, null);
1167                                else
1168                                    mGL.bindFramebuffer(mGL.FRAMEBUFFER, tex.mObjectID);
1169
1170                                //mGL.drawBuffers([mGL.COLOR_ATTACHMENT0, mGL.COLOR_ATTACHMENT1]);
1171                             };
1172
1173        me.CreateRenderTargetNew = function ( wantColor0, wantZbuffer, xres, yres, samples )
1174                                {
1175                                    var id =  mGL.createFramebuffer();
1176                                    mGL.bindFramebuffer(mGL.FRAMEBUFFER, id);
1177
1178                                    if( wantZbuffer===true )
1179                                    {
1180                                        var zb = mGL.createRenderbuffer();
1181                                        mGL.bindRenderbuffer(mGL.RENDERBUFFER, zb);
1182
1183                                        if( samples==1 )
1184                                        mGL.renderbufferStorage(mGL.RENDERBUFFER, mGL.DEPTH_COMPONENT16, xres, yres);
1185                                        else
1186                                        mGL.renderbufferStorageMultisample(mGL.RENDERBUFFER, samples, mGL.DEPTH_COMPONENT16, xres, yres);
1187                                        mGL.framebufferRenderbuffer(mGL.FRAMEBUFFER, mGL.DEPTH_ATTACHMENT, mGL.RENDERBUFFER, zb);
1188                                    }
1189
1190                                    if( wantColor0 )
1191                                    {
1192                                        var cb = mGL.createRenderbuffer();
1193                                        mGL.bindRenderbuffer(mGL.RENDERBUFFER, cb);
1194                                        if( samples==1 )
1195                                        mGL.renderbufferStorage(mGL.RENDERBUFFER, mGL.RGBA8, xres, yres);
1196                                        else
1197                                        mGL.renderbufferStorageMultisample(mGL.RENDERBUFFER, samples, mGL.RGBA8, xres, yres);
1198                                        mGL.framebufferRenderbuffer(mGL.FRAMEBUFFER, mGL.COLOR_ATTACHMENT0, mGL.RENDERBUFFER, cb);
1199                                    }
1200
1201                                    if (mGL.checkFramebufferStatus(mGL.FRAMEBUFFER) != mGL.FRAMEBUFFER_COMPLETE)
1202                                    {
1203                                        return null;
1204                                    }
1205                                    mGL.bindRenderbuffer(mGL.RENDERBUFFER, null);
1206                                    mGL.bindFramebuffer(mGL.FRAMEBUFFER, null);
1207                                    return { mObjectID: id, mXres: xres, mYres:yres, mTex0: color0 };
1208                                };
1209
1210        me.CreateRenderTargetCubeMap = function ( color0, depth, wantZbuffer )
1211                                {
1212                                    var id =  mGL.createFramebuffer();
1213                                    mGL.bindFramebuffer(mGL.FRAMEBUFFER, id);
1214
1215                                    if (depth === null)
1216                                    {
1217                                        if( wantZbuffer===true )
1218                                        {
1219                                            var zb = mGL.createRenderbuffer();
1220                                            mGL.bindRenderbuffer(mGL.RENDERBUFFER, zb);
1221                                            mGL.renderbufferStorage(mGL.RENDERBUFFER, mGL.DEPTH_COMPONENT16, color0.mXres, color0.mYres);
1222                                            mGL.framebufferRenderbuffer(mGL.FRAMEBUFFER, mGL.DEPTH_ATTACHMENT, mGL.RENDERBUFFER, zb);
1223                                        }
1224                                    }
1225                                    else
1226                                    {
1227                                        mGL.framebufferTexture2D(mGL.FRAMEBUFFER, mGL.DEPTH_ATTACHMENT, mGL.TEXTURE_2D, depth.mOb
1227jectID, 0);
1228                                    }
1229
1230                                    if( color0 !=null ) mGL.framebufferTexture2D(mGL.FRAMEBUFFER, mGL.COLOR_ATTACHMENT0, mGL.TEXTURE_CUBE_MAP_POSITIVE_X, color0.mObjectID, 0);
1231
1232                                    if (mGL.checkFramebufferStatus(mGL.FRAMEBUFFER) != mGL.FRAMEBUFFER_COMPLETE)
1233                                        return null;
1234
1235                                    mGL.bindRenderbuffer(mGL.RENDERBUFFER, null);
1236                                    mGL.bindFramebuffer(mGL.FRAMEBUFFER, null);
1237                                    return { mObjectID: id, mTex0: color0 };
1238                                };
1239
1240        me.SetRenderTargetCubeMap = function (fbo, face)
1241                             {
1242                                if( fbo===null )
1243                                    mGL.bindFramebuffer(mGL.FRAMEBUFFER, null);
1244                                else
1245                                {
1246                                    mGL.bindFramebuffer(mGL.FRAMEBUFFER, fbo.mOb
1246jectID);
1247                                    mGL.framebufferTexture2D(mGL.FRAMEBUFFER, mGL.COLOR_ATTACHMENT0, mGL.TEXTURE_CUBE_MAP_POSITIVE_X+face, fbo.mTex0.mObjectID, 0);
1248                                }
1249                             };
1250
1251
1252        me.BlitRenderTarget = function( dst, src )
1253                                {
1254                                    mGL.bindFramebuffer(mGL.READ_FRAMEBUFFER, src.mObjectID);
1255                                    mGL.bindFramebuffer(mGL.DRAW_FRAMEBUFFER, dst.mObjectID);
1256                                    mGL.clearBufferfv(mGL.COLOR, 0, [0.0, 0.0, 0.0, 1.0]);
1257                                    mGL.blitFramebuffer( 0, 0, src.mXres, src.mYres,
1258                                                         0, 0, src.mXres, src.mYres,
1259                                                         mGL.COLOR_BUFFER_BIT, mGL.LINEAR
1260                                    );
1261                                };
1262
1263        me.SetViewport = function( vp )
1264                         {
1265                              mGL.viewport( vp[0], vp[1], vp[2], vp[3] );
1266                         };
1267
1268        me.SetWriteMask = function( c0, c1, c2, c3, z )
1269                          {
1270                              mGL.depthMask(z);
1271                              mGL.colorMask(c0,c0,c0,c0);
1272                          };
1273
1274        me.SetState = function( stateName, stateValue )
1275                      {
1276                            if (stateName === me.RENDSTGATE.WIREFRAME)
1277                            {
1278                                if( stateValue ) mGL.polygonMode( mGL.FRONT_AND_BACK, mGL.LINE );
1279                                else             mGL.polygonMode( mGL.FRONT_AND_BACK, mGL.FILL );
1280                            }
1281                            else if (stateName === me.RENDSTGATE.FRONT_FACE)
1282                            {
1283                                if( stateValue ) mGL.cullFace( mGL.BACK );
1284                                else             mGL.cullFace( mGL.FRONT );
1285                            }
1286                            else if (stateName === me.RENDSTGATE.CULL_FACE)
1287                            {
1288                                if( stateValue ) mGL.enable( mGL.CULL_FACE );
1289                                else             mGL.disable( mGL.CULL_FACE );
1290                            }
1291                            else if (stateName === me.RENDSTGATE.DEPTH_TEST)
1292                            {
1293                                if( stateValue ) mGL.enable( mGL.DEPTH_TEST );
1294                                else             mGL.disable( mGL.DEPTH_TEST );
1295                            }
1296                            else if (stateName === me.RENDSTGATE.ALPHA_TO_COVERAGE)
1297                            {
1298                                if( stateValue ) { mGL.enable(  mGL.SAMPLE_ALPHA_TO_COVERAGE ); }
1299                                else             { mGL.disable( mGL.SAMPLE_ALPHA_TO_COVERAGE ); }
1300                            }
1301                      };
1302
1303        me.SetMultisample = function( v)
1304                    {
1305                        if( v===true )
1306                        {
1307                            mGL.enable(mGL.SAMPLE_COVERAGE);
1308                            mGL.sampleCoverage(1.0, false);
1309                        }
1310                        else
1311                        {
1312                            mGL.disable(mGL.SAMPLE_COVERAGE);
1313                        }
1314                    };
1315
1316        me.GetTranslatedShaderSource = function (shader)
1317                          {
1318                            if( mGL===null ) return null;
1319                            if( mDebugShader===null ) return null;
1320                            let vfs = mGL.getAttachedShaders(shader.mProgram);
1321                            let str = mDebugShader.getTranslatedShaderSource(vfs[1]);
1322                            let parts = str.split("GLSL END"); str = (parts.length<2) ? str : parts[1];
1323                            return str;
1324                          };
1325
1326        me.CreateShader = function (vsSource, fsSource, preventCache, forceSynch, onResolve)
1327                          {
1328                            if( mGL===null ) return;
1329
1330                            var vs = mGL.createShader( mGL.VERTEX_SHADER   );
1331                            var fs = mGL.createShader( mGL.FRAGMENT_SHADER );
1332
1333                            vsSource = mShaderHeader[0] + vsSource;
1334                            fsSource = mShaderHeader[1] + fsSource;
1335
1336                            if( preventCache )
1337                            {
1338                                let vran = Math.random().toString(36).substring(7);
1339                                let fran = Math.random().toString(36).substring(7);
1340                                vsSource += "\n#define K" + vran + "\n";
1341                                fsSource += "\n#define K" + fran + "\n";
1342                            }
1343
1344                            var timeStart = (new Date()).getTime();
1345
1346                            mGL.shaderSource(vs, vsSource);
1347                            mGL.shaderSource(fs, fsSource);
1348                            mGL.compileShader(vs);
1349                            mGL.compileShader(fs);
1350
1351                            var pr = mGL.createProgram();
1352                            mGL.attachShader(pr, vs);
1353                            mGL.attachShader(pr, fs);
1354                            mGL.linkProgram(pr);
1355
1356                            //-------------
1357                            let checkErrors = function()
1358                            {
1359                                if (!mGL.getProgramParameter(pr, mGL.LINK_STATUS))
1360                                {
1361                                    // vs error
1362                                    if (!mGL.getShaderParameter(vs, mGL.COMPILE_STATUS))
1363                                    {
1364                                        let vsLog = mGL.getShaderInfoLog(vs);
1365                                        onResolve(false, { mErrorType: 0, mErrorStr: vsLog });
1366                                        mGL.deleteProgram(pr);
1367                                    }
1368                                    // fs error
1369                                    else if (!mGL.getShaderParameter(fs, mGL.COMPILE_STATUS))
1370                                    {
1371                                        let fsLog = mGL.getShaderInfoLog(fs);
1372                                        onResolve(false, { mErrorType: 1, mErrorStr: fsLog });
1373                                        mGL.deleteProgram(pr);
1374                                    }
1375                                    // link error
1376                                    else
1377                                    {
1378                                        let infoLog = mGL.getProgramInfoLog(pr);
1379                                        onResolve(false, { mErrorType: 2, mErrorStr: infoLog });
1380                                        mGL.deleteProgram(pr);
1381                                    }
1382                                }
1383                                // no errors
1384                                else
1385                                {
1386                                    let compilationTime = (new Date()).getTime() - timeStart;
1387                                    onResolve(true, { mProgram: pr, mTime: compilationTime });
1388                                }
1389                            };
1390
1391                            // check compilation
1392                            if (mAsynchCompile === null || forceSynch===true )
1393                            {
1394                                checkErrors();
1395                            }
1396                            else
1397                            {
1398                                let loopCheckCompletion = function ()
1399                                {
1400                                    if( mGL.getProgramParameter(pr, mAsynchCompile.COMPLETION_STATUS_KHR
1400) === true )
1401                                        checkErrors();
1402                                    else
1403                                        setTimeout(loopCheckCompletion, 10);
1404                                };
1405                                setTimeout(loopCheckCompletion, 10);
1406                            }
1407                        };
1408
1409        me.AttachShader = function( shader )
1410                          {
1411                                if( shader===null )
1412                                {
1413                                    mBindedShader = null;
1414                                    mGL.useProgram( null );
1415                                }
1416                                else
1417                                {
1418                                    mBindedShader = shader;
1419                                    mGL.useProgram(shader.mProgram);
1420                                }
1421                          };
1422
1423        me.DetachShader = function ()
1424                        {
1425                            mGL.useProgram(null);
1426                        };
1427
1428        me.DestroyShader = function( tex )
1429                        {
1430                            mGL.deleteProgram(tex.mProgram);
1431                        };
1432
1433        me.GetAttribLocation = function (shader, name)
1434                        {
1435                            return mGL.getAttribLocation(shader.mProgram, name);
1436                        };
1437
1438        me.SetShaderConstantLocation = function (shader, name)
1439                        {
1440                            return mGL.getUniformLocation(shader.mProgram, name);
1441                        };
1442
1443        me.SetShaderConstantMat4F = function( uname, params, istranspose )
1444                        {
1445                            var program = mBindedShader;
1446
1447                            let pos = mGL.getUniformLocation( program.mProgram, uname );
1448                            if( pos===null )
1449                                return false;
1450
1451                            if( istranspose===false )
1452                            {
1453                                var tmp = new Float32Array( [ params[0], params[4], params[ 8], params[12],
1454                                                              params[1], params[5], params[ 9], params[13],
1455                                                              params[2], params[6], params[10], params[14],
1456                                                              params[3], params[7], params[11], params[15] ] );
1457	                            mGL.uniformMatrix4fv(pos,false,tmp);
1458                            }
1459                            else
1460                                mGL.uniformMatrix4fv(pos,false,new Float32Array(params) );
1461                            return true;
1462                        };
1463
1464        me.SetShaderConstant1F_Pos = function(pos, x)
1465                        {
1466                            mGL.uniform1f(pos, x);
1467                            return true;
1468                        };
1469
1470        me.SetShaderConstant1FV_Pos = function(pos, x)
1471                        {
1472                            mGL.uniform1fv(pos, x);
1473                            return true;
1474                        };
1475
1476        me.SetShaderConstant1F = function( uname, x )
1477                        {
1478                            var pos = mGL.getUniformLocation(mBindedShader.mProgram, uname);
1479                            if (pos === null)
1480                                return false;
1481                            mGL.uniform1f(pos, x);
1482                            return true;
1483                        };
1484
1485        me.SetShaderConstant1I = function(uname, x)
1486                        {
1487                            let pos = mGL.getUniformLocation(mBindedShader.mProgram, uname);
1488                            if (pos === null)
1489                                return false;
1490                            mGL.uniform1i(pos, x);
1491                            return true;
1492                        };
1493        me.SetShaderConstant1I_Pos = function(pos, x)
1494                        {
1495                            mGL.uniform1i(pos, x);
1496                            return true;
1497                        };
1498
1499
1500        me.SetShaderConstant2F = function(uname, x)
1501                        {
1502                            let pos = mGL.getUniformLocation(mBindedShader.mProgram, uname);
1503                            if (pos === null)
1504                                return false;
1505                            mGL.uniform2fv(pos, x);
1506                            return true;
1507                        };
1508
1509        me.SetShaderConstant3F = function(uname, x, y, z)
1510                        {
1511                            let pos = mGL.getUniformLocation(mBindedShader.mProgram, uname);
1512                            if (pos === null)
1513                                return false;
1514                            mGL.uniform3f(pos, x, y, z);
1515                            return true;
1516                        };
1517
1518        me.SetShaderConstant1FV = function(uname, x)
1519                        {
1520                            let pos = mGL.getUniformLocation(mBindedShader.mProgram, uname);
1521                            if (pos === null)
1522                                return false;
1523                            mGL.uniform1fv(pos, new Float32Array(x)
1523);
1524                            return true;
1525                        };
1526
1527        me.SetShaderConstant3FV = function(uname, x)
1528                        {
1529                            let pos = mGL.getUniformLocation(mBindedShader.mProgram, uname);
1530                            if (pos === null) return false;
1531                            mGL.uniform3fv(pos, new Float32Array(x) );
1532                            return true;
1533                        };
1534
1535        me.SetShaderConstant4FV = function(uname, x)
1536                        {
1537                            let pos = mGL.getUniformLocation(mBindedShader.mProgram, uname);
1538                            if (pos === null) return false;
1539                            mGL.uniform4fv(pos, new Float32Array(x) );
1540                            return true;
1541                        };
1542
1543        me.SetShaderTextureUnit = function( uname, unit )
1544                        {
1545                            var program = mBindedShader;
1546                            let pos = mGL.getUniformLocation(program.mProgram, uname);
1547                            if (pos === null) return false;
1548                            mGL.uniform1i(pos, unit);
1549                            return true;
1550                        };
1551
1552        me.CreateVertexArray = function( data, mode )
1553                        {
1554                            let id = mGL.createBuffer();
1555                            mGL.bindBuffer(mGL.ARRAY_BUFFER, id);
1556                            if (mode === me.BUFTYPE.STATIC)
1557                                mGL.bufferData(mGL.ARRAY_BUFFER, data, mGL.STATIC_DRAW);
1558                            else
1559                                mGL.bufferData(mGL.ARRAY_BUFFER, data, mGL.DYNAMIC_DRAW);
1560                            return { mObject: id };
1561                        };
1562
1563        me.CreateIndexArray = function( data, mode )
1564                        {
1565                            let id = mGL.createBuffer();
1566                            mGL.bindBuffer(mGL.ELEMENT_ARRAY_BUFFER, id );
1567                            if (mode === me.BUFTYPE.STATIC)
1568                                mGL.bufferData(mGL.ELEMENT_ARRAY_BUFFER, data, mGL.STATIC_DRAW);
1569                            else
1570                                mGL.bufferData(mGL.ELEMENT_ARRAY_BUFFER, data, mGL.DYNAMIC_DRAW);
1571                            return { mObject: id };
1572                        };
1573
1574        me.DestroyArray = function( tex )
1575                        {
1576                            mGL.destroyBuffer(tex.mObject);
1577                        };
1578
1579        me.AttachVertexArray = function( tex, attribs, pos )
1580                        {
1581                            let shader = mBindedShader;
1582
1583                            mGL.bindBuffer( mGL.ARRAY_BUFFER, tex.mObject);
1584
1585                            var num = attribs.mChannels.length;
1586                            var stride = attribs.mStride;
1587
1588                            var offset = 0;
1589                            for (var i = 0; i < num; i++)
1590                            {
1591                                var id = pos[i];
1592                                mGL.enableVertexAttribArray(id);
1593                                var dtype = mGL.FLOAT;
1594                                var dsize = 4;
1595                                     if( attribs.mChannels[i].mType === me.TYPE.UINT8   ) { dtype = mGL.UNSIGNED_BYTE;  dsize = 1; }
1596                                else if( attribs.mChannels[i].mType === me.TYPE.UINT16  ) { dtype = mGL.UNSIGNED_SHORT; dsize = 2; }
1597                                else if( attribs.mChannels[i].mType === me.TYPE.FLOAT32 ) { dtype = mGL.FLOAT;          dsize = 4; }
1598                                mGL.vertexAttribPointer(id, attribs.mChannels[i].mNumComponents, dtype, attribs.mChannels[i].mNormalize, stride, offset);
1599                                offset += attribs.mChannels[i].mNumComponents * dsize;
1600                            }
1601                        };
1602
1603        me.AttachIndexArray = function( tex )
1604                        {
1605                            mGL.bindBuffer(mGL.ELEMENT_ARRAY_BUFFER, tex.mObject);
1606                        };
1607
1608        me.DetachVertexArray = function (tex, attribs)
1609                        {
1610                            let num = attribs.mChannels.length;
1611                            for (let i = 0; i < num; i++)
1612                                mGL.disableVertexAttribArray(i);
1613                            mGL.bindBuffer(mGL.ARRAY_BUFFER, null);
1614                        };
1615
1616        me.DetachIndexArray = function( tex )
1617                        {
1618                            mGL.bindBuffer(mGL.ELEMENT_ARRAY_BUFFER, null);
1619                        };
1620
1621        me.DrawPrimitive = function( typeOfPrimitive, num, useIndexArray, numInstances )
1622                        {
1623                            let glType = mGL.POINTS;
1624                            if( typeOfPrimitive===me.PRIMTYPE.POINTS ) glType = mGL.POINTS;
1625                            if( typeOfPrimitive===me.PRIMTYPE.LINES ) glType = mGL.LINES;
1626                            if( typeOfPrimitive===me.PRIMTYPE.LINE_LOOP ) glType = mGL.LINE_LOOP;
1627                            if( typeOfPrimitive===me.PRIMTYPE.LINE_STRIP ) glType = mGL.LINE_STRIP;
1628                            if( typeOfPrimitive===me.PRIMTYPE.TRIANGLES ) glType = mGL.TRIANGLES;
1629                            if( typeOfPrimitive===me.PRIMTYPE.TRIANGLE_STRIP ) glType = mGL.TRIANGLE_STRIP;
1630
1631                            if( numInstances<=1 )
1632                            {
1633  	                            if( useIndexArray ) mGL.drawElements( glType, num, mGL.UNSIGNED_SHORT, 0 );
1634	                            else                mGL.drawArrays( glType, 0, num );
1635                            }
1636                            else
1637                            {
1638                                mGL.drawArraysInstanced(glType, 0, num, numInstances);
1639                                mGL.drawElementsInstanced( glType, num, mGL.UNSIGNED_SHORT, 0, numInstances);
1640                            }
1641                        };
1642
1643
1644        me.DrawFullScreenTriangle_XY = function( vpos )
1645                        {
1646                            mGL.bindBuffer( mGL.ARRAY_BUFFER, mVBO_Tri );
1647                            mGL.vertexAttribPointer( vpos, 2, mGL.FLOAT, false, 0, 0 );
1648                            mGL.enableVertexAttribArray( vpos );
1649                            mGL.drawArrays( mGL.TRIANGLES, 0, 3 );
1650                            mGL.disableVertexAttribArray( vpos );
1651                            mGL.bindBuffer( mGL.ARRAY_BUFFER, null );
1652                        };
1653
1654
1655        me.DrawUnitQuad_XY = function( vpos )
1656                        {
1657                            mGL.bindBuffer( mGL.ARRAY_BUFFER, mVBO_Quad );
1658                            mGL.vertexAttribPointer( vpos, 2, mGL.FLOAT, false, 0, 0 );
1659                            mGL.enableVertexAttribArray( vpos );
1660                            mGL.drawArrays( mGL.TRIANGLES, 0, 6 );
1661                            mGL.disableVertexAttribArray( vpos );
1662                            mGL.bindBuffer( mGL.ARRAY_BUFFER, null );
1663                        };
1664
1665        me.DrawUnitCube_XYZ_NOR = function( vpos )
1666                        {
1667                            mGL.bindBuffer( mGL.ARRAY_BUFFER, mVBO_CubePosNor );
1668                            mGL.vertexAttribPointer( vpos[0], 3, mGL.FLOAT, false, 0, 0 );
1669                            mGL.vertexAttribPointer( vpos[1], 3, mGL.FLOAT, false, 0, 0 );
1670                            mGL.enableVertexAttribArray( vpos[0] );
1671                            mGL.enableVertexAttribArray( vpos[1] );
1672                            mGL.drawArrays(mGL.TRIANGLE_STRIP, 0, 4);
1673                            mGL.drawArrays(mGL.TRIANGLE_STRIP, 4, 4);
1674                            mGL.drawArrays(mGL.TRIANGLE_STRIP, 8, 4);
1675                            mGL.drawArrays(mGL.TRIANGLE_STRIP, 12, 4);
1676                            mGL.drawArrays(mGL.TRIANGLE_STRIP, 16, 4);
1677                            mGL.drawArrays(mGL.TRIANGLE_STRIP, 20, 4);
1678                            mGL.disableVertexAttribArray( vpos[0] );
1679                            mGL.disableVertexAttribArray( vpos[1] );
1680                            mGL.bindBuffer( mGL.ARRAY_BUFFER, null );
1681                        }
1682
1683        me.DrawUnitCube_XYZ = function( vpos )
1684                        {
1685                            mGL.bindBuffer( mGL.ARRAY_BUFFER, mVBO_CubePos );
1686                            mGL.vertexAttribPointer( vpos, 3, mGL.FLOAT, false, 0, 0 );
1687                            mGL.enableVertexAttribArray( vpos );
1688                            mGL.drawArrays(mGL.TRIANGLE_STRIP, 0, 4);
1689                            mGL.drawArrays(mGL.TRIANGLE_STRIP, 4, 4);
1690                            mGL.drawArrays(mGL.TRIANGLE_STRIP, 8, 4);
1691                            mGL.drawArrays(mGL.TRIANGLE_STRIP, 12, 4);
1692                            mGL.drawArrays(mGL.TRIANGLE_STRIP, 16, 4);
1693                            mGL.drawArrays(mGL.TRIANGLE_STRIP, 20, 4);
1694                            mGL.disableVertexAttribArray( vpos );
1695                            mGL.bindBuffer( mGL.ARRAY_BUFFER, null );
1696                        }
1697
1698        me.SetBlend = function( enabled )
1699                    {
1700                        if( enabled )
1701                        {
1702                            mGL.enable( mGL.BLEND );
1703                            mGL.blendEquationSeparate( mGL.FUNC_ADD, mGL.FUNC_ADD );
1704                            mGL.blendFuncSeparate( mGL.SRC_ALPHA, mGL.ONE_MINUS_SRC_ALPHA, mGL.ONE, mGL.ONE_MINUS_SRC_ALPHA );
1705                        }
1706                        else
1707                        {
1708                            mGL.disable( mGL.BLEND );
1709                        }
1710                    };
1711
1712        me.GetPixelData = function( data, offset, xres, yres )
1713                        {
1714                            mGL.readPixels(0, 0, xres, yres, mGL.RGBA, mGL.UNSIGNED_BYTE, data, offset);
1715                        };
1716
1717        me.GetPixelDataRenderTarget = function( obj, data, xres, yres )
1718                        {
1719                            mGL.bindFramebuffer(mGL.FRAMEBUFFER, obj.mObjectID);
1720                            mGL.readBuffer(mGL.COLOR_ATTACHMENT0);
1721                            mGL.readPixels(0, 0, xres, yres, mGL.RGBA, mGL.FLOAT, data, 0);
1722                            mGL.bindFramebuffer(mGL.FRAMEBUFFER, null);
1723                        };
1724    return me;
1725}
1726//==============================================================================
1727//
1728// piLibs 2015-2017 - http://www.iquilezles.org/www/material/piLibs/piLibs.htm
1729//
1730// piShading
1731//
1732//==============================================================================
1733
1734function smoothstep(a, b, x)
1735{
1736    x = (x - a) / (b - a);
1737    if (x < 0) x = 0; else if (x > 1) x = 1;
1738    return x * x * (3.0 - 2.0 * x);
1739}
1740
1741function clamp01(x)
1742{
1743    if( x < 0.0 ) x = 0.0;
1744    if( x > 1.0 ) x = 1.0;
1745    return x;
1746}
1747
1748function clamp(x, a, b)
1749{
1750    if( x < a ) x = a;
1751    if( x > b ) x = b;
1752    return x;
1753}
1754
1755function screen(a, b)
1756{
1757    return 1.0 - (1.0 - a) * (1.0 - b);
1758}
1759
1760function parabola(x)
1761{
1762    return 4.0 * x * (1.0 - x);
1763}
1764
1765function min(a, b)
1766{
1767    return (a < b) ? a : b;
1768}
1769
1770function max(a, b)
1771{
1772    return (a > b) ? a : b;
1773}
1774
1775function noise( x )
1776{
1777    function grad(i, j, x, y)
1778    {
1779        var h = 7 * i + 131 * j;
1780        h = (h << 13) ^ h;
1781        h = (h * (h * h * 15731 + 789221) + 1376312589);
1782
1783        var rx = (h & 0x20000000) ? x : -x;
1784        var ry = (h & 0x10000000) ? y : -y;
1785
1786        return rx + ry;
1787    }
1788
1789    var i = [ Math.floor(x[0]), Math.floor(x[1]) ];
1790    var f = [ x[0] - i[0], x[1] - i[1] ];
1791    var w = [ f[0]*f[0]*(3.0-2.0*f[0]), f[1]*f[1]*(3.0-2.0*f[1]) ];
1792
1793    var a = grad( i[0]+0, i[1]+0, f[0]+0.0, f[1]+0.0 );
1794    var b = grad( i[0]+1, i[1]+0, f[0]-1.0, f[1]+0.0 );
1795    var c = grad( i[0]+0, i[1]+1, f[0]+0.0, f[1]-1.0 );
1796    var d = grad( i[0]+1, i[1]+1, f[0]-1.0, f[1]-1.0 );
1797
1798    return a + (b-a)*w[0] + (c-a)*w[1] + (a-b-c+d)*w[0]*w[1];
1799}//==============================================================================
1800//
1801// piLibs 2015-2017 - http://www.iquilezles.org/www/material/piLibs/piLibs.htm
1802//
1803// piVecTypes
1804//
1805//==============================================================================
1806
1807
1808function vec3( a, b, c )
1809{
1810    return [ a, b, c ];
1811}
1812
1813function add( a, b )
1814{
1815    return [ a[0]+b[0], a[1]+b[1], a[2]+b[2] ];
1816}
1817
1818function sub( a, b )
1819{
1820    return [ a[0]-b[0], a[1]-b[1], a[2]-b[2] ];
1821}
1822
1823function mul( a, s )
1824{
1825    return [ a[0]*s, a[1]*s, a[2]*s ];
1826}
1827
1828function cross( a, b )
1829{
1830    return [ a[1]*b[2] - a[2]*b[1],
1831             a[2]*b[0] - a[0]*b[2],
1832             a[0]*b[1] - a[1]*b[0] ];
1833}
1834
1835function dot( a, b )
1836{
1837    return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
1838}
1839
1840function normalize( v )
1841{
1842    var is = 1.0 / Math.sqrt( v[0]*v[0] + v[1]*v[1] + v[2]*v[2] );
1843    return [ v[0]*is, v[1]*is, v[2]*is ];
1844}
1845
1846function createCirclePoint( cen, uuu, vvv, rad, s, t )
1847{
1848    return [ cen[0] + rad*(uuu[0]*s + vvv[0]*t),
1849             cen[1] + rad*(uuu[1]*s + vvv[1]*t),
1850             cen[2] + rad*(uuu[2]*s + vvv[2]*t) ];
1851}
1852
1853function createTangent( a, b, c )
1854{
1855    var cb = normalize( [ c[0]-b[0], c[1]-b[1], c[2]-b[2] ] );
1856    var ba = normalize( [ b[0]-a[0], b[1]-a[1], b[2]-a[2] ] );
1857    return normalize( [ ba[0]+cb[0], ba[1]+cb[1], ba[2]+cb[2] ] );
1858
1859}
1860
1861//===================================
1862
1863function vec4( a, b, c, d )
1864{
1865    return [ a, b, c, d ];
1866}
1867
1868function getXYZ( v )
1869{
1870    return [ v[0], v[1], v[2] ];
1871}
1872
1873//===================================
1874
1875function setIdentity()
1876{
1877    return [ 1.0, 0.0, 0.0, 0.0,
1878             0.0, 1.0, 0.0, 0.0,
1879             0.0, 0.0, 1.0, 0.0,
1880             0.0, 0.0, 0.0, 1.0 ];
1881}
1882
1883function setRotationX( t )
1884{
1885    var sint = Math.sin(t);
1886    var cost = Math.cos(t);
1887
1888    return [ 1.0,   0.0,   0.0, 0.0,
1889             0.0,  cost, -sint, 0.0,
1890             0.0,  sint,  cost, 0.0,
1891             0.0,   0.0,   0.0, 1.0 ];
1892}
1893
1894function setRotationY( t )
1895{
1896    var sint = Math.sin(t);
1897    var cost = Math.cos(t);
1898
1899    return [ cost, 0.0, -sint, 0.0,
1900              0.0, 1.0,   0.0, 0.0,
1901             sint, 0.0,  cost, 0.0,
1902              0.0, 0.0,   0.0, 1.0 ];
1903}
1904
1905function extractRotationEuler( m)
1906{
1907    var res = [];
1908    if (m[0] == 1.0)
1909    {
1910        res[0] = Math.atan2(m[2], m[11]);
1911        res[1] = 0.0;
1912        res[2] = 0.0;
1913
1914    }
1915    else if (m[0] == -1.0)
1916    {
1917        res[0] = Math.atan2( m[2], m[11]);
1918        res[1] = 0.0;
1919        res[2] = 0.0;
1920    }
1921    else
1922    {
1923        res[0] = Math.atan2( -m[9], m[10]);
1924        res[1] = Math.atan2( m[8], Math.sqrt(m[9]*m[9] + m[10]*m[10]));
1925        res[2] = Math.atan2( m[4], m[0]);
1926    }
1927    return res;
1928}
1929
1930function setFromQuaternion( q )
1931{
1932    var ww = q[3]*q[3];
1933    var xx = q[0]*q[0];
1934    var yy = q[1]*q[1];
1935    var zz = q[2]*q[2];
1936
1937    return [ ww+xx-yy-zz,                   2.0*(q[0]*q[1] - q[3]*q[2]), 2.0*(q[0]*q[2] + q[3]*q[1]), 0.0,
1938               2.0*(q[0]*q[1] + q[3]*q[2]),   ww-xx+yy-zz,                 2.0*(q[1]*q[2] - q[3]*q[0]), 0.0,
1939               2.0*(q[0]*q[2] - q[3]*q[1]),   2.0*(q[1]*q[2] + q[3]*q[0]), ww-xx-yy+zz,                 0.0,
1940               0.0,                           0.0,                         0.0,                         1.0 ];
1941}
1942
1943function setPerspective( fovy, aspect, znear, zfar )
1944{
1945    var tan = Math.tan(fovy * Math.PI/180.0);
1946    var x = 1.0 / (tan*aspect);
1947    var y = 1.0 / (tan);
1948    var c = -(zfar + znear) / ( zfar - znear);
1949    var d = -(2.0 * zfar * znear) / (zfar - znear);
1950
1951    return [ x,    0.0,  0.0,  0.0,
1952             0.0,  y,    0.0,  0.0,
1953             0.0,  0.0,  c,     d,
1954             0.0,  0.0, -1.0,  0.0 ];
1955}
1956
1957function setLookAt( eye, tar, up )
1958{
1959    var dir = [ -tar[0]+eye[0], -tar[1]+eye[1], -tar[2]+eye[2] ];
1960
1961	var m00 = dir[2]*up[1] - dir[1]*up[2];
1962    var m01 = dir[0]*up[2] - dir[2]*up[0];
1963    var m02 = dir[1]*up[0] - dir[0]*up[1];
1964    var im = 1.0/Math.sqrt( m00*m00 + m01*m01 + m02*m02 );
1965    m00 *= im;
1966    m01 *= im;
1967    m02 *= im;
1968
1969	var m04 = m02*dir[1] - m01*dir[2];
1970    var m05 = m00*dir[2] - m02*dir[0];
1971    var m06 = m01*dir[0] - m00*dir[1];
1972    im = 1.0/Math.sqrt( m04*m04 + m05*m05 + m06*m06 );
1973    m04 *= im;
1974    m05 *= im;
1975    m06 *= im;
1976
1977	var m08 = dir[0];
1978	var m09 = dir[1];
1979	var m10 = dir[2];
1980    im = 1.0/Math.sqrt( m08*m08 + m09*m09 + m10*m10 );
1981    m08 *= im;
1982    m09 *= im;
1983    m10 *= im;
1984
1985	var m03 = -(m00*eye[0] + m01*eye[1] + m02*eye[2] );
1986	var m07 = -(m04*eye[0] + m05*eye[1] + m06*eye[2] );
1987	var m11 = -(m08*eye[0] + m09*eye[1] + m10*eye[2] );
1988
1989    return [ m00, m01, m02, m03,
1990             m04, m05, m06, m07,
1991             m08, m09, m10, m11,
1992             0.0, 0.0, 0.0, 1.0 ];
1993}
1994
1995
1996function setOrtho( left, right, bottom, top, znear, zfar )
1997{
1998   var x = 2.0 / (right - left);
1999   var y = 2.0 / (top - bottom);
2000   var a = (right + left) / (right - left);
2001   var b = (top + bottom) / (top - bottom);
2002   var c = -2.0 / (zfar - znear);
2003   var d = -(zfar + znear) / ( zfar - znear);
2004
2005   return [  x, 0.0, 0.0,   a,
2006           0.0,   y, 0.0,   b,
2007           0.0, 0.0,   c,   d,
2008           0.0, 0.0, 0.0, 1.0 ];
2009}
2010
2011function setTranslation( p )
2012{
2013    return [ 1.0, 0.0, 0.0, p[0],
2014             0.0, 1.0, 0.0, p[1],
2015             0.0, 0.0, 1.0, p[2],
2016             0.0, 0.0, 0.0, 1.0 ];
2017}
2018
2019function setScale( s )
2020{
2021    return [ s[0], 0.0,  0.0,  0.0,
2022             0.0,  s[1], 0.0,  0.0,
2023             0.0,  0.0,  s[2], 0.0,
2024             0.0,  0.0,  0.0,  1.0];
2025}
2026
2027function setProjection( fov, znear, zfar )
2028{
2029    var x = 2.0 / (fov[3]+fov[2]);
2030    var y = 2.0 / (fov[0]+fov[1]);
2031    var a = (fov[3]-fov[2]) / (fov[3]+fov[2]);
2032    var b = (fov[0]-fov[1]) / (fov[0]+fov[1]);
2033    var c = -(zfar + znear) / ( zfar - znear);
2034    var d = -(2.0*zfar*znear) / (zfar - znear);
2035    return [   x, 0.0,    a, 0.0,
2036             0.0,   y,    b, 0.0,
2037             0.0, 0.0,    c,   d,
2038             0.0, 0.0, -1.0, 0.0 ];
2039   // inverse is:
2040   //return mat4x4( 1.0/x, 0.0f,  0.0f,   a/x,
2041   //               0.0f,  1.0/y, 0.0f,   b/x,
2042   //               0.0f,  0.0f,  0.0f,   -1.0,
2043   //               0.0f,  0.0f,  1.0f/d, c/d );
2044}
2045
2046
2047function invertFast( m )
2048{
2049    var inv = [
2050
2051             m[5]  * m[10] * m[15] -
2052             m[5]  * m[11] * m[14] -
2053             m[9]  * m[6]  * m[15] +
2054             m[9]  * m[7]  * m[14] +
2055             m[13] * m[6]  * m[11] -
2056             m[13] * m[7]  * m[10],
2057
2058             -m[1]  * m[10] * m[15] +
2059              m[1]  * m[11] * m[14] +
2060              m[9]  * m[2] * m[15] -
2061              m[9]  * m[3] * m[14] -
2062              m[13] * m[2] * m[11] +
2063              m[13] * m[3] * m[10],
2064
2065             m[1]  * m[6] * m[15] -
2066             m[1]  * m[7] * m[14] -
2067             m[5]  * m[2] * m[15] +
2068             m[5]  * m[3] * m[14] +
2069             m[13] * m[2] * m[7] -
2070             m[13] * m[3] * m[6],
2071
2072             -m[1] * m[6] * m[11] +
2073              m[1] * m[7] * m[10] +
2074              m[5] * m[2] * m[11] -
2075              m[5] * m[3] * m[10] -
2076              m[9] * m[2] * m[7] +
2077              m[9] * m[3] * m[6],
2078
2079             -m[4]  * m[10] * m[15] +
2080              m[4]  * m[11] * m[14] +
2081              m[8]  * m[6]  * m[15] -
2082              m[8]  * m[7]  * m[14] -
2083              m[12] * m[6]  * m[11] +
2084              m[12] * m[7]  * m[10],
2085
2086             m[0]  * m[10] * m[15] -
2087             m[0]  * m[11] * m[14] -
2088             m[8]  * m[2] * m[15] +
2089             m[8]  * m[3] * m[14] +
2090             m[12] * m[2] * m[11] -
2091             m[12] * m[3] * m[10],
2092
2093             -m[0]  * m[6] * m[15] +
2094              m[0]  * m[7] * m[14] +
2095              m[4]  * m[2] * m[15] -
2096              m[4]  * m[3] * m[14] -
2097              m[12] * m[2] * m[7] +
2098              m[12] * m[3] * m[6],
2099
2100
2101             m[0] * m[6] * m[11] -
2102             m[0] * m[7] * m[10] -
2103             m[4] * m[2] * m[11] +
2104             m[4] * m[3] * m[10] +
2105             m[8] * m[2] * m[7] -
2106             m[8] * m[3] * m[6],
2107
2108
2109             m[4]  * m[9] * m[15] -
2110             m[4]  * m[11] * m[13] -
2111             m[8]  * m[5] * m[15] +
2112             m[8]  * m[7] * m[13] +
2113             m[12] * m[5] * m[11] -
2114             m[12] * m[7] * m[9],
2115
2116
2117
2118             -m[0]  * m[9] * m[15] +
2119              m[0]  * m[11] * m[13] +
2120              m[8]  * m[1] * m[15] -
2121              m[8]  * m[3] * m[13] -
2122              m[12] * m[1] * m[11] +
2123              m[12] * m[3] * m[9],
2124
2125              m[0]  * m[5] * m[15] -
2126              m[0]  * m[7] * m[13] -
2127              m[4]  * m[1] * m[15] +
2128              m[4]  * m[3] * m[13] +
2129              m[12] * m[1] * m[7] -
2130              m[12] * m[3] * m[5],
2131
2132              -m[0] * m[5] * m[11] +
2133               m[0] * m[7] * m[9] +
2134               m[4] * m[1] * m[11] -
2135               m[4] * m[3] * m[9] -
2136               m[8] * m[1] * m[7] +
2137               m[8] * m[3] * m[5],
2138
2139              -m[4]  * m[9] * m[14] +
2140               m[4]  * m[10] * m[13] +
2141               m[8]  * m[5] * m[14] -
2142               m[8]  * m[6] * m[13] -
2143               m[12] * m[5] * m[10] +
2144               m[12] * m[6] * m[9],
2145
2146              m[0]  * m[9] * m[14] -
2147              m[0]  * m[10] * m[13] -
2148              m[8]  * m[1] * m[14] +
2149              m[8]  * m[2] * m[13] +
2150              m[12] * m[1] * m[10] -
2151              m[12] * m[2] * m[9],
2152
2153              -m[0]  * m[5] * m[14] +
2154               m[0]  * m[6] * m[13] +
2155               m[4]  * m[1] * m[14] -
2156               m[4]  * m[2] * m[13] -
2157               m[12] * m[1] * m[6] +
2158               m[12] * m[2] * m[5],
2159
2160              m[0] * m[5] * m[10] -
2161              m[0] * m[6] * m[9] -
2162              m[4] * m[1] * m[10] +
2163              m[4] * m[2] * m[9] +
2164              m[8] * m[1] * m[6] -
2165              m[8] * m[2] * m[5] ];
2166
2167    var det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];
2168
2169    det = 1.0/det;
2170
2171    for( var i = 0; i<16; i++ ) inv[i] = inv[i] * det;
2172
2173    return inv;
2174}
2175
2176function matMul( a, b )
2177{
2178    var res = [];
2179    for( var i=0; i<4; i++ )
2180    {
2181        var x = a[4*i+0];
2182        var y = a[4*i+1];
2183        var z = a[4*i+2];
2184        var w = a[4*i+3];
2185
2186        res[4*i+0] = x * b[ 0] + y * b[ 4] + z * b[ 8] + w * b[12];
2187        res[4*i+1] = x * b[ 1] + y * b[ 5] + z * b[ 9] + w * b[13];
2188        res[4*i+2] = x * b[ 2] + y * b[ 6] + z * b[10] + w * b[14];
2189        res[4*i+3] = x * b[ 3] + y * b[ 7] + z * b[11] + w * b[15];
2190    }
2191
2192    return res;
2193}
2194
2195function matMulpoint( m, v )
2196{
2197    return [ m[0]*v[0] + m[1]*v[1] + m[ 2]*v[2] + m[ 3],
2198             m[4]*v[0] + m[5]*v[1] + m[ 6]*v[2] + m[ 7],
2199             m[8]*v[0] + m[9]*v[1] + m[10]*v[2] + m[11] ];
2200}
2201
2202function matMulvec( m, v )
2203{
2204    return [ m[0]*v[0] + m[1]*v[1] + m[ 2]*v[2],
2205             m[4]*v[0] + m[5]*v[1] + m[ 6]*v[2],
2206             m[8]*v[0] + m[9]*v[1] + m[10]*v[2] ];
2207}
2208
2209
2210function bound3( infi )
2211{
2212    return [ infi, -infi, infi, -infi, infi, -infi ];
2213}
2214
2215function bound3_include( a, p )
2216{
2217    return [
2218        (p[0]<a[0]) ? p[0] : a[0],
2219        (p[0]>a[1]) ? p[0] : a[1],
2220        (p[1]<a[2]) ? p[1] : a[2],
2221        (p[1]>a[3]) ? p[1] : a[3],
2222        (p[2]<a[4]) ? p[2] : a[4],
2223        (p[2]>a[5]) ? p[2] : a[5] ];
2224}
2225
2226function bound3_center( b )
2227{
2228    return [ 0.5*(b[0]+b[1]),
2229             0.5*(b[2]+b[3]),
2230             0.5*(b[4]+b[5]) ];
2231}
2232
2233function bound3_radius( b )
2234{
2235    return [ 0.5*(b[1]-b[0]),
2236             0.5*(b[3]-b[2]),
2237             0.5*(b[5]-b[4]) ];
2238}
2239//==============================================================================
2240//
2241// piLibs 2015-2017 - http://www.iquilezles.org/www/material/piLibs/piLibs.htm
2242//
2243// piWebVR
2244//
2245//==============================================================================
2246
2247function WebVR( isVREnabledCallback, canvasElement )
2248{
2249    isVREnabledCallback(false);
2250}
2251
2252WebVR.prototype.IsSupported = function()
2253{
2254    return false;
2255    //return this.mSupportVR;
2256}
2257
2258WebVR.prototype.GetData = function( id )
2259{
2260    return {};
2261}
2262
2263WebVR.prototype.Enable = function( id )
2264{
2265}
2266
2267WebVR.prototype.Disable = function( id )
2268{
2269}
2270
2271WebVR.prototype.RequestAnimationFrame = function (id)
2272{
2273}
2274
2275WebVR.prototype.IsPresenting = function (id)
2276{
2277    return false;
2278}
2279
2280WebVR.prototype.Finish = function (id)
2281{
2282}
2283
2284//==============================================================================
2285//
2286// piLibs 2015-2017 - http://www.iquilezles.org/www/material/piLibs/piLibs.htm
2287//
2288// piWebUtils
2289//
2290//==============================================================================
2291
2292
2293
2294function htmlEntities(str)
2295{
2296    return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g,'&apos;');
2297}
2298
2299function piDisableTouch()
2300{}
2301
2302var piGetTime = function ( timestamp )
2303{
2304    if (timestamp == 0)
2305        return "";
2306    return new Date(timestamp * 1000).toISOString().substr(0, 10);
2307}
2308
2309function piGetCoords( obj )
2310{
2311    var x = 0;
2312    var y = 0;
2313    do
2314    {
2315         x += obj.offsetLeft;
2316         y += obj.offsetTop;
2317    }while( obj = obj.offsetParent );
2318
2319    return { mX:x, mY:y };
2320}
2321
2322function piGetMouseCoords( ev, canvasElement )
2323{
2324    var pos = piGetCoords(canvasElement );
2325    var mcx =                        (ev.pageX - pos.mX) * canvasElement.width / canvasElement.offsetWidth;
2326    var mcy = canvasElement.height - (ev.pageY - pos.mY) * canvasElement.height / canvasElement.offsetHeight;
2327
2328    return { mX: mcx, mY: mcy };
2329
2330}
2331
2332function piGetSourceElement( e )
2333{
2334    var ele = null;
2335    if( e.target )     ele = e.target;
2336    if( e.srcElement ) ele = e.srcElement;
2337    return ele;
2338}
2339
2340function piRequestFullScreen( ele )
2341{}
2342
2343function piIsFullScreen()
2344{
2345    return false;
2346}
2347
2348function piExitFullScreen()
2349{}
2350
2351function piIsMobile()
2352{
2353    return false;
2354}
2355
2356function piCreateGlContext( cv, useAlpha, useDepth, usePreserveBuffer, useSupersampling )
2357{
2358    var opts = { alpha: useAlpha,
2359                 depth: useDepth,
2360                 stencil: false,
2361                 premultipliedAlpha: false,
2362                 antialias: useSupersampling,
2363                 preserveDrawingBuffer: usePreserveBuffer,
2364                 powerPreference: "high-performance" }; // "low_power", "high_performance", "default"
2365
2366    var gl = null;
2367    if( gl === null) gl = cv.getContext( "webgl2", opts );
2368    if( gl === null) gl = cv.getContext( "experimental-webgl2", opts );
2369    if( gl === null) gl = cv.getContext( "webgl", opts );
2370    if( gl === null) gl = cv.getContext( "experimental-webgl", opts );
2371
2372    return gl;
2373}
2374
2375function piCreateAudioContext()
2376{
2377    return null;
2378}
2379
2380function piHexColorToRGB(str) // "#ff3041"
2381{
2382    var rgb = parseInt(str.slice(1), 16);
2383    var r = (rgb >> 16) & 255;
2384    var g = (rgb >> 8) & 255;
2385    var b = (rgb >> 0) & 255;
2386    return [r, g, b];
2387}
2388
2389function piCreateFPSCounter()
2390{
2391    var mFrame;
2392    var mTo;
2393    var mFPS;
2394
2395    var iReset = function( time )
2396    {
2397        mFrame = 0;
2398        mTo = time;
2399        mFPS = 60.0;
2400    }
2401
2402    var iCount = function( time )
2403    {
2404        mFrame++;
2405
2406        if( (time-mTo)>500.0 )
2407        {
2408            mFPS = 1000.0*mFrame/(time-mTo);
2409            mFrame = 0;
2410            mTo = time;
2411            return true;
2412        }
2413        return false;
2414    }
2415
2416    var iGetFPS = function()
2417    {
2418        return mFPS;
2419    }
2420
2421    return { Reset : iReset, Count : iCount, GetFPS : iGetFPS };
2422}
2423
2424function piCanMediaRecorded(canvas)
2425{
2426    return true;
2427}
2428
2429function piCreateMediaRecorder(isRecordingCallback, canvas)
2430{
2431    if (piCanMediaRecorded(canvas) == false)
2432    {
2433        return null;
2434    }
2435
2436    var options = { audioBitsPerSecond : 0, videoBitsPerSecond : 8000000 };
2437	     if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) options.mimeType = 'video/webm;codecs=h264';
2438    else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9' )) options.mimeType = 'video/webm;codecs=vp9';
2439    else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8' )) options.mimeType = 'video/webm;codecs=vp8';
2440    else                                                              options.mimeType = 'video/webm;';
2441
2442    var mediaRecorder = new MediaRecorder(canvas.captureStream(), options);
2443    var chunks = [];
2444
2445    mediaRecorder.ondataavailable = function(e)
2446    {
2447        if (e.data.size > 0)
2448        {
2449            chunks.push(e.data);
2450        }
2451    };
2452
2453    mediaRecorder.onstart = function(){
2454        isRecordingCallback( true );
2455    };
2456
2457    mediaRecorder.onstop = function()
2458    {
2459         isRecordingCallback( false );
2460     };
2461
2462    return mediaRecorder;
2463}
2464
2465function piExportToEXR(width, height, numComponents, type, bytes)
2466{
2467    var bytesPerComponent = 0;
2468    if      (type=="Uint")   bytesPerComponent = 4;
2469    else if (type=="Half")   bytesPerComponent = 2;
2470    else if (type=="Float")  bytesPerComponent = 4;
2471
2472    var tHeader = 258 + (18 * numComponents + 1);
2473    var tTable = 8 * height;
2474    var tScanlines = height * (4 + 4 + (numComponents * bytesPerComponent * width));
2475    var tTotal = tHeader + tTable + tScanlines;
2476
2477    var buffer = new ArrayBuffer(tTotal);
2478    var data = new DataView(buffer);
2479
2480    // Header
2481    {
2482        // Header : 4 bytes -> 0x76, 0x2f, 0x31, 0x01
2483        var c = 0;
2484        data.setUint8 (c++, 0x76);
2485        data.setUint8 (c++, 0x2f);
2486        data.setUint8 (c++, 0x31);
2487        data.setUint8 (c++, 0x01);
2488
2489        // Version : 4 bytes -> 2, 0, 0, 0
2490        data.setUint8 (c++, 0x02);
2491        data.setUint8 (c++, 0x0);
2492        data.setUint8 (c++, 0x0);
2493        data.setUint8 (c++, 0x0);
2494
2495        // Write channel info
2496        // Write attribute name : "channels"
2497            data.setUint8 (c++, 0x63);
2498            data.setUint8 (c++, 0x68);
2499            data.setUint8 (c++, 0x61);
2500            data.setUint8 (c++, 0x6e);
2501            data.setUint8 (c++, 0x6e);
2502            data.setUint8 (c++, 0x65);
2503            data.setUint8 (c++, 0x6c);
2504            data.setUint8 (c++, 0x73);
2505            data.setUint8 (c++, 0x0);
2506
2507            // Write attribute type : "chlist"
2508            data.setUint8 (c++, 0x63);
2509            data.setUint8 (c++, 0x68);
2510            data.setUint8 (c++, 0x6c);
2511            data.setUint8 (c++, 0x69);
2512            data.setUint8 (c++, 0x73);
2513            data.setUint8 (c++, 0x74);
2514            data.setUint8 (c++, 0x00);
2515
2516            // Write attribute size : 18 x 3 + 1 = 55
2517            var attribSize = 18 * numComponents + 1;
2518            data.setUint8 (c++, attribSize);
2519            data.setUint8 (c++, 0x00);
2520            data.setUint8 (c++, 0x00);
2521            data.setUint8 (c++, 0x00);
2522
2523            var i;
2524            for (i = 0; i < numComponents; i++)
2525            {
2526                // Attribute : "B" (42) "G" (47) "R" (52)
2527                if (i==0)       data.setUint8 (c++, 0x42);
2528                else if (i==1)  data.setUint8 (c++, 0x47);
2529                else if (i==2)  data.setUint8 (c++, 0x52);
2530                data.setUint8 (c++, 0x00);
2531
2532                // Value : Float (2), Half (1), Uint (0)
2533                if      (type=="Uint")   data.setUint8 (c++, 0x00);
2534                else if (type=="Half")   data.setUint8 (c++, 0x01);
2535                else if (type=="Float")  data.setUint8 (c++, 0x02);
2536                data.setUint8 (c++, 0x00);
2537                data.setUint8 (c++, 0x00);
2538                data.setUint8 (c++, 0x00);
2539
2540                // Plinear
2541                data.setUint8 (c++, 0x01);
2542
2543                // Reserved
2544                data.setUint8 (c++, 0x00);
2545                data.setUint8 (c++, 0x00);
2546                data.setUint8 (c++, 0x00);
2547
2548                // X sampling
2549                data.setUint8 (c++, 0x01);
2550                data.setUint8 (c++, 0x00);
2551                data.setUint8 (c++, 0x00);
2552                data.setUint8 (c++, 0x00);
2553
2554                // Y sampling
2555                data.setUint8 (c++, 0x01);
2556                data.setUint8 (c++, 0x00);
2557                data.setUint8 (c++, 0x00);
2558                data.setUint8 (c++, 0x00);
2559            }
2560            // End attribute
2561            data.setUint8 (c++, 0x00);
2562
2563        // Write attribute name : "compression"
2564            data.setUint8 (c++, 0x63);
2565            data.setUint8 (c++, 0x6f);
2566            data.setUint8 (c++, 0x6d);
2567            data.setUint8 (c++, 0x70);
2568            data.setUint8 (c++, 0x72);
2569            data.setUint8 (c++, 0x65);
2570            data.setUint8 (c++, 0x73);
2571            data.setUint8 (c++, 0x73);
2572            data.setUint8 (c++, 0x69);
2573            data.setUint8 (c++, 0x6f);
2574            data.setUint8 (c++, 0x6e);
2575            data.setUint8 (c++, 0x00);
2576
2577            // Write attribute type : "compression"
2578            data.setUint8 (c++, 0x63);
2579            data.setUint8 (c++, 0x6f);
2580            data.setUint8 (c++, 0x6d);
2581            data.setUint8 (c++, 0x70);
2582            data.setUint8 (c++, 0x72);
2583            data.setUint8 (c++, 0x65);
2584            data.setUint8 (c++, 0x73);
2585            data.setUint8 (c++, 0x73);
2586            data.setUint8 (c++, 0x69);
2587            data.setUint8 (c++, 0x6f);
2588            data.setUint8 (c++, 0x6e);
2589            data.setUint8 (c++, 0x00);
2590
2591            // Write attribute size : "1"
2592            data.setUint8 (c++, 0x01);
2593            data.setUint8 (c++, 0x00);
2594            data.setUint8 (c++, 0x00);
2595            data.setUint8 (c++, 0x00);
2596
2597            // Write attribute value : "0" (None)
2598            data.setUint8 (c++, 0x00);
2599
2600        // datawindow
2601            data.setUint8 (c++, 0x64);
2602            data.setUint8 (c++, 0x61);
2603            data.setUint8 (c++, 0x74);
2604            data.setUint8 (c++, 0x61);
2605            data.setUint8 (c++, 0x57);
2606            data.setUint8 (c++, 0x69);
2607            data.setUint8 (c++, 0x6e);
2608            data.setUint8 (c++, 0x64);
2609            data.setUint8 (c++, 0x6f);
2610            data.setUint8 (c++, 0x77);
2611            data.setUint8 (c++, 0x00);
2612
2613            // box2i
2614            data.setUint8 (c++, 0x62);
2615            data.setUint8 (c++, 0x6f);
2616            data.setUint8 (c++, 0x78);
2617            data.setUint8 (c++, 0x32);
2618            data.setUint8 (c++, 0x69);
2619            data.setUint8 (c++, 0x00);
2620
2621            // size 16
2622            data.setUint8 (c++, 0x10);
2623            data.setUint8 (c++, 0x00);
2624            data.setUint8 (c++, 0x00);
2625            data.setUint8 (c++, 0x00);
2626
2627            // value 0 0 3 2
2628            data.setUint8 (c++, 0x00);
2629            data.setUint8 (c++, 0x00);
2630            data.setUint8 (c++, 0x00);
2631            data.setUint8 (c++, 0x00);
2632
2633            data.setUint8 (c++, 0x00);
2634            data.setUint8 (c++, 0x00);
2635            data.setUint8 (c++, 0x00);
2636            data.setUint8 (c++, 0x00);
2637
2638            data.setUint32 (c, width-1, true);
2639            c += 4;
2640
2641            data.setUint32 (c, height-1, true);
2642            c += 4;
2643
2644        // displayWindow
2645            data.setUint8 (c++, 0x64);
2646            data.setUint8 (c++, 0x69);
2647            data.setUint8 (c++, 0x73);
2648            data.setUint8 (c++, 0x70);
2649            data.setUint8 (c++, 0x6c);
2650            data.setUint8 (c++, 0x61);
2651            data.setUint8 (c++, 0x79);
2652            data.setUint8 (c++, 0x57);
2653            data.setUint8 (c++, 0x69);
2654            data.setUint8 (c++, 0x6e);
2655            data.setUint8 (c++, 0x64);
2656            data.setUint8 (c++, 0x6f);
2657            data.setUint8 (c++, 0x77);
2658            data.setUint8 (c++, 0x00);
2659
2660            // box2i
2661            data.setUint8 (c++, 0x62);
2662            data.setUint8 (c++, 0x6f);
2663            data.setUint8 (c++, 0x78);
2664            data.setUint8 (c++, 0x32);
2665            data.setUint8 (c++, 0x69);
2666            data.setUint8 (c++, 0x00);
2667
2668            // size 16
2669            data.setUint8 (c++, 0x10);
2670            data.setUint8 (c++, 0x00);
2671            data.setUint8 (c++, 0x00);
2672            data.setUint8 (c++, 0x00);
2673
2674            // value 0 0 3 2
2675            data.setUint8 (c++, 0x00);
2676            data.setUint8 (c++, 0x00);
2677            data.setUint8 (c++, 0x00);
2678            data.setUint8 (c++, 0x00);
2679
2680            data.setUint8 (c++, 0x00);
2681            data.setUint8 (c++, 0x00);
2682            data.setUint8 (c++, 0x00);
2683            data.setUint8 (c++, 0x00);
2684
2685            data.setUint32 (c, width-1, true);
2686            c += 4;
2687
2688            data.setUint32 (c, height-1, true);
2689            c += 4;
2690
2691        // lineOrder
2692            data.setUint8 (c++, 0x6c);
2693            data.setUint8 (c++, 0x69);
2694            data.setUint8 (c++, 0x6e);
2695            data.setUint8 (c++, 0x65);
2696            data.setUint8 (c++, 0x4f);
2697            data.setUint8 (c++, 0x72);
2698            data.setUint8 (c++, 0x64);
2699            data.setUint8 (c++, 0x65);
2700            data.setUint8 (c++, 0x72);
2701            data.setUint8 (c++, 0x00);
2702
2703            // lineOrder
2704            data.setUint8 (c++, 0x6c);
2705            data.setUint8 (c++, 0x69);
2706            data.setUint8 (c++, 0x6e);
2707            data.setUint8 (c++, 0x65);
2708            data.setUint8 (c++, 0x4f);
2709            data.setUint8 (c++, 0x72);
2710            data.setUint8 (c++, 0x64);
2711            data.setUint8 (c++, 0x65);
2712            data.setUint8 (c++, 0x72);
2713            data.setUint8 (c++, 0x00);
2714
2715            // size
2716            data.setUint8 (c++, 0x01);
2717            data.setUint8 (c++, 0x00);
2718            data.setUint8 (c++, 0x00);
2719            data.setUint8 (c++, 0x00);
2720
2721            // value
2722            data.setUint8 (c++, 0x00);
2723
2724        // PixelAspectRatio
2725            data.setUint8 (c++, 0x70);
2726            data.setUint8 (c++, 0x69);
2727            data.setUint8 (c++, 0x78);
2728            data.setUint8 (c++, 0x65);
2729            data.setUint8 (c++, 0x6c);
2730            data.setUint8 (c++, 0x41);
2731            data.setUint8 (c++, 0x73);
2732            data.setUint8 (c++, 0x70);
2733            data.setUint8 (c++, 0x65);
2734            data.setUint8 (c++, 0x63);
2735            data.setUint8 (c++, 0x74);
2736            data.setUint8 (c++, 0x52);
2737            data.setUint8 (c++, 0x61);
2738            data.setUint8 (c++, 0x74);
2739            data.setUint8 (c++, 0x69);
2740            data.setUint8 (c++, 0x6f);
2741            data.setUint8 (c++, 0x00);
2742
2743            // float
2744            data.setUint8 (c++, 0x66);
2745            data.setUint8 (c++, 0x6c);
2746            data.setUint8 (c++, 0x6f);
2747            data.setUint8 (c++, 0x61);
2748            data.setUint8 (c++, 0x74);
2749            data.setUint8 (c++, 0x00);
2750
2751            // size 4
2752            data.setUint8 (c++, 0x04);
2753            data.setUint8 (c++, 0x00);
2754            data.setUint8 (c++, 0x00);
2755            data.setUint8 (c++, 0x00);
2756
2757            // value 1.0
2758            data.setUint8 (c++, 0x00);
2759            data.setUint8 (c++, 0x00);
2760            data.setUint8 (c++, 0x80);
2761            data.setUint8 (c++, 0x3f);
2762
2763        // screenWindowCenter
2764            data.setUint8 (c++, 0x73);
2765            data.setUint8 (c++, 0x63);
2766            data.setUint8 (c++, 0x72);
2767            data.setUint8 (c++, 0x65);
2768            data.setUint8 (c++, 0x65);
2769            data.setUint8 (c++, 0x6e);
2770            data.setUint8 (c++, 0x57);
2771            data.setUint8 (c++, 0x69);
2772            data.setUint8 (c++, 0x6e);
2773            data.setUint8 (c++, 0x64);
2774            data.setUint8 (c++, 0x6f);
2775            data.setUint8 (c++, 0x77);
2776            data.setUint8 (c++, 0x43);
2777            data.setUint8 (c++, 0x65);
2778            data.setUint8 (c++, 0x6e);
2779            data.setUint8 (c++, 0x74);
2780            data.setUint8 (c++, 0x65);
2781            data.setUint8 (c++, 0x72);
2782            data.setUint8 (c++, 0x00);
2783
2784            // v2f
2785            data.setUint8 (c++, 0x76);
2786            data.setUint8 (c++, 0x32);
2787            data.setUint8 (c++, 0x66);
2788            data.setUint8 (c++, 0x00);
2789
2790            // size 8
2791            data.setUint8 (c++, 0x08);
2792            data.setUint8 (c++, 0x00);
2793            data.setUint8 (c++, 0x00);
2794            data.setUint8 (c++, 0x00);
2795
2796            // value 0 0
2797            data.setUint8 (c++, 0x00);
2798            data.setUint8 (c++, 0x00);
2799            data.setUint8 (c++, 0x00);
2800            data.setUint8 (c++, 0x00);
2801
2802            data.setUint8 (c++, 0x00);
2803            data.setUint8 (c++, 0x00);
2804            data.setUint8 (c++, 0x00);
2805            data.setUint8 (c++, 0x00);
2806
2807        // screenWindowWidth
2808            data.setUint8 (c++, 0x73);
2809            data.setUint8 (c++, 0x63);
2810            data.setUint8 (c++, 0x72);
2811            data.setUint8 (c++, 0x65);
2812            data.setUint8 (c++, 0x65);
2813            data.setUint8 (c++, 0x6e);
2814            data.setUint8 (c++, 0x57);
2815            data.setUint8 (c++, 0x69);
2816            data.setUint8 (c++, 0x6e);
2817            data.setUint8 (c++, 0x64);
2818            data.setUint8 (c++, 0x6f);
2819            data.setUint8 (c++, 0x77);
2820            data.setUint8 (c++, 0x57);
2821            data.setUint8 (c++, 0x69);
2822            data.setUint8 (c++, 0x64);
2823            data.setUint8 (c++, 0x74);
2824            data.setUint8 (c++, 0x68);
2825            data.setUint8 (c++, 0x00);
2826
2827            // float
2828            data.setUint8 (c++, 0x66);
2829            data.setUint8 (c++, 0x6c);
2830            data.setUint8 (c++, 0x6f);
2831            data.setUint8 (c++, 0x61);
2832            data.setUint8 (c++, 0x74);
2833            data.setUint8 (c++, 0x00);
2834
2835            // size
2836            data.setUint8 (c++, 0x04);
2837            data.setUint8 (c++, 0x00);
2838            data.setUint8 (c++, 0x00);
2839            data.setUint8 (c++, 0x00);
2840
2841            // value
2842            data.setUint8 (c++, 0x00);
2843            data.setUint8 (c++, 0x00);
2844            data.setUint8 (c++, 0x80);
2845            data.setUint8 (c++, 0x3f);
2846
2847        // End of header
2848        data.setUint8 (c++, 0x00);
2849    }
2850
2851    // Scanline table
2852    var initc = c + height * 8;
2853    for (var scanline = 0 ; scanline < height ; scanline ++)
2854    {
2855        var jump = initc + scanline * (8 + width * bytesPerComponent * numC
2855omponents);
2856        data.setUint32 (c, jump, true);
2857        c += 4;
2858
2859        data.setUint32 (c, 0x00, true);
2860        c += 4;
2861    }
2862
2863    // Scanlines
2864    for (var scanline = 0 ; scanline < height ; scanline ++)
2865    {
2866        // Scanline
2867        data.setUint32(c, scanline, true);
2868        c += 4;
2869
2870        // size 24
2871        var size = width * numComponents * bytesPerComponent;
2872        data.setUint32(c, size, true);
2873        c += 4;
2874
2875        var numComponentsSource = 4; // number of components in the SOURCE image
2876        for (var component = 0; component < numComponents ; component ++)
2877        {
2878            for (var pixel = 0 ; pixel < width ; pixel ++)
2879            {
2880                // flip vertical, so we read OpenGL buffers without JS image flipping
2881                var v = bytes[(height-1-scanline) * width *numComponentsSource + pixel * numComponentsSource + (2-component)];
2882                if      (type=="Float") data.setFloat32(c, v, true);
2883                else if (type=="Half")  data.setUint16(c, v, true);
2884
2885                c += bytesPerComponent;
2886            }
2887        }
2888    }
2889
2890    return new Blob([buffer], {type: 'application/octet-stream'});
2891}
2892
2893
2894function piExportToWAV(numSamples, rate, bits, numChannels, words)
2895{
2896    let numBytes = numSamples * numChannels * bits/8;
2897
2898    let buffer = new ArrayBuffer(44 + numBytes);
2899    let data = new DataView(buffer);
2900
2901    {
2902        data.setUint32( 0, 0x46464952, true );  // RIFF
2903        data.setUint32( 4, numBytes + 36, true);
2904        {
2905            data.setUint32( 8, 0x45564157, true );  // WAV_WAVE
2906            data.setUint32( 12, 0x20746D66, true );  // WAV_FMT
2907            {
2908                data.setUint32( 16, 16, true);
2909                data.setUint16( 20, 1, true ); // WAV_FORMAT_PCM
2910                data.setUint16( 22, numChannels, true);
2911                data.setUint32( 24, rate, true);
2912                data.setUint32( 28, rate*numChannels*bits / 8, true);
2913                data.setUint16( 32, numChannels*bits / 8, true);
2914                data.setUint16( 34, bits, true);
2915            }
2916
2917            data.setUint32( 36, 0x61746164, true);  // WAV_DATA
2918            {
2919                data.setUint32( 40, numBytes, true);
2920                let numWords = numSamples * numChannels;
2921                for(let i=0; i<numWords; i++ )
2922                {
2923                    data.setInt16( 44 + i*2, words[i], true );
2924                }
2925            }
2926        }
2927    }
2928
2929
2930    return new Blob([buffer], {type: 'application/octet-stream'});
2931}
2932
2933function piTriggerDownload(name, blob)
2934{}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.