cocos2d-x 源码分析




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
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值