std::string FileUtils::fullPathForFilename(const std::string &filename)
{ //如果文件名为string的size()==0
if (filename.empty())
{
return "";
}
//如果是绝对路径
if (isAbsolutePath(filename))
{
return filename;
}
// Already Cached ? 如果已经缓存了,则直接从缓存里面取
auto cacheIter = _fullPathCache.find(filename);
if( cacheIter != _fullPathCache.end() )
{
return cacheIter->second;
}
// Get the new file name. 获得一份新文件名
const std::string newFilename( getNewFilename(filename) );
std::string fullpath;
//cbegin()返回确定范围中第一个元素地址的const 迭代器。cend()指向刚超出范围末尾的位置的 const 随机访问迭代器。
for (auto searchIt = _searchPathArray.cbegin(); searchIt != _searchPathArray.cend(); ++searchIt)
{
for (auto resolutionIt = _searchResolutionsOrderArray.cbegin(); resolutionIt != _searchResolutionsOrderArray.cend(); ++resolutionIt)
{
fullpath = this->getPathForFilename(newFilename, *resolutionIt, *searchIt);
if (fullpath.length() > 0)
{
// Using the filename passed in as key.
_fullPathCache.insert(std::make_pair(filename, fullpath));
return fullpath;
}
}
}
CCLOG("cocos2d: fullPathForFilename: No file found at %s. Possible missing file.", filename.c_str());
// XXX: Should it return nullptr ? or an empty string ?
// The file wasn't found, return the file name passed in.
return filename;
}
/**
获取文件的路径
@param 文件名
@param 文件夹
@param 文件路径
*/
std::string FileUtils::getPathForFilename(const std::string& filename, const std::string& resolutionDirectory, const std::string& searchPath)
{
std::string file = filename;
std::string file_path = "";
size_t pos = filename.find_last_of("/"); //找到文件名匹配“/”最后一个字符的索引,没有返回npos
if (pos != std::string::npos)
{
file_path = filename.substr(0, pos+1); //截取字符串获得文件路径
file = filename.substr(pos+1); //截取字符串获得文件名
}
// searchPath + file_path + resourceDirectory 搜索路径 + 文件路径 + 资源文件夹
std::string path = searchPath;
path += file_path;
path += resolutionDirectory;
//获取目录的完整路径和文件名。调用相应平台的获取路径的方法。
path = getFullPathForDirectoryAndFilename(path, file);
//CCLOG("getPathForFilename, fullPath = %s", path.c_str());
return path;
}
static Data getData(const std::string& filename, bool forString)
{
if (filename.empty())
{
return Data::Null;
}
Data ret;
unsigned char* buffer = nullptr;
ssize_t size = 0;
const char* mode = nullptr; //文件读取模式
if (forString)
mode = "rt";
else
mode = "rb";
do
{
// Read the file from hardware 从硬件读取文件
std::string fullPath = FileUtils::getInstance()->fullPathForFilename(filename);
FILE *fp = fopen(fullPath.c_str(), mode);
CC_BREAK_IF(!fp);
fseek(fp,0,SEEK_END); //移动文件指针到指定的位置。fp是文件的指针,0 是起源的字节,SEEK_END 文件尾,从文件头读到文件尾
size = ftell(fp); //获取当前文件指针的位置。
fseek(fp,0,SEEK_SET); //从文件头读到文件开始处
if (forString)
{
buffer = (unsigned char*)malloc(sizeof(unsigned char) * (size + 1)); //分配内存
buffer[size] = '\0'; //某位加'\0',可能表示结束吧
}
else
{
buffer = (unsigned char*)malloc(sizeof(unsigned char) * size);
}
size = fread(buffer, sizeof(unsigned char), size, fp); //读取文件
fclose(fp); //关闭文件
} while (0);
if (nullptr == buffer || 0 == size)
{
std::string msg = "Get data from file(";
msg.append(filename).append(") failed!");
CCLOG("%s", msg.c_str());
}
else
{
ret.fastSet(buffer, size); //设置Data的数据 _bytes = bytes; _size = size;
}
return ret;
}
// 返回data的字节
std::string FileUtils::getStringFromFile(const std::string& filename)
{
Data data = getData(filename, true);
if (data.isNull())
return "";
std::string ret((const char*)data.getBytes());
return ret;
}
bool GLProgram::initWithByteArrays(const GLchar* vShaderByteArray, const GLchar* fShaderByteArray)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) || (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
GLboolean hasCompiler = false;
glGetBooleanv(GL_SHADER_COMPILER, &hasCompiler);
_hasShaderCompiler = (hasCompiler == GL_TRUE);
if(!_hasShaderCompiler)
{
return initWithPrecompiledProgramByteArray(vShaderByteArray,fShaderByteArray);
}
#endif
//创建一个空程序对象并返回一个它可以引用的非0值。
_program = glCreateProgram();
//openGL 的错误输出
CHECK_GL_ERROR_DEBUG();
_vertShader = _fragShader = 0;
if (vShaderByteArray)
{
if (!compileShader(&_vertShader, GL_VERTEX_SHADER, vShaderByteArray))
{
CCLOG("cocos2d: ERROR: Failed to compile vertex shader");
return false;
}
}
// Create and compile fragment shader
if (fShaderByteArray)
{
if (!compileShader(&_fragShader, GL_FRAGMENT_SHADER, fShaderByteArray))
{
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 = nullptr;
CHECK_GL_ERROR_DEBUG();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) || (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
_shaderId = CCPrecompiledShaders::getInstance()->addShaders(vShaderByteArray, fShaderByteArray);
#endif
return true;
}
注意 :
CHECK_GL_ERROR_DEBUG(); 是OpenGL得debug错误输出,有用
// 编译着色器
bool GLProgram::compileShader(GLuint * shader, GLenum type, const GLchar* source)
{
GLint status;
if (!source)
{
return false;
}
//修改在特定平台下的type值,并添加上一些着色器的代码
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,
};
//创建一个着色器对象
*shader = glCreateShader(type);
// 替换一个着色器对象中的源代码。
第一个参数:指定源代码被替换你的着色器对象的句柄,
第二个参数:指定string和length数组中得元素数量,
第三个参数:指定一个包含将要被载入着色器源代码的字符串的指针数组
第四个参数:指定字符串长度数组。
//着色器对象中原来存储的任何源代码将完全被替换。
//如果最后一个参数为nullptr,那么每个字符串将被假定以空结束符结束。否则,它将指向一个为每一个string的相应元素包含一个字符串长度的数组
glShaderSource(*shader, sizeof(sources)/sizeof(*sources), sources, nullptr);
<span style="font-family: Arial, Helvetica, sans-serif;">//编译一个着色器对象,编译已经被存储到有shader指定的着色器对象的源代码字符串。 P519 opengl超级宝典</span>
glCompileShader(*shader);
// 返回一个来自着色器对象的参数
// GL_COMPILE_STATUS 在最后一次着色器上编译操作成功的情况下返回GL_TURE,否则返回GL_FALSE。
P602 超级宝典
glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
if (! status)
{
GLsizei length;
// 获取被请去用来存储返回源代码字符串的缓冲区的大小
glGetShaderiv(*shader, GL_SHADER_SOURCE_LENGTH, &lengt