pouët.net

intro to the process of making a 4k

category: code [glöplog]
Has anyone ever written sort of a "making of" blow-by-blow account of creating a 4k, 1k, 64k or whatever with some level of technical detail?

I have some programmerish types who are interested in this sort of thing, but I struggle to explain to them, in detail, what goes on in the process of creating one of these magical things. I am specifically thinking about:

- how is a 4k structured in code (and how does this differ from a normal application)?
- What tricks are used to generate sound, effects and animation?
- How does tools like crinkler, 4klang/clinkster(?) etc factor in?
added on the 2013-10-24 11:35:33 by nic0 nic0
pure fucking gold, thats exactly what they need :D (and adds to my own understanding as well)
added on the 2013-10-24 11:50:31 by nic0 nic0
Then again, you might not want to give them the idea that they _must_ make custom tools in order to produce their first 4k.
Many a young programmer has ventured into engine- and tool-coding never to be seen again.
Quote:
Many a young programmer has ventured into engine- and tool-coding never to be seen again.

amen.
added on the 2013-10-24 11:52:25 by ferris ferris
yes, there are defintely maner other approaches - also some stuff from iq: http://iquilezles.org/www/material/isystem1k4k/isystem1k4k.htm
added on the 2013-10-24 11:52:49 by Puryx Puryx
but, yeah, the article puryx mentioned is pretty rad
added on the 2013-10-24 11:52:51 by ferris ferris
maner=many
added on the 2013-10-24 11:53:08 by Puryx Puryx
But engines and tools are so cool!
added on the 2013-10-24 11:55:58 by msqrt msqrt
I've done a writeup of how i made white one, a 4k and my first prod (which won tUM 4k in 2010). It's both technical and personal in some way. Almost no custom tools were used.
Read it here
added on the 2013-10-24 12:18:23 by cupe cupe
How it worked for me:


  • make some audio + fx
  • put early version executable into an exe compressor
  • realise it's <2kb, decide to make a 4k
added on the 2013-10-24 12:23:26 by psonice psonice
Quote:
Many a young programmer has ventured into engine- and tool-coding never to be seen again.


Words of wisdom.
added on the 2013-10-24 13:21:06 by Zavie Zavie
thanks a ton guys! learning something myself as well, so thats all good. Since you are all my idols, your input is valuable :)
added on the 2013-10-24 19:45:32 by nic0 nic0
or perhaps: http://zine.bitfellas.org/article.php?zine=14&id=24

Basically, I guess, you could say that making a 1k/4k, would be like breaking every rule about coding ever made :)

It's about cheating, making things happen, more that about making pretty code or making it the "right" way.
added on the 2013-10-24 19:57:33 by maytz maytz
and p01 blahhh'ed me.
added on the 2013-10-24 19:58:13 by maytz maytz
Yeah, coding anti-style is important.

Make it as cheap as possible. Use global variables. Never ever write any deinit/cleanup code, the OS is good enough at this. Install a macro that instantly deletes the whole source file when you press the keys C, L, A, S and S in sequence. Write plain procedural code in C++ because it potentially optimizes better than C. If you make API calls, try setting all parameters that you don't really need to 0 instead of whatever default would be the most sensible in "real" code, or leave them out and see if it still works. BUT: Everything that doesn't survive the compilation process becomes more important. Make your variable names as clear as possible. Comment the shit out of any hack you type into the code.

Also, remember that you need to disable whatever runtime comes with your language/platform of choice. No libc, no STL, all you get is plain C pointers/arrays and the operating system's API. The exception are all the intrinsics that your compiler offers you - much of the stuff in math.h and string.h gets compiled to a single assembly instruction when the compiler settings are right. The links above should potentially lead you to some code that sets up the stuff correctly.

Apart from that: Yeah, use Crinkler and a 4K synth such as 4Klang or Clinkster from the get go, and also using eg. iq's 1K/4K framework is no shame. It's how it looks/sounds like in the end that's most important.
added on the 2013-10-24 22:03:35 by kb_ kb_
I've been (very slowly) writing a series of articles on how to make a 1k/4k for Linux. In Russian only, sorry, but you still can look at the code and screenshots: part1, part2, part4.
added on the 2013-10-25 06:19:13 by provod provod
Extra hint: Use static allocation almost everywhere. Reserving hundreds of MB directly in the
binary is basically free, and best of all: already initialized to 0!
added on the 2013-10-25 23:35:11 by T$ T$
If you go the assembly only way:
I suspect a certain consistent "style" really helps to get crinkler to compress your stuff well over the whole development process. Changing instruction order and applying magic things is IMHO only useful at the end of the development process when you have to kill of the last 100 bytes. Of course you can/should play around with that over the whole process to accumulate options, but since your compression rate is affected by all the things, you save yourself a lot of time by doing the code reordering at the end.
added on the 2013-10-26 13:44:19 by las las
funny (yet quite obvious) fact: larger original binaries due to duplicated code can actually be smaller after crinklering than code stuffed into loops or functions
added on the 2013-10-26 18:23:32 by T$ T$
FWIW, I started my modern small intro making after attending Revision 2012. I went to www.google.com and typed (literally) "how to make 4k intros" in the search box. In a very short time I learned about Crinkler, 4klang, the pouet.net "raymarching beginner's thread" and iq's intro framework. Before that, I hadn't really been following the modern Windows demo coding scene very much. After the introduction of 3d accelerators about the year 2000 or so, I had thought the whole demo scene thing had turned to uninteresting crap, so I stopped following. But after that 10+ year period of boring shit there's this shader programming thing, which made it interesting and fun again. I made the compofiller intro "My first GLSL raymarcher" 4k intro using the only Windows laptop I had access to, which didn't even have a real GPU, so everything was soft-rendered in a 320x200 window while debugging. At the party place I saw it on a real GPU for the first time (the compo pc, GTX 560 Ti or something), and I was totally blown away by the awesome fullscreen 60fps rendering.

TL;DR: go to Google.com and type what you want.
added on the 2013-10-26 18:40:19 by yzi yzi
great tips maytz, but most of them do not apply if your demo IS a html file (60k.html, zips to 16k.zip)
the fun part of that one is, its plain text, very newbie friendly and compatible:
[spoiler]
Code: <!DOCTYPE html><html><!-- a 64k demo, where video and audio are synchronized? I hear these are quite the mystery, unless they are a plain text .html file like this one: this is an offline version of shadertoy.com, with many features removed; no codemirror, a crippled UI, LOSTS of hacky junk code and bridges It still does Webgl and Webgl2 and fmSynth within opengl to webaudio; [3,6,12]minutes in [44,22,11]kHz, from 2 small textures. and its still less than 64k! (is 17k as .zip file) This is [tinyFm307] boilerplate+demo, an offline version of shadertoy.com, with many features removed, a crippled UI and LOSTS of junk code Fragment shaders have source links that explain more how these parts work tinyFm307 is a dead-end project, i have smaller/cleaner versions of it, but they never play more than 90sec audio ,an inacceptable bug that i noticed 5 days too late [tinyFm] is a discontinued dead end project, its last useful instance is [tinyFm307c] (c for [crunched]) - i restarted it, and it is obsoleted by its sucessor [tS324] , a 230k offline shadertoy project, that has MouseIn&Webaudio&VideoRecord (like [tinyFm307]), working KeyboardIn, 4Doublebuffers, webVR , actually, screw that, [tS324] can easily have more than 4 BuffN's, but let me fix its main issues first, a VERY bad UI and way too much junk code. i hope to crunch that one down to 100k, or even less, but it may make the buffers/ui more static it surely will have my integer modulo for webgl function, modulo in opengl2 is messier than it seems, when you give negative inputs! --><style> input{width:100%;position:relative;} input,table,tr,th,td,input,body,canvas{top:0px;left:0px;border:0px; border-collapse:collapse;padding:0px;margin:0px;border-spacing:0px;} </style><script>var verC="tinyFm307c"//<55k webaudioBoilerplate +5k OpenglDemo //i know that roughly 10k of the boilerplate code is unused/uneccessary. this can be crunched down to a 40k boilerplate with the same fucntions var vol=.2 //initial volume var wM=3,wMs=["experimental-webgl","webgl","experimental-webgl2","webgl2"]//try version wMs[wM],and if that is not supported,diminish wM and retry. var sR=0,sRs=[44100,22050,11025]//sRs[sR]==sample rate function piCreateGlContext(c,a,d,p,s){var opts={alpha:a,depth:d,stencil:false,premultipliedAlpha:false,antialias:s,preserveDrawingBuffer:p ,powerPreference:"high-performance"};//"low_power","high_performance","default" ;m=null;while(wM>-1&&!m){m=c.getContext(wMs[wM--],opts)};wM++;return m;} function gei(a){return document.getElementById(a).textContent;} </script><!--commontab code--><script id="o"> //see for fcommented version: https://www.shadertoy.com/view/4t3fDN #define vec1 float #define pi acos(-1.) #define sat(a) clamp(a,0.,1.) #define dd(a) dot(a,a) #define u2(a) ((a)*2.-1.) #define u5(a) ((a)*.5+.5) #define sat(a) clamp(a,0.,1.) #define pow2 exp2 #define TT(d) mod(mod(time,1.0)-d,1.0) #define trunc(a) float(int(a)) #define ma0(a) max(0.,a) vec2 fr(float a){return vec2(fract(a),floor(a));} float su(vec4 a){return a.x+a.y+a.z+a.w;} #define HASHSCALE1 .1031 float hash1(float p ){vec3 q=fract(vec3(p)*HASHSCALE1) ;q+=dot(q,q.yzx+19.19) ;return fract((q.x+q.y)*q.z);} int rand1To8(float t){return int(hash1(t)*8.);} //ldXBzH opengl2 only code, this variant also wuns in opengl [experimental-webgl] //https://www.shadertoy.com/view/ldXBzH float n2f (float n){return 55.*pow(2.,(n- 3.)/12.);} vec4 n2f (vec4 n){return 55.*pow(vec4(2),(n- 3.)/12.);} float noteFreq (int n){return n2f(float(n+39));} float noteKeyA (float n){n=mod(n,8.) ;if(n==0.)return 1046.5 ;if(n==1.)return 1174.66;if(n==2.)return 1318.51;if(n==3.)return 1396.91 ;if(n==4.)return 1567.98;if(n==5.)return 1760.00;if(n==6.)return 1975.53;return 2093.;} vec4 noteMIDI(vec4 n){return 440.*pow(vec4(2),(n-69.)/12.);} float noteMIDI (float n){return 440.*pow(2.,(n-69.)/12.);} float calcHertz(float n){return 440.*pow(2.,(n )/12.);} float ix(float o,float idx){return exp2(o)*noteKeyA(idx) ;} float ox(float t,float o,float idx){return ix(o,idx)*fract(t/2.)*pi*.8;} //instruments of: https://www.shadertoy.com/view/ldXBzH float note(float k,float o,float t){return sin(ox(t,o,k));} float noteSaw(float k,float o,float t){return tan(note(k,o,t));} float noteSquare(float idx,float o,float t ){float a=floor(fract(t*2.)*2.+1.)*fract(t*.5)*.1 ;return 3.*(fract(a*ix(o,idx))-.5);} #define parentMelody #ifdef parentMelody float melody(float t//https://www.shadertoy.com/view/ldXBzH ){float note ;t=mod(t,64.)< 32. ? mod(t,32.0)-94. : t ;float s=floor(2.*hash1(floor(t*2.+241.)))+1. ;t*=.25*s ;if(s==2.&& hash1(floor(t*4.0+738.))>.7)t*=2. ;float r=hash1(floor(t-3280.)) ;if(r<=.8);r=floor(mod(t*((r<.4)?-4.:4.),8.)) ;return r;} #else float melody(float t ){t = mod(t,64.)< 32. ? mod(t,32.0)-94. : t ;float s=floor(2.*hash1(floor(t*2.+241.)))+1.0 ;t*=mix(1.,4.,smoothstep(0.,1.,s-2.)) ;s=hash1(floor(t*4.+738.)) ;t*=mix(1.,2.,step(s-.7,0.)) ;//t*=.5*s ;float r=hash1(floor(t-3280.)) ;if(r<=.8);r=float(mod(t*4.*mix(1.,-1.,step(.4,r)),8.));return r;} #endif vec4 av(float t ){float i=4. ;float l=mod(t,64.)<32.?4.:32. ;float j=float(rand1To8(mod(floor(t*2./i),l)-900.)) ;float d=floor(melody(t)+24.) ;float c=floor(fract((2.*t+2.))*2.) ;return vec4(j+vec3(4,9,-c*8.-8.),d);} float orchestrate(float t){float c=0. ;vec4 nn=(floor(av(t))) ;float j=nn.x ;c+=.2*noteSaw(nn.w,2.,t) ;c+=.8*(noteSquare((nn.z+0.),0.,t)*.3 +noteSaw((nn.y+2.),1.,t)*.3 +noteSaw((nn.x+4.),0.,t)*.15);return c;} float mi(vec4 a){return min(min(a.x,a.y),min(a.z,a.w));} #define ab012(a,b)(a+b*vec3(0,1,2)) vec3 rainbowt(float a,float b){return abs(u2(fract(ab012(a,b))));} vec3 rainbowt(float a){return rainbowt(-a,1./3.);} vec3 rainbows(float a,float b){return u5(cos(2.*pi*ab012(a,b)));} vec3 rainbows(float a){return rainbows(-a,1./3.);} #define ToRgb(w) return c.z*mix(vec3(1.),sat(w(-c.x)),c.y);} vec3 rainbows(vec3 c){ToRgb(rainbows) vec3 rainbowt(vec3 c){ToRgb(rainbowt) #define hsv2rgb(c) c.z*mix(vec3(1),sat(abs(fract(c.x+vec3(3,2,1)/3.)*6.-3.)-1.),c.y) #define rgb2hsv2(a,b,c,d,e,f) mx(vec4(a,b),vec4(c,d),st(e,f)) #define rgb2hsv3(K) rgb2hsv2(a.zy,K.wz,a.yz,K.xy,a.z,a.y) #define rgb2hsv4(P) rgb2hsv2(P.xyw,a.x,a.x,P.yzx,P.x,a.x) #define rgb2hsv5(D,q) abx(vec2(q.w-q.y,D)/(vec2(6.*D,q.x)+1e-10)+vec2(q.z,0)) #define rgb2hsv6(q) vec3(rgb2hsv5((q.x-min(q.w,q.y)),q),q.x) #define rgb2hsv(a) rgb2hsv6(rgb2hsv4(rgb2hsv3((vec4(0,-1,2,-3)/3.))))//https://www.shadertoy.com/view/MdGfWm vec4 ut(vec4 a,vec1 b){return a*(1.-b);} vec4 pdOut(vec4 a,vec4 b){return ut(b,a.w);} vec4 pdOver(vec4 a,vec4 b){return ut(b,a.w)+a;} vec4 pdAtop(vec4 a,vec4 b){return ut(b,a.w)+a*b.w;} vec4 pdXor(vec4 a,vec4 b){return ut(b,a.w)+ut(a,b.w);} vec4 colorNote(vec4 n,float y ){vec4 b=vec4(mi(abs(n-y)));b=sat(b);vec4 c=vec4(rainbows(y*.02),1.);return pdOut(b,c);} vec2 Port(float t){return vec2(orchestrate(t));} vec4 Port(vec2 u,vec4 m,vec2 r,float t ){u=u.xy/r.xy;float delay=.5;if(u.y>.1)delay=m.x/r.x;vec4 c=av(t+u.x-1.);c.w=floor(c.w) ;c=colorNote(c,u.y*60.-20.);c=max(c,smoothstep(.01,-.01,abs(u.x-delay)));return c;} </script><!--Sound tab code--><script id="s"> vec2 mainSound(float t){return Port(t)*.1;} </script><!--Image tab code--><script id="i"> void mainImage(out vec4 o,vec2 u){o=Port(u,iMouse,iResolution.xy,iTime+.5);} </script><script> "use strict" window.requestAnimFrame=(function(){return window.requestAnimationFrame ||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame ||window.msRequestAnimationFrame||function(cb){window.setTimeout(cb,1000/60);};})(); window.getRealTime=(function(){if("performance" in window)return function(){return window.performance.now();} return function(){return (new Date()).getTime();}})(); window.URL=window.URL||window.webkitURL; navigator.getUserMedia=navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia||navigator.msGetUserMedia; //tiny shadertoy (opengl2, Webaudio, bo DoubleBuffers, no streaming, can record video!) //piLibs 2015-2017-http://www.iquilezles.org/www/material/piLibs/piLibs.htm var ltime=0.,dtime=0.,mOffset=0; function piMesh(){this.mChunks=[];this.mPrimitiveType=0;this.mVertexFormat=null;} 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){return true;} piMesh.prototype.GPURender=function(renderer,positions){} var mIs20,gShaderToy=null,gCode=null,gIsLiked=0,gRes=null,mAudioContext=null,mEffect=null,mTOffset=0,paused,mForceFrame=false,mTf=0,mRestarted=true; function piRenderer( ){var m,pBindedShader,pFloat32Textures,pFloat32Filter,pFloat16Textures,pDrawBuffers,pDepthTextures,pDerivatives,pFloat32Filter,pFloat16Filter ,pShaderTextureLOD,pAnisotropic,pRenderToFloat32F,pVBO_Quad,pVBO_Tri,pShaderHeader=["",""],pm={} ;pm.TEXFMT ={C4I8:0,C1I8:1,C1F16:2,C4F16:3,C1F32:4,C4F32:5,Z16:6,Z24:7,Z32:8} ;pm.TYPE ={UINT8:0,UINT16:1,UINT32:2,FLOAT16:3,FLOAT32:4,FLOAT64:5} ;var iFormatPI2GL=function(format){if(mIs20 ){if(format===0)return{mFormat:m.RGBA8 ,mExternal:m.RGBA ,mType:m.UNSIGNED_BYTE} else if(format===1)return{mFormat:m.R8 ,mExternal:m.RED ,mType:m.UNSIGNED_BYTE} else if(format===5)return{mFormat:m.RGBA32F ,mExternal:m.RGBA ,mType:m.FLOAT} }else{if(format===0)return{mFormat:m.RGBA ,mExternal:m.RGBA ,mType:m.UNSIGNED_BYTE} else if(format===1)return{mFormat:m.LUMINANCE ,mExternal:m.LUMINANCE,mType:m.UNSIGNED_BYTE} else if(format===5)return{mFormat:m.RGBA ,mExternal:m.RGBA ,mType:m.FLOAT} else if(format===6)return{mFormat:m.DEPTH_COMPONENT,mExternal:m.DEPTH_COMPONENT,mType:m.UNSIGNED_SHORT}} return null;} ;pm.Initialize=function(gl ){m=gl ;mIs20=!(gl instanceof WebGLRenderingContext) ;if(mIs20 ){pFloat32Textures=pFloat16Textures=pDerivatives=pDrawBuffers=pDepthTextures =pShaderTextureLOD=true ;pFloat32Filter =m.getExtension('OES_texture_float_linear') ;pFloat16Filter =m.getExtension('OES_texture_half_float_linear') ;pAnisotropic=m.getExtension('EXT_texture_filter_anisotropic') ;pRenderToFloat32F=m.getExtension('EXT_color_buffer_float') ;}else {pFloat32Textures=m.getExtension('OES_texture_float') ;pFloat32Filter =m.getExtension('OES_texture_float_linear') ;pFloat16Textures=m.getExtension('OES_texture_half_float') ;pFloat16Filter =m.getExtension('OES_texture_half_float_linear') ;pDerivatives =m.getExtension('OES_standard_derivatives') ;pDrawBuffers =m.getExtension('WEBGL_draw_buffers') ;pDepthTextures =m.getExtension('WEBGL_depth_texture') ;pShaderTextureLOD=m.getExtension('EXT_shader_texture_lod') ;pAnisotropic =m.getExtension('EXT_texture_filter_anisotropic') ;pRenderToFloat32F=pFloat32Textures;} ;var maxTexSize=m.getParameter(m.MAX_TEXTURE_SIZE) ;var maxCubeSize=m.getParameter(m.MAX_CUBE_MAP_TEXTURE_SIZE) ;var maxRenderbufferSize=m.getParameter(m.MAX_RENDERBUFFER_SIZE) ;var extensions=m.getSupportedExtensions() ;var textureUnits=m.getParameter(m.MAX_TEXTURE_IMAGE_UNITS) ;var ph="precision highp " ;pVBO_Quad=m.createBuffer();m.bindBuffer(m.ARRAY_BUFFER,pVBO_Quad);m.bufferData(m.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]),m.STATIC_DRAW);m.bindBuffer(m.ARRAY_BUFFER,null) ;pVBO_Tri=m.createBuffer();m.bindBuffer(m.ARRAY_BUFFER,pVBO_Tri);m.bufferData(m.ARRAY_BUFFER//screenspace filling triangle ,new Float32Array([-1.0,-1.0,3.0,-1.0,-1.0,3.0]),m.STATIC_DRAW);m.bindBuffer(m.ARRAY_BUFFER,null) ;pShaderHeader[0]="" ;var es300for100="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 csch(float x){return 1./sinh(x);}\n" +"float coth(float x){return cosh(x)/sinh(x);}\n float sech(float x){return 1./cosh(x);}\n" +"float atanh(float x){return .5*log((1.+x)/(1.-x));}\n float asinh(float x){return log(x+sqrt(x*x+1.));}\n float asech(float x){return log((1.+sqrt(1.-x*x))/x);}\n" +"float acoth(float x){return .5*log((x+1.)/(x-1.));}\n float acosh(float x){return log(x+sqrt(x*x-1.));}\n float acsch(float x){return log((1.+sqrt(1.+x*x))/x);}\n" ;var prec="#ifdef GL_ES\n"+ph+"float;\n"+"precision highp int;\n",v300="#version 300 es\n",v300e="precision mediump sampler3D;\n"+"#endif\n" ;if(mIs20)pShaderHeader[0]+=v300+prec+v300e ;else pShaderHeader[0]+=prec+"#endif\n"+es300for100 ;pShaderHeader[1]="" ;if(mIs20){pShaderHeader[1]+=v300+prec+v300e;}else {if(pDerivatives){pShaderHeader[1]+="#ifdef GL_OES_standard_derivatives\n#extension GL_OES_standard_derivatives:enable\n#endif\n";} ;if(pShaderTextureLOD){pShaderHeader[1]+="#extension GL_EXT_shader_texture_lod:enable\n";} ;var t4="vec4 texture",ts=t4+"(sampler",tc="){return textureCube(s,c",sa="(sampler2D s,vec2 c,",r2="){return texture2D" ;pShaderHeader[1]+="#ifdef GL_ES\n"+ph+"float;\n"+ph+"int;\n"+"#endif\n" +ts+"2D s,vec2 c"+r2+"(s,c);}\n"+ts+"2D s,vec2 c,float b" +r2+"(s,c,b);}\n"+ts+"Cube s,vec3 c"+tc+");}\n" +ts+"Cube s,vec3 c,float b"+tc+",b);}\n"+es300for100 ;if(pShaderTextureLOD){pShaderHeader[1]+=t4+"Lod"+sa+"float b "+r2+"LodEXT(s,c,b);}\n"+t4+"Grad"+sa+"vec2 dx,vec2 dy"+r2+"GradEXT(s,c,dx,dy);}\n"}}return true;} ;pm.GetCaps=function( ){return{mIsGL20:mIs20 ,pFloat32Textures:pFloat32Textures!=null ,pFloat16Textures:pFloat16Textures!=null ,pDrawBuffers:pDrawBuffers!=null ,pDepthTextures:pDepthTextures!=null ,pDerivatives:pDerivatives!=null ,pShaderTextureLOD:pShaderTextureLOD!=null};} ;pm.CheckErrors=function( ){var error=m.getError() ;if(error!=m.NO_ERROR ){for(var prop in m ){if(typeof m[prop]=='number' ){if(m[prop]==error){ ;break;}}}}} ;pm.Clear=function(flags,ccolor,cdepth,cstencil ){var mode=0 ;if(flags&1){mode |=m.COLOR_BUFFER_BIT;m.clearColor(ccolor[0],ccolor[1],ccolor[2],ccolor[3]);} ;if(flags&2){mode |=m.DEPTH_BUFFER_BIT;m.clearDepth(cdepth);} ;if(flags&4){mode |=m.STENCIL_BUFFER_BIT;m.clearStencil(cstencil);} ;m.clear(mode);} ;pm.CreateTexture=function(type,x,y,format,filter,wrap,buffer ){if(m===null)return null ;var id=m.createTexture(),glFoTy=iFormatPI2GL(format),glWrap=1;if(wrap===0)glWrap=m.CLAMP_TO_EDGE ;if(type===0 ){m.bindTexture(m.TEXTURE_2D,id) ;m.texImage2D(m.TEXTURE_2D,0,glFoTy.mFormat,x,y,0,glFoTy.mExternal,glFoTy.mType,buffer) ;m.texParameteri(m.TEXTURE_2D,m.TEXTURE_WRAP_S,glWrap) ;m.texParameteri(m.TEXTURE_2D,m.TEXTURE_WRAP_T,glWrap) ;m.texParameteri(m.TEXTURE_2D,m.TEXTURE_MAG_FILTER,m.NEAREST) ;m.texParameteri(m.TEXTURE_2D,m.TEXTURE_MIN_FILTER,m.NEAREST) ;m.bindTexture(m.TEXTURE_2D,null);} ;return{mObjectID:id,mXres:x,mYres:y,mFormat:format,mType:type,mFilter:filter,mWrap:wrap,mVFlip:false};} ;pm.CreateTextureFromImage=function(type,image,format,filter,wrap,flipY ){if(m===null)return null ;var id=m.createTexture(),glFoTy=iFormatPI2GL(format),glWrap=1;if(wrap===0)glWrap=m.CLAMP_TO_EDGE ;if(type===0 ){m.bindTexture(m.TEXTURE_2D,id) ;m.pixelStorei(m.UNPACK_FLIP_Y_WEBGL,flipY) ;m.pixelStorei(m.UNPACK_PREMULTIPLY_ALPHA_WEBGL,false) ;if(mIs20)m.pixelStorei(m.UNPACK_COLORSPACE_CONVERSION_WEBGL,m.NONE) ;m.texImage2D(m.TEXTURE_2D,0,glFoTy.mFormat,glFoTy.mExternal,glFoTy.mType,image) ;m.texParameteri(m.TEXTURE_2D,m.TEXTURE_WRAP_S,glWrap) ;m.texParameteri(m.TEXTURE_2D,m.TEXTURE_WRAP_T,glWrap) ;m.texParameteri(m.TEXTURE_2D,m.TEXTURE_MAG_FILTER,m.NEAREST) ;m.texParameteri(m.TEXTURE_2D,m.TEXTURE_MIN_FILTER,m.NEAREST) ;m.bindTexture(m.TEXTURE_2D,null);} ;return{mObjectID:id,mXres:image.width,mYres:image.height,mFormat:format,mType:type,mFilter:filter,mWrap:wrap,mVFlip:flipY};} ;pm.UpdateTexture=function(tex,x0,y0,x,y,buffer ){var glFoTy=iFormatPI2GL(tex.mFormat) ;if(tex.mType===0 ){m.activeTexture(m.TEXTURE0) ;m.bindTexture(m.TEXTURE_2D,tex.mObjectID) ;m.pixelStorei(m.UNPACK_FLIP_Y_WEBGL,tex.mVFlip) ;m.texSubImage2D(m.TEXTURE_2D,0,x0,y0,x,y,glFoTy.mExternal,glFoTy.mType,buffer) ;m.bindTexture(m.TEXTURE_2D,null);}} ;pm.UpdateTextureFromImage=function(tex,image ){var glFoTy=iFormatPI2GL(tex.mFormat) ;if(tex.mType===0 ){m.activeTexture(m.TEXTURE0) ;m.bindTexture(m.TEXTURE_2D,tex.mObjectID) ;m.pixelStorei(m.UNPACK_FLIP_Y_WEBGL,tex.mVFlip) ;m.texImage2D(m.TEXTURE_2D,0,glFoTy.mFormat,glFoTy.mExternal,glFoTy.mType,image) ;m.bindTexture(m.TEXTURE_2D,null);}} ;pm.CreateRenderTarget=function(color0,color1,color2,color3,depth,wantZbuffer ){var i=m.createFramebuffer() ;m.bindFramebuffer(m.FRAMEBUFFER,i) ;if(color0!=null)m.framebufferTexture2D(m.FRAMEBUFFER,m.COLOR_ATTACHMENT0,m.TEXTURE_2D,color0.mObjectID,0) ;m.bindRenderbuffer(m.RENDERBUFFER,null);m.bindFramebuffer(m.FRAMEBUFFER,null);return{mObjectID:i};} ;pm.DestroyRenderTarget=function(tex){m.deleteFramebuffer(tex.mObjectID);} ;pm.SetRenderTarget=function(t){m.bindFramebuffer(m.FRAMEBUFFER,(t===null?null:t.mObjectID));} ;pm.CreateRenderTargetNew=function(wantColor0,wantZbuffer,x,y,samples ){var id=m.createFramebuffer() ;m.bindFramebuffer(m.FRAMEBUFFER,id) ;if(want2===true ){var zb=m.createRenderbuffer() ;m.bindRenderbuffer(m.RENDERBUFFER,zb) ;if(samples==1)m.renderbufferStorage(m.RENDERBUFFER,m.DEPTH_COMPONENT16,x,y) ;else m.renderbufferStorageMultisample(m.RENDERBUFFER,samples,m.DEPTH_COMPONENT16,x,y) ;m.framebufferRenderbuffer(m.FRAMEBUFFER,m.DEPTH_ATTACHMENT,m.RENDERBUFFER,zb);} ;if(wantColor0 ){var cb=m.createRenderbuffer() ;m.bindRenderbuffer(m.RENDERBUFFER,cb) ;if(samples==1)m.renderbufferStorage(m.RENDERBUFFER,m.RGBA8,x,y) ;else m.renderbufferStorageMultisample(m.RENDERBUFFER,samples,m.RGBA8,x,y) ;m.framebufferRenderbuffer(m.FRAMEBUFFER,m.COLOR_ATTACHMENT0,m.RENDERBUFFER,cb);} ;if(m.checkFramebufferStatus(m.FRAMEBUFFER)!=m.FRAMEBUFFER_COMPLETE){return null;} ;m.bindRenderbuffer(m.RENDERBUFFER,null);m.bindFramebuffer(m.FRAMEBUFFER,null) ;return{mObjectID:id,mXres:x,mYres:y};} ;pm.BlitRenderTarget=function(dst,src ){m.bindFramebuffer(m.READ_FRAMEBUFFER,src.mObjectID) ;m.bindFramebuffer(m.DRAW_FRAMEBUFFER,dst.mObjectID) ;m.clearBufferfv(m.COLOR,0,[0.0,0.0,0.0,1.0]) ;m.blitFramebuffer(0,0,src.mXres,src.mYres,0,0,src.mXres,src.mYres,m.COLOR_BUFFER_BIT,m.LINEAR);} ;pm.SetViewport=function(vp){m.viewport(vp[0],vp[1],vp[2],vp[3]);} ;pm.SetWriteMask=function(c0,c1,c2,c3,z){m.depthMask(z);m.colorMask(c0,c0,c0,c0);} ;pm.SetState=function(stateName,stateValue){} ;pm.SetMultisample=function(v ){if(v===true){m.enable(m.SAMPLE_COVERAGE);m.sampleCoverage(1.0,false);}else{m.disable(m.SAMPLE_COVERAGE);}} ;pm.CreateShader=function(vsSource,fsSource ){if(m===null)return{mProgram:null,mResult:false,mInfo:"No WebGL",mHeaderLines:0} ;var te={mProgram:null,mResult:true,mInfo:"compile success",mHeaderLines:0,mErrorType:0} ;var vs=m.createShader(m.VERTEX_SHADER) ;var fs=m.createShader(m.FRAGMENT_SHADER) ;vsSource=pShaderHeader[0]+vsSource ;fsSource=pShaderHeader[1]+fsSource ;m.shaderSource(vs,vsSource) ;m.shaderSource(fs,fsSource) ;m.compileShader(vs) ;m.compileShader(fs) ;if(!m.getShaderParameter(vs,m.COMPILE_STATUS)){;te.mResult=false;return te;} ;if(!m.getShaderParameter(fs,m.COMPILE_STATUS)){te.mResult=false;return te;} ;te.mProgram=m.createProgram() ;m.attachShader(te.mProgram,vs) ;m.attachShader(te.mProgram,fs) ;m.linkProgram(te.mProgram) ;if(!m.getProgramParameter(te.mProgram,m.LINK_STATUS) ){var infoLog=m.getProgramInfoLog(te.mProgram);m.deleteProgram(te.mProgram);te.mResult=false;return te;}return te;} ;pm.AttachShader=function(s){if(s===null){pBindedShader=null;m.useProgram(null);}else{pBindedShader=s;m.useProgram(s.mProgram);}} ;pm.DetachShader=function(){m.useProgram(null);} ;pm.DestroyShader=function(tex){m.deleteProgram(tex.mProgram);} ;pm.GetAttribLocation=function(shader,name){return m.getAttribLocation(shader.mProgram,name);} ;pm.sscLocation=function(shader,name){return m.getUniformLocation(shader.mProgram,name);} ;pm.sscMat4F=function(uname,params,istranspose ){var program=pBindedShader ;var pos=m.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]]) ;m.uniformMatrix4fv(pos,false,tmp) ;}else m.uniformMatrix4fv(pos,false,new Float32Array(params)) ;return true;} ;pm.gulf=function(m,u){return m.getUniformLocation(pBindedShader.mProgram,u);} ;pm.ssc1F =function(u,x){var p=pm.gulf(m,u);if(p===null)return false;m.uniform1f(p,x);return true;} ;pm.ssc1I =function(u,x){var p=pm.gulf(m,u);if(p===null)return false;m.uniform1i(p,x);return true;} ;pm.ssc2F =function(u,x){var p=pm.gulf(m,u);if(p===null)return false;m.uniform2fv(p,x);return true;} ;pm.ssc1FV=function(u,x){var p=pm.gulf(m,u);if(p===null)return false;m.uniform1fv(p,new Float32Array(x));return true;} ;pm.ssc3FV=function(u,x){var p=pm.gulf(m,u);if(p===null)return false;m.uniform3fv(p,new Float32Array(x));return true;} ;pm.ssc4FV=function(u,x){var p=pm.gulf(m,u);if(p===null)return false;m.uniform4fv(p,new Float32Array(x));return true;} ;pm.ssc1F_Pos=function(p,x){m.uniform1f(p,x);return true;} ;pm.ssc3F=function(u,x,y,z){var p=pm.gulf(m,u);if(p===null)return false;m.uniform3f(p,x,y,z);return true;} ;pm.SetShaderTextureUnit=function(u,unit ){var program=pBindedShader;var p=m.getUniformLocation(program.mProgram,u);if(p===null)return false;m.uniform1i(p,unit);return true;} ;pm.DrawFullScreenTriangle_XY=function(v){m.bindBuffer(m.ARRAY_BUFFER,pVBO_Tri) ;m.vertexAttribPointer(v,2,m.FLOAT,false,0,0);m.enableVertexAttribArray(v) ;m.drawArrays(4,0,3);m.disableVertexAttribArray(v);m.bindBuffer(m.ARRAY_BUFFER,null);} ;pm.DrawUnitQuad_XY=function(v){m.bindBuffer(m.ARRAY_BUFFER,pVBO_Quad) ;m.vertexAttribPointer(v,2,m.FLOAT,false,0,0);m.enableVertexAttribArray(v) ;m.drawArrays(4,0,6);m.disableVertexAttribArray(v);m.bindBuffer(m.ARRAY_BUFFER,null);} ;pm.SetBlend=function(t ){if(t){m.enable(m.BLEND) ;m.blendEquationSeparate(m.FUNC_ADD,m.FUNC_ADD) ;m.blendFuncSeparate(m.SRC_ALPHA,m.ONE_MINUS_SRC_ALPHA,m.ONE,m.ONE_MINUS_SRC_ALPHA);}else{m.disable(m.BLEND);}} ;pm.GetPixelData=function(data,x,y){m.readPixels(0,0,x,y,m.RGBA,m.UNSIGNED_BYTE,data);};return pm;} function min(a,b){return (a<b)? a:b;} var piGetTime=function(t){if(t==0)return "" ;return new Date(t*1000).toISOString().substr(0,10);} function piGetCoords(o){var x=0;var y=0;do{x+=o.offsetLeft;y+=o.offsetTop;}while(o=o.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 ){if(ele==null)ele=document.documentElement ;if(ele.requestFullscreen)ele.requestFullscreen() ;else if(ele.msRequestFullscreen)ele.msRequestFullscreen() ;else if(ele.mozRequestFullScreen)ele.mozRequestFullScreen() ;else if(ele.webkitRequestFullscreen)ele.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);} function piIsFullScreen(){return document.fullscreen||document.mozFullScreen||document.webkitIsFullScreen||document.msFullscreenElement||false;} function piExitFullScreen( ){if(document.exitFullscreen)document.exitFullscreen() ;else if(document.msExitFullscreen)document.msExitFullscreen() ;else if(document.mozCancelFullScreen)document.mozCancelFullScreen() ;else if(document.webkitExitFullscreen)document.webkitExitFullscreen();} function piCreateAudioContext( ){var res=null;try{if(window.AudioContext)res=new AudioContext() ;if(res==null&&window.webkitAudioContext)res=new webkitAudioContext();}catch(e){res=null;}return res;} function piCreateFPSCounter( ){var mFrame,mTo,mFPS,iReset=function(time){mFrame=0;mTo=time;mFPS=60.0;},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 ){if(typeof window.MediaRecorder !=='function'||typeof canvas.captureStream !=='function'){return false;}return true;} function piCreateMediaRecorder(isRecordingCallback,canvas ){if(piCanMediaRecorded(canvas)==false){return null;} ;var mediaRecorder=new MediaRecorder(canvas.captureStream()) ;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) ;let blob =new Blob(chunks,{type:"video/webm"}) ;chunks =[] ;let videoURL=window.URL.createObjectURL(blob) ;let url =window.URL.createObjectURL(blob) ;let a =document.createElement("a") ;document.body.appendChild(a) ;a.style ="display:none" ;a.href =url ;a.download ="capture.webm" ;a.click();window.URL.revokeObjectURL(url);};return mediaRecorder;} function EffectPass(renderer,is20,hasShaderTextureLOD,callback,obj,forceMuted,forcePaused,outputGainNode,copyProgram,id ){this.mID=id ;this.mInputs=[null,null,null,null] ;this.mOutputs=[null,null,null,null] ;this.mSource=null ;this.mGainNode=outputGainNode ;this.mRenderer=renderer ;this.mProgramCopy=copyProgram ;this.mType="image" ;this.mName="none" ;this.mFrame=0 ;this.pShaderTextureLOD=hasShaderTextureLOD ;this.mTextureCallbackFun=callback ;this.mTextureCallbackObj=obj ;this.mForceMuted=forceMuted ;this.mForcePaused=forcePaused ;} EffectPass.prototype.MakeHeader=function( ){if(this.mType=="image"){this.mHeader="uniform vec3 iResolution;uniform float iTime;" +"uniform float iChannelTime[4];uniform vec4 iMouse;" }else this.mHeader="uniform float iChannelTime[4];uniform float iBlockOffset;\n" ;this.mHeader+="uniform vec4 iDate;uniform float iSampleRate;uniform vec3 iChannelResolution[4];\n"; if(this.mType=="image" ){this.mHeader+="uniform int iFrame;uniform float iTimeDelta;uniform float iFrameRate;" +"struct Channel{vec3 resolution;float time;};uniform Channel iChannel[4];" ;for(var i=0;i<this.mInputs.length;i++){var inp=this.mInputs[i];this.mHeader+="uniform sampler2D iChannel"+i+";";} ;this.mHeader+="void mainImage(out vec4 c,in vec2 f);" ;this.mImagePassFooter=(mIs20?"\nout vec4 outColor;":"") +"\nvoid main(void){vec4 color=vec4(0,0,0,1);mainImage(color,gl_FragCoord.xy);color.w=1.0;" +(mIs20?"out":"gl_Frag")+"Color=color;}";}} EffectPass.prototype.Destroy_Sound=function(wa ){ if(this.mPlayNode!=null)this.mPlayNode.stop() ;this.mPlayNode=null ;this.mBuffer=null ;this.mData=null ;this.mRenderer.DestroyTexture(this.mRenderTexture);} EffectPass.prototype.Create=function(passType,passName,wa ){this.mType=passType ;this.mName=passName ;this.mSource=null ;this.MakeHeader() ;if(passType=="sound" ){if(mIs20 ){this.mSoundPassFooter="\nout vec4 outColor;void main(){" +"float t=iBlockOffset+((gl_FragCoord.x-0.5)+(gl_FragCoord.y-0.5)*512.0)/iSampleRate;" +"vec2 y=mainSound(t);" +"vec2 v=floor((0.5+0.5*y)*65536.0);" +"vec2 vl=mod(v,256.0)/255.0;" +"vec2 vh=floor(v/256.0)/255.0;" +"outColor=vec4(vl.x,vh.x,vl.y,vh.y);}" ;}else{ ;this.mSoundPassFooter="\nvoid main(){" +"float t=iBlockOffset+((gl_FragCoord.x-0.5)+(gl_FragCoord.y-0.5)*512.0)/iSampleRate;" +"vec2 y=mainSound(t);" +"vec2 v=floor((0.5+0.5*y)*65536.0);" +"vec2 vl=mod(v,256.0)/255.0;" +"vec2 vh=floor(v/256.0)/255.0;" +"gl_FragColor=vec4(vl.x,vh.x,vl.y,vh.y);}";} ;this.mProgram=null ;this.mSampleRate=sRs[sR] ;this.mPlayTime=180*sRs[0]/sRs[sR]//oh wow,i can just arbitiarily scale this here //,and it generates a longer buffer. //shadertoy default settign was a list of 3 images,so it stored 180seconds in 44100Hz ;this.mPlaySamples=this.mPlayTime*this.mSampleRate ;this.mBuffer=wa.createBuffer(2,this.mPlaySamples,this.mSampleRate) //but createBuffer() here worked for me with much larger [mPlaySamples] ;this.mTextureDimensions=512 ;this.mRenderTexture=this.mRenderer.CreateTexture(0 , this.mTextureDimensions,this.mTextureDimensions , this.mRenderer.TEXFMT.C4I8,0, 0,null) ;this.mRenderFBO=this.mRenderer.CreateRenderTarget(this.mRenderTexture,null,null,null,null,false) ;this.mTmpBufferSamples=this.mTextureDimensions*this.mTextureDimensions ;this.mData=new Uint8Array(this.mTmpBufferSamples*4) ;this.mPlayNode=null;}} EffectPass.prototype.Destroy=function(wa ){this.mSource=null ;if(this.mType=="sound")this.Destroy_Sound(wa) ;else if(this.mType=="common")this.Destroy_Common(wa);} EffectPass.prototype.NewShader_Sound=function(shaderCode,commonShaderCodes ){var vsSource=((mIs20)?"layout(location=0)in":"attribute")+" vec2 pos;void main(){gl_Position=vec4(pos.xy,0.0,1.0);}" ;var fsSource=this.mHeader ;fsSource+=gei('o') ;fsSource+=shaderCode ;fsSource+=this.mSoundPassFooter ;var res=this.mRenderer.CreateShader(vsSource,fsSource) ;if(res.mResult==false)return res.mInfo ;if(this.mProgram!=null)this.mRenderer.DestroyShader(this.mProgram) ;this.mProgram=res ;this.mFrame=0 ;return null;} EffectPass.prototype.NewShader_Image=function(shaderCode,commonShaderCodes ){var vsSource=((mIs20)?"layout(location=0)in":"attribute")+" vec2 pos;void main(){gl_Position=vec4(pos.xy,0.0,1.0);}" ;var fsSource=this.mHeader ;for(var i=0;i<commonShaderCodes.length;i++){fsSource+=commonShaderCodes[i]+'\n';} ;this.mHeaderLength=fsSource.split(/\r\n|\r|\n/).length ;fsSource+=shaderCode ;fsSource+=this.mImagePassFooter ;var res=this.mRenderer.CreateShader(vsSource,fsSource) ;if(res.mResult==false)return res.mInfo ;if(this.mProgram!=null)this.mRenderer.DestroyShader(this.mProgram) ;this.mProgram=res ;this.mSupportsVR=false ;return null;} EffectPass.prototype.NewShader_Common=function(shaderCode ){var vsSource=((mIs20)?"layout(location=0)in":"attribute")+" vec2 pos;void main(){gl_Position=vec4(pos.xy,0.0,1.0);}" ;var fsSource=this.mHeader+shaderCode+this.mImagePassFooter ;var res=this.mRenderer.CreateShader(vsSource,fsSource) ;if(res.mResult==false)return res.mInfo ;if(this.mProgram!=null)this.mRenderer.DestroyShader(this.mProgram) ;this.mProgram=res ;return null;} EffectPass.prototype.NewShader=function(shaderCode,commonSourceCodes ){if(this.mRenderer==null)return null ;var res=null ;if(this.mType=="sound")res=this.NewShader_Sound(shaderCode,commonSourceCodes) ;else if(this.mType=="image")res=this.NewShader_Image(shaderCode,commonSourceCodes) ;else if(this.mType=="buffer")res=this.NewShader_Image(shaderCode,commonSourceCodes) ;else if(this.mType=="common")res=this.NewShader_Common(shaderCode) ;this.mSource=shaderCode;return res;} EffectPass.prototype.DestroyInput=function(id ){if(this.mInputs[id]==null)return ;if(this.mInputs[id].mInfo.mType=="texture"){if(this.mInputs[id].globject!=null)this.mRenderer.DestroyTexture(this.mInputs[id].globject);} ;if(this.mInputs[id].mInfo.mType=="volume"){if(this.mInputs[id].globject!=null)this.mRenderer.DestroyTexture(this.mInputs[id].globject) ;}else if(this.mInputs[id].mInfo.mType=="webcam" ){this.mInputs[id].video.pause() ;this.mInputs[id].video.src="" ;var tracks=this.mInputs[id].video.stream.getVideoTracks() ;if(tracks)tracks[0].stop() ;this.mInputs[id].video=null ;if(this.mInputs[id].globject!=null)this.mRenderer.DestroyTexture(this.mInputs[id].globject) ;}else if(this.mInputs[id].mInfo.mType=="video" ){this.mInputs[id].video.pause() ;this.mInputs[id].video=null ;if(this.mInputs[id].globject!=null) this.mRenderer.DestroyTexture(this.mInputs[id].globject) ;}else if(this.mInputs[id].mInfo.mType=="music"||this.mInputs[id].mInfo.mType=="musicstream" ){this.mInputs[id].audio.pause() ;this.mInputs[id].audio.mSound.mFreqData=null ;this.mInputs[id].audio.mSound.mWaveData=null ;this.mInputs[id].audio=null ;if(this.mInputs[id].globject!=null) this.mRenderer.DestroyTexture(this.mInputs[id].globject) ;}else if(this.mInputs[id].mInfo.mType=="cubemap"){if(this.mInputs[id].globject!=null)this.mRenderer.DestroyTexture(this.mInputs[id].globject) ;}else if(this.mInputs[id].mInfo.mType=="keyboard" ){}else if(this.mInputs[id].mInfo.mType=="mic" ){this.mInputs[id].mic=null ;if(this.mInputs[id].globject!=null)this.mRenderer.DestroyTexture(this.mInputs[id].globject) ;} ;this.mInputs[id]=null;} EffectPass.prototype.StopInput=function(id ){var inp=this.mInputs[id] ;if(inp==null){ ;}else if(inp.mInfo.mType=="music"||inp.mInfo.mType=="musicstream" ){if(inp.audio.mPaused==false){inp.audio.pause();inp.audio.mPaused=true;}return inp.audio.mPaused;} ;return null;} EffectPass.prototype.ResumeInput=function(id ){var inp=this.mInputs[id] ;if(inp==null){ ;}else if(inp.mInfo.mType=="music"||inp.mInfo.mType=="musicstream" ){if(inp.audio.mPaused){inp.audio.play();inp.audio.mPaused=false;}return inp.audio.mPaused;} ;return null;} EffectPass.prototype.Paint_Image=function(vrData,wa,d,time,dtime,fps,mouseOriX,mouseOriY,mousePosX,mousePosY,x,y,buffers,keyboard ){var dates=[d.getFullYear(),d.getMonth(),d.getDate()//YYYY,MM,DD, ,d.getHours()*60*60+d.getMinutes()*60+d.getSeconds()+d.getMilliseconds()/1000.0]//secondsSince0AM ;this.mRenderer.AttachShader(this.mProgram) ;this.mRenderer.ssc1F("iTime",time) ;this.mRenderer.ssc3F("iResolution",x,y,1.0) ;this.mRenderer.ssc4FV("iMouse",[mousePosX,mousePosY,mouseOriX,mouseOriY]) ;this.mRenderer.ssc4FV("iDate",dates)//YYYY,MM,DD,sssssss.ssss ;this.mRenderer.ssc1F("iSampleRate",this.mSampleRate) ;this.mRenderer.ssc1I("iFrame",this.mFrame) ;this.mRenderer.ssc1F("iTimeDelta",dtime) ;this.mRenderer.SetViewport([0,0,x,y]) ;this.mRenderer.DrawFullScreenTriangle_XY(this.mRenderer.GetAttribLocation(this.mProgram,"pos"));} EffectPass.prototype.Paint_Sound=function(wa,d ){var dates=[d.getFullYear(),d.getDate(),d.getHours()*60.0*60+d.getMinutes()*60+d.getSeconds()] ;var resos=[0,0,0,0,0,0,0,0,0,0,0,0] ;this.mRenderer.SetRenderTarget(this.mRenderFBO) ;this.mRenderer.SetViewport([0,0,this.mTextureDimensions,this.mTextureDimensions]) ;this.mRenderer.AttachShader(this.mProgram) ;this.mRenderer.SetBlend(false) ;var texID=[null,null,null,null] ;for(var i=0;i<this.mInputs.length;i++ ){var inp=this.mInputs[i] ;if(inp==null){}else if(inp.mInfo.mType=="texture" ){if(inp.loaded==true ){texID[i]=inp.globject ;resos[3*i+0]=inp.image.width;resos[3*i+1]=inp.image.height;resos[3*i+2]=1 ;}}else if(inp.mInfo.mType=="volume" ){if(inp.loaded==true ){texID[i]=inp.globject ;resos[3*i+0]=inp.mImage.mXres ;resos[3*i+1]=inp.mImage.mYres ;resos[3*i+2]=inp.mImage.mZres;}}} ; ;var l2=this.mRenderer.sscLocation(this.mProgram,"iBlockOffset") ;this.mRenderer.ssc4FV("iDate",dates) ;this.mRenderer.ssc3FV("iChannelResolution",resos) ;this.mRenderer.ssc1F("iSampleRate",this.mSampleRate) ;var l1=this.mRenderer.GetAttribLocation(this.mProgram,"pos") ;var numSamples=this.mTmpBufferSamples ;var bufL=this.mBuffer.getChannelData(0) ;var bufR=this.mBuffer.getChannelData(1) ;var numBlocks=this.mPlaySamples/numSamples ;for(var j=0;j<numBlocks;j++ ){var off=j*this.mTmpBufferSamples ;this.mRenderer.ssc1F_Pos(l2,off/this.mSampleRate) ;this.mRenderer.DrawUnitQuad_XY(l1) ;this.mRenderer.GetPixelData(this.mData,this.mTextureDimensions,this.mTextureDimensions) ;for(var i=0;i<numSamples;i++ ){bufL[off+i]=-1.0+2.0*(this.mData[4*i+0]+256.0*this.mData[4*i+1])/65535.0 ;bufR[off+i]=-1.0+2.0*(this.mData[4*i+2]+256.0*this.mData[4*i+3])/65535.0;}} ;this.mRenderer.DetachShader() ;this.mRenderer.SetRenderTarget(null) ;if(this.mPlayNode!=null){this.mPlayNode.disconnect();this.mPlayNode.stop();} ;this.mPlayNode=wa.createBufferSource() ;this.mPlayNode.buffer=this.mBuffer ;this.mPlayNode.connect(this.mGainNode) ;this.mPlayNode.state=this.mPlayNode.noteOn ;this.mPlayNode.start(0);} EffectPass.prototype.Paint=function(vrData,wa,da,time,dtime,fps,mouseOriX,mouseOriY ,mousePosX,mousePosY,x,y,isPaused,bufferID,bufferNeedsMimaps,buffers,keyboard ){if(this.mType==="sound" ){if(this.mFrame==0&&!isPaused ){this.Paint_Sound(wa,da) ;this.mFrame++ ;}}else if(this.mType==="image" ){this.mRenderer.SetRenderTarget(null) ;this.Paint_Image(vrData,wa,da,time,dtime,fps,mouseOriX,mouseOriY,mousePosX,mousePosY,x,y,buffers,keyboard) ;this.mFrame++ ;}else if(this.mType==="common"){}else if(this.mType=="buffer"){}} EffectPass.prototype.StopOutput_Sound=function(wa ){if(this.mPlayNode===null)return;this.mPlayNode.disconnect();}; EffectPass.prototype.ResumeOutput_Sound=function(wa){if(this.mPlayNode===null)return;this.mPlayNode.connect(this.mGainNode);}; EffectPass.prototype.StopOutput_Image=function(wa){}; EffectPass.prototype.ResumeOutput_Image=function(wa){}; EffectPass.prototype.StopOutput=function(wa ){for(var j=0;j<this.mInputs.length;j++)this.StopInput(j) ;if(this.mType=="sound")this.StopOutput_Sound(wa) ;else this.StopOutput_Image(wa);} EffectPass.prototype.ResumeOutput=function(wa ){for(var j=0;j<this.mInputs.length;j++)this.ResumeInput(j) ;if(this.mType=="sound") this.ResumeOutput_Sound(wa) ;else this.ResumeOutput_Image(wa);} function Effect(vr,ac,gl,x,y,callback,obj,forceMuted,forcePaused ){this.eCreated=false ;this.mRenderer=null ;this.mAudioContext=ac ;this.mContext=gl ;this.mRenderingStereo=false ;this.mXres=x ;this.mYres=y ;this.mForceMuted=forceMuted ;if(ac==null)this.mForceMuted=true ;this.mForcePaused=forcePaused ;this.mGainNode=null ;this.mPasses=[] ;this.mFrame=0 ;this.mTextureCallbackFun=callback ;this.mTextureCallbackObj=obj ;this.mMaxBuffers=4 ;this.mMaxPasses=this.mMaxBuffers+1+1//some day decouple passes from buffers ;this.mBuffers=[] ;if(gl==null)return ;this.mRenderer=piRenderer() ;if(!this.mRenderer.Initialize(gl))return ;var caps=this.mRenderer.GetCaps() ,i2=mIs20=caps.mIsGL20 ,of=(i2?"out":"gl_Frag")+"Color=texture" ,oc=i2?"out vec4 outColor;":"" ,vs1=(i2?"layout(location=0)in":"attribute")+" vec2 p;void main(){gl_Position=vec4(p.xy,0,1);}" ;this.pShaderTextureLOD=caps.pShaderTextureLOD ;if(ac!=null ){this.mGainNode=ac.createGain() ;if(!forceMuted){this.mGainNode.connect(ac.destination);} ;if(this.mForceMuted)this.mGainNode.gain.value=0.0 ;else this.mGainNode.gain.value=vol;} ;var res=this.mRenderer.CreateShader(vs1,"uniform vec4 v;uniform sampler2D t;"+oc+"void main(){"+of+(i2?"Lod":"2D")+"(t,gl_FragCoord.xy/v.zw,"+(i2?"":"-10")+"0.0);}") ;if(res.mResult==false)return; ;this.mProgramCopy=res ;var res=this.mRenderer.CreateShader(vs1,"uniform vec4 v;uniform sampler2D t;"+oc+"void main(){vec2 uv=gl_FragCoord.xy/v.zw;"+of+(i2?"":"2D")+"(t,vec2(uv.x,1.-uv.y));}") ;if(res.mResult==false)return; ;this.mProgramDownscale=res ;this.ResizeBuffers(null,null) ;var keyboardData=new Uint8Array(256*3) ;for(var j=0;j<(256*3);j++){keyboardData[j]=0;} ;var kayboardTexture=this.mRenderer.CreateTexture(0,256,3,this.mRenderer.TEXFMT.C1I8,0,0,null) ;var keyboardImage=new Image() ;if(callback!=null)keyboardImage.src="/keyboard.png" ;this.mKeyboard={mData:keyboardData,mTexture:kayboardTexture,mIcon:keyboardImage} ;this.eCreated=true;} Effect.prototype.ResizeBuffers=function(oldXres,oldYres ){var needCopy=(oldXres!=null&&oldYres!=null) ;if(!needCopy //first time! ){var thumnailRes=[256,128] ;for(var i=0;i<this.mMaxBuffers;i++ ){this.mBuffers[i]={mTexture:[null,null] ,mTarget: [null,null] ,mLastRenderDone:0 ,mThumbnailRenderTarget:null ,mThumbnailTexture:null ,mThumbnailBuffer: null ,mThumbnailRes:thumnailRes};}} ;if(needCopy){} ;for(var i=0;i<this.mMaxBuffers;i++ ){var texture1=this.mRenderer.CreateTexture(0 ,this.mXres,this.mYres ,this.mRenderer.TEXFMT.C4F32 ,(needCopy)? this.mBuffers[i].mTexture[0].mFilter:0 ,(needCopy)? this.mBuffers[i].mTexture[0].mWrap :0 ,null) ;var target1=this.mRenderer.CreateRenderTarget(texture1,null,null,null,null,false) ;var texture2=this.mRenderer.CreateTexture(0 ,this.mXres,this.mYres ,this.mRenderer.TEXFMT.C4F32 ,(needCopy)? this.mBuffers[i].mTexture[1].mFilter:0 ,(needCopy)? this.mBuffers[i].mTexture[1].mWrap :0,null) ;var target2=this.mRenderer.CreateRenderTarget(texture2,null,null,null,null,false) ;if(needCopy){this.mRenderer.SetRenderTarget(target1) ;this.mRenderer.DrawUnitQuad_XY(l1) ;this.mRenderer.SetRenderTarget(target2) ;this.mRenderer.DrawUnitQuad_XY(l1) ;this.mRenderer.DestroyTexture(this.mBuffers[i].mTexture[0]) ;this.mRenderer.DestroyRenderTarget(this.mBuffers[i].mTarget[0]) ;this.mRenderer.DestroyTexture(this.mBuffers[i].mTexture[1]) ;this.mRenderer.DestroyRenderTarget(this.mBuffers[i].mTarget[1]);} ;this.mBuffers[i].mTexture=[texture1,texture2],this.mBuffers[i].mTarget=[target1,target2],this.mBuffers[i].mLastRenderDone=0;} ;if(needCopy){this.mRenderer.DetachShader();this.mRenderer.SetRenderTarget(null);};} Effect.prototype.ToggleVolume=function( ){this.mForceMuted=!this.mForceMuted ;if(this.mForceMuted)this.mGainNode.gain.value=0.0 ;else this.mGainNode.gain.value=vol ;var num=this.mPasses.length ;for(var j=0;j<num;j++){for(var i=0;i<this.mPasses[j].mInputs.length;i++){}} ;return this.mForceMuted;} Effect.prototype.SetKeyDown=function(passid,k ){this.mKeyboard.mData[k+0*256]=255 ;this.mKeyboard.mData[k+1*256]=255 ;this.mKeyboard.mData[k+2*256]=255-this.mKeyboard.mData[k+2*256] ;this.mRenderer.UpdateTexture(this.mKeyboard.mTexture,0,0,256,3,this.mKeyboard.mData) ;var num=this.mPasses.length ;for(var j=0;j<num;j++ ){for(var i=0;i<this.mPasses[j].mInputs.length;i++ ){var inp=this.mPasses[j].mInputs[i] ;if(inp!=null&&inp.mInfo.mType=="keyboard" ){if(this.mTextureCallbackFun!=null)this.mTextureCallbackFun(this.mTextureCallbackObj,i,{mImage:this.mKeyboard.mIcon,mData:this.mKeyboard.mData} ,false,6,1,-1.0,this.mPasses[j].mID);}}}} Effect.prototype.SetKeyUp=function(passid,k ){this.mKeyboard.mData[k+0*256]=0 ;this.mKeyboard.mData[k+1*256]=0 ;this.mRenderer.UpdateTexture(this.mKeyboard.mTexture,0,0,256,3,this.mKeyboard.mData) ;var num=this.mPasses.length ;for(var j=0;j<num;j++ ){for(var i=0;i<this.mPasses[j].mInputs.length;i++ ){var inp=this.mPasses[j].mInputs[i] ;if(inp!=null&&inp.mInfo.mType=="keyboard" ){if(this.mTextureCallbackFun!=null )this.mTextureCallbackFun(this.mTextureCallbackObj,i,{mImage:this.mKeyboard.mIcon,mData:this.mKeyboard.mData} ,false,6,1,-1.0,this.mPasses[j].mID);}}}} Effect.prototype.StopOutputs=function( ){var wa=this.mAudioContext,num=this.mPasses.length;for(var i=0;i<num;i++){this.mPasses[i].StopOutput(wa);}} Effect.prototype.ResumeOutputs=function( ){var wa=this.mAudioContext,num=this.mPasses.length;for(var i=0;i<num;i++){this.mPasses[i].ResumeOutput(wa);}} Effect.prototype.SetSize=function(x,y ){if(x !==this.mXres||y !==this.mYres ){var oldXres=this.mXres;var oldYres=this.mYres;this.mXres=x;this.mYres=y;this.ResizeBuffers(oldXres,oldYres);return true;};return false;} Effect.prototype.UpdateInputs=function(passid,fu){this.mPasses[passid].UpdateInputs(this.mAudioContext,fu,this.mKeyboard);} Effect.prototype.ResetTime=function(){this.mFrame=0;var num=this.mPasses.length;for(var i=0;i<num;i++){this.mPasses[i].mFrame=0}} Effect.prototype.RequestAnimationFrame=function(id){requestAnimFrame(id);} Effect.prototype.Paint=function(time,dtime,fps,mouseOriX,mouseOriY,mousePosX,mousePosY,isPaused ){var wa=this.mAudioContext ;var da=new Date() ;var vrData=null ;var x=this.mXres/1 ;var y=this.mYres/1 ;var num=this.mPasses.length ;if(this.mFrame==0 ){for(var i=0;i<this.mMaxBuffers;i++ ){this.mRenderer.SetRenderTarget(this.mBuffers[i].mTarget[0]) ;this.mRenderer.Clear(1,[0.0,0.0,0.0,0.0],1.0,0) ;this.mRenderer.SetRenderTarget(this.mBuffers[i].mTarget[1]) ;this.mRenderer.Clear(1,[0.0,0.0,0.0,0.0],1.0,0);}} ;for(var i=0;i<num;i++//render sound first ){if(this.mPasses[i].mType!="sound")continue ;if(this.mPasses[i].mProgram==null)continue ;this.mPasses[i].Paint(vrData,wa,da,time,dtime,fps,mouseOriX,mouseOriY,mousePosX,mousePosY,x,y,isPaused,null ,false,this.mBuffers,this.mKeyboard);} ;for(var i=0;i<num;i++//render buffers second ){if(this.mPasses[i].mType!="buffer")continue ;if(this.mPasses[i].mProgram==null)continue ;var needMipMaps=false ;for(var j=0;j<num;j++ ){for(var k=0;k<this.mPasses[j].mInputs.length;k++ ){var inp=this.mPasses[j].mInputs[k] ;if(inp!=null&&inp.mInfo.mType=="buffer"&&inp.id===bufferID&&inp.mInfo.mSampler.filter==="mipmap"){needMipMaps=true;break;}}} ;this.mPasses[i].Paint(vrData,wa,da,time,dtime,fps,mouseOriX,mouseOriY,mousePosX,mousePosY,x,y,isPaused ,bufferID,needMipMaps,this.mBuffers,this.mKeyboard);} ;for(var i=0;i<num;i++//render image last ){if(this.mPasses[i].mType!="image")continue ;if(this.mPasses[i].mProgram==null)continue ;this.mPasses[i].Paint(vrData,wa,da,time,dtime,fps,mouseOriX,mouseOriY,mousePosX,mousePosY,x,y,isPaused,null,false,this.mBuffers,this.mKeyboard);} ;for(var k=0;k<256;k++){this.mKeyboard.mData[k+1*256]=0;}//erase keypresses ;this.mRenderer.UpdateTexture(this.mKeyboard.mTexture,0,0,256,3,this.mKeyboard.mData) ;this.mFrame++;} Effect.prototype.NewShader=function(shaderCode,passid ){var commonSourceCodes=[] ;for(var i=0;i<this.mPasses.length;i++){if(this.mPasses[i].mType=="common"){commonSourceCodes.push(this.mPasses[i].mSource);}} ;return this.mPasses[passid].NewShader(shaderCode,commonSourceCodes);} Effect.prototype.GetNumPasses=function(){return this.mPasses.length;} Effect.prototype.GetNumOfType=function(passtype ){var id=0;for(var j=0;j<this.mPasses.length;j++){if(this.mPasses[j].mType===passtype){id++;}}return id;} Effect.prototype.GetPassType=function(id){return this.mPasses[id].mType;} Effect.prototype.GetPassName=function(id){return this.mPasses[id].mName;} Effect.prototype.newPass=function(jobj ){var numPasses=jobj.renderpass.length ;if(numPasses<1||numPasses>this.mMaxPasses ){return{mFailed:true,mError:"Incorrect number of passes,wrong shader format",mShader:null};} ;var res=[] ;res.mFailed=false ;for(var j=0;j<numPasses;j++ ){var rpass=jobj.renderpass[j] ;this.mPasses[j]=new EffectPass(this.mRenderer,mIs20,this.pShaderTextureLOD ,this.mTextureCallbackFun,this.mTextureCallbackObj,this.mForceMuted,this.mForcePaused,this.mGainNode ,this.mProgramDownscale,j) ;if(this.mForceMuted&&rpass.type=="sound")continue ;var numInputs=rpass.inputs.length ;for(var i=0;i<numInputs;i++){} ;for(var i=0;i<4;i++){} ;var numOutputs=rpass.outputs.length ;for(var i=0;i<numOutputs;i++){} ;var rpassName="" ;if(rpass.type=="common")rpassName="Common" ;if(rpass.type=="sound")rpassName="Sound" ;this.mPasses[j].Create(rpass.type,rpassName,this.mAudioContext);} ;for(var pt=0;pt<4;pt++ ){for(var j=0;j<numPasses;j++ ){var rpass=jobj.renderpass[j] ;if(pt==0&&rpass.type!="common")continue ;if(pt==3&&rpass.type!="sound")continue ;if(this.mForceMuted&&rpass.type=="sound")continue ;var shaderStr=rpass.code ;var result=this.NewShader(shaderStr,j) ;if(result!=null){res.mFailed=true;res[j]={mFailed:true,mError:result,mShader:shaderStr} ;}else {res[j]={mFailed:false,mError:null,mShader:shaderStr};}}} ;return res;} Effect.prototype.DestroyPass=function(id){this.mPasses[id].Destroy(this.mAudioContext);this.mPasses.splice(id,1);} Effect.prototype.addep=function(passType,passName ){var shaderStr=null ;if(passType=="sound")shaderStr=gei('s') ;var id=this.GetNumPasses() ;this.mPasses[id]=new EffectPass(this.mRenderer,mIs20,this.pShaderTextureLOD ,this.mTextureCallbackFun,this.mTextureCallbackObj,this.mForceMuted,this.mForcePaused,this.mGainNode,this.mProgramDownscale,id) ;this.mPasses[id].Create(passType,passName,this.mAudioContext) ;var res=this.NewShader(shaderStr,id) ;return{mId:id,mShader:shaderStr,mError:res};} function ShaderToy( ){var me=this ;me.mContext=null ;me.mTo=null ;me.mCanvas=null ;me.mFPS=piCreateFPSCounter() ;me.mInfo=null ;me.mPass=[] ;var devicePixelRatio=window.devicePixelRatio||1 ;me.mCanvas=document.getElementById("demogl") ;me.mCanvas.tabIndex="0"//make it react to keyboard ;me.mCanvas.width=me.mCanvas.offsetWidth//* devicePixelRatio ;me.mCanvas.height=me.mCanvas.offsetHeight//* devicePixelRatio ;me.mHttpReq=new XMLHttpRequest() ;me.mTo=getRealTime() ;mTf=0 ;me.mFPS.Reset(me.mTo) ;me.mMouseIsDown=false ;me.mMouseOriX=0 ;me.mMouseOriY=0 ;me.mMousePosX=0 ;me.mMousePosY=0 ;me.mContext=piCreateGlContext(me.mCanvas,false,false,true,false)//need preserve-buffe to true in order to capture screenshots ;mAudioContext=piCreateAudioContext() ;window.onfocus=function(){if(!paused){mTOffset=me.mTf;me.mTo=getRealTime();me.mRestarted=true;}} ;var refreshCharsAndFlags=function(){setTimeout(refreshCharsAndFlags,1500);} ;me.mEditorState={mCursorChange:false,mViewportChange:false,mCodeChange:false} ;me.mErrors=new Array() ;me.mCanvas.onmousedown=function(ev ){var rect=me.mCanvas.getBoundingClientRect() ;me.mMouseOriX=Math.floor((ev.clientX-rect.left)/(rect.right-rect.left)*me.mCanvas.width) ;me.mMouseOriY=Math.floor(me.mCanvas.height-(ev.clientY-rect.top)/(rect.bottom-rect.top)*me.mCanvas.height) ;me.mMousePosX=me.mMouseOriX ;me.mMousePosY=me.mMouseOriY ;me.mMouseIsDown=true;} ;me.mCanvas.onmousemove=function(ev ){if(me.mMouseIsDown ){var rect=me.mCanvas.getBoundingClientRect() ;me.mMousePosX=Math.floor((ev.clientX-rect.left)/(rect.right-rect.left)*me.mCanvas.width) ;me.mMousePosY=Math.floor(me.mCanvas.height-(ev.clientY-rect.top)/(rect.bottom-rect.top)*me.mCanvas.height);}} ;me.mCanvas.onmouseup=function(ev ){me.mMouseIsDown=false ;me.mMouseOriX=-Math.abs(me.mMouseOriX) ;me.mMouseOriY=-Math.abs(me.mMouseOriY);} ;document.getElementById("myResetButton").onclick=function(ev){me.resetTime(true);} ;document.getElementById("myPauseButton").onclick=function(ev){me.pauseTime(true);} ;document.getElementById("myVolume").onclick=function(ev ){var res=mEffect.ToggleVolume();} ;var mFullScreenExitHandler=function(){} ;me.mCanvas.addEventListener('webkitfullscreenchange',mFullScreenExitHandler,false) ;me.mCanvas.addEventListener('mozfullscreenchange',mFullScreenExitHandler,false) ;me.mCanvas.addEventListener('fullscreenchange',mFullScreenExitHandler,false) ;me.mCanvas.addEventListener('MSFullscreenChange',mFullScreenExitHandler,false) ;document.getElementById("myFullScreen").onclick=function(ev){piRequestFullScreen(me.mCanvas);me.mCanvas.focus();} ;mEffect=new Effect(null,mAudioContext,me.mContext,me.mCanvas.width,me.mCanvas.height,me.RefreshTexturThumbail,this,false,false) ;if(!mEffect.eCreated){paused=true;return;} ;me.mCanvas.addEventListener("webglcontextlost",function(event){event.preventDefault();paused=true;},false); ;this.mMediaRecorder=null ;document.getElementById("myRecord").onclick=function(ev ){if(me.mMediaRecorder==null ){me.mMediaRecorder=piCreateMediaRecorder(function(b ){var ele=document.getElementById("myRecord") ;if(b){}else{}//currently recording or not ;},me.mCanvas);} ;if(me.mMediaRecorder==null ){let ele=document.getElementById("myRecord") ;ele.style.background="url('/img/themes/classic/recordDisabled.png')" ;return;} ;if(me.mMediaRecorder.state=="inactive"){me.mMediaRecorder.start() ;}else{me.mMediaRecorder.stop();}};} ShaderToy.prototype.startRendering=function( ){var me=this ;function renderLoop2( ){if(me.mContext==null)return ;mEffect.RequestAnimationFrame(renderLoop2) ;if(paused){mEffect.UpdateInputs(me.mActiveDoc,false);return;} ;var time=getRealTime() ;if(paused){ltime=me.mTf;dtime=1000./60. ;}else{ltime=mTOffset+time-me.mTo;if(me.mRestarted)dtime=1000./60.;else dtime=ltime-me.mTf;me.mTf=ltime;} ;me.mRestarted=false ;mEffect.Paint(ltime/1000.0,dtime/1000.0,me.mFPS.GetFPS(),me.mMouseOriX,me.mMouseOriY,me.mMousePosX,me.mMousePosY,paused) ;var newFPS=me.mFPS.Count(time),d=180*sRs[0]/sRs[sR],st=document.getElementById("myTimeNow") ;st.value=time*.5 ;var t=ltime/1000.,s="";if(t<10.)s+="0";if(t<100.&&d>=100.)s+="0" ;document.getElementById("myTime").textContent=s+(t).toFixed(2)+"/" ;document.getElementById("myTimE").textContent=d+".00" //can nopt use newline,because firefox fails to parse that one ;document.getElementById("myVer").textContent=wMs[wM] ;var v=vol*100,vs="";if(v<100)vs+="0";if(v<10)vs+="0" ;document.getElementById("myVol").textContent="volume:"+vs+(vol*100).toFixed(2)+"%" ;document.getElementById("myVerC").textContent=verC ;if(!paused&&newFPS){document.getElementById("myFramerate").textContent=" fps:"+me.mFPS.GetFPS().toFixed(1)+" "+sRs[sR]+"Hz";}} ;renderLoop2();} function resize(){var s=document.getElementById("demogl");if(s){ ;s.setAttribute("width",s.offsetWidth);s.setAttribute("height",s.offsetHeight) ;s.width=s.offsetWidth;s.height=s.offsetHeight;mEffect.SetSize(s.offsetWidth,s.offsetHeight);}} ShaderToy.prototype.pauseTime=function(doFocusCanvas ){if(!paused){paused=true;mEffect.StopOutputs() ;}else{mTOffset=mTf;this.mTo=getRealTime();paused=false;mRestarted=true;mEffect.ResumeOutputs();if(doFocusCanvas)this.mCanvas.focus();}} ShaderToy.prototype.resetTime=function(doFocusOnCanvas ){mTOffset=0;this.mTo=getRealTime();mTf=0;mRestarted=true;this.mFpsTo=this.mTo;this.mFpsFrame=0 ;var st=document.getElementById("myTimeNow");st.value=0 ;mEffect.ResetTime() ;if(doFocusOnCanvas)this.mCanvas.focus();}//put mouse/keyboard focus on canvas function setResTo(zoom,ratio){var x=zoom;var y=zoom/ratio ;document.getElementById("myZoom").textContent=(zoom).toFixed(2) ;document.getElementById("myRatio").textContent=(ratio).toFixed(2) ;document.getElementById("myResX").textContent=(zoom).toFixed(2) ;document.getElementById("myResY").textContent=(zoom/ratio).toFixed(2);} function setZoom(a ){zoom =a*320 ;setResTo(zoom,ratio);} function setRatio(a){ratio=1.-a*2.;setResTo(zoom,ratio);} function watchInit( ){gShaderToy=new ShaderToy() ;var kk={"renderpass":[{"inputs":[],"outputs":[{"channel":0,"id":37 }],"type":"image" ,"code":gei('i')} ,{"inputs":[],"outputs":[{"channel":0,"id":"none"}],"type":"common","code":gei('o')}]} ;gShaderToy.pauseTime(); ;gRes=mEffect.newPass(kk) ;gShaderToy.pauseTime(); ;gShaderToy.startRendering() ;if(mEffect.GetNumOfType("sound")<1){ ;var res=mEffect.addep("sound","Sound") ;gShaderToy.mPass[res.mId]={mDocs:CodeMirror.Doc(res.mShader,"text/x-glsl")}}gShaderToy.pauseTime();} function setVol(a){mEffect.ToggleVolume();vol=a;mEffect.ToggleVolume();} function setTime(a){} </script><head></head><body onload="watchInit();" onresize="resize()"> <table> <table bgcolor=#99F width="100%"><tr><td> <table bgcolor=#FF0 width="100%"><tr><td> <span id="myZoom">z</span><span id="myRario">a</span></tr><tr><td> <span id="myResX">x</span><span id="myResY">y</span></tr></table><td> <table bgcolor=#F0F width="100%"><tr> <td><input id="myZoom" min="0" max="90000" onchange="setZoom(this.value/90000.0)" oninput="setZoom(this.value/90000.0)" value="0" type="range"></input></tr><tr><td> <button id="myFullScreen" >fullscreen</button><span id="myVer"></span></tr></table><td> <table bgcolor=#0FF width="100%"><tr> <td><input id="myRatio" min="0" max="90000" onchange="setRatio(this.value/90000.0)" oninput="setRatio(this.value/90000.0)" value="0" type="range"></input></tr><tr><td> <button id="myRecord">record</button><span id="myVerC"></tr></table><td> <table bgcolor=#FFF width="100%"> <td><input id="myVolS" min="0" max="90000" onchange="setVol(this.value/90000.0)" oninput="setVol(this.value/90000.0)" value="20000" type="range"></input> <tr><td><span><button id="myVolume">0</button><span id="myVol">100%</span></span></tr></table> <td><table bgcolor=#FF0 width="100%"><tr> <td><input id="myTimeNow" min="0" max="90000" onchange="setTime(this.value/90000.0)" oninput="setTime(this.value/90000.0)" value="0" type="range"></input></tr><tr> <td><button id="myResetButton"><=</button><button id="myPauseButton">p</button> <span id="myTime">0.00/</span><span id="myTimE">0.00</span> <span id="myFramerate">0.5 fps</span></tr></table><td></tr></table><tr><td> <div style="width100%;height:100%;"><canvas id="demogl" tabindex="0" style="width100%;height:474px;"></canvas></div></tr></table> </body></html>

[/spoiler]

not because its a good idea, but because i can
added on the 2019-03-04 06:19:48 by ollj ollj

login