A custom shader draw 3d cube in colorful ASCII characters.
A Pen by Lingjia Liu on CodePen.
A custom shader draw 3d cube in colorful ASCII characters.
A Pen by Lingjia Liu on CodePen.
| <body> | |
| <canvas id="scene" width="520" height="520"> | |
| Your browser does not support canvas! | |
| </canvas> | |
| <script id="canvas_vsh" type="x-shader/x-vertex"> | |
| attribute vec2 a_pos; | |
| attribute vec2 a_texcoord; | |
| varying vec2 v_texcoord; | |
| void main() { | |
| gl_Position = vec4(a_pos, 0.0, 1.0); | |
| v_texcoord = a_texcoord; | |
| } | |
| </script> | |
| <script id="canvas_fsh" type="x-shader/x-fragment"> | |
| #ifdef GL_ES | |
| precision mediump float; | |
| #endif | |
| uniform sampler2D u_fontmap; | |
| uniform sampler2D u_tex; | |
| varying vec2 v_texcoord; | |
| void main() { | |
| vec4 pixel = texture2D(u_tex, v_texcoord); | |
| float brightness = float(pixel.r) * 0.2 + float(pixel.g) * 0.7 + float(pixel.b) * 0.1; | |
| float index = (1.0-brightness)*63.0; | |
| int col = int(mod(index, 9.0)); | |
| int row = int(index/9.0); | |
| float x = float(col) * 14.0 + mod(gl_FragCoord.x, 14.0); | |
| float y = 2.0 + float(6 - row) * 18.0 + mod(gl_FragCoord.y, 18.0); | |
| vec4 pif = texture2D(u_fontmap, vec2(x, y) / 128.0); | |
| if(pif.r>0.5) | |
| discard; | |
| gl_FragColor = pixel; | |
| } | |
| </script> | |
| <script id="cube_vsh" type="x-shader/x-vertex"> | |
| attribute vec3 a_pos; | |
| attribute vec3 a_color; | |
| uniform mat4 u_M; | |
| uniform mat4 u_V; | |
| uniform mat4 u_P; | |
| varying vec3 v_color; | |
| void main() { | |
| gl_Position = u_P * u_V * u_M * vec4(a_pos, 1.0); | |
| v_color = a_color; | |
| } | |
| </script> | |
| <script id="cube_fsh" type="x-shader/x-fragment"> | |
| #ifdef GL_ES | |
| precision mediump float; | |
| #endif | |
| varying vec3 v_color; | |
| void main() { | |
| gl_FragColor = vec4(v_color, 1.0); | |
| } | |
| </script> | |
| </body> |
| // cuon-matrix.js (c) 2012 kanda and matsuda | |
| var Matrix4=function(opt_src){var i,s,d;if(opt_src&&typeof opt_src==="object"&&opt_src.hasOwnProperty("elements")){s=opt_src.elements;d=new Float32Array(16);for(i=0;i<16;++i){d[i]=s[i]}this.elements=d}else{this.elements=new Float32Array([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1])}};Matrix4.prototype.setIdentity=function(){var e=this.elements;e[0]=1;e[4]=0;e[8]=0;e[12]=0;e[1]=0;e[5]=1;e[9]=0;e[13]=0;e[2]=0;e[6]=0;e[10]=1;e[14]=0;e[3]=0;e[7]=0;e[11]=0;e[15]=1;return this};Matrix4.prototype.set=function(src){var i,s,d;s=src.elements;d=this.elements;if(s===d){return}for(i=0;i<16;++i){d[i]=s[i]}return this};Matrix4.prototype.concat=function(other){var i,e,a,b,ai0,ai1,ai2,ai3;e=this.elements;a=this.elements;b=other.elements;if(e===b){b=new Float32Array(16);for(i=0;i<16;++i){b[i]=e[i]}}for(i=0;i<4;i++){ai0=a[i];ai1=a[i+4];ai2=a[i+8];ai3=a[i+12];e[i]=ai0*b[0]+ai1*b[1]+ai2*b[2]+ai3*b[3];e[i+4]=ai0*b[4]+ai1*b[5]+ai2*b[6]+ai3*b[7];e[i+8]=ai0*b[8]+ai1*b[9]+ai2*b[10]+ai3*b[11];e[i+12]=ai0*b[12]+ai1*b[13]+ai2*b[14]+ai3*b[15]}return this};Matrix4.prototype.multiply=Matrix4.prototype.concat;Matrix4.prototype.multiplyVector3=function(pos){var e=this.elements;var p=pos.elements;var v=new Vector3;var result=v.elements;result[0]=p[0]*e[0]+p[1]*e[4]+p[2]*e[8]+e[11];result[1]=p[0]*e[1]+p[1]*e[5]+p[2]*e[9]+e[12];result[2]=p[0]*e[2]+p[1]*e[6]+p[2]*e[10]+e[13];return v};Matrix4.prototype.multiplyVector4=function(pos){var e=this.elements;var p=pos.elements;var v=new Vector4;var result=v.elements;result[0]=p[0]*e[0]+p[1]*e[4]+p[2]*e[8]+p[3]*e[12];result[1]=p[0]*e[1]+p[1]*e[5]+p[2]*e[9]+p[3]*e[13];result[2]=p[0]*e[2]+p[1]*e[6]+p[2]*e[10]+p[3]*e[14];result[3]=p[0]*e[3]+p[1]*e[7]+p[2]*e[11]+p[3]*e[15];return v};Matrix4.prototype.transpose=function(){var e,t;e=this.elements;t=e[1];e[1]=e[4];e[4]=t;t=e[2];e[2]=e[8];e[8]=t;t=e[3];e[3]=e[12];e[12]=t;t=e[6];e[6]=e[9];e[9]=t;t=e[7];e[7]=e[13];e[13]=t;t=e[11];e[11]=e[14];e[14]=t;return this};Matrix4.prototype.setInverseOf=function(other){var i,s,d,inv,det;s=other.elements;d=this.elements;inv=new Float32Array(16);inv[0]=s[5]*s[10]*s[15]-s[5]*s[11]*s[14]-s[9]*s[6]*s[15]+s[9]*s[7]*s[14]+s[13]*s[6]*s[11]-s[13]*s[7]*s[10];inv[4]=-s[4]*s[10]*s[15]+s[4]*s[11]*s[14]+s[8]*s[6]*s[15]-s[8]*s[7]*s[14]-s[12]*s[6]*s[11]+s[12]*s[7]*s[10];inv[8]=s[4]*s[9]*s[15]-s[4]*s[11]*s[13]-s[8]*s[5]*s[15]+s[8]*s[7]*s[13]+s[12]*s[5]*s[11]-s[12]*s[7]*s[9];inv[12]=-s[4]*s[9]*s[14]+s[4]*s[10]*s[13]+s[8]*s[5]*s[14]-s[8]*s[6]*s[13]-s[12]*s[5]*s[10]+s[12]*s[6]*s[9];inv[1]=-s[1]*s[10]*s[15]+s[1]*s[11]*s[14]+s[9]*s[2]*s[15]-s[9]*s[3]*s[14]-s[13]*s[2]*s[11]+s[13]*s[3]*s[10];inv[5]=s[0]*s[10]*s[15]-s[0]*s[11]*s[14]-s[8]*s[2]*s[15]+s[8]*s[3]*s[14]+s[12]*s[2]*s[11]-s[12]*s[3]*s[10];inv[9]=-s[0]*s[9]*s[15]+s[0]*s[11]*s[13]+s[8]*s[1]*s[15]-s[8]*s[3]*s[13]-s[12]*s[1]*s[11]+s[12]*s[3]*s[9];inv[13]=s[0]*s[9]*s[14]-s[0]*s[10]*s[13]-s[8]*s[1]*s[14]+s[8]*s[2]*s[13]+s[12]*s[1]*s[10]-s[12]*s[2]*s[9];inv[2]=s[1]*s[6]*s[15]-s[1]*s[7]*s[14]-s[5]*s[2]*s[15]+s[5]*s[3]*s[14]+s[13]*s[2]*s[7]-s[13]*s[3]*s[6];inv[6]=-s[0]*s[6]*s[15]+s[0]*s[7]*s[14]+s[4]*s[2]*s[15]-s[4]*s[3]*s[14]-s[12]*s[2]*s[7]+s[12]*s[3]*s[6];inv[10]=s[0]*s[5]*s[15]-s[0]*s[7]*s[13]-s[4]*s[1]*s[15]+s[4]*s[3]*s[13]+s[12]*s[1]*s[7]-s[12]*s[3]*s[5];inv[14]=-s[0]*s[5]*s[14]+s[0]*s[6]*s[13]+s[4]*s[1]*s[14]-s[4]*s[2]*s[13]-s[12]*s[1]*s[6]+s[12]*s[2]*s[5];inv[3]=-s[1]*s[6]*s[11]+s[1]*s[7]*s[10]+s[5]*s[2]*s[11]-s[5]*s[3]*s[10]-s[9]*s[2]*s[7]+s[9]*s[3]*s[6];inv[7]=s[0]*s[6]*s[11]-s[0]*s[7]*s[10]-s[4]*s[2]*s[11]+s[4]*s[3]*s[10]+s[8]*s[2]*s[7]-s[8]*s[3]*s[6];inv[11]=-s[0]*s[5]*s[11]+s[0]*s[7]*s[9]+s[4]*s[1]*s[11]-s[4]*s[3]*s[9]-s[8]*s[1]*s[7]+s[8]*s[3]*s[5];inv[15]=s[0]*s[5]*s[10]-s[0]*s[6]*s[9]-s[4]*s[1]*s[10]+s[4]*s[2]*s[9]+s[8]*s[1]*s[6]-s[8]*s[2]*s[5];det=s[0]*inv[0]+s[1]*inv[4]+s[2]*inv[8]+s[3]*inv[12];if(det===0){return this}det=1/det;for(i=0;i<16;i++){d[i]=inv[i]*det}return this};Matrix4.prototype.invert=function(){return this.setInverseOf(this)};Matrix4.prototype.setOrtho=function(left,right,bottom,top,near,far){var e,rw,rh,rd;if(left===right||bottom===top||near===far){throw"null frustum"}rw=1/(right-left);rh=1/(top-bottom);rd=1/(far-near);e=this.elements;e[0]=2*rw;e[1]=0;e[2]=0;e[3]=0;e[4]=0;e[5]=2*rh;e[6]=0;e[7]=0;e[8]=0;e[9]=0;e[10]=-2*rd;e[11]=0;e[12]=-(right+left)*rw;e[13]=-(top+bottom)*rh;e[14]=-(far+near)*rd;e[15]=1;return this};Matrix4.prototype.ortho=function(left,right,bottom,top,near,far){return this.concat((new Matrix4).setOrtho(left,right,bottom,top,near,far))};Matrix4.prototype.setFrustum=function(left,right,bottom,top,near,far){var e,rw,rh,rd;if(left===right||top===bottom||near===far){throw"null frustum"}if(near<=0){throw"near <= 0"}if(far<=0){throw"far <= 0"}rw=1/(right-left);rh=1/(top-bottom);rd=1/(far-near);e=this.elements;e[0]=2*near*rw;e[1]=0;e[2]=0;e[3]=0;e[4]=0;e[5]=2*near*rh;e[6]=0;e[7]=0;e[8]=(right+left)*rw;e[9]=(top+bottom)*rh;e[10]=-(far+near)*rd;e[11]=-1;e[12]=0;e[13]=0;e[14]=-2*near*far*rd;e[15]=0;return this};Matrix4.prototype.frustum=function(left,right,bottom,top,near,far){return this.concat((new Matrix4).setFrustum(left,right,bottom,top,near,far))};Matrix4.prototype.setPerspective=function(fovy,aspect,near,far){var e,rd,s,ct;if(near===far||aspect===0){throw"null frustum"}if(near<=0){throw"near <= 0"}if(far<=0){throw"far <= 0"}fovy=Math.PI*fovy/180/2;s=Math.sin(fovy);if(s===0){throw"null frustum"}rd=1/(far-near);ct=Math.cos(fovy)/s;e=this.elements;e[0]=ct/aspect;e[1]=0;e[2]=0;e[3]=0;e[4]=0;e[5]=ct;e[6]=0;e[7]=0;e[8]=0;e[9]=0;e[10]=-(far+near)*rd;e[11]=-1;e[12]=0;e[13]=0;e[14]=-2*near*far*rd;e[15]=0;return this};Matrix4.prototype.perspective=function(fovy,aspect,near,far){return this.concat((new Matrix4).setPerspective(fovy,aspect,near,far))};Matrix4.prototype.setScale=function(x,y,z){var e=this.elements;e[0]=x;e[4]=0;e[8]=0;e[12]=0;e[1]=0;e[5]=y;e[9]=0;e[13]=0;e[2]=0;e[6]=0;e[10]=z;e[14]=0;e[3]=0;e[7]=0;e[11]=0;e[15]=1;return this};Matrix4.prototype.scale=function(x,y,z){var e=this.elements;e[0]*=x;e[4]*=y;e[8]*=z;e[1]*=x;e[5]*=y;e[9]*=z;e[2]*=x;e[6]*=y;e[10]*=z;e[3]*=x;e[7]*=y;e[11]*=z;return this};Matrix4.prototype.setTranslate=function(x,y,z){var e=this.elements;e[0]=1;e[4]=0;e[8]=0;e[12]=x;e[1]=0;e[5]=1;e[9]=0;e[13]=y;e[2]=0;e[6]=0;e[10]=1;e[14]=z;e[3]=0;e[7]=0;e[11]=0;e[15]=1;return this};Matrix4.prototype.translate=function(x,y,z){var e=this.elements;e[12]+=e[0]*x+e[4]*y+e[8]*z;e[13]+=e[1]*x+e[5]*y+e[9]*z;e[14]+=e[2]*x+e[6]*y+e[10]*z;e[15]+=e[3]*x+e[7]*y+e[11]*z;return this};Matrix4.prototype.setRotate=function(angle,x,y,z){var e,s,c,len,rlen,nc,xy,yz,zx,xs,ys,zs;angle=Math.PI*angle/180;e=this.elements;s=Math.sin(angle);c=Math.cos(angle);if(0!==x&&0===y&&0===z){if(x<0){s=-s}e[0]=1;e[4]=0;e[8]=0;e[12]=0;e[1]=0;e[5]=c;e[9]=-s;e[13]=0;e[2]=0;e[6]=s;e[10]=c;e[14]=0;e[3]=0;e[7]=0;e[11]=0;e[15]=1}else if(0===x&&0!==y&&0===z){if(y<0){s=-s}e[0]=c;e[4]=0;e[8]=s;e[12]=0;e[1]=0;e[5]=1;e[9]=0;e[13]=0;e[2]=-s;e[6]=0;e[10]=c;e[14]=0;e[3]=0;e[7]=0;e[11]=0;e[15]=1}else if(0===x&&0===y&&0!==z){if(z<0){s=-s}e[0]=c;e[4]=-s;e[8]=0;e[12]=0;e[1]=s;e[5]=c;e[9]=0;e[13]=0;e[2]=0;e[6]=0;e[10]=1;e[14]=0;e[3]=0;e[7]=0;e[11]=0;e[15]=1}else{len=Math.sqrt(x*x+y*y+z*z);if(len!==1){rlen=1/len;x*=rlen;y*=rlen;z*=rlen}nc=1-c;xy=x*y;yz=y*z;zx=z*x;xs=x*s;ys=y*s;zs=z*s;e[0]=x*x*nc+c;e[1]=xy*nc+zs;e[2]=zx*nc-ys;e[3]=0;e[4]=xy*nc-zs;e[5]=y*y*nc+c;e[6]=yz*nc+xs;e[7]=0;e[8]=zx*nc+ys;e[9]=yz*nc-xs;e[10]=z*z*nc+c;e[11]=0;e[12]=0;e[13]=0;e[14]=0;e[15]=1}return this};Matrix4.prototype.rotate=function(angle,x,y,z){return this.concat((new Matrix4).setRotate(angle,x,y,z))};Matrix4.prototype.setLookAt=function(eyeX,eyeY,eyeZ,centerX,centerY,centerZ,upX,upY,upZ){var e,fx,fy,fz,rlf,sx,sy,sz,rls,ux,uy,uz;fx=centerX-eyeX;fy=centerY-eyeY;fz=centerZ-eyeZ;rlf=1/Math.sqrt(fx*fx+fy*fy+fz*fz);fx*=rlf;fy*=rlf;fz*=rlf;sx=fy*upZ-fz*upY;sy=fz*upX-fx*upZ;sz=fx*upY-fy*upX;rls=1/Math.sqrt(sx*sx+sy*sy+sz*sz);sx*=rls;sy*=rls;sz*=rls;ux=sy*fz-sz*fy;uy=sz*fx-sx*fz;uz=sx*fy-sy*fx;e=this.elements;e[0]=sx;e[1]=ux;e[2]=-fx;e[3]=0;e[4]=sy;e[5]=uy;e[6]=-fy;e[7]=0;e[8]=sz;e[9]=uz;e[10]=-fz;e[11]=0;e[12]=0;e[13]=0;e[14]=0;e[15]=1;return this.translate(-eyeX,-eyeY,-eyeZ)};Matrix4.prototype.lookAt=function(eyeX,eyeY,eyeZ,centerX,centerY,centerZ,upX,upY,upZ){return this.concat((new Matrix4).setLookAt(eyeX,eyeY,eyeZ,centerX,centerY,centerZ,upX,upY,upZ))};Matrix4.prototype.dropShadow=function(plane,light){var mat=new Matrix4;var e=mat.elements;var dot=plane[0]*light[0]+plane[1]*light[1]+plane[2]*light[2]+plane[3]*light[3];e[0]=dot-light[0]*plane[0];e[1]=-light[1]*plane[0];e[2]=-light[2]*plane[0];e[3]=-light[3]*plane[0];e[4]=-light[0]*plane[1];e[5]=dot-light[1]*plane[1];e[6]=-light[2]*plane[1];e[7]=-light[3]*plane[1];e[8]=-light[0]*plane[2];e[9]=-light[1]*plane[2];e[10]=dot-light[2]*plane[2];e[11]=-light[3]*plane[2];e[12]=-light[0]*plane[3];e[13]=-light[1]*plane[3];e[14]=-light[2]*plane[3];e[15]=dot-light[3]*plane[3];return this.concat(mat)};Matrix4.prototype.dropShadowDirectionally=function(normX,normY,normZ,planeX,planeY,planeZ,lightX,lightY,lightZ){var a=planeX*normX+planeY*normY+planeZ*normZ;return this.dropShadow([normX,normY,normZ,-a],[lightX,lightY,lightZ,0])};var Vector3=function(opt_src){var v=new Float32Array(3);if(opt_src&&typeof opt_src==="object"){v[0]=opt_src[0];v[1]=opt_src[1];v[2]=opt_src[2]}this.elements=v};Vector3.prototype.normalize=function(){var v=this.elements;var c=v[0],d=v[1],e=v[2],g=Math.sqrt(c*c+d*d+e*e);if(g){if(g==1)return this}else{v[0]=0;v[1]=0;v[2]=0;return this}g=1/g;v[0]=c*g;v[1]=d*g;v[2]=e*g;return this};var Vector4=function(opt_src){var v=new Float32Array(4);if(opt_src&&typeof opt_src==="object"){v[0]=opt_src[0];v[1]=opt_src[1];v[2]=opt_src[2];v[3]=opt_src[3]}this.elements=v}; | |
| // programm start here | |
| var scene, gl; | |
| /* | |
| var fontMapData = "data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAIAAABMXPacAAAFOElEQVR42u2dW3YjIQxEx/vfWvbEnDNfGafdVJVKgOPSb0gbuDz0QPBnRDbJ1z/5k44IgADol8fjsf6bjyuZlgwA9IMIAIFZliAU50cDQOb1U0mqDPhf9lkIlplW76nAZWEdwNO3LA1bMFo76okMke8YDAC0Sco23jVa2cLCnJvOA/MSFAAUAP8e0AcA310D4M0AuEoeAaBpE36XksIm3K6GWmzRDvu26ZtsmVcl4wv6JF9QJAACIBIAARAJgJMBUAYLq4wjZgsVlsJ/1GWvCG5zzg5odTNQVrvLF2138FFu8/tf3wBgjY9F6yw7gGnJ/wBoSwrSU9o3jwWAzyoOwPYliO19LWYZAKhTDN97cQYWt93TIKjgf+8ZIChX9r19DwBhXmuA5c3Ntbx8EABKCzoBgEVfuraEkeWVVa7tdoBQgS1hTtoOEExH427BGtVUSbthT5nrp0TEVh78izMuAA4DkN7fAGDLufsAiARAAEROAdB0ho49m8bq7K6I2P5NWLOEKxZm3bK9T+dzaXftAIoeHtnHYvFAyIFGEcD3qafZ7r8MgGv+Ea4IPNDR4Y+U/TAdSxBYmPrpuTOuEm5uHWXaJqz9KHW+ptgiHYCgYwjMLKvwmow2rZdKAKiS3l7o2AO0KVjUABcBsHdBEQCoGhQBIB907gH2kq6IGA7Ae4buZ3MmACgbT7iCxJV7JVvCiMasqeB4c57KxxcUZ1wABEAABEAkAAIg8qsBPGnElKLtrQZoMdRtC6Ty646lUDVrOsAy7VnWXJ9azqcAWOM4QqrhdRm1AMC9C6DHQlumKC8IPqW8ISawABcRk8dpHYDcbIvbrgkAcTy9I0ViAYBiUFD7rGuszNNUDwQg9/6wBvhaAFRavh6AlnNhjHKvANARkBkNp0gsZzI2Axi1mNS91iTr464N8z0AjEJMqn47f58aOq2AcDWDRV+PLyjOuAAIgAAIgEgABEDkDAByMlfHxRJTdd51wyF1gK5y1BV9Q8Z7cR17Z5XRDO44mVup/x4AxgaMnniA8U0GAwDtLiiq2KV36NVyMe2dxTcLIavfzZrpByDM1vtOvP+4HLoyevmFCD66B+A9C/rXTgAw+u800zabEgDvDHgap/e56k0zoALJCaAytA8EYE/nawTQkaZqz0Dffiri/QDgdoB3ARy12DUV4zNswoLdKFiw+HRZ+USuYAnLamgiYnHGRQIgACIBEACRAPgYAGyOWN2kGIULLX4VACFHTHbICLboq2K/CkDFk+EFMHweVjOAVxer3Aeqpka58LwDuFJd1lPGL4S4W1wR9suVKkkfdrcd3kzqEa1hjIhprmMq8YqaK8VfpwAUXy5ZHREDt9O+FLOmznqbkOQJAIYaZcQj0hsACG1zLQJrlqC6GnoEACr/1rVl1TdhXFla0yLlZBylhiLbL6uGUkqwlsw1gOvrGw9mjWOeOzrz3Z9FRxMD4NMBHPvsVSOA7W9+nf/omFzDy39MPGCzBEAABMDUHY2sa6DRUM/nMh7Wm9YTbHKlni+vqxEu41r20gB1bV5FtymeDUXusrwG4L0w5n0BDOAYvVBsAqCSbVKMPgqobgbNzyCUcGPWagB9aRcIDBYAkspxSajoj0Pw//zrZeFFM8D+mKeQS4MAYLODWgCMQi7VgTOAAiA0s/jroha0fQ8YfDKTds0w2LN+APbR6i15DoDBBHk4AIOJCq20A5YBKEbuOAD3B7NAS7iee4W/VI1vqgO43bFiCd83nLCEZcvlcAdynHGRAAiAyB2Ar8hWCYDN8hdO6ayFlEpanwAAAABJRU5ErkJggg=="; | |
| /*/ | |
| var fontMapData = "data:image/png;base64, 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"; | |
| //*/ | |
| function main() { | |
| scene = document.getElementById("scene"); | |
| gl = scene.getContext("webgl"); | |
| var canvas_program = createShaderProgram("canvas_vsh", "canvas_fsh"); | |
| gl.useProgram(canvas_program); | |
| var canvas_a_pos = gl.getAttribLocation(canvas_program, "a_pos"); | |
| var canvas_a_texcoord = gl.getAttribLocation(canvas_program, "a_texcoord"); | |
| var u_fontmap = gl.getUniformLocation(canvas_program, "u_fontmap"); | |
| gl.uniform1i(u_fontmap, 0); // texture0 | |
| var u_tex = gl.getUniformLocation(canvas_program, "u_tex"); | |
| gl.uniform1i(u_tex, 1); // texture1 | |
| var cube_program = createShaderProgram("cube_vsh", "cube_fsh"); | |
| gl.useProgram(cube_program); | |
| var cube_a_pos = gl.getAttribLocation(cube_program, "a_pos"); | |
| var cube_a_color = gl.getAttribLocation(cube_program, "a_color"); | |
| var u_p = gl.getUniformLocation(cube_program, "u_P"); | |
| var projection = new Matrix4(); | |
| projection.perspective(30, 1, 0.1, 10); | |
| gl.uniformMatrix4fv(u_p, false, projection.elements); | |
| var u_v = gl.getUniformLocation(cube_program, "u_V"); | |
| var view = new Matrix4(); | |
| view.lookAt(2, 2, 2, 0, 0, 0, 0, 1, 0); | |
| gl.uniformMatrix4fv(u_v, false, view.elements); | |
| var u_m = gl.getUniformLocation(cube_program, "u_M"); | |
| var canvas_vertices = new Float32Array([ | |
| -1, -1, 0, 0, | |
| 1, -1, 36 / 64, 0, | |
| 1, 1, 36 / 64, 28 / 64, | |
| -1, 1, 0, 28 / 64 | |
| ]); | |
| var canvas_indices = new Uint8Array([ | |
| 0, 1, 2, 2, 3, 0 | |
| ]); | |
| var canvas_vbo = gl.createBuffer(); | |
| gl.bindBuffer(gl.ARRAY_BUFFER, canvas_vbo); | |
| gl.bufferData(gl.ARRAY_BUFFER, canvas_vertices, gl.STATIC_DRAW); | |
| var canvas_ebo = gl.createBuffer(); | |
| gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, canvas_ebo); | |
| gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, canvas_indices, gl.STATIC_DRAW); | |
| var cube_vertices = new Float32Array([ | |
| 0.5, 0.5, 0.5, 1, 0, 1, | |
| 0.5, 0.5, -0.5, 0, 1, 1, | |
| -0.5, 0.5, -0.5, 1, 1, 0, | |
| -0.5, 0.5, 0.5, 1, 0, 0, | |
| 0.5, -0.5, 0.5, 1, 1, 1, | |
| 0.5, -0.5, -0.5, 1, 1, 1, | |
| -0.5, -0.5, -0.5, 1, 0, 1, | |
| -0.5, -0.5, 0.5, 1, 1, 1 | |
| ]); | |
| var cube_indices = new Uint8Array([ | |
| 0, 1, 2, | |
| 2, 3, 0, | |
| 0, 4, 1, | |
| 1, 4, 5, | |
| 5, 6, 1, | |
| 1, 6, 2, | |
| 2, 6, 3, | |
| 3, 6, 7, | |
| 7, 6, 3, | |
| 3, 4, 7, | |
| 7, 4, 3, | |
| 3, 4, 0 | |
| ]); | |
| var cube_vbo = gl.createBuffer(); | |
| gl.bindBuffer(gl.ARRAY_BUFFER, cube_vbo); | |
| gl.bufferData(gl.ARRAY_BUFFER, cube_vertices, gl.STATIC_DRAW); | |
| var cube_ebo = gl.createBuffer(); | |
| gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cube_ebo); | |
| gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, cube_indices, gl.STATIC_DRAW); | |
| var fbo = gl.createFramebuffer(); | |
| gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); | |
| var fontMapImg = new Image(); | |
| fontMapImg.src = fontMapData; | |
| fontMapImg.onload = function() { | |
| gl.activeTexture(gl.TEXTURE0); | |
| var fontMapTex = gl.createTexture(); | |
| gl.bindTexture(gl.TEXTURE_2D, fontMapTex); | |
| gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1); | |
| gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, fontMapImg); | |
| gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); | |
| gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); | |
| } | |
| gl.activeTexture(gl.TEXTURE1); | |
| var canvasTex = gl.createTexture(); | |
| gl.bindTexture(gl.TEXTURE_2D, canvasTex); | |
| gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 64, 64, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); | |
| gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); | |
| gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); | |
| gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, canvasTex, 0); | |
| var dbo = gl.createRenderbuffer(); | |
| gl.bindRenderbuffer(gl.RENDERBUFFER, dbo); | |
| gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 64, 64); | |
| gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, dbo); | |
| gl.clearColor(1, 1, 1, 1); | |
| gl.enable(gl.DEPTH_TEST); | |
| var r = 0; | |
| requestAnimationFrame(function run() { | |
| gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); | |
| gl.viewport(0, 0, 36, 28); | |
| gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); | |
| gl.bindBuffer(gl.ARRAY_BUFFER, cube_vbo); | |
| gl.vertexAttribPointer(cube_a_pos, 3, gl.FLOAT, false, cube_vertices.BYTES_PER_ELEMENT * 6, 0); | |
| gl.enableVertexAttribArray(cube_a_pos); | |
| gl.vertexAttribPointer(cube_a_color, 3, gl.FLOAT, false, cube_vertices.BYTES_PER_ELEMENT * 6, cube_vertices.BYTES_PER_ELEMENT * 3); | |
| gl.enableVertexAttribArray(cube_a_color); | |
| gl.useProgram(cube_program); | |
| var model = new Matrix4(); | |
| model.rotate(r++, 0, 1, 0); | |
| gl.uniformMatrix4fv(u_m, false, model.elements); | |
| gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cube_ebo); | |
| gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_BYTE, 0); | |
| gl.bindFramebuffer(gl.FRAMEBUFFER, null); | |
| gl.viewport(0, 0, 504, 504); | |
| gl.clear(gl.COLOR_BUFFER_BIT); | |
| gl.bindBuffer(gl.ARRAY_BUFFER, canvas_vbo); | |
| gl.vertexAttribPointer(canvas_a_pos, 2, gl.FLOAT, false, canvas_vertices.BYTES_PER_ELEMENT * 4, 0); | |
| gl.enableVertexAttribArray(canvas_a_pos); | |
| gl.vertexAttribPointer(canvas_a_texcoord, 2, gl.FLOAT, false, canvas_vertices.BYTES_PER_ELEMENT * 4, canvas_vertices.BYTES_PER_ELEMENT * 2); | |
| gl.enableVertexAttribArray(canvas_a_texcoord); | |
| gl.useProgram(canvas_program); | |
| gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, canvas_ebo); | |
| gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0); | |
| requestAnimationFrame(run); | |
| }) | |
| } | |
| function createShader(type, src) { | |
| var node = document.getElementById(src); | |
| var shader = gl.createShader(type); | |
| gl.shaderSource(shader, node.innerHTML); | |
| gl.compileShader(shader); | |
| var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS); | |
| if (!compiled) { | |
| var error = gl.getShaderInfoLog(shader); | |
| console.log('Failed to compile shader: ' + error); | |
| gl.deleteShader(shader); | |
| return null; | |
| } | |
| return shader; | |
| } | |
| function createShaderProgram(vsh, fsh) { | |
| var vShader = createShader(gl.VERTEX_SHADER, vsh); | |
| var fShader = createShader(gl.FRAGMENT_SHADER, fsh); | |
| var shaderProgram = gl.createProgram(); | |
| gl.attachShader(shaderProgram, vShader); | |
| gl.attachShader(shaderProgram, fShader); | |
| gl.linkProgram(shaderProgram); | |
| var linked = gl.getProgramParameter(shaderProgram, gl.LINK_STATUS); | |
| if (!linked) { | |
| var error = gl.getProgramInfoLog(shaderProgram); | |
| console.log('Failed to link shaderProgram: ' + error); | |
| gl.deleteProgram(shaderProgram); | |
| gl.deleteShader(vShader); | |
| gl.deleteShader(fShader); | |
| return null; | |
| } | |
| return shaderProgram; | |
| } | |
| main(); |