mark下:轉載:http://www.cocoachina.com/bbs/read.php?tid=220630
1.cocos2d的shader都是共用的, 存放在 GLProgramCache 中。 當setGLProgram() 的時候是從GLProgramStateCache 中尋找是否有這個shader的State, 有就返回,這個也是共用的,任意一個GLProgramState修改了, 都會影響到使用這個shader的對象
添加shader的方法:
先編寫shader: (直接復制cocos/renderer/ 下的 **.frag或者**.vert ) frag是PS階段的shader .vert是VS,然后按照自己的修改。
注意 這些shader在加載的時候,cocos2d會自動添加幾個必須的屬性變量:
const GLchar *sources[] = {
#if (CC_TARGET_PLATFORM != CC_PLATFORM_WIN32 && CC_TARGET_PLATFORM != CC_PLATFORM_LINUX && CC_TARGET_PLATFORM != CC_PLATFORM_MAC)
(type == GL_VERTEX_SHADER ? "precision highp float;\n" : "precision mediump float;\n"),
#endif
"uniform mat4 CC_PMatrix;\n"
"uniform mat4 CC_MVMatrix;\n"
"uniform mat4 CC_MVPMatrix;\n"
"uniform vec4 CC_Time;\n"
"uniform vec4 CC_SinTime;\n"
"uniform vec4 CC_CosTime;\n"
"uniform vec4 CC_Random01;\n"
"uniform sampler2D CC_Texture0;\n"
"uniform sampler2D CC_Texture1;\n"
"uniform sampler2D CC_Texture2;\n"
"uniform sampler2D CC_Texture3;\n"
"//CC INCLUDES END\n\n",
source,
};
這段代碼在: bool GLProgram::compileShader(GLuint * shader, GLenum type, const GLchar* source) 中,所以你在編寫自己的shader時候要注意不要和上面的變量重名
編寫方式:
現在ccShaders.h中添加shader的編碼保存的變量:(拿做的灰度效果為列:)
extern CC_DLL const GLchar * ccPositionTextureColor_noMVP_gray_frag;
我直接修改 ccShader_PositionTextureColor_noMVP.frag 這個文件的
源文件:
const char* ccPositionTextureColor_noMVP_frag = STRINGIFY(
\n#ifdef GL_ES\n
precision lowp float;
\n#endif\n
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
uniform int n_isGray;
void main()
{
if (n_isGray == 1)
{
float alpha = texture2D(CC_Texture0, v_texCoord).a;
float grey = dot(texture2D(CC_Texture0, v_texCoord).rgb, vec3(0.299, 0.587, 0.114));
gl_FragColor = vec4(1, grey, grey, 0.0);
}
else
{
gl_FragColor = v_fragmentColor * texture2D(CC_Texture0, v_texCoord);
}
}
);
修改后:
const char* ccPositionTextureColor_noMVP_gray_frag = STRINGIFY(
\n#ifdef GL_ES\n
precision lowp float;
\n#endif\n
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
void main()
{
float alpha = texture2D(CC_Texture0, v_texCoord).a;
float grey = dot(texture2D(CC_Texture0, v_texCoord).rgb, vec3(0.299, 0.587, 0.114));
gl_FragColor = vec4(grey, grey, grey, alpha);
}
);
紅色部分是修改掉的 注意 const char* ccPositionTextureColor_noMVP_gray_frag = STRINGIFY( 紅色部分要和你在ccShaders.h中聲明的變量一致!
然后在ccShaders.cpp中引用 編寫好的shader文件 : #include "ccShader_PositionTextureColor_noMVP_gray.frag"
這樣編寫部分就結束
現在開始添加到默認shader里面:
先到 CCGLProgram.h GLProgram 中添加添加我們這個shader的名字:(這個名字只是對外使用的鍵值)
static const char* SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP_GRAY;
在.cpp中加上:
const char* GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP_GRAY = "ShaderPositionTextureColor_noMVP_gray";
然后到CCGLProgramCache.cpp 中的 最上面有一堆枚舉, 添加一個自己shader的枚舉 比如我添加的 kShaderType_PositionTextureColor_noMVP_gray,
然后在 void GLProgramCache::loadDefaultGLPrograms() 中寫加載我們shader的代碼:
p = new GLProgram();
loadDefaultGLProgram(p, kShaderType_PositionTextureColor_noMVP_gray);
_programs.insert( std::make_pair( GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP_GRAY, p ) );
到void GLProgramCache::loadDefaultGLProgram(GLProgram *p, int type) 中,配置我們shader用的VS 和PS階段的 的相關代碼:(因為做灰度只需要改動pos部分,所以可以直接用cocos2d現有的VS階段的代碼ccPositionTextureColor_noMVP_vert)
case kShaderType_PositionTextureColor_noMVP_gray:
p->initWithByteArrays(ccPositionTextureColor_noMVP_vert, ccPositionTextureColor_noMVP_gray_frag);
break;
這樣shader就添加好了, 使用方法:
GLProgram *program = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP_GRAY);
sprite->setGLProgram(program);
還原的話就
GLProgram *program = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP);
sprite->setGLProgram(program);
你可以脫離這套共用GLProgramState的方式 直接用: (這樣你就可以控制這個shader某一個值,而不影響其他使用這個shader的對象了)
GLProgram *program = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP_GRAY);
GLProgramState* state = GLProgramState::create(program);
sprite->setGLProgramState(state):
本人沒學過opengel今天ui那邊需要灰度,才開始看的, 寫得不好,大家就將就看吧~
還要說一個地方
std::string GLProgram::logForOpenGLObject(GLuint object, GLInfoFunction infoFunc, GLLogFunction logFunc) const
{
std::string ret;
GLint logLength = 0, charsWritten = 0;
//infoFunc(object, GL_INFO_LOG_LENGTH, &logLength); //編譯錯誤的話,到這里就崩潰了~~ 不知道為什么,
glGetShaderiv(object, GL_INFO_LOG_LENGTH, &logLength); //我直接改成調用opengel函數,
if (logLength < 1)
return "";
char *logBytes = (char*)malloc(logLength);
// logFunc(object, logLength, &charsWritten, logBytes);
glGetShaderInfoLog(object, logLength, &charsWritten, logBytes);
ret = logBytes;
free(logBytes);
return ret;
}
這里是我這篇筆記的地址: http://note.youdao.com/share/?id=f72378178898d34affe13a6dddd75df3&type=note
添加shader的方法:
先編寫shader: (直接復制cocos/renderer/ 下的 **.frag或者**.vert ) frag是PS階段的shader .vert是VS,然后按照自己的修改。
注意 這些shader在加載的時候,cocos2d會自動添加幾個必須的屬性變量:
const GLchar *sources[] = {
#if (CC_TARGET_PLATFORM != CC_PLATFORM_WIN32 && CC_TARGET_PLATFORM != CC_PLATFORM_LINUX && CC_TARGET_PLATFORM != CC_PLATFORM_MAC)
(type == GL_VERTEX_SHADER ? "precision highp float;\n" : "precision mediump float;\n"),
#endif
"uniform mat4 CC_PMatrix;\n"
"uniform mat4 CC_MVMatrix;\n"
"uniform mat4 CC_MVPMatrix;\n"
"uniform vec4 CC_Time;\n"
"uniform vec4 CC_SinTime;\n"
"uniform vec4 CC_CosTime;\n"
"uniform vec4 CC_Random01;\n"
"uniform sampler2D CC_Texture0;\n"
"uniform sampler2D CC_Texture1;\n"
"uniform sampler2D CC_Texture2;\n"
"uniform sampler2D CC_Texture3;\n"
"//CC INCLUDES END\n\n",
source,
};
這段代碼在: bool GLProgram::compileShader(GLuint * shader, GLenum type, const GLchar* source) 中,所以你在編寫自己的shader時候要注意不要和上面的變量重名
編寫方式:
現在ccShaders.h中添加shader的編碼保存的變量:(拿做的灰度效果為列:)
extern CC_DLL const GLchar * ccPositionTextureColor_noMVP_gray_frag;
我直接修改 ccShader_PositionTextureColor_noMVP.frag 這個文件的
源文件:
const char* ccPositionTextureColor_noMVP_frag = STRINGIFY(
\n#ifdef GL_ES\n
precision lowp float;
\n#endif\n
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
uniform int n_isGray;
void main()
{
if (n_isGray == 1)
{
float alpha = texture2D(CC_Texture0, v_texCoord).a;
float grey = dot(texture2D(CC_Texture0, v_texCoord).rgb, vec3(0.299, 0.587, 0.114));
gl_FragColor = vec4(1, grey, grey, 0.0);
}
else
{
gl_FragColor = v_fragmentColor * texture2D(CC_Texture0, v_texCoord);
}
}
);
修改后:
const char* ccPositionTextureColor_noMVP_gray_frag = STRINGIFY(
\n#ifdef GL_ES\n
precision lowp float;
\n#endif\n
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
void main()
{
float alpha = texture2D(CC_Texture0, v_texCoord).a;
float grey = dot(texture2D(CC_Texture0, v_texCoord).rgb, vec3(0.299, 0.587, 0.114));
gl_FragColor = vec4(grey, grey, grey, alpha);
}
);
紅色部分是修改掉的 注意 const char* ccPositionTextureColor_noMVP_gray_frag = STRINGIFY( 紅色部分要和你在ccShaders.h中聲明的變量一致!
然后在ccShaders.cpp中引用 編寫好的shader文件 : #include "ccShader_PositionTextureColor_noMVP_gray.frag"
這樣編寫部分就結束
現在開始添加到默認shader里面:
先到 CCGLProgram.h GLProgram 中添加添加我們這個shader的名字:(這個名字只是對外使用的鍵值)
static const char* SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP_GRAY;
在.cpp中加上:
const char* GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP_GRAY = "ShaderPositionTextureColor_noMVP_gray";
然后到CCGLProgramCache.cpp 中的 最上面有一堆枚舉, 添加一個自己shader的枚舉 比如我添加的 kShaderType_PositionTextureColor_noMVP_gray,
然后在 void GLProgramCache::loadDefaultGLPrograms() 中寫加載我們shader的代碼:
p = new GLProgram();
loadDefaultGLProgram(p, kShaderType_PositionTextureColor_noMVP_gray);
_programs.insert( std::make_pair( GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP_GRAY, p ) );
到void GLProgramCache::loadDefaultGLProgram(GLProgram *p, int type) 中,配置我們shader用的VS 和PS階段的 的相關代碼:(因為做灰度只需要改動pos部分,所以可以直接用cocos2d現有的VS階段的代碼ccPositionTextureColor_noMVP_vert)
case kShaderType_PositionTextureColor_noMVP_gray:
p->initWithByteArrays(ccPositionTextureColor_noMVP_vert, ccPositionTextureColor_noMVP_gray_frag);
break;
這樣shader就添加好了, 使用方法:
GLProgram *program = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP_GRAY);
sprite->setGLProgram(program);
還原的話就
GLProgram *program = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP);
sprite->setGLProgram(program);
你可以脫離這套共用GLProgramState的方式 直接用: (這樣你就可以控制這個shader某一個值,而不影響其他使用這個shader的對象了)
GLProgram *program = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP_GRAY);
GLProgramState* state = GLProgramState::create(program);
sprite->setGLProgramState(state):
本人沒學過opengel今天ui那邊需要灰度,才開始看的, 寫得不好,大家就將就看吧~
還要說一個地方
std::string GLProgram::logForOpenGLObject(GLuint object, GLInfoFunction infoFunc, GLLogFunction logFunc) const
{
std::string ret;
GLint logLength = 0, charsWritten = 0;
//infoFunc(object, GL_INFO_LOG_LENGTH, &logLength); //編譯錯誤的話,到這里就崩潰了~~ 不知道為什么,
glGetShaderiv(object, GL_INFO_LOG_LENGTH, &logLength); //我直接改成調用opengel函數,
if (logLength < 1)
return "";
char *logBytes = (char*)malloc(logLength);
// logFunc(object, logLength, &charsWritten, logBytes);
glGetShaderInfoLog(object, logLength, &charsWritten, logBytes);
ret = logBytes;
free(logBytes);
return ret;
}
這里是我這篇筆記的地址: http://note.youdao.com/share/?id=f72378178898d34affe13a6dddd75df3&type=note