cocos2dx的图片载入「建议收藏」

cocos2dx的图片载入

大家好,又见面了,我是全栈君。

//data: 图片文件数据  dataLen: 文件长度
bool Image::initWithImageData(const unsigned char * data, ssize_t dataLen)
{
    bool ret = false;

    do
    {
        CC_BREAK_IF(! data || dataLen <= 0);

        unsigned char* unpackedData = nullptr;
        ssize_t unpackedLen = 0;

        //解压缩pvr.ccz格式的图片
        //detecgt and unzip the compress file
        if (ZipUtils::isCCZBuffer(data, dataLen))
        {
            unpackedLen = ZipUtils::inflateCCZBuffer(data, dataLen, &unpackedData);
        }
        //解压缩pvr.gz格式的图片
        else if (ZipUtils::isGZipBuffer(data, dataLen))
        {
            unpackedLen = ZipUtils::inflateMemory(const_cast<unsigned char*>(data), dataLen, &unpackedData);
        }
        else
        {
            unpackedData = const_cast<unsigned char*>(data);
            unpackedLen = dataLen;
        }
        //识别文件类型
        _fileType = detectFormat(unpackedData, unpackedLen);

        switch (_fileType)
        {
        case Format::PNG:
            ret = initWithPngData(unpackedData, unpackedLen);
            break;
        ...
        //后面就是依据文件类型来进行图片解码初始化
        } while (0);

    return ret;
}

这里先介绍下图片解码到载入再到显示的流程。以后再具体地介绍每种格式图片的解码。

Texture2D * TextureCache::addImage(const std::string &path)
{
  ...
  //新建一个Image对象
  image = new (std::nothrow) Image();
  CC_BREAK_IF(nullptr == image);

  //图片解码
  bool bRet = image->initWithImageFile(fullpath);
  CC_BREAK_IF(!bRet);

  //新建一个2D的纹理
  texture = new (std::nothrow) Texture2D();

  //開始初始化纹理
  if( texture && texture->initWithImage(image) )
  {
    ...
  }
}

//使用指定像素格式来初始化(默认是auto,依据图片解码的结果来确定)
bool Texture2D::initWithImage(Image *image, PixelFormat format)
{
    ...
    //获取当前的OpenGL环境
    Configuration *conf = Configuration::getInstance();
    //推断纹理大小是否超出限制
    int maxTextureSize = conf->getMaxTextureSize();
    ...

    //获取mipmap贴图的数量
    if (image->getNumberOfMipmaps() > 1)
    {
        CCLOG("cocos2d: WARNING: This image has more than 1 mipmaps and we will not convert the data format");
        //载入mipmap贴图
        initWithMipmaps(image->getMipmaps(), image->getNumberOfMipmaps(), image->getRenderFormat(), imageWidth, imageHeight);

        return true;
    }
    else if (image->isCompressed())
    {
        ...
        initWithData(...)
        ...
        return true;
    }
    else
    {
        ...
        initWithData(...)
        ...
        return true;
    }
}

bool Texture2D::initWithMipmaps(MipmapInfo* mipmaps, int mipmapsNum, PixelFormat pixelFormat, int pixelsWide, int pixelsHigh)
{
    ...
    //设置像素的行字节对齐,在一定平台下有性能的提高。并且若不加注意,会导致glTexImage中系函数的读取越界
    //Set the row align only when mipmapsNum == 1 and the data is uncompressed
    if (mipmapsNum == 1 && !info.compressed)
    {
        unsigned int bytesPerRow = pixelsWide * info.bpp / 8;

        if(bytesPerRow % 8 == 0)
        {
            glPixelStorei(GL_UNPACK_ALIGNMENT, 8);
        }
        else if(bytesPerRow % 4 == 0)
        {
            glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
        }
        else if(bytesPerRow % 2 == 0)
        {
            glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
        }
        else
        {
            glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        }
    }else
    {
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    }
    ...
    //生成纹理索引
    glGenTextures(1, &_name);
    //bindTexture2函数中会调用glActiveTexture,glBindTexture来制定纹理单位和绑定纹理
    GL::bindTexture2D(_name);

    //依据mipmap贴图数和是否设置抗锯齿来选择纹理滤波方式,关于纹理滤波的选择后面会具体的再分析下
    if (mipmapsNum == 1)
    {
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _antialiasEnabled ? GL_LINEAR : GL_NEAREST);
    }else
    {
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _antialiasEnabled ? GL_LINEAR_MIPMAP_NEAREST : GL_NEAREST_MIPMAP_NEAREST);
    }

    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _antialiasEnabled ?

GL_LINEAR : GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); for (int i = 0; i < mipmapsNum; ++i) { unsigned char *data = mipmaps[i].address; GLsizei datalen = mipmaps[i].len; //纹理映射一个指定的纹理图像的一部分到每一个开启了纹理映射的图元上。在当前段着色器或顶点着色器使用内建纹理搜索函数时。贴图被启用。

if (info.compressed) { //压缩格式生成纹理 glCompressedTexImage2D(GL_TEXTURE_2D, i, info.internalFormat, (GLsizei)width, (GLsizei)height, 0, datalen, data); } else { //生成2D纹理 glTexImage2D(GL_TEXTURE_2D, i, info.internalFormat, (GLsizei)width, (GLsizei)height, 0, info.format, info.type, data); } if (i > 0 && (width != height || ccNextPOT(width) != width )) { CCLOG("cocos2d: Texture2D. WARNING. Mipmap level %u is not squared. Texture won't render correctly. width=%d != height=%d", i, width, height); } GLenum err = glGetError(); if (err != GL_NO_ERROR) { CCLOG("cocos2d: Texture2D: Error uploading compressed texture level: %u . glError: 0x%04X", i, err); return false; } //四分之中的一个大小的mipmap width = MAX(width >> 1, 1); height = MAX(height >> 1, 1); } _contentSize = Size((float)pixelsWide, (float)pixelsHigh); _pixelsWide = pixelsWide; _pixelsHigh = pixelsHigh; _pixelFormat = pixelFormat; _maxS = 1; _maxT = 1; //关闭alpha渐变 _hasPremultipliedAlpha = false; _hasMipmaps = mipmapsNum > 1; // shader setGLProgram(GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE)); }

对于非mipmaps的贴图直接指定为已mipmapsNum为1的形式进行初始化就可以,纹理纹理渲染完毕就可以增加到显示队列,当然这里仅仅是先简介下,关于渲染流程等我写完图片的解码部分再回来补充~

未完待续…

tp

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/115390.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • php将字符串内的指定字符全部替换,php中如何替换字符串中的某个字符[通俗易懂]

    php将字符串内的指定字符全部替换,php中如何替换字符串中的某个字符[通俗易懂]在PHP中,可以使用strtr()函数实现字符串替换。首先我们简单了解下strtr()函数的定义及语法。语法:stringstrtr(string$str,string$from,string$to)第一个参数表示待转换的字符串。第二个参数表示字符串中与将要被转换的目的字符to相对应的源字符。第三个参数表示字符串中与将要被转换的字符from相对应的目的字符。实例:…

    2022年5月23日
    37
  • Arduino学习笔记(12) — MPU6050与卡尔曼滤波算法实践「建议收藏」

    Arduino学习笔记(12) — MPU6050与卡尔曼滤波算法实践「建议收藏」01简介:WhyMPU6050?MPU6050等IMU传感器用于自平衡机器人,无人机,智能手机等。IMU传感器帮助我们在三维空间中获得连接到传感器的物体的位置。这些值通常是角度,以帮助我们确定其位置。它们用于检测智能手机的方向,或者用于Fitbit等可穿戴设备,它使用IMU传感器跟踪运动。MPU6050它是全球首例整合性6轴运动处理组件,俗称的六轴陀螺仪(xyz三轴的倾斜…

    2022年6月21日
    142
  • 05_Node js 文件管理模块 fs

    05_Node js 文件管理模块 fs

    2021年6月30日
    84
  • TFS 使用心得–权限管理

    TFS 使用心得–权限管理最近一段时间负责管理公司技术人员的 TFS 的权限分配 在此之前 我对 tfs 一点都不了解 没用过 也没听朋友用过 只在进公司时指导我的组长帮我把这个工具装上 告知要在上面报 bug 即 bug 管理在上面 之后的很长一段时间就只知道 tfs 可以管理 bug 可以管理文档 可以管理源代码 这点是从我负责测试的那个项目下的文件夹中看到的 至于怎么来管理 其中有多复杂 没有太多的了解 指导两个月前 接手 tfs 权限管理工作以来 才知道里面有多复杂 经理只告诉我怎么分配项目成员的项目权限 其他的都不知道 起初还以为这样

    2025年10月12日
    3
  • 链家秋招内推编程笔试题目

    链家秋招内推编程笔试题目

    2022年3月6日
    40
  • 关于SHFileOperation「建议收藏」

    关于SHFileOperation「建议收藏」
    CStringstr=”f://11″;
    FileOp.pFrom = (LPCTSTR)str;
     
    执行不成功,翻了下msdn
    ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.WIN32COM.v10.en/shellcc/platform/shell/reference/structures/shfileopstruct.htm
     pFromAddressofabuffertospecifyon

    2022年7月17日
    14

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号