Onclick approaching photos array with webgl. Today we continue HTML5 WebGL examples. I prepared a nice photo gallery for you. Images in this gallery will be replaced by a mouse click.
Here are our demo and downloadable package:
[sociallocker]
[/sociallocker]
Ok, download the example files and lets start coding !
Step 1. HTML
Here are html sources of our demo. As you can see – just empty page.
index.html
04 | < meta charset = "utf-8" /> |
05 | < title >Creating photo array in WebGL | Script Tutorials</ title > |
06 | < link href = "css/main.css" rel = "stylesheet" type = "text/css" /> |
07 | < script type = "text/javascript" src = "js/glMatrix-0.9.5.min.js" ></ script > |
08 | < script type = "text/javascript" src = "js/webgl-utils.js" ></ script > |
09 | < script type = "text/javascript" src = "js/script.js" ></ script > |
11 | < body onload = "initWebGl();" > |
12 | < div class = "container" id = "container" > |
13 | < h3 >You can use your mouse to switch images</ h3 > |
14 | < canvas id = "panel" width = "800" height = "600" ></ canvas > |
17 | < h2 >Creating photo array in WebGL</ h2 > |
Step 2. CSS
Here are used CSS styles.
css/main.css
08 | font : 14px / 1.3 Arial , sans-serif ; |
11 | background-color : #212121 ; |
13 | box-shadow: 0 -1px 2px #111111 ; |
30 | footer a.stuts,a.stuts:visited{ |
37 | margin : 23px 0 0 110px ; |
Step 3. JS
js/webgl-utils.js and js/glMatrix-0.9.5.min.js
These files we will use in project for working with WebGL. Both files will in our package.
js/script.js
003 | var pics_names=[ '1.png' , '2.png' , '3.png' , '4.png' , '5.png' , '6.png' , '7.png' ]; |
004 | var pics_num=pics_names.length; |
006 | function initGL(canvas) { |
008 | gl = canvas.getContext( 'experimental-webgl' ); |
009 | gl.viewportWidth = canvas.width; |
010 | gl.viewportHeight = canvas.height; |
013 | alert( 'Can`t initialise WebGL, not supported' ); |
016 | function getShader(gl, type) { |
019 | if (type == 'x-fragment' ) { |
020 | str = "#ifdef GL_ES\n" + |
021 | "precision highp float;\n" + |
023 | "varying vec2 vTextureCoord;\n" + |
024 | "uniform sampler2D uSampler;\n" + |
025 | "void main(void) {\n" + |
026 | " gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));\n" + |
028 | shader = gl.createShader(gl.FRAGMENT_SHADER); |
029 | } else if (type == 'x-vertex' ) { |
030 | str = "attribute vec3 aVertexPosition;\n" + |
031 | "attribute vec2 aTextureCoord;\n" + |
032 | "uniform mat4 uMVMatrix;\n" + |
033 | "uniform mat4 uPMatrix;\n" + |
034 | "varying vec2 vTextureCoord;\n" + |
035 | "void main(void) {\n" + |
036 | " gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);\n" + |
037 | " vTextureCoord = aTextureCoord;\n" + |
039 | shader = gl.createShader(gl.VERTEX_SHADER); |
043 | gl.shaderSource(shader, str); |
044 | gl.compileShader(shader); |
045 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { |
046 | alert(gl.getShaderInfoLog(shader)); |
051 | function initShaders() { |
052 | var fragmentShader = getShader(gl, 'x-fragment' ); |
053 | var vertexShader = getShader(gl, 'x-vertex' ); |
054 | shaderProgram = gl.createProgram(); |
055 | gl.attachShader(shaderProgram, vertexShader); |
056 | gl.attachShader(shaderProgram, fragmentShader); |
057 | gl.linkProgram(shaderProgram); |
058 | if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { |
059 | alert( 'Can`t initialise shaders' ); |
061 | gl.useProgram(shaderProgram); |
062 | shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, 'aVertexPosition' ); |
063 | gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); |
064 | shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, 'aTextureCoord' ); |
065 | gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); |
066 | shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, 'uPMatrix' ); |
067 | shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, 'uMVMatrix' ); |
068 | shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, 'uSampler' ); |
070 | var objVertexPositionBuffer= new Array(); |
071 | var objVertexTextureCoordBuffer= new Array(); |
072 | var objVertexIndexBuffer= new Array(); |
073 | function initObjBuffers() { |
074 | for ( var i=0;i<pics_num;i=i+1) { |
075 | objVertexPositionBuffer[i] = gl.createBuffer(); |
076 | gl.bindBuffer(gl.ARRAY_BUFFER, objVertexPositionBuffer[i]); |
083 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); |
084 | objVertexPositionBuffer[i].itemSize = 3; |
085 | objVertexPositionBuffer[i].numItems = 4; |
086 | objVertexTextureCoordBuffer[i] = gl.createBuffer(); |
087 | gl.bindBuffer(gl.ARRAY_BUFFER, objVertexTextureCoordBuffer[i] ); |
088 | var textureCoords = [ |
094 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW); |
095 | objVertexTextureCoordBuffer[i].itemSize = 2; |
096 | objVertexTextureCoordBuffer[i].numItems = 4; |
097 | objVertexIndexBuffer[i] = gl.createBuffer(); |
098 | gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, objVertexIndexBuffer[i]); |
099 | var objVertexIndices = [ |
103 | gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(objVertexIndices), gl.STATIC_DRAW); |
104 | objVertexIndexBuffer[i].itemSize = 1; |
105 | objVertexIndexBuffer[i].numItems = 6; |
108 | function handleLoadedTexture(texture) { |
109 | gl.bindTexture(gl.TEXTURE_2D, texture); |
110 | gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true ); |
111 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image); |
112 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); |
113 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); |
114 | gl.bindTexture(gl.TEXTURE_2D, null ); |
116 | var aTextures = Array(); |
117 | function initTexture(image) { |
118 | var crateImage = new Image(); |
119 | var texture = gl.createTexture(); |
120 | texture.image = crateImage; |
121 | crateImage.src = image; |
122 | crateImage.onload = function () { |
123 | handleLoadedTexture(texture) |
127 | function initTextures() { |
128 | for ( var i=0; i < pics_num; i++) { |
129 | aTextures[i]=initTexture(pics_names[i]); |
132 | var mvMatrix = mat4.create(); |
133 | var mvMatrixStack = []; |
134 | var pMatrix = mat4.create(); |
135 | function setMatrixUniforms() { |
136 | gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false , pMatrix); |
137 | gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false , mvMatrix); |
146 | function handleMouseDown(event) { |
147 | if (bMove == false && iTimer == 0) { |
154 | var MoveMatrix = mat4.create(); |
155 | mat4.identity(MoveMatrix); |
156 | function drawScene() { |
157 | gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight); |
158 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); |
159 | mat4.perspective(30, gl.viewportWidth / gl.viewportHeight, 2.0, 100.0, pMatrix); |
160 | mat4.identity(mvMatrix); |
161 | mat4.translate(mvMatrix, [0.0, 0.0, z]); |
162 | mat4.multiply(mvMatrix, MoveMatrix); |
163 | for ( var i=0;i<pics_num;i=i+1) { |
164 | gl.bindBuffer(gl.ARRAY_BUFFER, objVertexPositionBuffer[i]); |
165 | gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, objVertexPositionBuffer[i].itemSize, gl.FLOAT, false , 0, 0); |
166 | gl.bindBuffer(gl.ARRAY_BUFFER, objVertexTextureCoordBuffer[i]); |
167 | gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, objVertexTextureCoordBuffer[i].itemSize, gl.FLOAT, false , 0, 0); |
168 | gl.activeTexture(gl.TEXTURE0); |
169 | gl.bindTexture(gl.TEXTURE_2D, aTextures[i]); |
170 | gl.uniform1i(shaderProgram.samplerUniform, 0); |
171 | gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, objVertexIndexBuffer[i]); |
173 | gl.drawElements(gl.TRIANGLES, objVertexIndexBuffer[i].numItems, gl.UNSIGNED_SHORT, 0); |
178 | var timeNow = new Date().getTime(); |
180 | if (z > (pics_num - 2) * 2) { |
184 | if (bMove == true && iTimer > 0) { |
195 | function drawFrame() { |
196 | requestAnimFrame(drawFrame); |
200 | function initWebGl() { |
201 | var canvas = document.getElementById( 'panel' ); |
206 | gl.clearColor(1.0, 1.0, 1.0, 1.0); |
207 | gl.enable(gl.DEPTH_TEST); |
208 | canvas.onmousedown = handleMouseDown; |
This is pretty long code, but it is most important. I separated all code to 3 sides: initializations, handlers and drawing of scene. Hope that you already read our previos post where I told about creating another photo gallery with WebGL. In this case it will more easy to understand today’s code. Today we handle click events for other purposes. We’ll run some internal timer – and will change the Z coordinate on the timer (in the end – the pictures are moving forward, and then disappear).
Step 4. Images
All these images we will using for twisting:
Conclusion
I hope you enjoyed today`s result. If you have any suggestions or ideas – share it 🙂 Welcome back our friends!