cocos2d的Shader也就是差不多直接跟GPU打交道了,跟Flash的Stage3D(AGAL)類似,不過沒有AGAL這么惡心,不需要直接編寫匯編語言。而Fragment Shader又跟Flash的pixelbender類似。
本文以cocos2d-js為例,但cocos2dx其他版本也是同理的,只是函數名略有不同而已。
當然還是得先復習或者學習一下GPU的原理,至少得知道vertex shader和fragment shader的作用和區別。
詳細可以看看大神的說明:
http://www.opengpu.org/bbs/forum.php?mod=viewthread&tid=7550&extra=page%3D1
http://www.opengpu.org/bbs/forum.php?mod=viewthread&tid=7376&extra=page%3D1
cocos2d的Shader步驟還是類似的:
1、編寫vertex shader和fragment shader
2、定義頂點坐標和紋理坐標
3、定義紋理、綁定紋理
4、設置shader的參數
5、每幀draw的時候,gl.drawArrays推送到GPU繪制
1、Shader語法
語法有點類似Flash的pixelbender,但是一個更完整的C程序,可以按照C程序的語法來編寫。main函數最終輸出結果到一個指定變量中,都是矢量的點乘、加減等。
vertext shader最后賦值一個vec4給gl_Position,表示該點最終繪制到屏幕上的位置;fragment shader最后賦值vec4給gl_FragColor,表示顏色rgba。
詳細介紹:
http://blog.csdn.net/hgl868/article/details/7846269
http://blog.csdn.net/wangyuchun_799/article/details/7770500
attribute、uniform、varying區別:http://blog.csdn.net/jackers679/article/details/6848085
uniform變量是外部application程序傳遞給(vertex和fragment)shader的變量,類似常量
attribute變量是只能在vertex shader中使用的變量。(它不能在fragment shader中聲明attribute變量,也不能被fragment shader中使用)
varying變量是vertex和fragment shader之間做數據傳遞用的。一般vertex shader修改varying變量的值,然后fragment shader使用該varying變量的值。因此varying變量在vertex和fragment shader二者之間的聲明必須是一致的。application不能使用此變量。Varying can be used only with the data types float, vec2, vec3, vec4, mat2, mat3, mat4. (arrays of them too.)
2、定義頂點坐標和紋理坐標
var squareVertexPositionBuffer = this.squareVertexPositionBuffer = gl.createBuffer(); //創建一個buffer,並記錄下來,后續每幀draw的時候調用 gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer); //綁定位置,后一句bufferData就設置這個位置的數據 vertices = [ //這里是4個頂點 256, 256, 0, 256, 256, 0, 0, 0 ]; gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); /* gl.STATIC_DRAW The data store contents are modified once, and used many times as the source for WebGL drawing commands. gl.DYNAMIC_DRAW The data store contents are repeatedly respecified, and used many times as the source for WebGL drawing commands. gl.STREAM_DRAW The data store contents are specified once, and used occasionally as the source of a WebGL drawing command. */ gl.bindBuffer(gl.ARRAY_BUFFER, null);
3、綁定紋理
//定義紋理 var texture = this.my_texture = gl.createTexture(); gl.bindTexture( gl.TEXTURE_2D, texture ); var pixels = new Uint8Array(4096); //正好是32*32的圖片,每個像素4個byte for( var i=0; i<pixels.length; ) { pixels[i++] = i/4; // Red pixels[i++] = i/16; // Green pixels[i++] = i/8; // Blue pixels[i++] = 255; // Alpha } gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 32, 32, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels); //每幀draw之前綁定紋理 gl.bindTexture(gl.TEXTURE_2D, this.my_texture);
對應的fragment shader寫法
precision lowp float; varying vec2 v_texCoord; uniform sampler2D CC_Texture0; void main() { gl_FragColor = texture2D(CC_Texture0, v_texCoord); }
4、設置shader參數
//在初始化的時候記錄shader程序,記錄參數的入口位置 this.shader = cc.GLProgram.create(vertexShader, framentShader); this.shader.retain(); this.shader.addAttribute("aVertex", cc.VERTEX_ATTRIB_POSITION); //添加一個新參數到shader中,並指定為第幾個 this.shader.link(); this.shader.updateUniforms(); //表示使用cocos2d默認附加的一些參數,其實在_compileShader的時候添加到shader程序的 var program = this.shader.getProgram(); this.uniformCenter = gl.getUniformLocation( program, "center"); //記錄Uniform參數入口 this.uniformResolution = gl.getUniformLocation( program, "resolution"); //override原來的draw函數,在每幀draw的時候調用: this.shader.use(); this.shader.setUniformsForBuiltins(); //如果shader中使用了cocos2d默認附加的一些uniform參數,就需要每幀設置(例如TIME等),具體參數意義參考CCGLProgram.setUniformsForBuiltins this.shader.setUniformLocationF32( this.uniformCenter, winSize.width/2, winSize.height/2); this.shader.setUniformLocationF32( this.uniformResolution, 256, 256); //設置uniform參數,CCGLProgram類對opengl底層的接口做了封裝。例如這個就是對應uniform2f gl.bindBuffer(gl.ARRAY_BUFFER, this.squareVertexPositionBuffer); gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, gl.FLOAT, false, 0, 0); //設置attribute參數
參數參考:
http://msdn.microsoft.com/zh-cn/library/ie/dn302460(v=vs.85).aspx
函數第一個參數:表示shader程序的第幾個attribute參數
5、draw call
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
參數參考:
http://msdn.microsoft.com/zh-cn/library/ie/dn302460(v=vs.85).aspx
http://msdn.microsoft.com/zh-cn/library/ie/dn302395(v=vs.85).aspx
最后附上cocos2dx官方的一些教程: