上篇採用了HTML5的Canvas的globalCompositeOperation屬性達到了染色效果,其實CSS也提供了一些常規影象變化的設定引數,關於CSS的過濾器Filter設定可參考 http://www.html5rocks.com/en/tutorials/filters/understanding-css/,CSS的設定的確很方便,不需要我們瞭解底層實現邏輯,僅需要提供簡單的設定引數值即可,但這樣的方式畢竟無法達到隨心所欲變化的效果,這有點想OpenGL早期只能通過Fixed Function Pipeline進行開發,和如今採用Shading Language可實現豐富多彩變化的質變,因此這篇我們將採用WebGL的SL程式碼方式折騰點更好玩的效果。
在第一篇我們已經提到影象操作的本質是對輸入輸出的資料變化,因此染色僅是最簡單直觀的基本變化,通過WebGL的SL程式碼我們甚至可以實現影象扭曲等變化效果,先上張最終變化效果的截圖,原圖就是Hightopo官網的banner,染色+扭曲的效果如上:
Vertex程式碼如下:
attribute vec2 aVertexPosition; attribute vec2 aTexturePosition; varying vec2 vTexturePosition; void main() { vTexturePosition = aTexturePosition; gl_Position = vec4(aVertexPosition, 0.0, 1.0); }
Fragment程式碼如下:
precision mediump float; varying vec2 vTexturePosition; uniform sampler2D uSampler; uniform vec4 uColor; uniform float uRadius; uniform float uAngle; uniform vec2 uCenter; void main() { vec2 vec = vTexturePosition - uCenter; float distance = length(vec); if (distance < uRadius) { float ratio = (uRadius - distance) / uRadius; float angle = ratio * ratio * uAngle; float s = sin(angle); float c = cos(angle); vec = vec2(vec.x * c - vec.y * s, vec.x * s + vec.y * c); } gl_FragColor = texture2D(uSampler, uCenter+vec) * uColor; }
相應JavaScript程式碼如下:
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight); gl.clearColor(0.0, 0.0, 0.0, 1.0); gl.clear(gl.COLOR_BUFFER_BIT); vertexShader = loadShaderFromDOM("shader-vs"); fragmentShader = loadShaderFromDOM("shader-fs"); var program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); gl.useProgram(program); var vertexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ -0.7, 0.7, -0.7, -0.7, 0.7, 0.7, -0.7, -0.7, 0.7, -0.7, 0.7, 0.7 ]), gl.STATIC_DRAW); var vertexLocation = gl.getAttribLocation(program, "aVertexPosition"); gl.vertexAttribPointer(vertexLocation, 2, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(vertexLocation); var textureBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, textureBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1 ]), gl.STATIC_DRAW); var textureLocation = gl.getAttribLocation(program, "aTexturePosition"); gl.vertexAttribPointer(textureLocation, 2, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(textureLocation); gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, texture); gl.uniform1i(gl.getUniformLocation(program, 'uSampler'), 0); gl.uniform4fv(gl.getUniformLocation(program, 'uColor'), toRGBA(formPane.v('color'))); gl.uniform1f(gl.getUniformLocation(program, 'uRadius'), formPane.v('radius')); gl.uniform1f(gl.getUniformLocation(program, 'uAngle'), formPane.v('angle')); gl.uniform2fv(gl.getUniformLocation(program, 'uCenter'), [formPane.v('centerX'), 1-formPane.v('centerY')]); gl.drawArrays(gl.TRIANGLES, 0, 6); }
以上Vertext和Fragment的程式碼很多很容易理解,採用HT for Web的FromPane外掛很容易實現控制引數皮膚可進行編輯實時呈現變化效果,以下為操作控制皮膚動態變化的視訊效果:http://v.youku.com/v_show/id_XODMzMTU0OTA0.html
<iframe src="http://player.youku.com/embed/XODMzMTU0OTA0" frameborder="0" width="510" height="498"></iframe>
最後如果你耐心細緻地閱讀到此,對前端遊戲開發感興趣,感覺自己悟性不錯,願意在廈門發展的同學可與聯絡我,我的郵箱為eric@… 省略部分你應該知道的,不限制性別、學歷和年齡,只要你想用心做自己喜歡的事,我期待著與你交流和加盟!