cocos2dx 원본 분석:shader의 생성 과정
19554 단어 cocos2d-x
GLProgram* GLProgram::createWithByteArrays(const GLchar* vShaderByteArray, const GLchar* fShaderByteArray, const std::string& compileTimeDefines)
{
auto ret = new (std::nothrow) GLProgram();
/* */
if(ret && ret->initWithByteArrays(vShaderByteArray, fShaderByteArray, compileTimeDefines)) {
/* */
ret->link();
/* uniform , uniform*/
ret->updateUniforms();
ret->autorelease();
return ret;
}
CC_SAFE_DELETE(ret);
return nullptr;
}
/정점 착색기 및 픽셀 착색기 컴파일하기/
bool GLProgram::initWithByteArrays(const GLchar* vShaderByteArray, const GLchar* fShaderByteArray, const std::string& compileTimeDefines)
{
/* , */
_program = glCreateProgram();
CHECK_GL_ERROR_DEBUG();
// convert defines here. If we do it in "compileShader" we will do it it twice.
// a cache for the defines could be useful, but seems like overkill at this point
std::string replacedDefines = "";
replaceDefines(compileTimeDefines, replacedDefines);
_vertShader = _fragShader = 0;
/* */
if (vShaderByteArray)
{
if (!compileShader(&_vertShader, GL_VERTEX_SHADER, vShaderByteArray, replacedDefines))
{
CCLOG("cocos2d: ERROR: Failed to compile vertex shader");
return false;
}
}
/* */
// Create and compile fragment shader
if (fShaderByteArray)
{
if (!compileShader(&_fragShader, GL_FRAGMENT_SHADER, fShaderByteArray, replacedDefines))
{
CCLOG("cocos2d: ERROR: Failed to compile fragment shader");
return false;
}
}
/* */
if (_vertShader)
{
glAttachShader(_program, _vertShader);
}
CHECK_GL_ERROR_DEBUG();
if (_fragShader)
{
glAttachShader(_program, _fragShader);
}
_hashForUniforms.clear();
CHECK_GL_ERROR_DEBUG();
return true;
}
정점 착색기와 픽셀 착색기는 모두 이 함수를 사용하여 컴파일을 완성해야 한다
bool GLProgram::compileShader(GLuint* shader, GLenum type, const GLchar* source, const std::string& convertedDefines)
{
GLint status;
if (!source)
{
return false;
}
/* shander , , cocos2dx uniform , shader uniform 。
static const char * COCOS2D_SHADER_UNIFORMS =
"uniform mat4 CC_PMatrix;
"
"uniform mat4 CC_MVMatrix;
"
"uniform mat4 CC_MVPMatrix;
"
"uniform mat3 CC_NormalMatrix;
"
"uniform vec4 CC_Time;
"
"uniform vec4 CC_SinTime;
"
"uniform vec4 CC_CosTime;
"
"uniform vec4 CC_Random01;
"
"uniform sampler2D CC_Texture0;
"
"uniform sampler2D CC_Texture1;
"
"uniform sampler2D CC_Texture2;
"
"uniform sampler2D CC_Texture3;
"
"//CC INCLUDES END
";
*/
const GLchar *sources[] = {
#if CC_TARGET_PLATFORM == CC_PLATFORM_WINRT
(type == GL_VERTEX_SHADER ? "precision mediump float;
precision mediump int;
" : "precision mediump float;
precision mediump int;
"),
#elif (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;
precision highp int;
" : "precision mediump float;
precision mediump int;
"),
#endif
COCOS2D_SHADER_UNIFORMS,
convertedDefines.c_str(),
source};
/* shader */
*shader = glCreateShader(type);
glShaderSource(*shader, sizeof(sources)/sizeof(*sources), sources, nullptr);
glCompileShader(*shader);
/* */
glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
if (! status)
{
/* */
GLsizei length;
glGetShaderiv(*shader, GL_SHADER_SOURCE_LENGTH, &length);
GLchar* src = (GLchar *)malloc(sizeof(GLchar) * length);
glGetShaderSource(*shader, length, nullptr, src);
CCLOG("cocos2d: ERROR: Failed to compile shader:
%s", src);
if (type == GL_VERTEX_SHADER)
{
CCLOG("cocos2d: %s", getVertexShaderLog().c_str());
}
else
{
CCLOG("cocos2d: %s", getFragmentShaderLog().c_str());
}
free(src);
return false;;
}
return (status == GL_TRUE);
}
픽셀 착색기와 정점 착색기를 컴파일하여 착색 프로그램에 연결한 후 링크로 링크 완료
bool GLProgram::link()
{
CCASSERT(_program != 0, "Cannot link invalid program");
GLint status = GL_TRUE;
/* cocos2dx */
bindPredefinedVertexAttribs();
/* */
glLinkProgram(_program);
/* , _vertexAttribs */
parseVertexAttribs();
/* cocos2dx uniform _userUniforms */
parseUniforms();
/* */
clearShader();
#if DEBUG || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
glGetProgramiv(_program, GL_LINK_STATUS, &status);
if (status == GL_FALSE)
{
CCLOG("cocos2d: ERROR: Failed to link program: %i", _program);
GL::deleteProgram(_program);
_program = 0;
}
#endif
return (status == GL_TRUE);
}
코코스2dx의 정점 속성을 고정된 인덱스에 귀속합니다
void GLProgram::bindPredefinedVertexAttribs()
{
/*cocos2dx */
static const struct {
const char *attributeName;
int location;
} attribute_locations[] =
{
{GLProgram::ATTRIBUTE_NAME_POSITION, GLProgram::VERTEX_ATTRIB_POSITION},
{GLProgram::ATTRIBUTE_NAME_COLOR, GLProgram::VERTEX_ATTRIB_COLOR},
{GLProgram::ATTRIBUTE_NAME_TEX_COORD, GLProgram::VERTEX_ATTRIB_TEX_COORD},
{GLProgram::ATTRIBUTE_NAME_TEX_COORD1, GLProgram::VERTEX_ATTRIB_TEX_COORD1},
{GLProgram::ATTRIBUTE_NAME_TEX_COORD2, GLProgram::VERTEX_ATTRIB_TEX_COORD2},
{GLProgram::ATTRIBUTE_NAME_TEX_COORD3, GLProgram::VERTEX_ATTRIB_TEX_COORD3},
{GLProgram::ATTRIBUTE_NAME_NORMAL, GLProgram::VERTEX_ATTRIB_NORMAL},
};
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);
}
}
uniform의 위치를 기록하고 어떤 uniform을 사용했는지 기록합니다
void GLProgram::updateUniforms()
{
/* uniform , uniform , */
_builtInUniforms[UNIFORM_AMBIENT_COLOR] = glGetUniformLocation(_program, UNIFORM_NAME_AMBIENT_COLOR);
_builtInUniforms[UNIFORM_P_MATRIX] = glGetUniformLocation(_program, UNIFORM_NAME_P_MATRIX);
_builtInUniforms[UNIFORM_MV_MATRIX] = glGetUniformLocation(_program, UNIFORM_NAME_MV_MATRIX);
_builtInUniforms[UNIFORM_MVP_MATRIX] = glGetUniformLocation(_program, UNIFORM_NAME_MVP_MATRIX);
_builtInUniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, UNIFORM_NAME_NORMAL_MATRIX);
_builtInUniforms[UNIFORM_TIME] = glGetUniformLocation(_program, UNIFORM_NAME_TIME);
_builtInUniforms[UNIFORM_SIN_TIME] = glGetUniformLocation(_program, UNIFORM_NAME_SIN_TIME);
_builtInUniforms[UNIFORM_COS_TIME] = glGetUniformLocation(_program, UNIFORM_NAME_COS_TIME);
_builtInUniforms[UNIFORM_RANDOM01] = glGetUniformLocation(_program, UNIFORM_NAME_RANDOM01);
_builtInUniforms[UNIFORM_SAMPLER0] = glGetUniformLocation(_program, UNIFORM_NAME_SAMPLER0);
_builtInUniforms[UNIFORM_SAMPLER1] = glGetUniformLocation(_program, UNIFORM_NAME_SAMPLER1);
_builtInUniforms[UNIFORM_SAMPLER2] = glGetUniformLocation(_program, UNIFORM_NAME_SAMPLER2);
_builtInUniforms[UNIFORM_SAMPLER3] = glGetUniformLocation(_program, UNIFORM_NAME_SAMPLER3);
/* uniform, */
_flags.usesP = _builtInUniforms[UNIFORM_P_MATRIX] != -1;
_flags.usesMV = _builtInUniforms[UNIFORM_MV_MATRIX] != -1;
_flags.usesMVP = _builtInUniforms[UNIFORM_MVP_MATRIX] != -1;
_flags.usesNormal = _builtInUniforms[UNIFORM_NORMAL_MATRIX] != -1;
_flags.usesTime = (
_builtInUniforms[UNIFORM_TIME] != -1 ||
_builtInUniforms[UNIFORM_SIN_TIME] != -1 ||
_builtInUniforms[UNIFORM_COS_TIME] != -1
);
_flags.usesRandom = _builtInUniforms[UNIFORM_RANDOM01] != -1;
this->use();
/* */
// Since sample most probably won't change, set it to 0,1,2,3 now.
if(_builtInUniforms[UNIFORM_SAMPLER0] != -1)
setUniformLocationWith1i(_builtInUniforms[UNIFORM_SAMPLER0], 0);
if(_builtInUniforms[UNIFORM_SAMPLER1] != -1)
setUniformLocationWith1i(_builtInUniforms[UNIFORM_SAMPLER1], 1);
if(_builtInUniforms[UNIFORM_SAMPLER2] != -1)
setUniformLocationWith1i(_builtInUniforms[UNIFORM_SAMPLER2], 2);
if(_builtInUniforms[UNIFORM_SAMPLER3] != -1)
setUniformLocationWith1i(_builtInUniforms[UNIFORM_SAMPLER3], 3);
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Cocos Studio v3.x ListView에 PanelNode를 동적으로 추가해보기Cococs Studio에서 ListView를 설정한 BaseNode와 파트 부분이 되는 PasrtNode를 작성. ListView에 PasrtNode를 추가해 가고, 빨리 GridView적인 것을 만드는 비망록. ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.