securityos/public/System/ShaderToy/CoastalLandscape/piLibs.js

2935 lines
139 KiB
JavaScript

"use strict"
//==============================================================================
//
// piLibs 2015-2017 - http://www.iquilezles.org/www/material/piLibs/piLibs.htm
//
// piCamera
//
//==============================================================================
function piCamera()
{
var mMatrix = setIdentity();
var mMatrixInv = setIdentity();
var mPosition = [0.0,0.0,0.0];
var mXRotation = 0.0;
var mYRotation = 0.0;
var mPositionTarget = [0.0,0.0,0.0];
var mXRotationTarget = 0.0;
var mYRotationTarget = 0.0;
var me = {};
me.SetPos = function(pos)
{
mPosition = pos;
};
me.LocalMove = function( dis )
{
dis = matMulvec( setRotationY(-mYRotation), dis);
mPositionTarget = sub(mPositionTarget,dis)
};
me.RotateXY = function( x, y)
{
mXRotationTarget -= x;
mYRotationTarget -= y;
mXRotationTarget = Math.min( Math.max( mXRotationTarget, -Math.PI/2), Math.PI/2 );
};
me.CameraExectue = function( dt )
{
// smooth position
mXRotation += (mXRotationTarget-mXRotation) * 12.0*dt;
mYRotation += (mYRotationTarget-mYRotation) * 12.0*dt;
mPosition = add(mPosition, mul( sub(mPositionTarget, mPosition), 12.0*dt));
// Make Camera matrix
mMatrix = matMul( matMul(setRotationX(mXRotation),
setRotationY(mYRotation)),
setTranslation(mPosition));
mMatrixInv = invertFast(mMatrix);
}
me.GetMatrix = function() { return mMatrix; };
me.GetMatrixInverse = function() { return mMatrixInv; };
me.SetMatrix = function( mat )
{
mMatrix = mat;
mMatrixInv = invertFast(mMatrix);
mPosition = getXYZ(matMulpoint(mat, [0.0,0.0,0.0]));
mPositionTarget = mPosition;
};
me.GetPos = function() { return getXYZ(matMulpoint(mMatrixInv, [0.0,0.0,0.0])); }
me.GetDir = function() { return getXYZ(normalize(matMulvec(mMatrixInv, [0.0,0.0,-1.0]))); }
return me;
}
//==============================================================================
//
// piLibs 2015-2017 - http://www.iquilezles.org/www/material/piLibs/piLibs.htm
//
// piFile
//
//==============================================================================
function piFile( binaryDataArrayBuffer )
{
// private
var mDataView = binaryDataArrayBuffer;
var mOffset = 0;
// public members
var me = {};
me.mDummy = 0;
me.Seek = function( off ) { mOffset = off; };
me.ReadUInt8 = function() { var res = (new Uint8Array(mDataView,mOffset))[0]; mOffset+=1; return res; };
me.ReadUInt16 = function() { var res = (new Uint16Array(mDataView,mOffset))[0]; mOffset+=2; return res; };
me.ReadUInt32 = function() { var res = (new Uint32Array(mDataView,mOffset))[0]; mOffset+=4; return res; };
me.ReadUInt64 = function() { return me.ReadUInt32() + (me.ReadUInt32()<<32); };
me.ReadFloat32 = function() { var res = (new Float32Array(mDataView,mOffset))[0]; mOffset+=4; return res; };
me.ReadFloat32Array = function(n)
{
var src = new Float32Array(mDataView, mOffset);
var res = []; for( var i=0; i<n; i++ ) { res[i] = src[i]; }
mOffset += 4*n;
return res;
};
me.ReadFloat32ArrayNative = function(n) { var src = new Float32Array(mDataView, mOffset); mOffset += 4*n; return src; };
return me;
}
//==============================================================================
//
// piLibs 2015-2017 - http://www.iquilezles.org/www/material/piLibs/piLibs.htm
//
// piMesh
//
//==============================================================================
function piMesh()
{
this.mChunks = [];
this.mPrimitiveType = 0;
this.mVertexFormat = null;
}
piMesh.prototype.createCube = function(renderer)
{
this.mPrimitiveType = 0;
this.mChunks[0] = { mVerts : 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,
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0 ]),
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 ]),
mNumVertices : 8,
mNumFaces : 12,
mTransform : setIdentity(),
mVBO : null,
mIBO : null };
this.mVertexFormat = { mStride:12, mChannels:[ { mNumComponents:3, mType: renderer.TYPE.FLOAT32, mNormalize: false } ] };
return true;
}
piMesh.prototype.createCubeSharp = function (renderer)
{
this.mPrimitiveType = 0;
this.mChunks[0] = { mVerts : new Float32Array([-1.0, 1.0,-1.0, 0.0, 1.0, 0.0, 0.0, 0.0,
-1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0,
1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0,
1.0, 1.0,-1.0, 0.0, 1.0, 0.0, 1.0, 0.0,
-1.0,-1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
1.0,-1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0,
1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0,
-1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0,
1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0,
1.0,-1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0,
1.0,-1.0,-1.0, 1.0, 0.0, 0.0, 1.0, 1.0,
1.0, 1.0,-1.0, 1.0, 0.0, 0.0, 1.0, 0.0,
1.0,-1.0,-1.0, 0.0, 0.0,-1.0, 0.0, 0.0,
-1.0,-1.0,-1.0, 0.0, 0.0,-1.0, 0.0, 1.0,
-1.0, 1.0,-1.0, 0.0, 0.0,-1.0, 1.0, 1.0,
1.0, 1.0,-1.0, 0.0, 0.0,-1.0, 1.0, 0.0,
-1.0,-1.0, 1.0, 0.0,-1.0, 0.0, 0.0, 0.0,
-1.0,-1.0,-1.0, 0.0,-1.0, 0.0, 0.0, 1.0,
1.0,-1.0,-1.0, 0.0,-1.0, 0.0, 1.0, 1.0,
1.0,-1.0, 1.0, 0.0,-1.0, 0.0, 1.0, 0.0,
-1.0, 1.0, 1.0, -1.0, 0.0, 0.0, 0.0, 0.0,
-1.0, 1.0,-1.0, -1.0, 0.0, 0.0, 0.0, 1.0,
-1.0,-1.0,-1.0, -1.0, 0.0, 0.0, 1.0, 1.0,
-1.0,-1.0, 1.0, -1.0, 0.0, 0.0, 1.0, 0.0 ]),
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]),
mNumVertices : 24,
mNumFaces : 12,
mTransform : setIdentity(),
mVBO : null,
mIBO : null };
this.mVertexFormat = { mStride:32, mChannels:[ { mNumComponents:3, mType: renderer.TYPE.FLOAT32, mNormalize: false },
{ mNumComponents:3, mType: renderer.TYPE.FLOAT32, mNormalize: false },
{ mNumComponents:2, mType: renderer.TYPE.FLOAT32, mNormalize: false } ] };
return true;
}
piMesh.prototype.createUnitQuad = function (renderer)
{
this.mPrimitiveType = 0;
this.mVertexFormat = { mStride:8, mChannels: [ {mNumComponents:2, mType: renderer.TYPE.FLOAT32, mNormalize: false} ] };
this.mChunks[0] = { mVerts : new Float32Array([-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0]),
mIndices : new Uint16Array([0, 2, 1, 1, 2, 3]),
mNumVertices : 4,
mNumFaces : 2,
mTransform : setIdentity(),
mVBO : null,
mIBO : null };
return true;
}
piMesh.prototype.destroy = function()
{ }
piMesh.prototype.scale = function (x, y, z)
{
var stride = this.mVertexFormat.mStride/4;
for( var j=0; j<this.mChunks.length; j++ )
{
var nv = this.mChunks[j].mNumVertices;
for (var i = 0; i < nv; i++)
{
this.mChunks[j].mVerts[stride * i + 0] *= x;
this.mChunks[j].mVerts[stride * i + 1] *= y;
this.mChunks[j].mVerts[stride * i + 2] *= z;
}
}
}
piMesh.prototype.translate = function (x, y, z)
{
var stride = this.mVertexFormat.mStride/4;
for( var j=0; j<this.mChunks.length; j++ )
{
var nv = this.mChunks[j].mNumVertices;
for (var i = 0; i < nv; i++)
{
this.mChunks[j].mVerts[stride * i + 0] += x;
this.mChunks[j].mVerts[stride * i + 1] += y;
this.mChunks[j].mVerts[stride * i + 2] += z;
}
}
}
piMesh.prototype.GPULoad = function (renderer)
{
for( var i=0; i<this.mChunks.length; i++ )
{
var vbo = renderer.CreateVertexArray(this.mChunks[i].mVerts, renderer.BUFTYPE.STATIC );
if (vbo == null)
return false;
var ibo = renderer.CreateIndexArray(this.mChunks[i].mIndices, renderer.BUFTYPE.STATIC);
if (ibo == null)
return false;
this.mChunks[i].mVBO = vbo;
this.mChunks[i].mIBO = ibo;
}
return true;
}
piMesh.prototype.GPURender = function (renderer, positions )//, matPrj, matCam )
{
var num = this.mChunks.length;
for( var i=0; i<num; i++ )
{
renderer.AttachVertexArray(this.mChunks[i].mVBO, this.mVertexFormat, positions );
renderer.AttachIndexArray(this.mChunks[i].mIBO );
renderer.DrawPrimitive(renderer.PRIMTYPE.TRIANGLES, this.mChunks[i].mNumFaces * 3, true, 1);
renderer.DetachIndexArray(this.mChunks[i].mIBO);
renderer.DetachVertexArray(this.mChunks[i].mVBO, this.mVertexFormat );
}
}
//==============================================================================
//
// piLibs 2014-2017 - http://www.iquilezles.org/www/material/piLibs/piLibs.htm
//
// piRenderer
//
//==============================================================================
function piRenderer()
{
// private members
var mGL = null;
var mBindedShader = null;
var mIs20 = false;
var mFloat32Textures;
var mFloat32Filter;
var mFloat16Textures;
var mDrawBuffers;
var mDepthTextures;
var mDerivatives;
var mFloat16Filter;
var mShaderTextureLOD;
var mAnisotropic;
var mRenderToFloat32F;
var mDebugShader;
var mAsynchCompile;
var mVBO_Quad = null;
var mVBO_Tri = null;
var mVBO_CubePosNor = null;
var mVBO_CubePos = null;
var mShaderHeader = ["",""];
var mShaderHeaderLines = [0,0];
// public members
var me = {};
me.CLEAR = { Color: 1, Zbuffer : 2, Stencil : 4 };
me.TEXFMT = { C4I8 : 0, C1I8 : 1, C1F16 : 2, C4F16 : 3, C1F32 : 4, C4F32 : 5, Z16 : 6, Z24 : 7, Z32 : 8, C3F32:9 };
me.TEXWRP = { CLAMP : 0, REPEAT : 1 };
me.BUFTYPE = { STATIC : 0, DYNAMIC : 1 };
me.PRIMTYPE = { POINTS : 0, LINES : 1, LINE_LOOP : 2, LINE_STRIP : 3, TRIANGLES : 4, TRIANGLE_STRIP : 5 };
me.RENDSTGATE = { WIREFRAME : 0, FRONT_FACE : 1, CULL_FACE : 2, DEPTH_TEST : 3, ALPHA_TO_COVERAGE : 4 };
me.TEXTYPE = { T2D : 0, T3D : 1, CUBEMAP : 2 };
me.FILTER = { NONE : 0, LINEAR : 1, MIPMAP : 2, NONE_MIPMAP : 3 };
me.TYPE = { UINT8 : 0, UINT16 : 1, UINT32 : 2, FLOAT16: 3, FLOAT32 : 4, FLOAT64: 5 };
// private functions
var iFormatPI2GL = function( format )
{
if( mIs20 )
{
if (format === me.TEXFMT.C4I8) return { mGLFormat: mGL.RGBA8, mGLExternal: mGL.RGBA, mGLType: mGL.UNSIGNED_BYTE }
else if (format === me.TEXFMT.C1I8) return { mGLFormat: mGL.R8, mGLExternal: mGL.RED, mGLType: mGL.UNSIGNED_BYTE }
else if (format === me.TEXFMT.C1F16) return { mGLFormat: mGL.R16F, mGLExternal: mGL.RED, mGLType: mGL.FLOAT }
else if (format === me.TEXFMT.C4F16) return { mGLFormat: mGL.RGBA16F, mGLExternal: mGL.RGBA, mGLType: mGL.FLOAT }
else if (format === me.TEXFMT.C1F32) return { mGLFormat: mGL.R32F, mGLExternal: mGL.RED, mGLType: mGL.FLOAT }
else if (format === me.TEXFMT.C4F32) return { mGLFormat: mGL.RGBA32F, mGLExternal: mGL.RGBA, mGLType: mGL.FLOAT }
else if (format === me.TEXFMT.C3F32) return { mGLFormat: mGL.RGB32F, mGLExternal: mGL.RGB, mGLType: mGL.FLOAT }
else if (format === me.TEXFMT.Z16) return { mGLFormat: mGL.DEPTH_COMPONENT16, mGLExternal: mGL.DEPTH_COMPONENT, mGLType: mGL.UNSIGNED_SHORT }
else if (format === me.TEXFMT.Z24) return { mGLFormat: mGL.DEPTH_COMPONENT24, mGLExternal: mGL.DEPTH_COMPONENT, mGLType: mGL.UNSIGNED_SHORT }
else if (format === me.TEXFMT.Z32) return { mGLFormat: mGL.DEPTH_COMPONENT32F, mGLExternal: mGL.DEPTH_COMPONENT, mGLType: mGL.UNSIGNED_SHORT }
}
else
{
if (format === me.TEXFMT.C4I8) return { mGLFormat: mGL.RGBA, mGLExternal: mGL.RGBA, mGLType: mGL.UNSIGNED_BYTE }
else if (format === me.TEXFMT.C1I8) return { mGLFormat: mGL.LUMINANCE, mGLExternal: mGL.LUMINANCE, mGLType: mGL.UNSIGNED_BYTE }
else if (format === me.TEXFMT.C1F16) return { mGLFormat: mGL.LUMINANCE, mGLExternal: mGL.LUMINANCE, mGLType: mGL.FLOAT }
else if (format === me.TEXFMT.C4F16) return { mGLFormat: mGL.RGBA, mGLExternal: mGL.RGBA, mGLType: mGL.FLOAT }
else if (format === me.TEXFMT.C1F32) return { mGLFormat: mGL.LUMINANCE, mGLExternal: mGL.RED, mGLType: mGL.FLOAT }
else if (format === me.TEXFMT.C4F32) return { mGLFormat: mGL.RGBA, mGLExternal: mGL.RGBA, mGLType: mGL.FLOAT }
else if (format === me.TEXFMT.Z16) return { mGLFormat: mGL.DEPTH_COMPONENT, mGLExternal: mGL.DEPTH_COMPONENT, mGLType: mGL.UNSIGNED_SHORT }
}
return null;
}
// public functions
me.Initialize = function( gl )
{
mGL = gl;
mIs20 = !(gl instanceof WebGLRenderingContext);
if( mIs20 )
{
mFloat32Textures = true;
mFloat32Filter = mGL.getExtension( 'OES_texture_float_linear');
mFloat16Textures = true;
mFloat16Filter = mGL.getExtension( 'OES_texture_half_float_linear' );
mDerivatives = true;
mDrawBuffers = true;
mDepthTextures = true;
mShaderTextureLOD = true;
mAnisotropic = mGL.getExtension( 'EXT_texture_filter_anisotropic' );
mRenderToFloat32F = mGL.getExtension( 'EXT_color_buffer_float');
mDebugShader = mGL.getExtension('WEBGL_debug_shaders');
mAsynchCompile = mGL.getExtension('KHR_parallel_shader_compile');
mGL.hint( mGL.FRAGMENT_SHADER_DERIVATIVE_HINT, mGL.NICEST);
}
else
{
mFloat32Textures = mGL.getExtension( 'OES_texture_float' );
mFloat32Filter = mGL.getExtension( 'OES_texture_float_linear');
mFloat16Textures = mGL.getExtension( 'OES_texture_half_float' );
mFloat16Filter = mGL.getExtension( 'OES_texture_half_float_linear' );
mDerivatives = mGL.getExtension( 'OES_standard_derivatives' );
mDrawBuffers = mGL.getExtension( 'WEBGL_draw_buffers' );
mDepthTextures = mGL.getExtension( 'WEBGL_depth_texture' );
mShaderTextureLOD = mGL.getExtension( 'EXT_shader_texture_lod' );
mAnisotropic = mGL.getExtension( 'EXT_texture_filter_anisotropic' );
mRenderToFloat32F = mFloat32Textures;
mDebugShader = null;
mAsynchCompile = null;
if( mDerivatives !== null) mGL.hint( mDerivatives.FRAGMENT_SHADER_DERIVATIVE_HINT_OES, mGL.NICEST);
}
var maxTexSize = mGL.getParameter( mGL.MAX_TEXTURE_SIZE );
var maxCubeSize = mGL.getParameter( mGL.MAX_CUBE_MAP_TEXTURE_SIZE );
var maxRenderbufferSize = mGL.getParameter( mGL.MAX_RENDERBUFFER_SIZE );
var extensions = mGL.getSupportedExtensions();
var textureUnits = mGL.getParameter( mGL.MAX_TEXTURE_IMAGE_UNITS );
console.log("WebGL (2.0=" + mIs20 + "):" +
" Asynch Compile: " + ((mAsynchCompile !==null) ? "yes" : "no") +
", Textures: F32 [" + ((mFloat32Textures !==null) ? "yes" : "no") +
"], F16 [" + ((mFloat16Textures !==null) ? "yes" : "no") +
"], Depth [" + ((mDepthTextures !==null) ? "yes" : "no") +
"], LOD [" + ((mShaderTextureLOD!==null) ? "yes" : "no") +
"], Aniso [" + ((mAnisotropic !==null) ? "yes" : "no") +
"], Units [" + textureUnits +
"], Max Size [" + maxTexSize +
"], Cube Max Size [" + maxCubeSize +
"], Targets: MRT [" + ((mDrawBuffers !==null) ? "yes" : "no") +
"], F32 [" + ((mRenderToFloat32F!==null) ? "yes" : "no") +
"], Max Size [" + maxRenderbufferSize + "]");
// create a 2D quad Vertex Buffer
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] );
mVBO_Quad = mGL.createBuffer();
mGL.bindBuffer( mGL.ARRAY_BUFFER, mVBO_Quad );
mGL.bufferData( mGL.ARRAY_BUFFER, vertices, mGL.STATIC_DRAW );
mGL.bindBuffer( mGL.ARRAY_BUFFER, null );
// create a 2D triangle Vertex Buffer
mVBO_Tri = mGL.createBuffer();
mGL.bindBuffer( mGL.ARRAY_BUFFER, mVBO_Tri );
mGL.bufferData( mGL.ARRAY_BUFFER, new Float32Array( [ -1.0, -1.0, 3.0, -1.0, -1.0, 3.0] ), mGL.STATIC_DRAW );
mGL.bindBuffer( mGL.ARRAY_BUFFER, null );
// create a 3D cube Vertex Buffer
mVBO_CubePosNor = mGL.createBuffer();
mGL.bindBuffer( mGL.ARRAY_BUFFER, mVBO_CubePosNor );
mGL.bufferData( mGL.ARRAY_BUFFER, new Float32Array( [ -1.0, -1.0, -1.0, -1.0, 0.0, 0.0,
-1.0, -1.0, 1.0, -1.0, 0.0, 0.0,
-1.0, 1.0, -1.0, -1.0, 0.0, 0.0,
-1.0, 1.0, 1.0, -1.0, 0.0, 0.0,
1.0, 1.0, -1.0, 1.0, 0.0, 0.0,
1.0, 1.0, 1.0, 1.0, 0.0, 0.0,
1.0, -1.0, -1.0, 1.0, 0.0, 0.0,
1.0, -1.0, 1.0, 1.0, 0.0, 0.0,
1.0, 1.0, 1.0, 0.0, 1.0, 0.0,
1.0, 1.0, -1.0, 0.0, 1.0, 0.0,
-1.0, 1.0, 1.0, 0.0, 1.0, 0.0,
-1.0, 1.0, -1.0, 0.0, 1.0, 0.0,
1.0, -1.0, -1.0, 0.0, -1.0, 0.0,
1.0, -1.0, 1.0, 0.0, -1.0, 0.0,
-1.0, -1.0, -1.0, 0.0, -1.0, 0.0,
-1.0, -1.0, 1.0, 0.0, -1.0, 0.0,
-1.0, 1.0, 1.0, 0.0, 0.0, 1.0,
-1.0, -1.0, 1.0, 0.0, 0.0, 1.0,
1.0, 1.0, 1.0, 0.0, 0.0, 1.0,
1.0, -1.0, 1.0, 0.0, 0.0, 1.0,
-1.0, -1.0, -1.0, 0.0, 0.0, -1.0,
-1.0, 1.0, -1.0, 0.0, 0.0, -1.0,
1.0, -1.0, -1.0, 0.0, 0.0, -1.0,
1.0, 1.0, -1.0, 0.0, 0.0, -1.0 ] ), mGL.STATIC_DRAW );
mGL.bindBuffer( mGL.ARRAY_BUFFER, null );
// create a 3D cube Vertex Buffer
mVBO_CubePos = mGL.createBuffer();
mGL.bindBuffer( mGL.ARRAY_BUFFER, mVBO_CubePos );
mGL.bufferData( mGL.ARRAY_BUFFER, 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,
1.0, 1.0, -1.0,
1.0, 1.0, 1.0,
1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0,
1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
1.0, -1.0, 1.0,
-1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
1.0, -1.0, -1.0,
1.0, 1.0, -1.0 ] ), mGL.STATIC_DRAW );
mGL.bindBuffer( mGL.ARRAY_BUFFER, null );
//-------------------------------------------------------------------
mShaderHeader[0] = "";
mShaderHeaderLines[0] = 0;
if( mIs20 )
{
mShaderHeader[0] += "#version 300 es\n" +
"#ifdef GL_ES\n"+
"precision highp float;\n" +
"precision highp int;\n"+
"precision mediump sampler3D;\n"+
"#endif\n";
mShaderHeaderLines[0] += 6;
}
else
{
mShaderHeader[0] += "#ifdef GL_ES\n"+
"precision highp float;\n" +
"precision highp int;\n"+
"#endif\n"+
"float round( float x ) { return floor(x+0.5); }\n"+
"vec2 round(vec2 x) { return floor(x + 0.5); }\n"+
"vec3 round(vec3 x) { return floor(x + 0.5); }\n"+
"vec4 round(vec4 x) { return floor(x + 0.5); }\n"+
"float trunc( float x, float n ) { return floor(x*n)/n; }\n"+
"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"+
"float determinant( in mat2 m ) { return m[0][0]*m[1][1] - m[0][1]*m[1][0]; }\n"+
"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"+
"mat2 inverse(mat2 m) { float det = determinant(m); return mat2(m[1][1], -m[0][1], -m[1][0], m[0][0]) / det; }\n"+
"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; 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"+
"float sinh(float x) { return (exp(x)-exp(-x))/2.; }\n"+
"float cosh(float x) { return (exp(x)+exp(-x))/2.; }\n"+
"float tanh(float x) { return sinh(x)/cosh(x); }\n"+
"float coth(float x) { return cosh(x)/sinh(x); }\n"+
"float sech(float x) { return 1./cosh(x); }\n"+
"float csch(float x) { return 1./sinh(x); }\n"+
"float asinh(float x) { return log(x+sqrt(x*x+1.)); }\n"+
"float acosh(float x) { return log(x+sqrt(x*x-1.)); }\n"+
"float atanh(float x) { return .5*log((1.+x)/(1.-x)); }\n"+
"float acoth(float x) { return .5*log((x+1.)/(x-1.)); }\n"+
"float asech(float x) { return log((1.+sqrt(1.-x*x))/x); }\n"+
"float acsch(float x) { return log((1.+sqrt(1.+x*x))/x); }\n";
mShaderHeaderLines[0] += 26;
}
//-------------------------------------------------------
mShaderHeader[1] = "";
mShaderHeaderLines[1] = 0;
if( mIs20 )
{
mShaderHeader[1] += "#version 300 es\n"+
"#ifdef GL_ES\n"+
"precision highp float;\n"+
"precision highp int;\n"+
"precision mediump sampler3D;\n"+
"#endif\n";
mShaderHeaderLines[1] += 6;
}
else
{
if( mDerivatives ) { mShaderHeader[1] += "#ifdef GL_OES_standard_derivatives\n#extension GL_OES_standard_derivatives : enable\n#endif\n"; mShaderHeaderLines[1]+=3; }
if( mShaderTextureLOD ) { mShaderHeader[1] += "#extension GL_EXT_shader_texture_lod : enable\n"; mShaderHeaderLines[1]++; }
mShaderHeader[1] += "#ifdef GL_ES\n"+
"precision highp float;\n"+
"precision highp int;\n"+
"#endif\n"+
"vec4 texture( sampler2D s, vec2 c) { return texture2D(s,c); }\n"+
"vec4 texture( sampler2D s, vec2 c, float b) { return texture2D(s,c,b); }\n"+
"vec4 texture( samplerCube s, vec3 c ) { return textureCube(s,c); }\n"+
"vec4 texture( samplerCube s, vec3 c, float b) { return textureCube(s,c,b); }\n"+
"float round( float x ) { return floor(x+0.5); }\n"+
"vec2 round(vec2 x) { return floor(x + 0.5); }\n"+
"vec3 round(vec3 x) { return floor(x + 0.5); }\n"+
"vec4 round(vec4 x) { return floor(x + 0.5); }\n"+
"float trunc( float x, float n ) { return floor(x*n)/n; }\n"+
"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"+
"float determinant( in mat2 m ) { return m[0][0]*m[1][1] - m[0][1]*m[1][0]; }\n"+
"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"+
"mat2 inverse(mat2 m) { float det = determinant(m); return mat2(m[1][1], -m[0][1], -m[1][0], m[0][0]) / det; }\n"+
"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; 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"+
"float sinh(float x) { return (exp(x)-exp(-x))/2.; }\n"+
"float cosh(float x) { return (exp(x)+exp(-x))/2.; }\n"+
"float tanh(float x) { return sinh(x)/cosh(x); }\n"+
"float coth(float x) { return cosh(x)/sinh(x); }\n"+
"float sech(float x) { return 1./cosh(x); }\n"+
"float csch(float x) { return 1./sinh(x); }\n"+
"float asinh(float x) { return log(x+sqrt(x*x+1.)); }\n"+
"float acosh(float x) { return log(x+sqrt(x*x-1.)); }\n"+
"float atanh(float x) { return .5*log((1.+x)/(1.-x)); }\n"+
"float acoth(float x) { return .5*log((x+1.)/(x-1.)); }\n"+
"float asech(float x) { return log((1.+sqrt(1.-x*x))/x); }\n"+
"float acsch(float x) { return log((1.+sqrt(1.+x*x))/x); }\n";
mShaderHeaderLines[1] += 30;
if( mShaderTextureLOD )
{
mShaderHeader[1] += "vec4 textureLod( sampler2D s, vec2 c, float b) { return texture2DLodEXT(s,c,b); }\n";
mShaderHeader[1] += "vec4 textureGrad( sampler2D s, vec2 c, vec2 dx, vec2 dy) { return texture2DGradEXT(s,c,dx,dy); }\n";
mShaderHeaderLines[1] += 2;
//mShaderHeader[1] += "vec4 texelFetch( sampler2D s, ivec2 c, int l) { return texture2DLodEXT(s,(vec2(c)+0.5)/vec2(800,450),float(l)); }\n";
//mShaderHeaderLines[1] += 1;
}
}
return true;
};
me.GetCaps = function ()
{
return { mIsGL20 : mIs20,
mFloat32Textures: mFloat32Textures != null,
mFloat16Textures: mFloat16Textures != null,
mDrawBuffers: mDrawBuffers != null,
mDepthTextures: mDepthTextures != null,
mDerivatives: mDerivatives != null,
mShaderTextureLOD: mShaderTextureLOD != null };
};
me.GetShaderHeaderLines = function (shaderType)
{
return mShaderHeaderLines[shaderType];
};
me.CheckErrors = function()
{
var error = mGL.getError();
if( error != mGL.NO_ERROR )
{
for( var prop in mGL )
{
if( typeof mGL[prop] == 'number' )
{
if( mGL[prop] == error )
{
console.log( "GL Error " + error + ": " + prop );
break;
}
}
}
}
};
me.Clear = function( flags, ccolor, cdepth, cstencil )
{
var mode = 0;
if( flags & 1 ) { mode |= mGL.COLOR_BUFFER_BIT; mGL.clearColor( ccolor[0], ccolor[1], ccolor[2], ccolor[3] ); }
if( flags & 2 ) { mode |= mGL.DEPTH_BUFFER_BIT; mGL.clearDepth( cdepth ); }
if( flags & 4 ) { mode |= mGL.STENCIL_BUFFER_BIT; mGL.clearStencil( cstencil ); }
mGL.clear( mode );
};
me.CreateTexture = function ( type, xres, yres, format, filter, wrap, buffer)
{
if( mGL===null ) return null;
var id = mGL.createTexture();
var glFoTy = iFormatPI2GL( format );
var glWrap = mGL.REPEAT; if (wrap === me.TEXWRP.CLAMP) glWrap = mGL.CLAMP_TO_EDGE;
if( type===me.TEXTYPE.T2D )
{
mGL.bindTexture( mGL.TEXTURE_2D, id );
mGL.texImage2D( mGL.TEXTURE_2D, 0, glFoTy.mGLFormat, xres, yres, 0, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
mGL.texParameteri( mGL.TEXTURE_2D, mGL.TEXTURE_WRAP_S, glWrap );
mGL.texParameteri( mGL.TEXTURE_2D, mGL.TEXTURE_WRAP_T, glWrap );
if (filter === me.FILTER.NONE)
{
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST);
}
else if (filter === me.FILTER.LINEAR)
{
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR);
}
else if (filter === me.FILTER.MIPMAP)
{
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR_MIPMAP_LINEAR);
mGL.generateMipmap(mGL.TEXTURE_2D);
}
else
{
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST_MIPMAP_LINEAR);
mGL.generateMipmap(mGL.TEXTURE_2D);
}
mGL.bindTexture( mGL.TEXTURE_2D, null );
}
else if( type===me.TEXTYPE.T3D )
{
if( mIs20 )
{
mGL.bindTexture( mGL.TEXTURE_3D, id );
mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_BASE_LEVEL, 0);
mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAX_LEVEL, Math.log2(xres));
if (filter === me.FILTER.NONE)
{
mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST);
}
else if (filter === me.FILTER.LINEAR)
{
mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR);
}
else if (filter === me.FILTER.MIPMAP)
{
mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR_MIPMAP_LINEAR);
}
else
{
mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST_MIPMAP_LINEAR);
mGL.generateMipmap(mGL.TEXTURE_3D);
}
mGL.texImage3D( mGL.TEXTURE_3D, 0, glFoTy.mGLFormat, xres, yres, yres, 0, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
mGL.texParameteri( mGL.TEXTURE_3D, mGL.TEXTURE_WRAP_R, glWrap );
mGL.texParameteri( mGL.TEXTURE_3D, mGL.TEXTURE_WRAP_S, glWrap );
mGL.texParameteri( mGL.TEXTURE_3D, mGL.TEXTURE_WRAP_T, glWrap );
if (filter === me.FILTER.MIPMAP)
mGL.generateMipmap( mGL.TEXTURE_3D );
mGL.bindTexture( mGL.TEXTURE_3D, null );
}
else
{
return null;
}
}
else
{
mGL.bindTexture( mGL.TEXTURE_CUBE_MAP, id );
mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glFoTy.mGLFormat, xres, yres, 0, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glFoTy.mGLFormat, xres, yres, 0, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glFoTy.mGLFormat, xres, yres, 0, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glFoTy.mGLFormat, xres, yres, 0, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glFoTy.mGLFormat, xres, yres, 0, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glFoTy.mGLFormat, xres, yres, 0, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
if( filter === me.FILTER.NONE)
{
mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST);
}
else if (filter === me.FILTER.LINEAR)
{
mGL.texParameteri( mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR );
mGL.texParameteri( mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR );
}
else if (filter === me.FILTER.MIPMAP)
{
mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR_MIPMAP_LINEAR);
}
if (filter === me.FILTER.MIPMAP)
mGL.generateMipmap( mGL.TEXTURE_CUBE_MAP );
mGL.bindTexture( mGL.TEXTURE_CUBE_MAP, null );
}
return { mObjectID: id, mXres: xres, mYres: yres, mFormat: format, mType: type, mFilter: filter, mWrap: wrap, mVFlip:false };
};
me.CreateTextureFromImage = function ( type, image, format, filter, wrap, flipY)
{
if( mGL===null ) return null;
var id = mGL.createTexture();
var glFoTy = iFormatPI2GL( format );
var glWrap = mGL.REPEAT; if (wrap === me.TEXWRP.CLAMP) glWrap = mGL.CLAMP_TO_EDGE;
if( type===me.TEXTYPE.T2D )
{
mGL.bindTexture(mGL.TEXTURE_2D, id);
mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, flipY);
mGL.pixelStorei(mGL.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
if( mIs20 ) mGL.pixelStorei(mGL.UNPACK_COLORSPACE_CONVERSION_WEBGL, mGL.NONE );
mGL.texImage2D(mGL.TEXTURE_2D, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image);
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_WRAP_S, glWrap);
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_WRAP_T, glWrap);
if (filter === me.FILTER.NONE)
{
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST);
}
else if (filter === me.FILTER.LINEAR)
{
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR);
}
else if( filter === me.FILTER.MIPMAP)
{
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR_MIPMAP_LINEAR);
mGL.generateMipmap(mGL.TEXTURE_2D);
}
else
{
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST_MIPMAP_LINEAR);
mGL.generateMipmap(mGL.TEXTURE_2D);
}
mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, false);
mGL.bindTexture(mGL.TEXTURE_2D, null);
}
else if( type===me.TEXTYPE.T3D )
{
return null;
}
else
{
mGL.bindTexture( mGL.TEXTURE_CUBE_MAP, id );
mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, flipY);
mGL.activeTexture( mGL.TEXTURE0 );
mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image[0] );
mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image[1] );
mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, (flipY ? image[3] : image[2]) );
mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, (flipY ? image[2] : image[3]) );
mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image[4] );
mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image[5] );
if( filter === me.FILTER.NONE)
{
mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST);
}
else if (filter === me.FILTER.LINEAR)
{
mGL.texParameteri( mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR );
mGL.texParameteri( mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR );
}
else if (filter === me.FILTER.MIPMAP)
{
mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR_MIPMAP_LINEAR);
mGL.generateMipmap( mGL.TEXTURE_CUBE_MAP );
}
mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, false);
mGL.bindTexture( mGL.TEXTURE_CUBE_MAP, null );
}
return { mObjectID: id, mXres: image.width, mYres: image.height, mFormat: format, mType: type, mFilter: filter, mWrap:wrap, mVFlip:flipY };
};
me.SetSamplerFilter = function (te, filter, doGenerateMipsIfNeeded)
{
if (te.mFilter === filter) return;
if (te.mType === me.TEXTYPE.T2D)
{
mGL.bindTexture(mGL.TEXTURE_2D, te.mObjectID);
if (filter === me.FILTER.NONE)
{
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST);
}
else if (filter === me.FILTER.LINEAR)
{
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR);
}
else if (filter === me.FILTER.MIPMAP)
{
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR_MIPMAP_LINEAR);
if( doGenerateMipsIfNeeded ) mGL.generateMipmap(mGL.TEXTURE_2D);
}
else
{
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST_MIPMAP_LINEAR);
if( doGenerateMipsIfNeeded ) mGL.generateMipmap(mGL.TEXTURE_2D);
}
mGL.bindTexture(mGL.TEXTURE_2D, null);
}
else if (te.mType === me.TEXTYPE.T3D)
{
mGL.bindTexture(mGL.TEXTURE_3D, te.mObjectID);
if (filter === me.FILTER.NONE)
{
mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST);
}
else if (filter === me.FILTER.LINEAR)
{
mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR);
}
else if (filter === me.FILTER.MIPMAP)
{
mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR_MIPMAP_LINEAR);
if( doGenerateMipsIfNeeded ) mGL.generateMipmap(mGL.TEXTURE_3D);
}
else
{
mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST_MIPMAP_LINEAR);
if( doGenerateMipsIfNeeded ) mGL.generateMipmap(mGL.TEXTURE_3D);
}
mGL.bindTexture(mGL.TEXTURE_3D, null);
}
else
{
mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, te.mObjectID);
if (filter === me.FILTER.NONE)
{
mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST);
}
else if (filter === me.FILTER.LINEAR)
{
mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR);
}
else if (filter === me.FILTER.MIPMAP)
{
mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR_MIPMAP_LINEAR);
if( doGenerateMipsIfNeeded ) mGL.generateMipmap(mGL.TEXTURE_CUBE_MAP);
}
else
{
mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST_MIPMAP_LINEAR);
if( doGenerateMipsIfNeeded ) mGL.generateMipmap(mGL.TEXTURE_CUBE_MAP);
}
mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, null);
}
te.mFilter = filter;
};
me.SetSamplerWrap = function (te, wrap)
{
if (te.mWrap === wrap) return;
var glWrap = mGL.REPEAT; if (wrap === me.TEXWRP.CLAMP) glWrap = mGL.CLAMP_TO_EDGE;
var id = te.mObjectID;
if (te.mType === me.TEXTYPE.T2D)
{
mGL.bindTexture(mGL.TEXTURE_2D, id);
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_WRAP_S, glWrap);
mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_WRAP_T, glWrap);
mGL.bindTexture(mGL.TEXTURE_2D, null);
}
else if (te.mType === me.TEXTYPE.T3D)
{
mGL.bindTexture(mGL.TEXTURE_3D, id);
mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_WRAP_R, glWrap);
mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_WRAP_S, glWrap);
mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_WRAP_T, glWrap);
mGL.bindTexture(mGL.TEXTURE_3D, null);
}
te.mWrap = wrap;
};
me.SetSamplerVFlip = function (te, vflip, image)
{
if (te.mVFlip === vflip) return;
var id = te.mObjectID;
if (te.mType === me.TEXTYPE.T2D)
{
if( image != null)
{
mGL.activeTexture( mGL.TEXTURE0 );
mGL.bindTexture(mGL.TEXTURE_2D, id);
mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, vflip);
var glFoTy = iFormatPI2GL( te.mFormat );
mGL.texImage2D(mGL.TEXTURE_2D, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image);
mGL.bindTexture(mGL.TEXTURE_2D, null);
mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, false);
}
}
else if (te.mType === me.TEXTYPE.CUBEMAP)
{
if( image != null)
{
var glFoTy = iFormatPI2GL( te.mFormat );
mGL.activeTexture( mGL.TEXTURE0 );
mGL.bindTexture( mGL.TEXTURE_CUBE_MAP, id );
mGL.pixelStorei( mGL.UNPACK_FLIP_Y_WEBGL, vflip);
mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image[0] );
mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image[1] );
mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, (vflip ? image[3] : image[2]) );
mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, (vflip ? image[2] : image[3]) );
mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image[4] );
mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image[5] );
mGL.bindTexture( mGL.TEXTURE_CUBE_MAP, null );
mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, false);
}
}
te.mVFlip = vflip;
};
me.CreateMipmaps = function (te)
{
if( te.mType===me.TEXTYPE.T2D )
{
mGL.activeTexture(mGL.TEXTURE0);
mGL.bindTexture(mGL.TEXTURE_2D, te.mObjectID);
mGL.generateMipmap(mGL.TEXTURE_2D);
mGL.bindTexture(mGL.TEXTURE_2D, null);
}
else if( te.mType===me.TEXTYPE.CUBEMAP )
{
mGL.activeTexture(mGL.TEXTURE0);
mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, te.mObjectID);
mGL.generateMipmap( mGL.TEXTURE_CUBE_MAP );
mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, null);
}
};
me.UpdateTexture = function( tex, x0, y0, xres, yres, buffer )
{
var glFoTy = iFormatPI2GL( tex.mFormat );
if( tex.mType===me.TEXTYPE.T2D )
{
mGL.activeTexture( mGL.TEXTURE0);
mGL.bindTexture( mGL.TEXTURE_2D, tex.mObjectID );
mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, tex.mVFlip );
mGL.texSubImage2D( mGL.TEXTURE_2D, 0, x0, y0, xres, yres, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
mGL.bindTexture( mGL.TEXTURE_2D, null );
mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, false);
}
};
me.UpdateTextureFromImage = function( tex, image )
{
var glFoTy = iFormatPI2GL( tex.mFormat );
if( tex.mType===me.TEXTYPE.T2D )
{
mGL.activeTexture( mGL.TEXTURE0 );
mGL.bindTexture( mGL.TEXTURE_2D, tex.mObjectID );
mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, tex.mVFlip );
mGL.texImage2D( mGL.TEXTURE_2D, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image );
mGL.bindTexture( mGL.TEXTURE_2D, null );
mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, false);
}
};
me.DestroyTexture = function( te )
{
mGL.deleteTexture( te.mObjectID );
};
me.AttachTextures = function (num, t0, t1, t2, t3)
{
if (num > 0 && t0 != null)
{
mGL.activeTexture(mGL.TEXTURE0);
if (t0.mType === me.TEXTYPE.T2D) mGL.bindTexture(mGL.TEXTURE_2D, t0.mObjectID);
else if (t0.mType === me.TEXTYPE.T3D) mGL.bindTexture(mGL.TEXTURE_3D, t0.mObjectID);
else if (t0.mType === me.TEXTYPE.CUBEMAP) mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, t0.mObjectID);
}
if (num > 1 && t1 != null)
{
mGL.activeTexture(mGL.TEXTURE1);
if (t1.mType === me.TEXTYPE.T2D) mGL.bindTexture(mGL.TEXTURE_2D, t1.mObjectID);
else if (t1.mType === me.TEXTYPE.T3D) mGL.bindTexture(mGL.TEXTURE_3D, t1.mObjectID);
else if (t1.mType === me.TEXTYPE.CUBEMAP) mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, t1.mObjectID);
}
if (num > 2 && t2 != null)
{
mGL.activeTexture(mGL.TEXTURE2);
if (t2.mType === me.TEXTYPE.T2D) mGL.bindTexture(mGL.TEXTURE_2D, t2.mObjectID);
else if (t2.mType === me.TEXTYPE.T3D) mGL.bindTexture(mGL.TEXTURE_3D, t2.mObjectID);
else if (t2.mType === me.TEXTYPE.CUBEMAP) mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, t2.mObjectID);
}
if (num > 3 && t3 != null)
{
mGL.activeTexture(mGL.TEXTURE3);
if (t3.mType === me.TEXTYPE.T2D) mGL.bindTexture(mGL.TEXTURE_2D, t3.mObjectID);
else if (t3.mType === me.TEXTYPE.T3D) mGL.bindTexture(mGL.TEXTURE_3D, t3.mObjectID);
else if (t3.mType === me.TEXTYPE.CUBEMAP) mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, t3.mObjectID);
}
};
me.DettachTextures = function()
{
mGL.activeTexture(mGL.TEXTURE0);
mGL.bindTexture(mGL.TEXTURE_2D, null);
mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, null);
mGL.activeTexture(mGL.TEXTURE1);
mGL.bindTexture(mGL.TEXTURE_2D, null);
mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, null);
mGL.activeTexture(mGL.TEXTURE2);
mGL.bindTexture(mGL.TEXTURE_2D, null);
mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, null);
mGL.activeTexture(mGL.TEXTURE3);
mGL.bindTexture(mGL.TEXTURE_2D, null);
mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, null);
};
me.CreateRenderTarget = function ( color0, color1, color2, color3, depth, wantZbuffer )
{
var id = mGL.createFramebuffer();
mGL.bindFramebuffer(mGL.FRAMEBUFFER, id);
if (depth === null)
{
if( wantZbuffer===true )
{
var zb = mGL.createRenderbuffer();
mGL.bindRenderbuffer(mGL.RENDERBUFFER, zb);
mGL.renderbufferStorage(mGL.RENDERBUFFER, mGL.DEPTH_COMPONENT16, color0.mXres, color0.mYres);
mGL.framebufferRenderbuffer(mGL.FRAMEBUFFER, mGL.DEPTH_ATTACHMENT, mGL.RENDERBUFFER, zb);
}
}
else
{
mGL.framebufferTexture2D(mGL.FRAMEBUFFER, mGL.DEPTH_ATTACHMENT, mGL.TEXTURE_2D, depth.mObjectID, 0);
}
if( color0 !=null ) mGL.framebufferTexture2D(mGL.FRAMEBUFFER, mGL.COLOR_ATTACHMENT0, mGL.TEXTURE_2D, color0.mObjectID, 0);
if (mGL.checkFramebufferStatus(mGL.FRAMEBUFFER) != mGL.FRAMEBUFFER_COMPLETE)
return null;
mGL.bindRenderbuffer(mGL.RENDERBUFFER, null);
mGL.bindFramebuffer(mGL.FRAMEBUFFER, null);
return { mObjectID: id, mTex0: color0 };
};
me.DestroyRenderTarget = function ( tex )
{
mGL.deleteFramebuffer(tex.mObjectID);
};
me.SetRenderTarget = function (tex)
{
if( tex===null )
mGL.bindFramebuffer(mGL.FRAMEBUFFER, null);
else
mGL.bindFramebuffer(mGL.FRAMEBUFFER, tex.mObjectID);
//mGL.drawBuffers([mGL.COLOR_ATTACHMENT0, mGL.COLOR_ATTACHMENT1]);
};
me.CreateRenderTargetNew = function ( wantColor0, wantZbuffer, xres, yres, samples )
{
var id = mGL.createFramebuffer();
mGL.bindFramebuffer(mGL.FRAMEBUFFER, id);
if( wantZbuffer===true )
{
var zb = mGL.createRenderbuffer();
mGL.bindRenderbuffer(mGL.RENDERBUFFER, zb);
if( samples==1 )
mGL.renderbufferStorage(mGL.RENDERBUFFER, mGL.DEPTH_COMPONENT16, xres, yres);
else
mGL.renderbufferStorageMultisample(mGL.RENDERBUFFER, samples, mGL.DEPTH_COMPONENT16, xres, yres);
mGL.framebufferRenderbuffer(mGL.FRAMEBUFFER, mGL.DEPTH_ATTACHMENT, mGL.RENDERBUFFER, zb);
}
if( wantColor0 )
{
var cb = mGL.createRenderbuffer();
mGL.bindRenderbuffer(mGL.RENDERBUFFER, cb);
if( samples==1 )
mGL.renderbufferStorage(mGL.RENDERBUFFER, mGL.RGBA8, xres, yres);
else
mGL.renderbufferStorageMultisample(mGL.RENDERBUFFER, samples, mGL.RGBA8, xres, yres);
mGL.framebufferRenderbuffer(mGL.FRAMEBUFFER, mGL.COLOR_ATTACHMENT0, mGL.RENDERBUFFER, cb);
}
if (mGL.checkFramebufferStatus(mGL.FRAMEBUFFER) != mGL.FRAMEBUFFER_COMPLETE)
{
return null;
}
mGL.bindRenderbuffer(mGL.RENDERBUFFER, null);
mGL.bindFramebuffer(mGL.FRAMEBUFFER, null);
return { mObjectID: id, mXres: xres, mYres:yres, mTex0: color0 };
};
me.CreateRenderTargetCubeMap = function ( color0, depth, wantZbuffer )
{
var id = mGL.createFramebuffer();
mGL.bindFramebuffer(mGL.FRAMEBUFFER, id);
if (depth === null)
{
if( wantZbuffer===true )
{
var zb = mGL.createRenderbuffer();
mGL.bindRenderbuffer(mGL.RENDERBUFFER, zb);
mGL.renderbufferStorage(mGL.RENDERBUFFER, mGL.DEPTH_COMPONENT16, color0.mXres, color0.mYres);
mGL.framebufferRenderbuffer(mGL.FRAMEBUFFER, mGL.DEPTH_ATTACHMENT, mGL.RENDERBUFFER, zb);
}
}
else
{
mGL.framebufferTexture2D(mGL.FRAMEBUFFER, mGL.DEPTH_ATTACHMENT, mGL.TEXTURE_2D, depth.mObjectID, 0);
}
if( color0 !=null ) mGL.framebufferTexture2D(mGL.FRAMEBUFFER, mGL.COLOR_ATTACHMENT0, mGL.TEXTURE_CUBE_MAP_POSITIVE_X, color0.mObjectID, 0);
if (mGL.checkFramebufferStatus(mGL.FRAMEBUFFER) != mGL.FRAMEBUFFER_COMPLETE)
return null;
mGL.bindRenderbuffer(mGL.RENDERBUFFER, null);
mGL.bindFramebuffer(mGL.FRAMEBUFFER, null);
return { mObjectID: id, mTex0: color0 };
};
me.SetRenderTargetCubeMap = function (fbo, face)
{
if( fbo===null )
mGL.bindFramebuffer(mGL.FRAMEBUFFER, null);
else
{
mGL.bindFramebuffer(mGL.FRAMEBUFFER, fbo.mObjectID);
mGL.framebufferTexture2D(mGL.FRAMEBUFFER, mGL.COLOR_ATTACHMENT0, mGL.TEXTURE_CUBE_MAP_POSITIVE_X+face, fbo.mTex0.mObjectID, 0);
}
};
me.BlitRenderTarget = function( dst, src )
{
mGL.bindFramebuffer(mGL.READ_FRAMEBUFFER, src.mObjectID);
mGL.bindFramebuffer(mGL.DRAW_FRAMEBUFFER, dst.mObjectID);
mGL.clearBufferfv(mGL.COLOR, 0, [0.0, 0.0, 0.0, 1.0]);
mGL.blitFramebuffer( 0, 0, src.mXres, src.mYres,
0, 0, src.mXres, src.mYres,
mGL.COLOR_BUFFER_BIT, mGL.LINEAR
);
};
me.SetViewport = function( vp )
{
mGL.viewport( vp[0], vp[1], vp[2], vp[3] );
};
me.SetWriteMask = function( c0, c1, c2, c3, z )
{
mGL.depthMask(z);
mGL.colorMask(c0,c0,c0,c0);
};
me.SetState = function( stateName, stateValue )
{
if (stateName === me.RENDSTGATE.WIREFRAME)
{
if( stateValue ) mGL.polygonMode( mGL.FRONT_AND_BACK, mGL.LINE );
else mGL.polygonMode( mGL.FRONT_AND_BACK, mGL.FILL );
}
else if (stateName === me.RENDSTGATE.FRONT_FACE)
{
if( stateValue ) mGL.cullFace( mGL.BACK );
else mGL.cullFace( mGL.FRONT );
}
else if (stateName === me.RENDSTGATE.CULL_FACE)
{
if( stateValue ) mGL.enable( mGL.CULL_FACE );
else mGL.disable( mGL.CULL_FACE );
}
else if (stateName === me.RENDSTGATE.DEPTH_TEST)
{
if( stateValue ) mGL.enable( mGL.DEPTH_TEST );
else mGL.disable( mGL.DEPTH_TEST );
}
else if (stateName === me.RENDSTGATE.ALPHA_TO_COVERAGE)
{
if( stateValue ) { mGL.enable( mGL.SAMPLE_ALPHA_TO_COVERAGE ); }
else { mGL.disable( mGL.SAMPLE_ALPHA_TO_COVERAGE ); }
}
};
me.SetMultisample = function( v)
{
if( v===true )
{
mGL.enable(mGL.SAMPLE_COVERAGE);
mGL.sampleCoverage(1.0, false);
}
else
{
mGL.disable(mGL.SAMPLE_COVERAGE);
}
};
me.GetTranslatedShaderSource = function (shader)
{
if( mGL===null ) return null;
if( mDebugShader===null ) return null;
let vfs = mGL.getAttachedShaders(shader.mProgram);
let str = mDebugShader.getTranslatedShaderSource(vfs[1]);
let parts = str.split("GLSL END"); str = (parts.length<2) ? str : parts[1];
return str;
};
me.CreateShader = function (vsSource, fsSource, preventCache, forceSynch, onResolve)
{
if( mGL===null ) return;
var vs = mGL.createShader( mGL.VERTEX_SHADER );
var fs = mGL.createShader( mGL.FRAGMENT_SHADER );
vsSource = mShaderHeader[0] + vsSource;
fsSource = mShaderHeader[1] + fsSource;
if( preventCache )
{
let vran = Math.random().toString(36).substring(7);
let fran = Math.random().toString(36).substring(7);
vsSource += "\n#define K" + vran + "\n";
fsSource += "\n#define K" + fran + "\n";
}
var timeStart = (new Date()).getTime();
mGL.shaderSource(vs, vsSource);
mGL.shaderSource(fs, fsSource);
mGL.compileShader(vs);
mGL.compileShader(fs);
var pr = mGL.createProgram();
mGL.attachShader(pr, vs);
mGL.attachShader(pr, fs);
mGL.linkProgram(pr);
//-------------
let checkErrors = function()
{
if (!mGL.getProgramParameter(pr, mGL.LINK_STATUS))
{
// vs error
if (!mGL.getShaderParameter(vs, mGL.COMPILE_STATUS))
{
let vsLog = mGL.getShaderInfoLog(vs);
onResolve(false, { mErrorType: 0, mErrorStr: vsLog });
mGL.deleteProgram(pr);
}
// fs error
else if (!mGL.getShaderParameter(fs, mGL.COMPILE_STATUS))
{
let fsLog = mGL.getShaderInfoLog(fs);
onResolve(false, { mErrorType: 1, mErrorStr: fsLog });
mGL.deleteProgram(pr);
}
// link error
else
{
let infoLog = mGL.getProgramInfoLog(pr);
onResolve(false, { mErrorType: 2, mErrorStr: infoLog });
mGL.deleteProgram(pr);
}
}
// no errors
else
{
let compilationTime = (new Date()).getTime() - timeStart;
onResolve(true, { mProgram: pr, mTime: compilationTime });
}
};
// check compilation
if (mAsynchCompile === null || forceSynch===true )
{
checkErrors();
}
else
{
let loopCheckCompletion = function ()
{
if( mGL.getProgramParameter(pr, mAsynchCompile.COMPLETION_STATUS_KHR) === true )
checkErrors();
else
setTimeout(loopCheckCompletion, 10);
};
setTimeout(loopCheckCompletion, 10);
}
};
me.AttachShader = function( shader )
{
if( shader===null )
{
mBindedShader = null;
mGL.useProgram( null );
}
else
{
mBindedShader = shader;
mGL.useProgram(shader.mProgram);
}
};
me.DetachShader = function ()
{
mGL.useProgram(null);
};
me.DestroyShader = function( tex )
{
mGL.deleteProgram(tex.mProgram);
};
me.GetAttribLocation = function (shader, name)
{
return mGL.getAttribLocation(shader.mProgram, name);
};
me.SetShaderConstantLocation = function (shader, name)
{
return mGL.getUniformLocation(shader.mProgram, name);
};
me.SetShaderConstantMat4F = function( uname, params, istranspose )
{
var program = mBindedShader;
let pos = mGL.getUniformLocation( program.mProgram, uname );
if( pos===null )
return false;
if( istranspose===false )
{
var tmp = new Float32Array( [ params[0], params[4], params[ 8], params[12],
params[1], params[5], params[ 9], params[13],
params[2], params[6], params[10], params[14],
params[3], params[7], params[11], params[15] ] );
mGL.uniformMatrix4fv(pos,false,tmp);
}
else
mGL.uniformMatrix4fv(pos,false,new Float32Array(params) );
return true;
};
me.SetShaderConstant1F_Pos = function(pos, x)
{
mGL.uniform1f(pos, x);
return true;
};
me.SetShaderConstant1FV_Pos = function(pos, x)
{
mGL.uniform1fv(pos, x);
return true;
};
me.SetShaderConstant1F = function( uname, x )
{
var pos = mGL.getUniformLocation(mBindedShader.mProgram, uname);
if (pos === null)
return false;
mGL.uniform1f(pos, x);
return true;
};
me.SetShaderConstant1I = function(uname, x)
{
let pos = mGL.getUniformLocation(mBindedShader.mProgram, uname);
if (pos === null)
return false;
mGL.uniform1i(pos, x);
return true;
};
me.SetShaderConstant1I_Pos = function(pos, x)
{
mGL.uniform1i(pos, x);
return true;
};
me.SetShaderConstant2F = function(uname, x)
{
let pos = mGL.getUniformLocation(mBindedShader.mProgram, uname);
if (pos === null)
return false;
mGL.uniform2fv(pos, x);
return true;
};
me.SetShaderConstant3F = function(uname, x, y, z)
{
let pos = mGL.getUniformLocation(mBindedShader.mProgram, uname);
if (pos === null)
return false;
mGL.uniform3f(pos, x, y, z);
return true;
};
me.SetShaderConstant1FV = function(uname, x)
{
let pos = mGL.getUniformLocation(mBindedShader.mProgram, uname);
if (pos === null)
return false;
mGL.uniform1fv(pos, new Float32Array(x));
return true;
};
me.SetShaderConstant3FV = function(uname, x)
{
let pos = mGL.getUniformLocation(mBindedShader.mProgram, uname);
if (pos === null) return false;
mGL.uniform3fv(pos, new Float32Array(x) );
return true;
};
me.SetShaderConstant4FV = function(uname, x)
{
let pos = mGL.getUniformLocation(mBindedShader.mProgram, uname);
if (pos === null) return false;
mGL.uniform4fv(pos, new Float32Array(x) );
return true;
};
me.SetShaderTextureUnit = function( uname, unit )
{
var program = mBindedShader;
let pos = mGL.getUniformLocation(program.mProgram, uname);
if (pos === null) return false;
mGL.uniform1i(pos, unit);
return true;
};
me.CreateVertexArray = function( data, mode )
{
let id = mGL.createBuffer();
mGL.bindBuffer(mGL.ARRAY_BUFFER, id);
if (mode === me.BUFTYPE.STATIC)
mGL.bufferData(mGL.ARRAY_BUFFER, data, mGL.STATIC_DRAW);
else
mGL.bufferData(mGL.ARRAY_BUFFER, data, mGL.DYNAMIC_DRAW);
return { mObject: id };
};
me.CreateIndexArray = function( data, mode )
{
let id = mGL.createBuffer();
mGL.bindBuffer(mGL.ELEMENT_ARRAY_BUFFER, id );
if (mode === me.BUFTYPE.STATIC)
mGL.bufferData(mGL.ELEMENT_ARRAY_BUFFER, data, mGL.STATIC_DRAW);
else
mGL.bufferData(mGL.ELEMENT_ARRAY_BUFFER, data, mGL.DYNAMIC_DRAW);
return { mObject: id };
};
me.DestroyArray = function( tex )
{
mGL.destroyBuffer(tex.mObject);
};
me.AttachVertexArray = function( tex, attribs, pos )
{
let shader = mBindedShader;
mGL.bindBuffer( mGL.ARRAY_BUFFER, tex.mObject);
var num = attribs.mChannels.length;
var stride = attribs.mStride;
var offset = 0;
for (var i = 0; i < num; i++)
{
var id = pos[i];
mGL.enableVertexAttribArray(id);
var dtype = mGL.FLOAT;
var dsize = 4;
if( attribs.mChannels[i].mType === me.TYPE.UINT8 ) { dtype = mGL.UNSIGNED_BYTE; dsize = 1; }
else if( attribs.mChannels[i].mType === me.TYPE.UINT16 ) { dtype = mGL.UNSIGNED_SHORT; dsize = 2; }
else if( attribs.mChannels[i].mType === me.TYPE.FLOAT32 ) { dtype = mGL.FLOAT; dsize = 4; }
mGL.vertexAttribPointer(id, attribs.mChannels[i].mNumComponents, dtype, attribs.mChannels[i].mNormalize, stride, offset);
offset += attribs.mChannels[i].mNumComponents * dsize;
}
};
me.AttachIndexArray = function( tex )
{
mGL.bindBuffer(mGL.ELEMENT_ARRAY_BUFFER, tex.mObject);
};
me.DetachVertexArray = function (tex, attribs)
{
let num = attribs.mChannels.length;
for (let i = 0; i < num; i++)
mGL.disableVertexAttribArray(i);
mGL.bindBuffer(mGL.ARRAY_BUFFER, null);
};
me.DetachIndexArray = function( tex )
{
mGL.bindBuffer(mGL.ELEMENT_ARRAY_BUFFER, null);
};
me.DrawPrimitive = function( typeOfPrimitive, num, useIndexArray, numInstances )
{
let glType = mGL.POINTS;
if( typeOfPrimitive===me.PRIMTYPE.POINTS ) glType = mGL.POINTS;
if( typeOfPrimitive===me.PRIMTYPE.LINES ) glType = mGL.LINES;
if( typeOfPrimitive===me.PRIMTYPE.LINE_LOOP ) glType = mGL.LINE_LOOP;
if( typeOfPrimitive===me.PRIMTYPE.LINE_STRIP ) glType = mGL.LINE_STRIP;
if( typeOfPrimitive===me.PRIMTYPE.TRIANGLES ) glType = mGL.TRIANGLES;
if( typeOfPrimitive===me.PRIMTYPE.TRIANGLE_STRIP ) glType = mGL.TRIANGLE_STRIP;
if( numInstances<=1 )
{
if( useIndexArray ) mGL.drawElements( glType, num, mGL.UNSIGNED_SHORT, 0 );
else mGL.drawArrays( glType, 0, num );
}
else
{
mGL.drawArraysInstanced(glType, 0, num, numInstances);
mGL.drawElementsInstanced( glType, num, mGL.UNSIGNED_SHORT, 0, numInstances);
}
};
me.DrawFullScreenTriangle_XY = function( vpos )
{
mGL.bindBuffer( mGL.ARRAY_BUFFER, mVBO_Tri );
mGL.vertexAttribPointer( vpos, 2, mGL.FLOAT, false, 0, 0 );
mGL.enableVertexAttribArray( vpos );
mGL.drawArrays( mGL.TRIANGLES, 0, 3 );
mGL.disableVertexAttribArray( vpos );
mGL.bindBuffer( mGL.ARRAY_BUFFER, null );
};
me.DrawUnitQuad_XY = function( vpos )
{
mGL.bindBuffer( mGL.ARRAY_BUFFER, mVBO_Quad );
mGL.vertexAttribPointer( vpos, 2, mGL.FLOAT, false, 0, 0 );
mGL.enableVertexAttribArray( vpos );
mGL.drawArrays( mGL.TRIANGLES, 0, 6 );
mGL.disableVertexAttribArray( vpos );
mGL.bindBuffer( mGL.ARRAY_BUFFER, null );
};
me.DrawUnitCube_XYZ_NOR = function( vpos )
{
mGL.bindBuffer( mGL.ARRAY_BUFFER, mVBO_CubePosNor );
mGL.vertexAttribPointer( vpos[0], 3, mGL.FLOAT, false, 0, 0 );
mGL.vertexAttribPointer( vpos[1], 3, mGL.FLOAT, false, 0, 0 );
mGL.enableVertexAttribArray( vpos[0] );
mGL.enableVertexAttribArray( vpos[1] );
mGL.drawArrays(mGL.TRIANGLE_STRIP, 0, 4);
mGL.drawArrays(mGL.TRIANGLE_STRIP, 4, 4);
mGL.drawArrays(mGL.TRIANGLE_STRIP, 8, 4);
mGL.drawArrays(mGL.TRIANGLE_STRIP, 12, 4);
mGL.drawArrays(mGL.TRIANGLE_STRIP, 16, 4);
mGL.drawArrays(mGL.TRIANGLE_STRIP, 20, 4);
mGL.disableVertexAttribArray( vpos[0] );
mGL.disableVertexAttribArray( vpos[1] );
mGL.bindBuffer( mGL.ARRAY_BUFFER, null );
}
me.DrawUnitCube_XYZ = function( vpos )
{
mGL.bindBuffer( mGL.ARRAY_BUFFER, mVBO_CubePos );
mGL.vertexAttribPointer( vpos, 3, mGL.FLOAT, false, 0, 0 );
mGL.enableVertexAttribArray( vpos );
mGL.drawArrays(mGL.TRIANGLE_STRIP, 0, 4);
mGL.drawArrays(mGL.TRIANGLE_STRIP, 4, 4);
mGL.drawArrays(mGL.TRIANGLE_STRIP, 8, 4);
mGL.drawArrays(mGL.TRIANGLE_STRIP, 12, 4);
mGL.drawArrays(mGL.TRIANGLE_STRIP, 16, 4);
mGL.drawArrays(mGL.TRIANGLE_STRIP, 20, 4);
mGL.disableVertexAttribArray( vpos );
mGL.bindBuffer( mGL.ARRAY_BUFFER, null );
}
me.SetBlend = function( enabled )
{
if( enabled )
{
mGL.enable( mGL.BLEND );
mGL.blendEquationSeparate( mGL.FUNC_ADD, mGL.FUNC_ADD );
mGL.blendFuncSeparate( mGL.SRC_ALPHA, mGL.ONE_MINUS_SRC_ALPHA, mGL.ONE, mGL.ONE_MINUS_SRC_ALPHA );
}
else
{
mGL.disable( mGL.BLEND );
}
};
me.GetPixelData = function( data, offset, xres, yres )
{
mGL.readPixels(0, 0, xres, yres, mGL.RGBA, mGL.UNSIGNED_BYTE, data, offset);
};
me.GetPixelDataRenderTarget = function( obj, data, xres, yres )
{
mGL.bindFramebuffer(mGL.FRAMEBUFFER, obj.mObjectID);
mGL.readBuffer(mGL.COLOR_ATTACHMENT0);
mGL.readPixels(0, 0, xres, yres, mGL.RGBA, mGL.FLOAT, data, 0);
mGL.bindFramebuffer(mGL.FRAMEBUFFER, null);
};
return me;
}
//==============================================================================
//
// piLibs 2015-2017 - http://www.iquilezles.org/www/material/piLibs/piLibs.htm
//
// piShading
//
//==============================================================================
function smoothstep(a, b, x)
{
x = (x - a) / (b - a);
if (x < 0) x = 0; else if (x > 1) x = 1;
return x * x * (3.0 - 2.0 * x);
}
function clamp01(x)
{
if( x < 0.0 ) x = 0.0;
if( x > 1.0 ) x = 1.0;
return x;
}
function clamp(x, a, b)
{
if( x < a ) x = a;
if( x > b ) x = b;
return x;
}
function screen(a, b)
{
return 1.0 - (1.0 - a) * (1.0 - b);
}
function parabola(x)
{
return 4.0 * x * (1.0 - x);
}
function min(a, b)
{
return (a < b) ? a : b;
}
function max(a, b)
{
return (a > b) ? a : b;
}
function noise( x )
{
function grad(i, j, x, y)
{
var h = 7 * i + 131 * j;
h = (h << 13) ^ h;
h = (h * (h * h * 15731 + 789221) + 1376312589);
var rx = (h & 0x20000000) ? x : -x;
var ry = (h & 0x10000000) ? y : -y;
return rx + ry;
}
var i = [ Math.floor(x[0]), Math.floor(x[1]) ];
var f = [ x[0] - i[0], x[1] - i[1] ];
var w = [ f[0]*f[0]*(3.0-2.0*f[0]), f[1]*f[1]*(3.0-2.0*f[1]) ];
var a = grad( i[0]+0, i[1]+0, f[0]+0.0, f[1]+0.0 );
var b = grad( i[0]+1, i[1]+0, f[0]-1.0, f[1]+0.0 );
var c = grad( i[0]+0, i[1]+1, f[0]+0.0, f[1]-1.0 );
var d = grad( i[0]+1, i[1]+1, f[0]-1.0, f[1]-1.0 );
return a + (b-a)*w[0] + (c-a)*w[1] + (a-b-c+d)*w[0]*w[1];
}//==============================================================================
//
// piLibs 2015-2017 - http://www.iquilezles.org/www/material/piLibs/piLibs.htm
//
// piVecTypes
//
//==============================================================================
function vec3( a, b, c )
{
return [ a, b, c ];
}
function add( a, b )
{
return [ a[0]+b[0], a[1]+b[1], a[2]+b[2] ];
}
function sub( a, b )
{
return [ a[0]-b[0], a[1]-b[1], a[2]-b[2] ];
}
function mul( a, s )
{
return [ a[0]*s, a[1]*s, a[2]*s ];
}
function cross( a, b )
{
return [ a[1]*b[2] - a[2]*b[1],
a[2]*b[0] - a[0]*b[2],
a[0]*b[1] - a[1]*b[0] ];
}
function dot( a, b )
{
return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
}
function normalize( v )
{
var is = 1.0 / Math.sqrt( v[0]*v[0] + v[1]*v[1] + v[2]*v[2] );
return [ v[0]*is, v[1]*is, v[2]*is ];
}
function createCirclePoint( cen, uuu, vvv, rad, s, t )
{
return [ cen[0] + rad*(uuu[0]*s + vvv[0]*t),
cen[1] + rad*(uuu[1]*s + vvv[1]*t),
cen[2] + rad*(uuu[2]*s + vvv[2]*t) ];
}
function createTangent( a, b, c )
{
var cb = normalize( [ c[0]-b[0], c[1]-b[1], c[2]-b[2] ] );
var ba = normalize( [ b[0]-a[0], b[1]-a[1], b[2]-a[2] ] );
return normalize( [ ba[0]+cb[0], ba[1]+cb[1], ba[2]+cb[2] ] );
}
//===================================
function vec4( a, b, c, d )
{
return [ a, b, c, d ];
}
function getXYZ( v )
{
return [ v[0], v[1], v[2] ];
}
//===================================
function setIdentity()
{
return [ 1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 ];
}
function setRotationX( t )
{
var sint = Math.sin(t);
var cost = Math.cos(t);
return [ 1.0, 0.0, 0.0, 0.0,
0.0, cost, -sint, 0.0,
0.0, sint, cost, 0.0,
0.0, 0.0, 0.0, 1.0 ];
}
function setRotationY( t )
{
var sint = Math.sin(t);
var cost = Math.cos(t);
return [ cost, 0.0, -sint, 0.0,
0.0, 1.0, 0.0, 0.0,
sint, 0.0, cost, 0.0,
0.0, 0.0, 0.0, 1.0 ];
}
function extractRotationEuler( m)
{
var res = [];
if (m[0] == 1.0)
{
res[0] = Math.atan2(m[2], m[11]);
res[1] = 0.0;
res[2] = 0.0;
}
else if (m[0] == -1.0)
{
res[0] = Math.atan2( m[2], m[11]);
res[1] = 0.0;
res[2] = 0.0;
}
else
{
res[0] = Math.atan2( -m[9], m[10]);
res[1] = Math.atan2( m[8], Math.sqrt(m[9]*m[9] + m[10]*m[10]));
res[2] = Math.atan2( m[4], m[0]);
}
return res;
}
function setFromQuaternion( q )
{
var ww = q[3]*q[3];
var xx = q[0]*q[0];
var yy = q[1]*q[1];
var zz = q[2]*q[2];
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,
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,
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,
0.0, 0.0, 0.0, 1.0 ];
}
function setPerspective( fovy, aspect, znear, zfar )
{
var tan = Math.tan(fovy * Math.PI/180.0);
var x = 1.0 / (tan*aspect);
var y = 1.0 / (tan);
var c = -(zfar + znear) / ( zfar - znear);
var d = -(2.0 * zfar * znear) / (zfar - znear);
return [ x, 0.0, 0.0, 0.0,
0.0, y, 0.0, 0.0,
0.0, 0.0, c, d,
0.0, 0.0, -1.0, 0.0 ];
}
function setLookAt( eye, tar, up )
{
var dir = [ -tar[0]+eye[0], -tar[1]+eye[1], -tar[2]+eye[2] ];
var m00 = dir[2]*up[1] - dir[1]*up[2];
var m01 = dir[0]*up[2] - dir[2]*up[0];
var m02 = dir[1]*up[0] - dir[0]*up[1];
var im = 1.0/Math.sqrt( m00*m00 + m01*m01 + m02*m02 );
m00 *= im;
m01 *= im;
m02 *= im;
var m04 = m02*dir[1] - m01*dir[2];
var m05 = m00*dir[2] - m02*dir[0];
var m06 = m01*dir[0] - m00*dir[1];
im = 1.0/Math.sqrt( m04*m04 + m05*m05 + m06*m06 );
m04 *= im;
m05 *= im;
m06 *= im;
var m08 = dir[0];
var m09 = dir[1];
var m10 = dir[2];
im = 1.0/Math.sqrt( m08*m08 + m09*m09 + m10*m10 );
m08 *= im;
m09 *= im;
m10 *= im;
var m03 = -(m00*eye[0] + m01*eye[1] + m02*eye[2] );
var m07 = -(m04*eye[0] + m05*eye[1] + m06*eye[2] );
var m11 = -(m08*eye[0] + m09*eye[1] + m10*eye[2] );
return [ m00, m01, m02, m03,
m04, m05, m06, m07,
m08, m09, m10, m11,
0.0, 0.0, 0.0, 1.0 ];
}
function setOrtho( left, right, bottom, top, znear, zfar )
{
var x = 2.0 / (right - left);
var y = 2.0 / (top - bottom);
var a = (right + left) / (right - left);
var b = (top + bottom) / (top - bottom);
var c = -2.0 / (zfar - znear);
var d = -(zfar + znear) / ( zfar - znear);
return [ x, 0.0, 0.0, a,
0.0, y, 0.0, b,
0.0, 0.0, c, d,
0.0, 0.0, 0.0, 1.0 ];
}
function setTranslation( p )
{
return [ 1.0, 0.0, 0.0, p[0],
0.0, 1.0, 0.0, p[1],
0.0, 0.0, 1.0, p[2],
0.0, 0.0, 0.0, 1.0 ];
}
function setScale( s )
{
return [ s[0], 0.0, 0.0, 0.0,
0.0, s[1], 0.0, 0.0,
0.0, 0.0, s[2], 0.0,
0.0, 0.0, 0.0, 1.0];
}
function setProjection( fov, znear, zfar )
{
var x = 2.0 / (fov[3]+fov[2]);
var y = 2.0 / (fov[0]+fov[1]);
var a = (fov[3]-fov[2]) / (fov[3]+fov[2]);
var b = (fov[0]-fov[1]) / (fov[0]+fov[1]);
var c = -(zfar + znear) / ( zfar - znear);
var d = -(2.0*zfar*znear) / (zfar - znear);
return [ x, 0.0, a, 0.0,
0.0, y, b, 0.0,
0.0, 0.0, c, d,
0.0, 0.0, -1.0, 0.0 ];
// inverse is:
//return mat4x4( 1.0/x, 0.0f, 0.0f, a/x,
// 0.0f, 1.0/y, 0.0f, b/x,
// 0.0f, 0.0f, 0.0f, -1.0,
// 0.0f, 0.0f, 1.0f/d, c/d );
}
function invertFast( m )
{
var inv = [
m[5] * m[10] * m[15] -
m[5] * m[11] * m[14] -
m[9] * m[6] * m[15] +
m[9] * m[7] * m[14] +
m[13] * m[6] * m[11] -
m[13] * m[7] * m[10],
-m[1] * m[10] * m[15] +
m[1] * m[11] * m[14] +
m[9] * m[2] * m[15] -
m[9] * m[3] * m[14] -
m[13] * m[2] * m[11] +
m[13] * m[3] * m[10],
m[1] * m[6] * m[15] -
m[1] * m[7] * m[14] -
m[5] * m[2] * m[15] +
m[5] * m[3] * m[14] +
m[13] * m[2] * m[7] -
m[13] * m[3] * m[6],
-m[1] * m[6] * m[11] +
m[1] * m[7] * m[10] +
m[5] * m[2] * m[11] -
m[5] * m[3] * m[10] -
m[9] * m[2] * m[7] +
m[9] * m[3] * m[6],
-m[4] * m[10] * m[15] +
m[4] * m[11] * m[14] +
m[8] * m[6] * m[15] -
m[8] * m[7] * m[14] -
m[12] * m[6] * m[11] +
m[12] * m[7] * m[10],
m[0] * m[10] * m[15] -
m[0] * m[11] * m[14] -
m[8] * m[2] * m[15] +
m[8] * m[3] * m[14] +
m[12] * m[2] * m[11] -
m[12] * m[3] * m[10],
-m[0] * m[6] * m[15] +
m[0] * m[7] * m[14] +
m[4] * m[2] * m[15] -
m[4] * m[3] * m[14] -
m[12] * m[2] * m[7] +
m[12] * m[3] * m[6],
m[0] * m[6] * m[11] -
m[0] * m[7] * m[10] -
m[4] * m[2] * m[11] +
m[4] * m[3] * m[10] +
m[8] * m[2] * m[7] -
m[8] * m[3] * m[6],
m[4] * m[9] * m[15] -
m[4] * m[11] * m[13] -
m[8] * m[5] * m[15] +
m[8] * m[7] * m[13] +
m[12] * m[5] * m[11] -
m[12] * m[7] * m[9],
-m[0] * m[9] * m[15] +
m[0] * m[11] * m[13] +
m[8] * m[1] * m[15] -
m[8] * m[3] * m[13] -
m[12] * m[1] * m[11] +
m[12] * m[3] * m[9],
m[0] * m[5] * m[15] -
m[0] * m[7] * m[13] -
m[4] * m[1] * m[15] +
m[4] * m[3] * m[13] +
m[12] * m[1] * m[7] -
m[12] * m[3] * m[5],
-m[0] * m[5] * m[11] +
m[0] * m[7] * m[9] +
m[4] * m[1] * m[11] -
m[4] * m[3] * m[9] -
m[8] * m[1] * m[7] +
m[8] * m[3] * m[5],
-m[4] * m[9] * m[14] +
m[4] * m[10] * m[13] +
m[8] * m[5] * m[14] -
m[8] * m[6] * m[13] -
m[12] * m[5] * m[10] +
m[12] * m[6] * m[9],
m[0] * m[9] * m[14] -
m[0] * m[10] * m[13] -
m[8] * m[1] * m[14] +
m[8] * m[2] * m[13] +
m[12] * m[1] * m[10] -
m[12] * m[2] * m[9],
-m[0] * m[5] * m[14] +
m[0] * m[6] * m[13] +
m[4] * m[1] * m[14] -
m[4] * m[2] * m[13] -
m[12] * m[1] * m[6] +
m[12] * m[2] * m[5],
m[0] * m[5] * m[10] -
m[0] * m[6] * m[9] -
m[4] * m[1] * m[10] +
m[4] * m[2] * m[9] +
m[8] * m[1] * m[6] -
m[8] * m[2] * m[5] ];
var det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];
det = 1.0/det;
for( var i = 0; i<16; i++ ) inv[i] = inv[i] * det;
return inv;
}
function matMul( a, b )
{
var res = [];
for( var i=0; i<4; i++ )
{
var x = a[4*i+0];
var y = a[4*i+1];
var z = a[4*i+2];
var w = a[4*i+3];
res[4*i+0] = x * b[ 0] + y * b[ 4] + z * b[ 8] + w * b[12];
res[4*i+1] = x * b[ 1] + y * b[ 5] + z * b[ 9] + w * b[13];
res[4*i+2] = x * b[ 2] + y * b[ 6] + z * b[10] + w * b[14];
res[4*i+3] = x * b[ 3] + y * b[ 7] + z * b[11] + w * b[15];
}
return res;
}
function matMulpoint( m, v )
{
return [ m[0]*v[0] + m[1]*v[1] + m[ 2]*v[2] + m[ 3],
m[4]*v[0] + m[5]*v[1] + m[ 6]*v[2] + m[ 7],
m[8]*v[0] + m[9]*v[1] + m[10]*v[2] + m[11] ];
}
function matMulvec( m, v )
{
return [ m[0]*v[0] + m[1]*v[1] + m[ 2]*v[2],
m[4]*v[0] + m[5]*v[1] + m[ 6]*v[2],
m[8]*v[0] + m[9]*v[1] + m[10]*v[2] ];
}
function bound3( infi )
{
return [ infi, -infi, infi, -infi, infi, -infi ];
}
function bound3_include( a, p )
{
return [
(p[0]<a[0]) ? p[0] : a[0],
(p[0]>a[1]) ? p[0] : a[1],
(p[1]<a[2]) ? p[1] : a[2],
(p[1]>a[3]) ? p[1] : a[3],
(p[2]<a[4]) ? p[2] : a[4],
(p[2]>a[5]) ? p[2] : a[5] ];
}
function bound3_center( b )
{
return [ 0.5*(b[0]+b[1]),
0.5*(b[2]+b[3]),
0.5*(b[4]+b[5]) ];
}
function bound3_radius( b )
{
return [ 0.5*(b[1]-b[0]),
0.5*(b[3]-b[2]),
0.5*(b[5]-b[4]) ];
}
//==============================================================================
//
// piLibs 2015-2017 - http://www.iquilezles.org/www/material/piLibs/piLibs.htm
//
// piWebVR
//
//==============================================================================
function WebVR( isVREnabledCallback, canvasElement )
{
isVREnabledCallback(false);
}
WebVR.prototype.IsSupported = function()
{
return false;
//return this.mSupportVR;
}
WebVR.prototype.GetData = function( id )
{
return {};
}
WebVR.prototype.Enable = function( id )
{
}
WebVR.prototype.Disable = function( id )
{
}
WebVR.prototype.RequestAnimationFrame = function (id)
{
}
WebVR.prototype.IsPresenting = function (id)
{
return false;
}
WebVR.prototype.Finish = function (id)
{
}
//==============================================================================
//
// piLibs 2015-2017 - http://www.iquilezles.org/www/material/piLibs/piLibs.htm
//
// piWebUtils
//
//==============================================================================
function htmlEntities(str)
{
return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g,'&apos;');
}
function piDisableTouch()
{}
var piGetTime = function ( timestamp )
{
if (timestamp == 0)
return "";
return new Date(timestamp * 1000).toISOString().substr(0, 10);
}
function piGetCoords( obj )
{
var x = 0;
var y = 0;
do
{
x += obj.offsetLeft;
y += obj.offsetTop;
}while( obj = obj.offsetParent );
return { mX:x, mY:y };
}
function piGetMouseCoords( ev, canvasElement )
{
var pos = piGetCoords(canvasElement );
var mcx = (ev.pageX - pos.mX) * canvasElement.width / canvasElement.offsetWidth;
var mcy = canvasElement.height - (ev.pageY - pos.mY) * canvasElement.height / canvasElement.offsetHeight;
return { mX: mcx, mY: mcy };
}
function piGetSourceElement( e )
{
var ele = null;
if( e.target ) ele = e.target;
if( e.srcElement ) ele = e.srcElement;
return ele;
}
function piRequestFullScreen( ele )
{}
function piIsFullScreen()
{
return false;
}
function piExitFullScreen()
{}
function piIsMobile()
{
return false;
}
function piCreateGlContext( cv, useAlpha, useDepth, usePreserveBuffer, useSupersampling )
{
var opts = { alpha: useAlpha,
depth: useDepth,
stencil: false,
premultipliedAlpha: false,
antialias: useSupersampling,
preserveDrawingBuffer: usePreserveBuffer,
powerPreference: "high-performance" }; // "low_power", "high_performance", "default"
var gl = null;
if( gl === null) gl = cv.getContext( "webgl2", opts );
if( gl === null) gl = cv.getContext( "experimental-webgl2", opts );
if( gl === null) gl = cv.getContext( "webgl", opts );
if( gl === null) gl = cv.getContext( "experimental-webgl", opts );
return gl;
}
function piCreateAudioContext()
{
return null;
}
function piHexColorToRGB(str) // "#ff3041"
{
var rgb = parseInt(str.slice(1), 16);
var r = (rgb >> 16) & 255;
var g = (rgb >> 8) & 255;
var b = (rgb >> 0) & 255;
return [r, g, b];
}
function piCreateFPSCounter()
{
var mFrame;
var mTo;
var mFPS;
var iReset = function( time )
{
mFrame = 0;
mTo = time;
mFPS = 60.0;
}
var iCount = function( time )
{
mFrame++;
if( (time-mTo)>500.0 )
{
mFPS = 1000.0*mFrame/(time-mTo);
mFrame = 0;
mTo = time;
return true;
}
return false;
}
var iGetFPS = function()
{
return mFPS;
}
return { Reset : iReset, Count : iCount, GetFPS : iGetFPS };
}
function piCanMediaRecorded(canvas)
{
return true;
}
function piCreateMediaRecorder(isRecordingCallback, canvas)
{
if (piCanMediaRecorded(canvas) == false)
{
return null;
}
var options = { audioBitsPerSecond : 0, videoBitsPerSecond : 8000000 };
if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) options.mimeType = 'video/webm;codecs=h264';
else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9' )) options.mimeType = 'video/webm;codecs=vp9';
else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8' )) options.mimeType = 'video/webm;codecs=vp8';
else options.mimeType = 'video/webm;';
var mediaRecorder = new MediaRecorder(canvas.captureStream(), options);
var chunks = [];
mediaRecorder.ondataavailable = function(e)
{
if (e.data.size > 0)
{
chunks.push(e.data);
}
};
mediaRecorder.onstart = function(){
isRecordingCallback( true );
};
mediaRecorder.onstop = function()
{
isRecordingCallback( false );
};
return mediaRecorder;
}
function piExportToEXR(width, height, numComponents, type, bytes)
{
var bytesPerComponent = 0;
if (type=="Uint") bytesPerComponent = 4;
else if (type=="Half") bytesPerComponent = 2;
else if (type=="Float") bytesPerComponent = 4;
var tHeader = 258 + (18 * numComponents + 1);
var tTable = 8 * height;
var tScanlines = height * (4 + 4 + (numComponents * bytesPerComponent * width));
var tTotal = tHeader + tTable + tScanlines;
var buffer = new ArrayBuffer(tTotal);
var data = new DataView(buffer);
// Header
{
// Header : 4 bytes -> 0x76, 0x2f, 0x31, 0x01
var c = 0;
data.setUint8 (c++, 0x76);
data.setUint8 (c++, 0x2f);
data.setUint8 (c++, 0x31);
data.setUint8 (c++, 0x01);
// Version : 4 bytes -> 2, 0, 0, 0
data.setUint8 (c++, 0x02);
data.setUint8 (c++, 0x0);
data.setUint8 (c++, 0x0);
data.setUint8 (c++, 0x0);
// Write channel info
// Write attribute name : "channels"
data.setUint8 (c++, 0x63);
data.setUint8 (c++, 0x68);
data.setUint8 (c++, 0x61);
data.setUint8 (c++, 0x6e);
data.setUint8 (c++, 0x6e);
data.setUint8 (c++, 0x65);
data.setUint8 (c++, 0x6c);
data.setUint8 (c++, 0x73);
data.setUint8 (c++, 0x0);
// Write attribute type : "chlist"
data.setUint8 (c++, 0x63);
data.setUint8 (c++, 0x68);
data.setUint8 (c++, 0x6c);
data.setUint8 (c++, 0x69);
data.setUint8 (c++, 0x73);
data.setUint8 (c++, 0x74);
data.setUint8 (c++, 0x00);
// Write attribute size : 18 x 3 + 1 = 55
var attribSize = 18 * numComponents + 1;
data.setUint8 (c++, attribSize);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
var i;
for (i = 0; i < numComponents; i++)
{
// Attribute : "B" (42) "G" (47) "R" (52)
if (i==0) data.setUint8 (c++, 0x42);
else if (i==1) data.setUint8 (c++, 0x47);
else if (i==2) data.setUint8 (c++, 0x52);
data.setUint8 (c++, 0x00);
// Value : Float (2), Half (1), Uint (0)
if (type=="Uint") data.setUint8 (c++, 0x00);
else if (type=="Half") data.setUint8 (c++, 0x01);
else if (type=="Float") data.setUint8 (c++, 0x02);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
// Plinear
data.setUint8 (c++, 0x01);
// Reserved
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
// X sampling
data.setUint8 (c++, 0x01);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
// Y sampling
data.setUint8 (c++, 0x01);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
}
// End attribute
data.setUint8 (c++, 0x00);
// Write attribute name : "compression"
data.setUint8 (c++, 0x63);
data.setUint8 (c++, 0x6f);
data.setUint8 (c++, 0x6d);
data.setUint8 (c++, 0x70);
data.setUint8 (c++, 0x72);
data.setUint8 (c++, 0x65);
data.setUint8 (c++, 0x73);
data.setUint8 (c++, 0x73);
data.setUint8 (c++, 0x69);
data.setUint8 (c++, 0x6f);
data.setUint8 (c++, 0x6e);
data.setUint8 (c++, 0x00);
// Write attribute type : "compression"
data.setUint8 (c++, 0x63);
data.setUint8 (c++, 0x6f);
data.setUint8 (c++, 0x6d);
data.setUint8 (c++, 0x70);
data.setUint8 (c++, 0x72);
data.setUint8 (c++, 0x65);
data.setUint8 (c++, 0x73);
data.setUint8 (c++, 0x73);
data.setUint8 (c++, 0x69);
data.setUint8 (c++, 0x6f);
data.setUint8 (c++, 0x6e);
data.setUint8 (c++, 0x00);
// Write attribute size : "1"
data.setUint8 (c++, 0x01);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
// Write attribute value : "0" (None)
data.setUint8 (c++, 0x00);
// datawindow
data.setUint8 (c++, 0x64);
data.setUint8 (c++, 0x61);
data.setUint8 (c++, 0x74);
data.setUint8 (c++, 0x61);
data.setUint8 (c++, 0x57);
data.setUint8 (c++, 0x69);
data.setUint8 (c++, 0x6e);
data.setUint8 (c++, 0x64);
data.setUint8 (c++, 0x6f);
data.setUint8 (c++, 0x77);
data.setUint8 (c++, 0x00);
// box2i
data.setUint8 (c++, 0x62);
data.setUint8 (c++, 0x6f);
data.setUint8 (c++, 0x78);
data.setUint8 (c++, 0x32);
data.setUint8 (c++, 0x69);
data.setUint8 (c++, 0x00);
// size 16
data.setUint8 (c++, 0x10);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
// value 0 0 3 2
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint32 (c, width-1, true);
c += 4;
data.setUint32 (c, height-1, true);
c += 4;
// displayWindow
data.setUint8 (c++, 0x64);
data.setUint8 (c++, 0x69);
data.setUint8 (c++, 0x73);
data.setUint8 (c++, 0x70);
data.setUint8 (c++, 0x6c);
data.setUint8 (c++, 0x61);
data.setUint8 (c++, 0x79);
data.setUint8 (c++, 0x57);
data.setUint8 (c++, 0x69);
data.setUint8 (c++, 0x6e);
data.setUint8 (c++, 0x64);
data.setUint8 (c++, 0x6f);
data.setUint8 (c++, 0x77);
data.setUint8 (c++, 0x00);
// box2i
data.setUint8 (c++, 0x62);
data.setUint8 (c++, 0x6f);
data.setUint8 (c++, 0x78);
data.setUint8 (c++, 0x32);
data.setUint8 (c++, 0x69);
data.setUint8 (c++, 0x00);
// size 16
data.setUint8 (c++, 0x10);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
// value 0 0 3 2
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint32 (c, width-1, true);
c += 4;
data.setUint32 (c, height-1, true);
c += 4;
// lineOrder
data.setUint8 (c++, 0x6c);
data.setUint8 (c++, 0x69);
data.setUint8 (c++, 0x6e);
data.setUint8 (c++, 0x65);
data.setUint8 (c++, 0x4f);
data.setUint8 (c++, 0x72);
data.setUint8 (c++, 0x64);
data.setUint8 (c++, 0x65);
data.setUint8 (c++, 0x72);
data.setUint8 (c++, 0x00);
// lineOrder
data.setUint8 (c++, 0x6c);
data.setUint8 (c++, 0x69);
data.setUint8 (c++, 0x6e);
data.setUint8 (c++, 0x65);
data.setUint8 (c++, 0x4f);
data.setUint8 (c++, 0x72);
data.setUint8 (c++, 0x64);
data.setUint8 (c++, 0x65);
data.setUint8 (c++, 0x72);
data.setUint8 (c++, 0x00);
// size
data.setUint8 (c++, 0x01);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
// value
data.setUint8 (c++, 0x00);
// PixelAspectRatio
data.setUint8 (c++, 0x70);
data.setUint8 (c++, 0x69);
data.setUint8 (c++, 0x78);
data.setUint8 (c++, 0x65);
data.setUint8 (c++, 0x6c);
data.setUint8 (c++, 0x41);
data.setUint8 (c++, 0x73);
data.setUint8 (c++, 0x70);
data.setUint8 (c++, 0x65);
data.setUint8 (c++, 0x63);
data.setUint8 (c++, 0x74);
data.setUint8 (c++, 0x52);
data.setUint8 (c++, 0x61);
data.setUint8 (c++, 0x74);
data.setUint8 (c++, 0x69);
data.setUint8 (c++, 0x6f);
data.setUint8 (c++, 0x00);
// float
data.setUint8 (c++, 0x66);
data.setUint8 (c++, 0x6c);
data.setUint8 (c++, 0x6f);
data.setUint8 (c++, 0x61);
data.setUint8 (c++, 0x74);
data.setUint8 (c++, 0x00);
// size 4
data.setUint8 (c++, 0x04);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
// value 1.0
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x80);
data.setUint8 (c++, 0x3f);
// screenWindowCenter
data.setUint8 (c++, 0x73);
data.setUint8 (c++, 0x63);
data.setUint8 (c++, 0x72);
data.setUint8 (c++, 0x65);
data.setUint8 (c++, 0x65);
data.setUint8 (c++, 0x6e);
data.setUint8 (c++, 0x57);
data.setUint8 (c++, 0x69);
data.setUint8 (c++, 0x6e);
data.setUint8 (c++, 0x64);
data.setUint8 (c++, 0x6f);
data.setUint8 (c++, 0x77);
data.setUint8 (c++, 0x43);
data.setUint8 (c++, 0x65);
data.setUint8 (c++, 0x6e);
data.setUint8 (c++, 0x74);
data.setUint8 (c++, 0x65);
data.setUint8 (c++, 0x72);
data.setUint8 (c++, 0x00);
// v2f
data.setUint8 (c++, 0x76);
data.setUint8 (c++, 0x32);
data.setUint8 (c++, 0x66);
data.setUint8 (c++, 0x00);
// size 8
data.setUint8 (c++, 0x08);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
// value 0 0
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
// screenWindowWidth
data.setUint8 (c++, 0x73);
data.setUint8 (c++, 0x63);
data.setUint8 (c++, 0x72);
data.setUint8 (c++, 0x65);
data.setUint8 (c++, 0x65);
data.setUint8 (c++, 0x6e);
data.setUint8 (c++, 0x57);
data.setUint8 (c++, 0x69);
data.setUint8 (c++, 0x6e);
data.setUint8 (c++, 0x64);
data.setUint8 (c++, 0x6f);
data.setUint8 (c++, 0x77);
data.setUint8 (c++, 0x57);
data.setUint8 (c++, 0x69);
data.setUint8 (c++, 0x64);
data.setUint8 (c++, 0x74);
data.setUint8 (c++, 0x68);
data.setUint8 (c++, 0x00);
// float
data.setUint8 (c++, 0x66);
data.setUint8 (c++, 0x6c);
data.setUint8 (c++, 0x6f);
data.setUint8 (c++, 0x61);
data.setUint8 (c++, 0x74);
data.setUint8 (c++, 0x00);
// size
data.setUint8 (c++, 0x04);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
// value
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x00);
data.setUint8 (c++, 0x80);
data.setUint8 (c++, 0x3f);
// End of header
data.setUint8 (c++, 0x00);
}
// Scanline table
var initc = c + height * 8;
for (var scanline = 0 ; scanline < height ; scanline ++)
{
var jump = initc + scanline * (8 + width * bytesPerComponent * numComponents);
data.setUint32 (c, jump, true);
c += 4;
data.setUint32 (c, 0x00, true);
c += 4;
}
// Scanlines
for (var scanline = 0 ; scanline < height ; scanline ++)
{
// Scanline
data.setUint32(c, scanline, true);
c += 4;
// size 24
var size = width * numComponents * bytesPerComponent;
data.setUint32(c, size, true);
c += 4;
var numComponentsSource = 4; // number of components in the SOURCE image
for (var component = 0; component < numComponents ; component ++)
{
for (var pixel = 0 ; pixel < width ; pixel ++)
{
// flip vertical, so we read OpenGL buffers without JS image flipping
var v = bytes[(height-1-scanline) * width *numComponentsSource + pixel * numComponentsSource + (2-component)];
if (type=="Float") data.setFloat32(c, v, true);
else if (type=="Half") data.setUint16(c, v, true);
c += bytesPerComponent;
}
}
}
return new Blob([buffer], {type: 'application/octet-stream'});
}
function piExportToWAV(numSamples, rate, bits, numChannels, words)
{
let numBytes = numSamples * numChannels * bits/8;
let buffer = new ArrayBuffer(44 + numBytes);
let data = new DataView(buffer);
{
data.setUint32( 0, 0x46464952, true ); // RIFF
data.setUint32( 4, numBytes + 36, true);
{
data.setUint32( 8, 0x45564157, true ); // WAV_WAVE
data.setUint32( 12, 0x20746D66, true ); // WAV_FMT
{
data.setUint32( 16, 16, true);
data.setUint16( 20, 1, true ); // WAV_FORMAT_PCM
data.setUint16( 22, numChannels, true);
data.setUint32( 24, rate, true);
data.setUint32( 28, rate*numChannels*bits / 8, true);
data.setUint16( 32, numChannels*bits / 8, true);
data.setUint16( 34, bits, true);
}
data.setUint32( 36, 0x61746164, true); // WAV_DATA
{
data.setUint32( 40, numBytes, true);
let numWords = numSamples * numChannels;
for(let i=0; i<numWords; i++ )
{
data.setInt16( 44 + i*2, words[i], true );
}
}
}
}
return new Blob([buffer], {type: 'application/octet-stream'});
}
function piTriggerDownload(name, blob)
{}