实践cocos2dx 2.x版本wp上增加自定义shader
根据cocos2dx 的官方文档http://www.cocos2d-x.org/wiki/How_to_update_wp8_shader
(吐个槽:不知道为什么cocos2dx团队做事总是做一半,实际上直接使用angle 是不能用的,需要修改)
1,首先从github上下载一个angle工程https://github.com/google/angle,
2.打开src\winrtcompiler\winrtcompiler_vs2013.sln 工程文件
3,修改main.cpp
enum { VERTEX_ATTRIB_POSITION, VERTEX_ATTRIB_COLOR, VERTEX_ATTRIB_TEX_COORD, }; void bindPredefinedVertexAttribs(GLuint program) { static const struct { const char *attributeName; int location; } attribute_locations[] = { { "a_position", VERTEX_ATTRIB_POSITION }, { "a_color", VERTEX_ATTRIB_COLOR }, { "a_texCoord", VERTEX_ATTRIB_TEX_COORD }, }; const int size = sizeof(attribute_locations) / sizeof(attribute_locations[0]); for (int i = 0; i<size; i++) { glBindAttribLocation(program, attribute_locations[i].location, attribute_locations[i].attributeName); } }
上述vertex属性定义可以在cocos源代码中找到。name和id,也是未来保持跟cocos一致
在
1 [Platform::MTAThread] 2 int __cdecl main(int argc, char* argv[])
之前即可,因为要在main中调用
4.在main函数中的glLinkProgram(program);之前调用bindPredefinedVertexAttribs(program);来实现绑定预定义的vertex 属性
另外发现在cocos加载编译过的shader还需要知道二进制的长度,就是需要修改main.cpp,增加导出时候的信息,修改后main中部分代码如下:
if(outputToHeaderFile)
{
FILE *fp = fopen(outputFile.c_str(), "w");
fprintf(fp, "unsigned char %s[] = {\n", variableName);
fprintf(fp, "%3i, ", binary[0]);
for(int i = 1; i < linkStatus - 1; ++i)
{
if(i % 8 == 0)
fprintf(fp, "\n");
fprintf(fp, "%3i, ", binary[i]);
}
if((linkStatus - 1) % 8 == 0)
fprintf(fp, "\n");
fprintf(fp, "%3i\n};\n", binary[linkStatus - 1]);
fprintf(fp, "unsigned int %s_len = %d;\n", variableName, linkStatus);
fclose(fp);
}
5.编译exe
注意:在编译shader是需要使用cocos增加了shader头部的代码,
例如:fragment shader
1 precision mediump float; 2 3 //CC INCLUDES END 4 5 6 /* 7 * cocos2d for iPhone: http://www.cocos2d-iphone.org 8 * 9 * Copyright (c) 2011 Ricardo Quesada 10 * Copyright (c) 2012 Zynga Inc. 11 * 12 * Permission is hereby granted, free of charge, to any person obtaining a copy 13 * of this software and associated documentation files (the "Software"), to deal 14 * in the Software without restriction, including without limitation the rights 15 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 * copies of the Software, and to permit persons to whom the Software is 17 * furnished to do so, subject to the following conditions: 18 * 19 * The above copyright notice and this permission notice shall be included in 20 * all copies or substantial portions of the Software. 21 * 22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 * THE SOFTWARE. 29 */ 30 31 32 33 34 35 36 37 varying vec4 v_fragmentColor; 38 39 varying vec2 v_texCoord; 40 41 uniform sampler2D CC_Texture0; 42 43 44 45 void main() 46 47 { 48 49 vec4 color = texture2D(CC_Texture0, v_texCoord); 50 51 float grey = color.r * 0.299 + color.g * 0.587 + color.b * 0.114; 52 53 gl_FragColor = vec4(grey*1.13, grey*1.13, grey*1.13,color.a); 54 55 56 }
vertex shader
1 precision highp float; 2 3 uniform mat4 CC_PMatrix; 4 5 uniform mat4 CC_MVMatrix; 6 7 uniform mat4 CC_MVPMatrix; 8 9 uniform vec4 CC_Time; 10 11 uniform vec4 CC_SinTime; 12 13 uniform vec4 CC_CosTime; 14 15 uniform vec4 CC_Random01; 16 17 //CC INCLUDES END 18 19 20 /* 21 * cocos2d for iPhone: http://www.cocos2d-iphone.org 22 * 23 * Copyright (c) 2011 Ricardo Quesada 24 * Copyright (c) 2012 Zynga Inc. 25 * 26 * Permission is hereby granted, free of charge, to any person obtaining a copy 27 * of this software and associated documentation files (the "Software"), to deal 28 * in the Software without restriction, including without limitation the rights 29 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 30 * copies of the Software, and to permit persons to whom the Software is 31 * furnished to do so, subject to the following conditions: 32 * 33 * The above copyright notice and this permission notice shall be included in 34 * all copies or substantial portions of the Software. 35 * 36 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 37 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 38 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 39 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 40 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 41 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 42 * THE SOFTWARE. 43 */ 44 45 46 47 attribute vec4 a_position; 48 49 attribute vec2 a_texCoord; 50 51 attribute vec4 a_color; 52 53 54 55 #ifdef GL_ES 56 57 varying lowp vec4 v_fragmentColor; 58 59 varying mediump vec2 v_texCoord; 60 61 #else 62 63 varying vec4 v_fragmentColor; 64 65 varying vec2 v_texCoord; 66 67 #endif 68 69 70 71 void main() 72 73 { 74 75 gl_Position = CC_MVPMatrix * a_position; 76 77 v_fragmentColor = a_color; 78 79 v_texCoord = a_texCoord; 80 81 }
vertex shader
命令行:winrtcompiler.exe -p=wp8 -o=shader_gray_wp.h -a=g_xc_gray_Program -v=vert_src.h -f=frag_src.h
可以查看编译出来文件:shader_gray_wp.h
unsigned char g_xc_gray_Program[] = { 166, 147, 0, 0, 142, 9, 2, 1, 0, 128, 0, 0, 82, 139, 0, 0, 10, 0, 0, 0, 97, 95, 112, 111, 115, 105, 116, 105, 111, 110, 1, 0, 0, 0, 82, 139, 0, 0, 7, 0, 0, 0, 97, 95, 99, 111, 108, 111, 114, 0, 0, 0, 0, 80, 139, 0, 0, 10, 0, 0, 0, 97, 95, 116, 101, 120, 67, 111, 111, 114, 100, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, .... }; unsigned int g_xc_gray_Program_len = 2954;
这样的shader才能编译后给cocos2dx使用,
使用:
我的做法是修改加载shader的代码,来加载编译出来的二进制
CCGLProgram增加bool initWithVertexShaderByteArray(const GLchar* vShaderByteArray, GLint buffsize); 可以使用导出的文件的两个变量来加载一个shader
1 bool CCGLProgram::initWithPrecompiledProgramByteArray(const GLchar* vShaderByteArray, GLint buffsize) 2 { 3 bool haveProgram = false; 4 5 m_uProgram = glCreateProgram(); 6 CHECK_GL_ERROR_DEBUG(); 7 8 m_uVertShader = m_uFragShader = 0; 9 10 haveProgram = CCPrecompiledShaders::sharedPrecompiledShaders()->loadProgram(m_uProgram, (const GLvoid*)vShaderByteArray, buffsize); 11 12 CHECK_GL_ERROR_DEBUG(); 13 m_pHashForUniforms = NULL; 14 15 CHECK_GL_ERROR_DEBUG(); 16 17 return haveProgram; 18 }
initWithPrecompiledProgramByteArray
在ccshaderCache.cpp中loadDefaultShaders()中增加
1 #if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) || (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) 2 CCGLProgram* pProgram = new CCGLProgram(); 3 #include "shader_xc_wp.h" 4 pProgram->initWithVertexShaderByteArray((const GLchar*)g_xc_gray_Program, g_xc_gray_Program_len); 5 6 pProgram->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position); 7 pProgram->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color); 8 pProgram->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords); 9 pProgram->link(); 10 pProgram->updateUniforms(); 11 12 13 m_pPrograms->setObject(pProgram, "greysprite"); 14 15 pProgram->release(); 16 #endif
add shader
在reloadDefaultShaders中增加
1 #if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) || (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) 2 CCGLProgram* pProgram = programForKey("greysprite"); 3 pProgram->reset(); 4 #include "shader_xc_wp.h" 5 pProgram->initWithVertexShaderByteArray((const GLchar*)g_xc_gray_Program, g_xc_gray_Program_len); 6 7 pProgram->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position); 8 pProgram->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color); 9 pProgram->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords); 10 pProgram->link(); 11 pProgram->updateUniforms(); 12 CHECK_GL_ERROR_DEBUG(); 13 #endif
reload shader
这样就可以使用了,当然要把.h拷贝到shader目录或者能包含到的目录中
happy coding!