2012-03-15 10:42:22 +08:00
/****************************************************************************
Copyright 2011 Jeff Lamarche
Copyright 2012 Goffredo Marocchi
Copyright 2012 Ricardo Quesada
2014-01-07 11:25:07 +08:00
Copyright 2012 cocos2d - x . org
2018-01-29 16:25:32 +08:00
Copyright ( c ) 2013 - 2016 Chukong Technologies Inc .
Copyright ( c ) 2017 - 2018 Xiamen Yaji Software Co . , Ltd .
2012-03-15 10:42:22 +08:00
http : //www.cocos2d-x.org
2015-04-20 17:00:40 +08:00
2012-03-15 10:42:22 +08:00
Permission is hereby granted , free of charge , to any person obtaining a copy
of this software and associated documentation files ( the " Software " ) , to deal
in the Software without restriction , including without limitation the rights
to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
copies of the Software , and to permit persons to whom the Software is
furnished to do so , subject to the following conditions :
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software .
THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN false EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-03-12 15:22:03 +08:00
2014-05-09 09:01:48 +08:00
# include "renderer/CCGLProgram.h"
2014-05-10 04:24:56 +08:00
# ifndef WIN32
2014-05-07 08:58:14 +08:00
# include <alloca.h>
2014-05-10 04:24:56 +08:00
# endif
2012-03-12 15:22:03 +08:00
2014-05-17 05:36:00 +08:00
# include "base/CCDirector.h"
2016-06-15 15:01:26 +08:00
# include "base/ccUTF8.h"
2014-05-17 05:36:00 +08:00
# include "platform/CCFileUtils.h"
2015-05-06 04:07:32 +08:00
// helper functions
static void replaceDefines ( const std : : string & compileTimeDefines , std : : string & out )
{
// Replace semicolons with '#define ... \n'
2016-03-07 22:05:20 +08:00
if ( ! compileTimeDefines . empty ( ) )
2015-05-06 04:07:32 +08:00
{
2016-04-07 04:27:59 +08:00
// append ';' if the last char doesn't have one
auto copyDefines = compileTimeDefines ;
if ( copyDefines [ copyDefines . length ( ) - 1 ] ! = ' ; ' )
copyDefines . append ( 1 , ' ; ' ) ;
2016-03-07 22:05:20 +08:00
std : : string currentDefine ;
2016-04-07 04:27:59 +08:00
for ( auto itChar : copyDefines )
2015-05-06 04:07:32 +08:00
{
2016-03-07 22:05:20 +08:00
if ( itChar = = ' ; ' )
{
if ( ! currentDefine . empty ( ) )
{
out . append ( " \n #define " + currentDefine ) ;
currentDefine . clear ( ) ;
}
}
else
{
currentDefine . append ( 1 , itChar ) ;
}
2015-05-06 04:07:32 +08:00
}
out + = " \n " ;
}
}
2014-03-22 20:58:07 +08:00
2012-03-12 15:22:03 +08:00
NS_CC_BEGIN
2016-07-25 17:31:54 +08:00
const char * GLProgram : : SHADER_NAME_ETC1AS_POSITION_TEXTURE_COLOR = " #ShaderETC1ASPositionTextureColor " ;
const char * GLProgram : : SHADER_NAME_ETC1AS_POSITION_TEXTURE_COLOR_NO_MVP = " #ShaderETC1ASPositionTextureColor_noMVP " ;
const char * GLProgram : : SHADER_NAME_ETC1AS_POSITION_TEXTURE_GRAY = " #ShaderETC1ASPositionTextureGray " ;
const char * GLProgram : : SHADER_NAME_ETC1AS_POSITION_TEXTURE_GRAY_NO_MVP = " #ShaderETC1ASPositionTextureGray_noMVP " ;
2012-03-12 15:22:03 +08:00
2013-07-25 17:48:22 +08:00
const char * GLProgram : : SHADER_NAME_POSITION_TEXTURE_COLOR = " ShaderPositionTextureColor " ;
2013-12-06 13:24:59 +08:00
const char * GLProgram : : SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP = " ShaderPositionTextureColor_noMVP " ;
2013-07-25 17:48:22 +08:00
const char * GLProgram : : SHADER_NAME_POSITION_TEXTURE_ALPHA_TEST = " ShaderPositionTextureColorAlphaTest " ;
2014-03-10 15:12:44 +08:00
const char * GLProgram : : SHADER_NAME_POSITION_TEXTURE_ALPHA_TEST_NO_MV = " ShaderPositionTextureColorAlphaTest_NoMV " ;
2013-07-25 17:48:22 +08:00
const char * GLProgram : : SHADER_NAME_POSITION_COLOR = " ShaderPositionColor " ;
2015-01-20 16:50:51 +08:00
const char * GLProgram : : SHADER_NAME_POSITION_COLOR_TEXASPOINTSIZE = " ShaderPositionColorTexAsPointsize " ;
2014-01-07 22:08:00 +08:00
const char * GLProgram : : SHADER_NAME_POSITION_COLOR_NO_MVP = " ShaderPositionColor_noMVP " ;
2015-03-21 14:50:48 +08:00
2013-07-25 17:48:22 +08:00
const char * GLProgram : : SHADER_NAME_POSITION_TEXTURE = " ShaderPositionTexture " ;
const char * GLProgram : : SHADER_NAME_POSITION_TEXTURE_U_COLOR = " ShaderPositionTexture_uColor " ;
const char * GLProgram : : SHADER_NAME_POSITION_TEXTURE_A8_COLOR = " ShaderPositionTextureA8Color " ;
const char * GLProgram : : SHADER_NAME_POSITION_U_COLOR = " ShaderPosition_uColor " ;
const char * GLProgram : : SHADER_NAME_POSITION_LENGTH_TEXTURE_COLOR = " ShaderPositionLengthTextureColor " ;
2015-04-20 17:00:40 +08:00
const char * GLProgram : : SHADER_NAME_POSITION_GRAYSCALE = " ShaderUIGrayScale " ;
2014-03-21 09:47:29 +08:00
const char * GLProgram : : SHADER_NAME_LABEL_DISTANCEFIELD_NORMAL = " ShaderLabelDFNormal " ;
2014-03-20 20:56:10 +08:00
const char * GLProgram : : SHADER_NAME_LABEL_DISTANCEFIELD_GLOW = " ShaderLabelDFGlow " ;
const char * GLProgram : : SHADER_NAME_LABEL_NORMAL = " ShaderLabelNormal " ;
2014-03-05 16:51:16 +08:00
const char * GLProgram : : SHADER_NAME_LABEL_OUTLINE = " ShaderLabelOutline " ;
2013-12-13 12:42:15 +08:00
2014-05-19 05:49:16 +08:00
const char * GLProgram : : SHADER_3D_POSITION = " Shader3DPosition " ;
const char * GLProgram : : SHADER_3D_POSITION_TEXTURE = " Shader3DPositionTexture " ;
2014-06-05 16:36:01 +08:00
const char * GLProgram : : SHADER_3D_SKINPOSITION_TEXTURE = " Shader3DSkinPositionTexture " ;
2014-08-21 11:33:00 +08:00
const char * GLProgram : : SHADER_3D_POSITION_NORMAL = " Shader3DPositionNormal " ;
const char * GLProgram : : SHADER_3D_POSITION_NORMAL_TEXTURE = " Shader3DPositionNormalTexture " ;
const char * GLProgram : : SHADER_3D_SKINPOSITION_NORMAL_TEXTURE = " Shader3DSkinPositionNormalTexture " ;
2015-11-25 10:45:03 +08:00
const char * GLProgram : : SHADER_3D_POSITION_BUMPEDNORMAL_TEXTURE = " Shader3DPositionBumpedNormalTexture " ;
const char * GLProgram : : SHADER_3D_SKINPOSITION_BUMPEDNORMAL_TEXTURE = " Shader3DSkinPositionBumpedNormalTexture " ;
2015-02-11 18:14:22 +08:00
const char * GLProgram : : SHADER_3D_PARTICLE_COLOR = " Shader3DParticleColor " ;
const char * GLProgram : : SHADER_3D_PARTICLE_TEXTURE = " Shader3DParticleTexture " ;
2015-03-26 11:59:26 +08:00
const char * GLProgram : : SHADER_3D_SKYBOX = " Shader3DSkybox " ;
2015-03-30 13:45:50 +08:00
const char * GLProgram : : SHADER_3D_TERRAIN = " Shader3DTerrain " ;
2015-05-07 15:09:06 +08:00
const char * GLProgram : : SHADER_CAMERA_CLEAR = " ShaderCameraClear " ;
2017-05-22 13:42:00 +08:00
const char * GLProgram : : SHADER_LAYER_RADIAL_GRADIENT = " ShaderLayerRadialGradient " ;
2014-05-19 05:49:16 +08:00
2013-12-13 12:42:15 +08:00
2013-07-25 17:48:22 +08:00
// uniform names
2014-08-18 17:10:07 +08:00
const char * GLProgram : : UNIFORM_NAME_AMBIENT_COLOR = " CC_AmbientColor " ;
2013-07-25 17:48:22 +08:00
const char * GLProgram : : UNIFORM_NAME_P_MATRIX = " CC_PMatrix " ;
2016-10-28 09:33:31 +08:00
const char * GLProgram : : UNIFORM_NAME_MULTIVIEW_P_MATRIX = " CC_MultiViewPMatrix " ;
2013-07-25 17:48:22 +08:00
const char * GLProgram : : UNIFORM_NAME_MV_MATRIX = " CC_MVMatrix " ;
const char * GLProgram : : UNIFORM_NAME_MVP_MATRIX = " CC_MVPMatrix " ;
2016-10-28 09:33:31 +08:00
const char * GLProgram : : UNIFORM_NAME_MULTIVIEW_MVP_MATRIX = " CC_MultiViewMVPMatrix " ;
2014-08-15 19:15:14 +08:00
const char * GLProgram : : UNIFORM_NAME_NORMAL_MATRIX = " CC_NormalMatrix " ;
2013-07-25 17:48:22 +08:00
const char * GLProgram : : UNIFORM_NAME_TIME = " CC_Time " ;
const char * GLProgram : : UNIFORM_NAME_SIN_TIME = " CC_SinTime " ;
const char * GLProgram : : UNIFORM_NAME_COS_TIME = " CC_CosTime " ;
const char * GLProgram : : UNIFORM_NAME_RANDOM01 = " CC_Random01 " ;
2014-05-14 09:12:58 +08:00
const char * GLProgram : : UNIFORM_NAME_SAMPLER0 = " CC_Texture0 " ;
const char * GLProgram : : UNIFORM_NAME_SAMPLER1 = " CC_Texture1 " ;
const char * GLProgram : : UNIFORM_NAME_SAMPLER2 = " CC_Texture2 " ;
const char * GLProgram : : UNIFORM_NAME_SAMPLER3 = " CC_Texture3 " ;
2013-07-25 17:48:22 +08:00
const char * GLProgram : : UNIFORM_NAME_ALPHA_TEST_VALUE = " CC_alpha_value " ;
// Attribute names
const char * GLProgram : : ATTRIBUTE_NAME_COLOR = " a_color " ;
const char * GLProgram : : ATTRIBUTE_NAME_POSITION = " a_position " ;
const char * GLProgram : : ATTRIBUTE_NAME_TEX_COORD = " a_texCoord " ;
2014-08-18 18:02:58 +08:00
const char * GLProgram : : ATTRIBUTE_NAME_TEX_COORD1 = " a_texCoord1 " ;
2014-08-21 18:14:24 +08:00
const char * GLProgram : : ATTRIBUTE_NAME_TEX_COORD2 = " a_texCoord2 " ;
const char * GLProgram : : ATTRIBUTE_NAME_TEX_COORD3 = " a_texCoord3 " ;
2014-05-09 03:34:26 +08:00
const char * GLProgram : : ATTRIBUTE_NAME_NORMAL = " a_normal " ;
2014-06-04 18:17:09 +08:00
const char * GLProgram : : ATTRIBUTE_NAME_BLEND_WEIGHT = " a_blendWeight " ;
const char * GLProgram : : ATTRIBUTE_NAME_BLEND_INDEX = " a_blendIndex " ;
2015-11-25 10:45:03 +08:00
const char * GLProgram : : ATTRIBUTE_NAME_TANGENT = " a_tangent " ;
const char * GLProgram : : ATTRIBUTE_NAME_BINORMAL = " a_binormal " ;
2014-03-25 16:54:29 +08:00
2015-05-06 04:07:32 +08:00
static const char * COCOS2D_SHADER_UNIFORMS =
" uniform mat4 CC_PMatrix; \n "
2016-10-28 09:33:31 +08:00
" uniform mat4 CC_MultiViewPMatrix[4]; \n "
2015-05-06 04:07:32 +08:00
" uniform mat4 CC_MVMatrix; \n "
" uniform mat4 CC_MVPMatrix; \n "
2016-10-28 09:33:31 +08:00
" uniform mat4 CC_MultiViewMVPMatrix[4]; \n "
2015-05-06 04:07:32 +08:00
" uniform mat3 CC_NormalMatrix; \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 " ;
static const std : : string EMPTY_DEFINE ;
2014-05-08 05:38:41 +08:00
GLProgram * GLProgram : : createWithByteArrays ( const GLchar * vShaderByteArray , const GLchar * fShaderByteArray )
2015-05-06 04:07:32 +08:00
{
return createWithByteArrays ( vShaderByteArray , fShaderByteArray , EMPTY_DEFINE ) ;
}
GLProgram * GLProgram : : createWithByteArrays ( const GLchar * vShaderByteArray , const GLchar * fShaderByteArray , const std : : string & compileTimeDefines )
2016-10-28 09:33:31 +08:00
{
return createWithByteArrays ( vShaderByteArray , fShaderByteArray , EMPTY_DEFINE , compileTimeDefines ) ;
}
GLProgram * GLProgram : : createWithByteArrays ( const GLchar * vShaderByteArray , const GLchar * fShaderByteArray , const std : : string & compileTimeHeaders , const std : : string & compileTimeDefines )
2014-05-08 05:38:41 +08:00
{
auto ret = new ( std : : nothrow ) GLProgram ( ) ;
2016-10-28 09:33:31 +08:00
if ( ret & & ret - > initWithByteArrays ( vShaderByteArray , fShaderByteArray , compileTimeHeaders , compileTimeDefines ) ) {
2014-05-09 07:04:59 +08:00
ret - > link ( ) ;
ret - > updateUniforms ( ) ;
2014-05-08 05:38:41 +08:00
ret - > autorelease ( ) ;
return ret ;
}
CC_SAFE_DELETE ( ret ) ;
return nullptr ;
}
GLProgram * GLProgram : : createWithFilenames ( const std : : string & vShaderFilename , const std : : string & fShaderFilename )
2015-05-06 04:07:32 +08:00
{
return createWithFilenames ( vShaderFilename , fShaderFilename , EMPTY_DEFINE ) ;
}
GLProgram * GLProgram : : createWithFilenames ( const std : : string & vShaderFilename , const std : : string & fShaderFilename , const std : : string & compileTimeDefines )
2016-10-28 09:33:31 +08:00
{
return createWithFilenames ( vShaderFilename , fShaderFilename , EMPTY_DEFINE , compileTimeDefines ) ;
}
2016-11-16 09:48:37 +08:00
GLProgram * GLProgram : : createWithFilenames ( const std : : string & vShaderFilename , const std : : string & fShaderFilename , const std : : string & /*compileTimeHeaders*/ , const std : : string & compileTimeDefines )
2014-05-08 05:38:41 +08:00
{
auto ret = new ( std : : nothrow ) GLProgram ( ) ;
2015-05-06 04:07:32 +08:00
if ( ret & & ret - > initWithFilenames ( vShaderFilename , fShaderFilename , compileTimeDefines ) ) {
2014-05-09 07:04:59 +08:00
ret - > link ( ) ;
ret - > updateUniforms ( ) ;
2014-05-08 05:38:41 +08:00
ret - > autorelease ( ) ;
return ret ;
}
CC_SAFE_DELETE ( ret ) ;
return nullptr ;
}
2013-06-20 14:13:12 +08:00
GLProgram : : GLProgram ( )
2013-06-15 14:03:30 +08:00
: _program ( 0 )
, _vertShader ( 0 )
, _fragShader ( 0 )
2013-11-01 08:56:15 +08:00
, _flags ( )
2012-03-12 15:22:03 +08:00
{
2014-12-04 18:37:57 +08:00
_director = Director : : getInstance ( ) ;
CCASSERT ( nullptr ! = _director , " Director is null when init a GLProgram " ) ;
2014-05-14 09:12:58 +08:00
memset ( _builtInUniforms , 0 , sizeof ( _builtInUniforms ) ) ;
2012-03-12 15:22:03 +08:00
}
2013-06-20 14:13:12 +08:00
GLProgram : : ~ GLProgram ( )
2012-03-12 15:22:03 +08:00
{
2013-08-22 11:05:06 +08:00
CCLOGINFO ( " %s %d deallocing GLProgram: %p " , __FUNCTION__ , __LINE__ , this ) ;
2012-03-12 15:22:03 +08:00
2015-11-17 13:38:42 +08:00
clearShader ( ) ;
2012-03-12 15:22:03 +08:00
2015-04-20 17:00:40 +08:00
if ( _program )
2012-04-19 14:35:52 +08:00
{
2018-09-11 14:39:30 +08:00
glDeleteProgram ( _program ) ;
2012-04-19 14:35:52 +08:00
}
2012-03-12 15:22:03 +08:00
2018-01-03 17:15:00 +08:00
2017-02-06 15:11:42 +08:00
clearHashUniforms ( ) ;
2012-03-12 15:22:03 +08:00
}
2014-03-05 05:51:43 +08:00
bool GLProgram : : initWithByteArrays ( const GLchar * vShaderByteArray , const GLchar * fShaderByteArray )
2012-03-12 15:22:03 +08:00
{
2015-05-06 04:07:32 +08:00
return initWithByteArrays ( vShaderByteArray , fShaderByteArray , EMPTY_DEFINE ) ;
}
2014-03-22 20:58:07 +08:00
2015-05-06 04:07:32 +08:00
bool GLProgram : : initWithByteArrays ( const GLchar * vShaderByteArray , const GLchar * fShaderByteArray , const std : : string & compileTimeDefines )
2016-10-28 09:33:31 +08:00
{
return initWithByteArrays ( vShaderByteArray , fShaderByteArray , " " , compileTimeDefines ) ;
}
bool GLProgram : : initWithByteArrays ( const GLchar * vShaderByteArray , const GLchar * fShaderByteArray , const std : : string & compileTimeHeaders , const std : : string & compileTimeDefines )
2012-03-12 15:22:03 +08:00
{
2013-06-15 14:03:30 +08:00
_program = glCreateProgram ( ) ;
2012-04-17 17:55:26 +08:00
CHECK_GL_ERROR_DEBUG ( ) ;
2012-03-12 15:22:03 +08:00
2016-03-29 09:52:17 +08:00
// convert defines here. If we do it in "compileShader" we will do it twice.
2015-05-06 04:07:32 +08:00
// a cache for the defines could be useful, but seems like overkill at this point
std : : string replacedDefines = " " ;
replaceDefines ( compileTimeDefines , replacedDefines ) ;
2013-06-15 14:03:30 +08:00
_vertShader = _fragShader = 0 ;
2012-03-12 15:22:03 +08:00
2012-11-09 12:08:18 +08:00
if ( vShaderByteArray )
{
2016-10-28 09:33:31 +08:00
if ( ! compileShader ( & _vertShader , GL_VERTEX_SHADER , vShaderByteArray , compileTimeHeaders , replacedDefines ) )
2012-11-09 12:08:18 +08:00
{
2012-04-19 14:35:52 +08:00
CCLOG ( " cocos2d: ERROR: Failed to compile vertex shader " ) ;
2014-04-28 09:51:10 +08:00
return false ;
2016-10-28 09:33:31 +08:00
}
2012-04-19 14:35:52 +08:00
}
2012-03-12 15:22:03 +08:00
2012-04-19 14:35:52 +08:00
// Create and compile fragment shader
2012-11-09 12:08:18 +08:00
if ( fShaderByteArray )
{
2016-10-28 09:33:31 +08:00
if ( ! compileShader ( & _fragShader , GL_FRAGMENT_SHADER , fShaderByteArray , compileTimeHeaders , replacedDefines ) )
2012-11-09 12:08:18 +08:00
{
2012-04-19 14:35:52 +08:00
CCLOG ( " cocos2d: ERROR: Failed to compile fragment shader " ) ;
2014-04-28 09:51:10 +08:00
return false ;
2012-04-19 14:35:52 +08:00
}
}
2012-03-12 15:22:03 +08:00
2013-06-15 14:03:30 +08:00
if ( _vertShader )
2012-11-09 12:08:18 +08:00
{
2013-06-15 14:03:30 +08:00
glAttachShader ( _program , _vertShader ) ;
2012-04-19 14:35:52 +08:00
}
2012-04-17 17:55:26 +08:00
CHECK_GL_ERROR_DEBUG ( ) ;
2012-03-12 15:22:03 +08:00
2013-06-15 14:03:30 +08:00
if ( _fragShader )
2012-11-09 12:08:18 +08:00
{
2013-06-15 14:03:30 +08:00
glAttachShader ( _program , _fragShader ) ;
2012-04-19 14:35:52 +08:00
}
2015-04-20 17:00:40 +08:00
2017-02-06 15:11:42 +08:00
clearHashUniforms ( ) ;
2015-04-20 17:00:40 +08:00
2012-04-17 17:55:26 +08:00
CHECK_GL_ERROR_DEBUG ( ) ;
2012-03-12 15:22:03 +08:00
2012-04-19 14:35:52 +08:00
return true ;
2012-03-15 10:42:22 +08:00
}
2015-05-06 04:07:32 +08:00
bool GLProgram : : initWithFilenames ( const std : : string & vShaderFilename , const std : : string & fShaderFilename )
2014-03-22 20:58:07 +08:00
{
2015-05-06 04:07:32 +08:00
return initWithFilenames ( vShaderFilename , fShaderFilename , EMPTY_DEFINE ) ;
2014-03-22 20:58:07 +08:00
}
2015-05-06 04:07:32 +08:00
bool GLProgram : : initWithFilenames ( const std : : string & vShaderFilename , const std : : string & fShaderFilename , const std : : string & compileTimeDefines )
2016-10-28 09:33:31 +08:00
{
return initWithFilenames ( vShaderFilename , fShaderFilename , EMPTY_DEFINE , compileTimeDefines ) ;
}
bool GLProgram : : initWithFilenames ( const std : : string & vShaderFilename , const std : : string & fShaderFilename , const std : : string & compileTimeHeaders , const std : : string & compileTimeDefines )
2012-03-15 10:42:22 +08:00
{
2014-03-05 05:51:43 +08:00
auto fileUtils = FileUtils : : getInstance ( ) ;
std : : string vertexSource = fileUtils - > getStringFromFile ( FileUtils : : getInstance ( ) - > fullPathForFilename ( vShaderFilename ) ) ;
std : : string fragmentSource = fileUtils - > getStringFromFile ( FileUtils : : getInstance ( ) - > fullPathForFilename ( fShaderFilename ) ) ;
2012-04-17 17:55:26 +08:00
2016-10-28 09:33:31 +08:00
return initWithByteArrays ( vertexSource . c_str ( ) , fragmentSource . c_str ( ) , compileTimeHeaders , compileTimeDefines ) ;
2012-03-12 15:22:03 +08:00
}
2014-05-09 03:34:26 +08:00
void GLProgram : : bindPredefinedVertexAttribs ( )
{
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 } ,
2014-08-18 18:02:58 +08:00
{ GLProgram : : ATTRIBUTE_NAME_TEX_COORD1 , GLProgram : : VERTEX_ATTRIB_TEX_COORD1 } ,
2014-08-21 18:14:24 +08:00
{ GLProgram : : ATTRIBUTE_NAME_TEX_COORD2 , GLProgram : : VERTEX_ATTRIB_TEX_COORD2 } ,
{ GLProgram : : ATTRIBUTE_NAME_TEX_COORD3 , GLProgram : : VERTEX_ATTRIB_TEX_COORD3 } ,
2014-05-09 03:34:26 +08:00
{ 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 ) ;
}
}
2014-05-07 08:58:14 +08:00
void GLProgram : : parseVertexAttribs ( )
2014-05-07 02:03:24 +08:00
{
2015-06-16 14:04:50 +08:00
//_vertexAttribs.clear();
2014-05-07 02:03:24 +08:00
2014-08-15 19:15:14 +08:00
// Query and store vertex attribute meta-data from the program.
GLint activeAttributes ;
GLint length ;
glGetProgramiv ( _program , GL_ACTIVE_ATTRIBUTES , & activeAttributes ) ;
if ( activeAttributes > 0 )
{
2014-05-07 08:58:14 +08:00
VertexAttrib attribute ;
2014-08-15 19:15:14 +08:00
glGetProgramiv ( _program , GL_ACTIVE_ATTRIBUTE_MAX_LENGTH , & length ) ;
if ( length > 0 )
{
GLchar * attribName = ( GLchar * ) alloca ( length + 1 ) ;
2014-05-07 08:58:14 +08:00
2014-08-15 19:15:14 +08:00
for ( int i = 0 ; i < activeAttributes ; + + i )
{
// Query attribute info.
glGetActiveAttrib ( _program , i , length , nullptr , & attribute . size , & attribute . type , attribName ) ;
attribName [ length ] = ' \0 ' ;
2014-05-09 05:01:03 +08:00
attribute . name = std : : string ( attribName ) ;
2014-05-07 08:58:14 +08:00
2014-08-15 19:15:14 +08:00
// Query the pre-assigned attribute location
attribute . index = glGetAttribLocation ( _program , attribName ) ;
2014-05-14 09:12:58 +08:00
_vertexAttribs [ attribute . name ] = attribute ;
2014-08-15 19:15:14 +08:00
}
}
}
2014-11-15 12:15:56 +08:00
else
{
2014-11-20 11:41:16 +08:00
GLchar ErrorLog [ 1024 ] ;
2016-05-25 02:09:11 +08:00
glGetProgramInfoLog ( _program , sizeof ( ErrorLog ) , nullptr , ErrorLog ) ;
2014-11-20 11:41:16 +08:00
CCLOG ( " Error linking shader program: '%s' \n " , ErrorLog ) ;
2014-11-15 12:15:56 +08:00
}
2014-05-07 08:58:14 +08:00
}
void GLProgram : : parseUniforms ( )
{
2015-06-16 14:04:50 +08:00
//_userUniforms.clear();
2014-05-07 02:19:51 +08:00
2014-08-15 19:15:14 +08:00
// Query and store uniforms from the program.
GLint activeUniforms ;
glGetProgramiv ( _program , GL_ACTIVE_UNIFORMS , & activeUniforms ) ;
if ( activeUniforms > 0 )
{
2014-05-07 08:58:14 +08:00
GLint length ;
2014-08-15 19:15:14 +08:00
glGetProgramiv ( _program , GL_ACTIVE_UNIFORM_MAX_LENGTH , & length ) ;
if ( length > 0 )
{
2014-05-07 08:58:14 +08:00
Uniform uniform ;
2014-08-15 19:15:14 +08:00
GLchar * uniformName = ( GLchar * ) alloca ( length + 1 ) ;
2014-05-07 08:58:14 +08:00
2014-08-15 19:15:14 +08:00
for ( int i = 0 ; i < activeUniforms ; + + i )
{
// Query uniform info.
glGetActiveUniform ( _program , i , length , nullptr , & uniform . size , & uniform . type , uniformName ) ;
uniformName [ length ] = ' \0 ' ;
2014-05-08 11:20:19 +08:00
2014-05-13 14:51:37 +08:00
// Only add uniforms that are not built-in.
2014-05-08 11:20:19 +08:00
// The ones that start with 'CC_' are built-ins
if ( strncmp ( " CC_ " , uniformName , 3 ) ! = 0 ) {
// remove possible array '[]' from uniform name
2014-10-13 15:17:22 +08:00
if ( length > 3 )
2014-05-08 11:20:19 +08:00
{
char * c = strrchr ( uniformName , ' [ ' ) ;
if ( c )
{
* c = ' \0 ' ;
}
}
2014-05-08 11:38:15 +08:00
uniform . name = std : : string ( uniformName ) ;
uniform . location = glGetUniformLocation ( _program , uniformName ) ;
2015-04-20 17:00:40 +08:00
GLenum __gl_error_code = glGetError ( ) ;
if ( __gl_error_code ! = GL_NO_ERROR )
{
2016-03-07 22:05:20 +08:00
CCLOG ( " error: 0x%x uniformName: %s " , ( int ) __gl_error_code , uniformName ) ;
2015-04-20 17:00:40 +08:00
}
2014-06-10 19:53:06 +08:00
assert ( __gl_error_code = = GL_NO_ERROR ) ;
2015-04-20 17:00:40 +08:00
2014-05-14 09:12:58 +08:00
_userUniforms [ uniform . name ] = uniform ;
2014-05-08 11:20:19 +08:00
}
2014-08-15 19:15:14 +08:00
}
}
}
2014-11-15 12:15:56 +08:00
else
{
2014-11-20 11:41:16 +08:00
GLchar ErrorLog [ 1024 ] ;
2016-05-25 02:09:11 +08:00
glGetProgramInfoLog ( _program , sizeof ( ErrorLog ) , nullptr , ErrorLog ) ;
2014-11-20 11:41:16 +08:00
CCLOG ( " Error linking shader program: '%s' \n " , ErrorLog ) ;
2014-11-15 12:15:56 +08:00
}
2014-05-07 02:03:24 +08:00
}
2014-05-08 01:44:45 +08:00
Uniform * GLProgram : : getUniform ( const std : : string & name )
2014-05-07 02:03:24 +08:00
{
2014-05-14 09:12:58 +08:00
const auto itr = _userUniforms . find ( name ) ;
if ( itr ! = _userUniforms . end ( ) )
2014-05-08 01:44:45 +08:00
return & itr - > second ;
2014-05-07 08:58:14 +08:00
return nullptr ;
2014-05-07 02:03:24 +08:00
}
2014-05-07 08:58:14 +08:00
VertexAttrib * GLProgram : : getVertexAttrib ( const std : : string & name )
2014-05-07 02:19:51 +08:00
{
2014-05-14 09:12:58 +08:00
const auto itr = _vertexAttribs . find ( name ) ;
if ( itr ! = _vertexAttribs . end ( ) )
2014-05-07 08:58:14 +08:00
return & itr - > second ;
return nullptr ;
2014-05-07 02:19:51 +08:00
}
2014-05-07 02:03:24 +08:00
2013-12-13 06:38:12 +08:00
std : : string GLProgram : : getDescription ( ) const
2012-03-12 15:22:03 +08:00
{
2013-12-25 11:00:27 +08:00
return StringUtils : : format ( " <GLProgram = "
2013-04-19 17:56:27 +08:00
CC_FORMAT_PRINTF_SIZE_T
" | Program = %i, VertexShader = %i, FragmentShader = %i> " ,
2013-12-25 11:00:27 +08:00
( size_t ) this , _program , _vertShader , _fragShader ) ;
2012-03-12 15:22:03 +08:00
}
2013-06-20 14:13:12 +08:00
bool GLProgram : : compileShader ( GLuint * shader , GLenum type , const GLchar * source )
2015-05-06 04:07:32 +08:00
{
return compileShader ( shader , type , source , " " ) ;
}
bool GLProgram : : compileShader ( GLuint * shader , GLenum type , const GLchar * source , const std : : string & convertedDefines )
2016-10-28 09:33:31 +08:00
{
return compileShader ( shader , type , source , " " , convertedDefines ) ;
}
bool GLProgram : : compileShader ( GLuint * shader , GLenum type , const GLchar * source , const std : : string & compileTimeHeaders , const std : : string & convertedDefines )
2012-03-12 15:22:03 +08:00
{
GLint status ;
2015-04-20 17:00:40 +08:00
2012-03-12 15:22:03 +08:00
if ( ! source )
2012-11-09 12:08:18 +08:00
{
2012-03-12 15:22:03 +08:00
return false ;
2012-11-09 12:08:18 +08:00
}
2015-04-20 17:00:40 +08:00
2016-10-28 09:33:31 +08:00
std : : string headersDef ;
if ( compileTimeHeaders . empty ( ) ) {
2014-10-23 22:13:38 +08:00
# if CC_TARGET_PLATFORM == CC_PLATFORM_WINRT
2016-10-28 09:33:31 +08:00
headersDef = ( type = = GL_VERTEX_SHADER ? " precision mediump float; \n precision mediump int; \n " : " precision mediump float; \n precision mediump int; \n " ) ;
2018-01-03 17:15:00 +08:00
// Bugfix to make shader variables types constant to be understood by the current Android Virtual Devices or Emulators. This will also eliminate the 0x501 and 0x502 OpenGL Errors during emulation.
# elif CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
headersDef = " #version 100 \n precision mediump float; \n precision mediump int; \n " ;
2014-10-23 22:13:38 +08:00
# elif (CC_TARGET_PLATFORM != CC_PLATFORM_WIN32 && CC_TARGET_PLATFORM != CC_PLATFORM_LINUX && CC_TARGET_PLATFORM != CC_PLATFORM_MAC)
2016-10-28 09:33:31 +08:00
headersDef = ( type = = GL_VERTEX_SHADER ? " precision highp float; \n precision highp int; \n " : " precision mediump float; \n precision mediump int; \n " ) ;
2012-11-09 12:08:18 +08:00
# endif
2016-10-28 09:33:31 +08:00
} else {
headersDef = compileTimeHeaders ;
}
const GLchar * sources [ ] = {
headersDef . c_str ( ) ,
2015-05-06 04:07:32 +08:00
COCOS2D_SHADER_UNIFORMS ,
convertedDefines . c_str ( ) ,
source } ;
2012-03-12 15:22:03 +08:00
* shader = glCreateShader ( type ) ;
2013-12-18 17:47:20 +08:00
glShaderSource ( * shader , sizeof ( sources ) / sizeof ( * sources ) , sources , nullptr ) ;
2012-03-12 15:22:03 +08:00
glCompileShader ( * shader ) ;
glGetShaderiv ( * shader , GL_COMPILE_STATUS , & status ) ;
2012-11-09 12:08:18 +08:00
if ( ! status )
{
GLsizei length ;
2014-04-28 09:51:10 +08:00
glGetShaderiv ( * shader , GL_SHADER_SOURCE_LENGTH , & length ) ;
GLchar * src = ( GLchar * ) malloc ( sizeof ( GLchar ) * length ) ;
2015-04-20 17:00:40 +08:00
2014-04-28 09:51:10 +08:00
glGetShaderSource ( * shader , length , nullptr , src ) ;
CCLOG ( " cocos2d: ERROR: Failed to compile shader: \n %s " , src ) ;
2015-04-20 17:00:40 +08:00
2012-11-09 12:08:18 +08:00
if ( type = = GL_VERTEX_SHADER )
{
2013-12-11 22:35:37 +08:00
CCLOG ( " cocos2d: %s " , getVertexShaderLog ( ) . c_str ( ) ) ;
2012-11-09 12:08:18 +08:00
}
2012-04-19 14:35:52 +08:00
else
2012-11-09 12:08:18 +08:00
{
2013-12-11 22:35:37 +08:00
CCLOG ( " cocos2d: %s " , getFragmentShaderLog ( ) . c_str ( ) ) ;
2012-11-09 12:08:18 +08:00
}
2012-11-16 17:08:34 +08:00
free ( src ) ;
2012-03-12 15:22:03 +08:00
2016-03-07 22:05:20 +08:00
return false ;
2012-04-19 14:35:52 +08:00
}
2016-03-07 22:05:20 +08:00
2012-11-13 11:06:32 +08:00
return ( status = = GL_TRUE ) ;
2012-03-12 15:22:03 +08:00
}
2014-05-07 08:58:14 +08:00
GLint GLProgram : : getAttribLocation ( const std : : string & attributeName ) const
2014-03-05 05:51:43 +08:00
{
2014-05-07 08:58:14 +08:00
return glGetAttribLocation ( _program , attributeName . c_str ( ) ) ;
2014-03-05 05:51:43 +08:00
}
2014-05-07 08:58:14 +08:00
GLint GLProgram : : getUniformLocation ( const std : : string & attributeName ) const
2014-03-05 05:51:43 +08:00
{
2014-05-07 08:58:14 +08:00
return glGetUniformLocation ( _program , attributeName . c_str ( ) ) ;
2014-03-05 05:51:43 +08:00
}
2014-05-07 08:58:14 +08:00
void GLProgram : : bindAttribLocation ( const std : : string & attributeName , GLuint index ) const
2012-03-12 15:22:03 +08:00
{
2014-05-07 08:58:14 +08:00
glBindAttribLocation ( _program , index , attributeName . c_str ( ) ) ;
2012-03-12 15:22:03 +08:00
}
2013-06-20 14:13:12 +08:00
void GLProgram : : updateUniforms ( )
2012-03-12 15:22:03 +08:00
{
2014-08-18 17:10:07 +08:00
_builtInUniforms [ UNIFORM_AMBIENT_COLOR ] = glGetUniformLocation ( _program , UNIFORM_NAME_AMBIENT_COLOR ) ;
2014-05-14 09:12:58 +08:00
_builtInUniforms [ UNIFORM_P_MATRIX ] = glGetUniformLocation ( _program , UNIFORM_NAME_P_MATRIX ) ;
2016-10-28 09:33:31 +08:00
_builtInUniforms [ UNIFORM_MULTIVIEW_P_MATRIX ] = glGetUniformLocation ( _program , UNIFORM_NAME_MULTIVIEW_P_MATRIX ) ;
2014-05-14 09:12:58 +08:00
_builtInUniforms [ UNIFORM_MV_MATRIX ] = glGetUniformLocation ( _program , UNIFORM_NAME_MV_MATRIX ) ;
_builtInUniforms [ UNIFORM_MVP_MATRIX ] = glGetUniformLocation ( _program , UNIFORM_NAME_MVP_MATRIX ) ;
2016-10-28 09:33:31 +08:00
_builtInUniforms [ UNIFORM_MULTIVIEW_MVP_MATRIX ] = glGetUniformLocation ( _program , UNIFORM_NAME_MULTIVIEW_MVP_MATRIX ) ;
2014-08-15 19:15:14 +08:00
_builtInUniforms [ UNIFORM_NORMAL_MATRIX ] = glGetUniformLocation ( _program , UNIFORM_NAME_NORMAL_MATRIX ) ;
2015-04-20 17:00:40 +08:00
2014-05-14 09:12:58 +08:00
_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 ) ;
2013-11-01 08:56:15 +08:00
2014-05-14 09:12:58 +08:00
_builtInUniforms [ UNIFORM_RANDOM01 ] = glGetUniformLocation ( _program , UNIFORM_NAME_RANDOM01 ) ;
2012-03-12 15:22:03 +08:00
2014-05-14 09:12:58 +08:00
_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 ) ;
2012-03-12 15:22:03 +08:00
2014-05-14 09:12:58 +08:00
_flags . usesP = _builtInUniforms [ UNIFORM_P_MATRIX ] ! = - 1 ;
2016-10-28 09:33:31 +08:00
_flags . usesMultiViewP = _builtInUniforms [ UNIFORM_MULTIVIEW_P_MATRIX ] ! = - 1 ;
2014-05-14 09:12:58 +08:00
_flags . usesMV = _builtInUniforms [ UNIFORM_MV_MATRIX ] ! = - 1 ;
_flags . usesMVP = _builtInUniforms [ UNIFORM_MVP_MATRIX ] ! = - 1 ;
2016-10-28 09:33:31 +08:00
_flags . usesMultiViewMVP = _builtInUniforms [ UNIFORM_MULTIVIEW_MVP_MATRIX ] ! = - 1 ;
2014-08-15 19:15:14 +08:00
_flags . usesNormal = _builtInUniforms [ UNIFORM_NORMAL_MATRIX ] ! = - 1 ;
2014-04-28 09:51:10 +08:00
_flags . usesTime = (
2014-05-14 09:12:58 +08:00
_builtInUniforms [ UNIFORM_TIME ] ! = - 1 | |
_builtInUniforms [ UNIFORM_SIN_TIME ] ! = - 1 | |
_builtInUniforms [ UNIFORM_COS_TIME ] ! = - 1
2013-11-01 08:56:15 +08:00
) ;
2014-05-14 09:12:58 +08:00
_flags . usesRandom = _builtInUniforms [ UNIFORM_RANDOM01 ] ! = - 1 ;
2013-11-01 08:56:15 +08:00
2012-04-19 14:35:52 +08:00
this - > use ( ) ;
2015-04-20 17:00:40 +08:00
2014-05-14 09:12:58 +08:00
// 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 ) ;
2017-02-08 09:44:06 +08:00
// clear any glErrors created by any not found uniforms
glGetError ( ) ;
2012-03-12 15:22:03 +08:00
}
2013-06-20 14:13:12 +08:00
bool GLProgram : : link ( )
2012-03-12 15:22:03 +08:00
{
2013-07-20 13:01:27 +08:00
CCASSERT ( _program ! = 0 , " Cannot link invalid program " ) ;
2014-03-22 20:58:07 +08:00
2012-11-09 12:08:18 +08:00
GLint status = GL_TRUE ;
2012-03-12 15:22:03 +08:00
2014-05-09 03:34:26 +08:00
bindPredefinedVertexAttribs ( ) ;
glLinkProgram ( _program ) ;
2014-05-08 03:41:04 +08:00
2016-07-27 23:48:10 +08:00
// Calling glGetProgramiv(...GL_LINK_STATUS...) will force linking of the program at this moment.
// Otherwise, they might be linked when they are used for the first time. (I guess this depends on the driver implementation)
// So it might slow down the "booting" process on certain devices. But, on the other hand it is important to know if the shader
2016-09-06 10:14:14 +08:00
// linked successfully. Some shaders might be downloaded in runtime so, release version should have this check.
2016-07-27 23:48:10 +08:00
// For more info, see Github issue #16231
2013-06-15 14:03:30 +08:00
glGetProgramiv ( _program , GL_LINK_STATUS , & status ) ;
2015-04-20 17:00:40 +08:00
2012-11-09 12:08:18 +08:00
if ( status = = GL_FALSE )
{
2013-06-15 14:03:30 +08:00
CCLOG ( " cocos2d: ERROR: Failed to link program: %i " , _program ) ;
2018-09-11 14:39:30 +08:00
glDeleteProgram ( _program ) ;
2013-06-15 14:03:30 +08:00
_program = 0 ;
2012-11-09 12:08:18 +08:00
}
2016-07-27 20:31:32 +08:00
else
{
parseVertexAttribs ( ) ;
parseUniforms ( ) ;
clearShader ( ) ;
}
2014-03-22 20:58:07 +08:00
2012-11-09 12:08:18 +08:00
return ( status = = GL_TRUE ) ;
2012-03-12 15:22:03 +08:00
}
2013-06-20 14:13:12 +08:00
void GLProgram : : use ( )
2012-03-12 15:22:03 +08:00
{
2018-09-11 14:39:30 +08:00
glUseProgram ( _program ) ;
2012-03-12 15:22:03 +08:00
}
2015-01-04 21:51:22 +08:00
static std : : string logForOpenGLShader ( GLuint shader )
2012-03-12 15:22:03 +08:00
{
1. We should define `std::string ret` in where we really need it. According to my test on android platform the function returns at `return "";`, which makes the `ret` unnecessary.
2. `charsWritten` is not used, we should either delete it or use it. Because we don't check the bytes written, I think we can just delete it.
3. We don't need (logLength+1) space for `logBytes`, because `logBytes` returned by calling glGetShaderInfoLog(shader, logLength, nullptr, logBytes) takes `logLength` bytes at most, including the ending null character, i.e. `(strlen(logBytes) + 1 == logLength)` always yield true. According to the offical opengles sdk docs: https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGetShaderInfoLog.xml.
and
https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGetShaderiv.xml
4. We don't need `logBytes[logLength] = '\0';`, because `logBytes` returned is already null-terminated.
2016-01-25 12:22:30 +08:00
GLint logLength = 0 ;
2012-03-12 15:22:03 +08:00
2015-01-04 21:51:22 +08:00
glGetShaderiv ( shader , GL_INFO_LOG_LENGTH , & logLength ) ;
2012-03-12 15:22:03 +08:00
if ( logLength < 1 )
2013-12-11 22:35:37 +08:00
return " " ;
2012-03-12 15:22:03 +08:00
1. We should define `std::string ret` in where we really need it. According to my test on android platform the function returns at `return "";`, which makes the `ret` unnecessary.
2. `charsWritten` is not used, we should either delete it or use it. Because we don't check the bytes written, I think we can just delete it.
3. We don't need (logLength+1) space for `logBytes`, because `logBytes` returned by calling glGetShaderInfoLog(shader, logLength, nullptr, logBytes) takes `logLength` bytes at most, including the ending null character, i.e. `(strlen(logBytes) + 1 == logLength)` always yield true. According to the offical opengles sdk docs: https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGetShaderInfoLog.xml.
and
https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGetShaderiv.xml
4. We don't need `logBytes[logLength] = '\0';`, because `logBytes` returned is already null-terminated.
2016-01-25 12:22:30 +08:00
char * logBytes = ( char * ) malloc ( sizeof ( char ) * logLength ) ;
glGetShaderInfoLog ( shader , logLength , nullptr , logBytes ) ;
std : : string ret ( logBytes ) ;
2015-01-04 21:51:22 +08:00
free ( logBytes ) ;
return ret ;
}
static std : : string logForOpenGLProgram ( GLuint program )
{
1. We should define `std::string ret` in where we really need it. According to my test on android platform the function returns at `return "";`, which makes the `ret` unnecessary.
2. `charsWritten` is not used, we should either delete it or use it. Because we don't check the bytes written, I think we can just delete it.
3. We don't need (logLength+1) space for `logBytes`, because `logBytes` returned by calling glGetShaderInfoLog(shader, logLength, nullptr, logBytes) takes `logLength` bytes at most, including the ending null character, i.e. `(strlen(logBytes) + 1 == logLength)` always yield true. According to the offical opengles sdk docs: https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGetShaderInfoLog.xml.
and
https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGetShaderiv.xml
4. We don't need `logBytes[logLength] = '\0';`, because `logBytes` returned is already null-terminated.
2016-01-25 12:22:30 +08:00
GLint logLength = 0 ;
2015-01-04 21:51:22 +08:00
glGetProgramiv ( program , GL_INFO_LOG_LENGTH , & logLength ) ;
if ( logLength < 1 )
return " " ;
2012-03-12 15:22:03 +08:00
1. We should define `std::string ret` in where we really need it. According to my test on android platform the function returns at `return "";`, which makes the `ret` unnecessary.
2. `charsWritten` is not used, we should either delete it or use it. Because we don't check the bytes written, I think we can just delete it.
3. We don't need (logLength+1) space for `logBytes`, because `logBytes` returned by calling glGetShaderInfoLog(shader, logLength, nullptr, logBytes) takes `logLength` bytes at most, including the ending null character, i.e. `(strlen(logBytes) + 1 == logLength)` always yield true. According to the offical opengles sdk docs: https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGetShaderInfoLog.xml.
and
https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGetShaderiv.xml
4. We don't need `logBytes[logLength] = '\0';`, because `logBytes` returned is already null-terminated.
2016-01-25 12:22:30 +08:00
char * logBytes = ( char * ) malloc ( sizeof ( char ) * logLength ) ;
glGetProgramInfoLog ( program , logLength , nullptr , logBytes ) ;
std : : string ret ( logBytes ) ;
2012-03-12 15:22:03 +08:00
free ( logBytes ) ;
2013-12-11 22:35:37 +08:00
return ret ;
2012-03-12 15:22:03 +08:00
}
2013-12-11 22:35:37 +08:00
std : : string GLProgram : : getVertexShaderLog ( ) const
2012-03-12 15:22:03 +08:00
{
2015-01-04 21:51:22 +08:00
return cocos2d : : logForOpenGLShader ( _vertShader ) ;
2012-03-12 15:22:03 +08:00
}
2013-12-11 22:35:37 +08:00
std : : string GLProgram : : getFragmentShaderLog ( ) const
2012-03-12 15:22:03 +08:00
{
2015-01-04 21:51:22 +08:00
return cocos2d : : logForOpenGLShader ( _fragShader ) ;
2012-03-12 15:22:03 +08:00
}
2013-12-11 22:35:37 +08:00
std : : string GLProgram : : getProgramLog ( ) const
2012-03-12 15:22:03 +08:00
{
2015-01-04 21:51:22 +08:00
return logForOpenGLProgram ( _program ) ;
2012-03-12 15:22:03 +08:00
}
2012-04-17 17:55:26 +08:00
// Uniform cache
2013-12-07 09:42:16 +08:00
bool GLProgram : : updateUniformLocation ( GLint location , const GLvoid * data , unsigned int bytes )
2012-04-17 17:55:26 +08:00
{
2012-11-09 12:08:18 +08:00
if ( location < 0 )
{
return false ;
}
2014-03-06 10:50:09 +08:00
2012-04-19 14:35:52 +08:00
bool updated = true ;
2015-04-20 17:00:40 +08:00
2014-10-21 17:29:24 +08:00
auto element = _hashForUniforms . find ( location ) ;
if ( element = = _hashForUniforms . end ( ) )
2012-11-09 12:08:18 +08:00
{
2014-10-21 17:29:24 +08:00
GLvoid * value = malloc ( bytes ) ;
memcpy ( value , data , bytes ) ;
2016-11-08 11:50:00 +08:00
_hashForUniforms . emplace ( location , std : : make_pair ( value , bytes ) ) ;
2012-04-19 14:35:52 +08:00
}
else
{
2016-07-13 02:10:16 +08:00
if ( element - > second . second < bytes )
2012-11-09 12:08:18 +08:00
{
2016-07-13 02:10:16 +08:00
GLvoid * value = realloc ( element - > second . first , bytes ) ;
memcpy ( value , data , bytes ) ;
_hashForUniforms [ location ] = std : : make_pair ( value , bytes ) ;
2012-11-09 12:08:18 +08:00
}
2012-04-19 14:35:52 +08:00
else
2012-11-09 12:08:18 +08:00
{
2016-07-13 02:10:16 +08:00
if ( memcmp ( element - > second . first , data , bytes ) = = 0 )
2015-01-27 16:31:15 +08:00
{
2016-07-13 02:10:16 +08:00
updated = false ;
2015-01-27 16:31:15 +08:00
}
else
2015-01-26 18:40:00 +08:00
memcpy ( element - > second . first , data , bytes ) ;
2012-11-09 12:08:18 +08:00
}
2012-04-19 14:35:52 +08:00
}
2012-04-17 17:55:26 +08:00
2012-04-19 14:35:52 +08:00
return updated ;
2012-04-17 17:55:26 +08:00
}
2013-07-07 13:01:21 +08:00
GLint GLProgram : : getUniformLocationForName ( const char * name ) const
2013-02-27 09:38:30 +08:00
{
2013-12-18 17:47:20 +08:00
CCASSERT ( name ! = nullptr , " Invalid uniform name " ) ;
2013-07-20 13:01:27 +08:00
CCASSERT ( _program ! = 0 , " Invalid operation. Cannot get uniform location when program is not initialized " ) ;
2015-04-20 17:00:40 +08:00
2013-06-15 14:03:30 +08:00
return glGetUniformLocation ( _program , name ) ;
2013-02-27 09:38:30 +08:00
}
2013-06-20 14:13:12 +08:00
void GLProgram : : setUniformLocationWith1i ( GLint location , GLint i1 )
2012-04-17 17:55:26 +08:00
{
2014-05-13 14:51:37 +08:00
bool updated = updateUniformLocation ( location , & i1 , sizeof ( i1 ) * 1 ) ;
2015-04-20 17:00:40 +08:00
2015-05-06 04:07:32 +08:00
if ( updated )
2012-04-19 14:35:52 +08:00
{
glUniform1i ( ( GLint ) location , i1 ) ;
}
2012-04-17 17:55:26 +08:00
}
2013-06-20 14:13:12 +08:00
void GLProgram : : setUniformLocationWith2i ( GLint location , GLint i1 , GLint i2 )
2013-03-27 02:20:38 +08:00
{
GLint ints [ 2 ] = { i1 , i2 } ;
2014-05-13 14:51:37 +08:00
bool updated = updateUniformLocation ( location , ints , sizeof ( ints ) ) ;
2015-04-20 17:00:40 +08:00
2015-05-06 04:07:32 +08:00
if ( updated )
2013-03-27 02:20:38 +08:00
{
glUniform2i ( ( GLint ) location , i1 , i2 ) ;
}
}
2013-06-20 14:13:12 +08:00
void GLProgram : : setUniformLocationWith3i ( GLint location , GLint i1 , GLint i2 , GLint i3 )
2013-03-27 02:20:38 +08:00
{
GLint ints [ 3 ] = { i1 , i2 , i3 } ;
2014-05-13 14:51:37 +08:00
bool updated = updateUniformLocation ( location , ints , sizeof ( ints ) ) ;
2015-04-20 17:00:40 +08:00
2015-05-06 04:07:32 +08:00
if ( updated )
2013-03-27 02:20:38 +08:00
{
glUniform3i ( ( GLint ) location , i1 , i2 , i3 ) ;
}
}
2013-06-20 14:13:12 +08:00
void GLProgram : : setUniformLocationWith4i ( GLint location , GLint i1 , GLint i2 , GLint i3 , GLint i4 )
2013-03-27 02:20:38 +08:00
{
GLint ints [ 4 ] = { i1 , i2 , i3 , i4 } ;
2014-05-13 14:51:37 +08:00
bool updated = updateUniformLocation ( location , ints , sizeof ( ints ) ) ;
2015-04-20 17:00:40 +08:00
2015-05-06 04:07:32 +08:00
if ( updated )
2013-03-27 02:20:38 +08:00
{
glUniform4i ( ( GLint ) location , i1 , i2 , i3 , i4 ) ;
}
}
2013-06-20 14:13:12 +08:00
void GLProgram : : setUniformLocationWith2iv ( GLint location , GLint * ints , unsigned int numberOfArrays )
2013-03-27 02:20:38 +08:00
{
2014-05-13 14:51:37 +08:00
bool updated = updateUniformLocation ( location , ints , sizeof ( int ) * 2 * numberOfArrays ) ;
2015-04-20 17:00:40 +08:00
2015-05-06 04:07:32 +08:00
if ( updated )
2013-03-27 02:20:38 +08:00
{
glUniform2iv ( ( GLint ) location , ( GLsizei ) numberOfArrays , ints ) ;
}
}
2013-06-20 14:13:12 +08:00
void GLProgram : : setUniformLocationWith3iv ( GLint location , GLint * ints , unsigned int numberOfArrays )
2013-03-27 02:20:38 +08:00
{
2014-05-13 14:51:37 +08:00
bool updated = updateUniformLocation ( location , ints , sizeof ( int ) * 3 * numberOfArrays ) ;
2015-04-20 17:00:40 +08:00
2015-05-06 04:07:32 +08:00
if ( updated )
2013-03-27 02:20:38 +08:00
{
glUniform3iv ( ( GLint ) location , ( GLsizei ) numberOfArrays , ints ) ;
}
}
2013-06-20 14:13:12 +08:00
void GLProgram : : setUniformLocationWith4iv ( GLint location , GLint * ints , unsigned int numberOfArrays )
2013-03-27 02:20:38 +08:00
{
2014-05-13 14:51:37 +08:00
bool updated = updateUniformLocation ( location , ints , sizeof ( int ) * 4 * numberOfArrays ) ;
2015-04-20 17:00:40 +08:00
2015-05-06 04:07:32 +08:00
if ( updated )
2013-03-27 02:20:38 +08:00
{
glUniform4iv ( ( GLint ) location , ( GLsizei ) numberOfArrays , ints ) ;
}
}
2013-06-20 14:13:12 +08:00
void GLProgram : : setUniformLocationWith1f ( GLint location , GLfloat f1 )
2012-04-17 17:55:26 +08:00
{
2014-05-13 14:51:37 +08:00
bool updated = updateUniformLocation ( location , & f1 , sizeof ( f1 ) * 1 ) ;
2012-04-17 17:55:26 +08:00
2015-05-06 04:07:32 +08:00
if ( updated )
2012-04-19 14:35:52 +08:00
{
glUniform1f ( ( GLint ) location , f1 ) ;
}
2012-04-17 17:55:26 +08:00
}
2013-06-20 14:13:12 +08:00
void GLProgram : : setUniformLocationWith2f ( GLint location , GLfloat f1 , GLfloat f2 )
2012-04-17 17:55:26 +08:00
{
2012-04-19 14:35:52 +08:00
GLfloat floats [ 2 ] = { f1 , f2 } ;
bool updated = updateUniformLocation ( location , floats , sizeof ( floats ) ) ;
2012-04-17 17:55:26 +08:00
2015-05-06 04:07:32 +08:00
if ( updated )
2012-04-19 14:35:52 +08:00
{
glUniform2f ( ( GLint ) location , f1 , f2 ) ;
}
2012-04-17 17:55:26 +08:00
}
2013-06-20 14:13:12 +08:00
void GLProgram : : setUniformLocationWith3f ( GLint location , GLfloat f1 , GLfloat f2 , GLfloat f3 )
2012-04-17 17:55:26 +08:00
{
2012-04-19 14:35:52 +08:00
GLfloat floats [ 3 ] = { f1 , f2 , f3 } ;
2014-05-13 14:51:37 +08:00
bool updated = updateUniformLocation ( location , floats , sizeof ( floats ) ) ;
2012-04-17 17:55:26 +08:00
2015-05-06 04:07:32 +08:00
if ( updated )
2012-04-19 14:35:52 +08:00
{
glUniform3f ( ( GLint ) location , f1 , f2 , f3 ) ;
}
2012-04-17 17:55:26 +08:00
}
2013-06-20 14:13:12 +08:00
void GLProgram : : setUniformLocationWith4f ( GLint location , GLfloat f1 , GLfloat f2 , GLfloat f3 , GLfloat f4 )
2012-04-17 17:55:26 +08:00
{
2012-04-19 14:35:52 +08:00
GLfloat floats [ 4 ] = { f1 , f2 , f3 , f4 } ;
2014-05-13 14:51:37 +08:00
bool updated = updateUniformLocation ( location , floats , sizeof ( floats ) ) ;
2012-04-17 17:55:26 +08:00
2015-05-06 04:07:32 +08:00
if ( updated )
2012-04-19 14:35:52 +08:00
{
glUniform4f ( ( GLint ) location , f1 , f2 , f3 , f4 ) ;
}
2012-04-17 17:55:26 +08:00
}
2014-08-15 19:15:14 +08:00
void GLProgram : : setUniformLocationWith1fv ( GLint location , const GLfloat * floats , unsigned int numberOfArrays )
{
bool updated = updateUniformLocation ( location , floats , sizeof ( float ) * numberOfArrays ) ;
2015-05-06 04:07:32 +08:00
if ( updated )
2014-08-15 19:15:14 +08:00
{
glUniform1fv ( ( GLint ) location , ( GLsizei ) numberOfArrays , floats ) ;
}
}
2013-12-07 09:42:16 +08:00
void GLProgram : : setUniformLocationWith2fv ( GLint location , const GLfloat * floats , unsigned int numberOfArrays )
2012-04-17 17:55:26 +08:00
{
2014-05-13 14:51:37 +08:00
bool updated = updateUniformLocation ( location , floats , sizeof ( float ) * 2 * numberOfArrays ) ;
2012-04-17 17:55:26 +08:00
2015-05-06 04:07:32 +08:00
if ( updated )
2012-04-19 14:35:52 +08:00
{
glUniform2fv ( ( GLint ) location , ( GLsizei ) numberOfArrays , floats ) ;
}
2012-04-17 17:55:26 +08:00
}
2013-12-07 09:42:16 +08:00
void GLProgram : : setUniformLocationWith3fv ( GLint location , const GLfloat * floats , unsigned int numberOfArrays )
2012-04-17 17:55:26 +08:00
{
2014-05-13 14:51:37 +08:00
bool updated = updateUniformLocation ( location , floats , sizeof ( float ) * 3 * numberOfArrays ) ;
2012-04-17 17:55:26 +08:00
2015-05-06 04:07:32 +08:00
if ( updated )
2012-04-19 14:35:52 +08:00
{
glUniform3fv ( ( GLint ) location , ( GLsizei ) numberOfArrays , floats ) ;
}
2012-04-17 17:55:26 +08:00
}
2013-12-07 09:42:16 +08:00
void GLProgram : : setUniformLocationWith4fv ( GLint location , const GLfloat * floats , unsigned int numberOfArrays )
2012-04-17 17:55:26 +08:00
{
2014-05-13 14:51:37 +08:00
bool updated = updateUniformLocation ( location , floats , sizeof ( float ) * 4 * numberOfArrays ) ;
2012-04-17 17:55:26 +08:00
2015-05-06 04:07:32 +08:00
if ( updated )
2012-04-19 14:35:52 +08:00
{
glUniform4fv ( ( GLint ) location , ( GLsizei ) numberOfArrays , floats ) ;
}
2012-04-17 17:55:26 +08:00
}
2013-12-07 09:42:16 +08:00
void GLProgram : : setUniformLocationWithMatrix2fv ( GLint location , const GLfloat * matrixArray , unsigned int numberOfMatrices ) {
2014-05-13 14:51:37 +08:00
bool updated = updateUniformLocation ( location , matrixArray , sizeof ( float ) * 4 * numberOfMatrices ) ;
2015-04-20 17:00:40 +08:00
2015-05-06 04:07:32 +08:00
if ( updated )
2013-10-28 00:58:57 +08:00
{
glUniformMatrix2fv ( ( GLint ) location , ( GLsizei ) numberOfMatrices , GL_FALSE , matrixArray ) ;
}
}
2013-12-07 09:42:16 +08:00
void GLProgram : : setUniformLocationWithMatrix3fv ( GLint location , const GLfloat * matrixArray , unsigned int numberOfMatrices ) {
2014-05-13 14:51:37 +08:00
bool updated = updateUniformLocation ( location , matrixArray , sizeof ( float ) * 9 * numberOfMatrices ) ;
2015-04-20 17:00:40 +08:00
2015-05-06 04:07:32 +08:00
if ( updated )
2013-10-28 00:58:57 +08:00
{
glUniformMatrix3fv ( ( GLint ) location , ( GLsizei ) numberOfMatrices , GL_FALSE , matrixArray ) ;
}
}
2012-04-17 17:55:26 +08:00
2013-12-07 09:42:16 +08:00
void GLProgram : : setUniformLocationWithMatrix4fv ( GLint location , const GLfloat * matrixArray , unsigned int numberOfMatrices )
2012-04-17 17:55:26 +08:00
{
2014-05-13 14:51:37 +08:00
bool updated = updateUniformLocation ( location , matrixArray , sizeof ( float ) * 16 * numberOfMatrices ) ;
2012-04-17 17:55:26 +08:00
2015-05-06 04:07:32 +08:00
if ( updated )
2012-04-19 14:35:52 +08:00
{
glUniformMatrix4fv ( ( GLint ) location , ( GLsizei ) numberOfMatrices , GL_FALSE , matrixArray ) ;
}
2012-04-17 17:55:26 +08:00
}
2013-06-20 14:13:12 +08:00
void GLProgram : : setUniformsForBuiltins ( )
2012-04-17 17:55:26 +08:00
{
2014-12-04 18:37:57 +08:00
setUniformsForBuiltins ( _director - > getMatrix ( MATRIX_STACK_TYPE : : MATRIX_STACK_MODELVIEW ) ) ;
2013-12-07 09:42:16 +08:00
}
2014-05-15 01:07:09 +08:00
void GLProgram : : setUniformsForBuiltins ( const Mat4 & matrixMV )
2013-12-07 09:42:16 +08:00
{
2016-02-09 03:25:37 +08:00
const auto & matrixP = _director - > getMatrix ( MATRIX_STACK_TYPE : : MATRIX_STACK_PROJECTION ) ;
2013-11-01 08:56:15 +08:00
2015-05-06 04:07:32 +08:00
if ( _flags . usesP )
2014-05-14 09:12:58 +08:00
setUniformLocationWithMatrix4fv ( _builtInUniforms [ UNIFORM_P_MATRIX ] , matrixP . m , 1 ) ;
2018-01-03 17:15:00 +08:00
2016-10-28 09:33:31 +08:00
if ( _flags . usesMultiViewP )
{
Mat4 mats [ 4 ] ;
2017-02-07 09:41:19 +08:00
const auto stackSize = std : : min < size_t > ( _director - > getProjectionMatrixStackSize ( ) , 4 ) ;
for ( size_t i = 0 ; i < stackSize ; + + i ) {
2016-10-28 09:33:31 +08:00
mats [ i ] = _director - > getProjectionMatrix ( i ) ;
}
setUniformLocationWithMatrix4fv ( _builtInUniforms [ UNIFORM_MULTIVIEW_P_MATRIX ] , mats [ 0 ] . m , 4 ) ;
}
2013-12-06 11:04:01 +08:00
2015-05-06 04:07:32 +08:00
if ( _flags . usesMV )
2014-05-14 09:12:58 +08:00
setUniformLocationWithMatrix4fv ( _builtInUniforms [ UNIFORM_MV_MATRIX ] , matrixMV . m , 1 ) ;
2013-12-06 11:04:01 +08:00
2016-02-09 03:25:37 +08:00
if ( _flags . usesMVP )
{
2014-05-15 01:07:09 +08:00
Mat4 matrixMVP = matrixP * matrixMV ;
2014-05-14 09:12:58 +08:00
setUniformLocationWithMatrix4fv ( _builtInUniforms [ UNIFORM_MVP_MATRIX ] , matrixMVP . m , 1 ) ;
2013-11-01 08:56:15 +08:00
}
2018-01-03 17:15:00 +08:00
2016-10-28 09:33:31 +08:00
if ( _flags . usesMultiViewMVP )
{
Mat4 mats [ 4 ] ;
2017-02-07 09:41:19 +08:00
const auto stackSize = std : : min < size_t > ( _director - > getProjectionMatrixStackSize ( ) , 4 ) ;
for ( size_t i = 0 ; i < stackSize ; + + i ) {
2016-10-28 09:33:31 +08:00
mats [ i ] = _director - > getProjectionMatrix ( i ) * matrixMV ;
}
setUniformLocationWithMatrix4fv ( _builtInUniforms [ UNIFORM_MULTIVIEW_MVP_MATRIX ] , mats [ 0 ] . m , 4 ) ;
}
2013-11-01 08:56:15 +08:00
2014-08-15 19:15:14 +08:00
if ( _flags . usesNormal )
{
Mat4 mvInverse = matrixMV ;
mvInverse . m [ 12 ] = mvInverse . m [ 13 ] = mvInverse . m [ 14 ] = 0.0f ;
mvInverse . inverse ( ) ;
mvInverse . transpose ( ) ;
GLfloat normalMat [ 9 ] ;
normalMat [ 0 ] = mvInverse . m [ 0 ] ; normalMat [ 1 ] = mvInverse . m [ 1 ] ; normalMat [ 2 ] = mvInverse . m [ 2 ] ;
2014-08-17 21:33:33 +08:00
normalMat [ 3 ] = mvInverse . m [ 4 ] ; normalMat [ 4 ] = mvInverse . m [ 5 ] ; normalMat [ 5 ] = mvInverse . m [ 6 ] ;
normalMat [ 6 ] = mvInverse . m [ 8 ] ; normalMat [ 7 ] = mvInverse . m [ 9 ] ; normalMat [ 8 ] = mvInverse . m [ 10 ] ;
2014-08-15 19:15:14 +08:00
setUniformLocationWithMatrix3fv ( _builtInUniforms [ UNIFORM_NORMAL_MATRIX ] , normalMat , 1 ) ;
}
2015-05-06 04:07:32 +08:00
if ( _flags . usesTime ) {
2014-04-28 09:51:10 +08:00
// This doesn't give the most accurate global time value.
// Cocos2D doesn't store a high precision time value, so this will have to do.
// Getting Mach time per frame per shader using time could be extremely expensive.
2014-12-04 18:37:57 +08:00
float time = _director - > getTotalFrames ( ) * _director - > getAnimationInterval ( ) ;
2015-04-20 17:00:40 +08:00
2016-07-04 22:12:45 +08:00
setUniformLocationWith4f ( _builtInUniforms [ GLProgram : : UNIFORM_TIME ] , time / 10.0f , time , time * 2 , time * 4 ) ;
setUniformLocationWith4f ( _builtInUniforms [ GLProgram : : UNIFORM_SIN_TIME ] , time / 8.0f , time / 4.0f , time / 2.0f , sinf ( time ) ) ;
setUniformLocationWith4f ( _builtInUniforms [ GLProgram : : UNIFORM_COS_TIME ] , time / 8.0f , time / 4.0f , time / 2.0f , cosf ( time ) ) ;
2014-04-28 09:51:10 +08:00
}
2015-04-20 17:00:40 +08:00
2015-05-06 04:07:32 +08:00
if ( _flags . usesRandom )
2014-05-14 09:12:58 +08:00
setUniformLocationWith4f ( _builtInUniforms [ GLProgram : : UNIFORM_RANDOM01 ] , CCRANDOM_0_1 ( ) , CCRANDOM_0_1 ( ) , CCRANDOM_0_1 ( ) , CCRANDOM_0_1 ( ) ) ;
2012-11-09 12:08:18 +08:00
}
2012-04-17 17:55:26 +08:00
2013-06-20 14:13:12 +08:00
void GLProgram : : reset ( )
2012-04-17 17:55:26 +08:00
{
2013-06-15 14:03:30 +08:00
_vertShader = _fragShader = 0 ;
2014-05-14 09:12:58 +08:00
memset ( _builtInUniforms , 0 , sizeof ( _builtInUniforms ) ) ;
2015-04-20 17:00:40 +08:00
2012-04-17 17:55:26 +08:00
// it is already deallocated by android
2013-07-26 09:42:53 +08:00
//GL::deleteProgram(_program);
2013-06-15 14:03:30 +08:00
_program = 0 ;
2012-04-17 17:55:26 +08:00
2017-02-06 15:11:42 +08:00
clearHashUniforms ( ) ;
2012-03-15 10:42:22 +08:00
}
2012-03-12 15:22:03 +08:00
2015-11-17 14:29:56 +08:00
inline void GLProgram : : clearShader ( )
2015-11-17 13:38:42 +08:00
{
if ( _vertShader )
{
glDeleteShader ( _vertShader ) ;
}
if ( _fragShader )
{
glDeleteShader ( _fragShader ) ;
}
_vertShader = _fragShader = 0 ;
}
2017-02-06 15:11:42 +08:00
inline void GLProgram : : clearHashUniforms ( )
{
for ( auto e : _hashForUniforms )
{
free ( e . second . first ) ;
}
_hashForUniforms . clear ( ) ;
}
2012-03-12 15:22:03 +08:00
NS_CC_END