RenderTexture

以下一些内容摘自http://www.cnblogs.com/newlist/p/3552340.html

 CCRenderTexture,它允许你来动态创建纹理,并且可以在游戏中重用这些纹理。也可用它来读取你想要的纹理信息。

  使用 CCRenderTexture非常简单 – 你只需要做以下5步就行了:

  1. 创建一个新的CCRenderTexture. 这里,你可以指定将要创建的纹理的宽度和高度。.
  2. 调用 CCRenderTexture:begin. 这个方法会启动OpenGL,并且接下来,任何绘图的命令都会渲染到CCRenderTexture里面去,而不是画到屏幕上。
  3. 绘制纹理. 你可以使用原始的OpenGL调用来绘图,或者你也可以使用cocos2d对象里面已经定义好的visit方法。(这个visit方法就会调用一些opengl命令来绘制cocos2d对象)
  4. 调用 CCRenderTexture:end. 这个方法会渲染纹理,并且会关闭渲染至CCRenderTexture的通道。
  5. 从生成的纹理中创建一个sprite. 你现在可以用CCRenderTexture的sprite.texture属性来轻松创建新的精灵了。

用已有的纹理创建一个纹理:

复制代码
class RenderTextureSave : public RenderTextureTest
{
public:
    RenderTextureSave();
    ~RenderTextureSave();
    virtual std::string title();
    virtual std::string subtitle();
    virtual void onTouchesMoved(const std::vector<Touch*>& touches, Event* event);
    void clearImage(Object *pSender);
    void saveImage(Object *pSender);

private:
    RenderTexture *_target;
    Sprite *_brush;
};
复制代码
复制代码
void RenderTextureSave::onTouchesMoved(const std::vector<Touch*>& touches, Event* event)
{
    auto touch = touches[0];
    auto start = touch->getLocation();
    auto end = touch->getPreviousLocation();
    // 开始渲染目标纹理         
     _target->begin();

    // for extra points, we'll draw this smoothly from the last position and vary the sprite's
    // scale/rotation/offset
    float distance = start.getDistance(end);
    if (distance > 1)
    {
        int d = (int)distance;
        for (int i = 0; i < d; i++)
        {
            float difx = end.x - start.x;
            float dify = end.y - start.y;
            float delta = (float)i / distance;
            _brush->setPosition(Point(start.x + (difx * delta), start.y + (dify * delta)));
            _brush->setRotation(rand() % 360);
            float r = (float)(rand() % 50 / 50.f) + 0.25f;
            _brush->setScale(r);
            /*_brush->setColor(Color3B(CCRANDOM_0_1() * 127 + 128, 255, 255));*/
            // Use CCRANDOM_0_1() will cause error when loading libtests.so on android, I don't know why.
            _brush->setColor(Color3B(rand() % 127 + 128, 255, 255));
            // Call visit to draw the brush, don't call draw..
            _brush->visit();
        }
    }

    // 完成渲染将目标缓存转移到离屏缓存中
    _target->end();
}
复制代码
复制代码
void RenderTextureSave::saveImage(cocos2d::Object *sender)
{
    static int counter = 0;

    char png[20];
    sprintf(png, "image-%d.png", counter);
    char jpg[20];
    sprintf(jpg, "image-%d.jpg", counter);

    _target->saveToFile(png, Image::Format::PNG);
    _target->saveToFile(jpg, Image::Format::JPG);
    

    auto image = _target->newImage();

    auto tex = TextureCache::getInstance()->addImage(image, png);

    CC_SAFE_DELETE(image);

    auto sprite = Sprite::createWithTexture(tex);

    sprite->setScale(0.3f);
    addChild(sprite);
    sprite->setPosition(Point(40, 40));
    sprite->setRotation(counter * 3);

    CCLOG("Image saved %s and %s", png, jpg);

    counter++;
}
 
读取一个纹理信息
//开始准备绘制
		this->m_pRenderTexture->begin();
		//绘制使用的临时精灵,与原图是同一图片
		CCSprite* pTempSpr = CCSprite::createWithSpriteFrame(this->m_imgMan->displayFrame());
		pTempSpr->setPosition(ccp(pTempSpr->getContentSize().width / 2, pTempSpr->getContentSize().height / 2));
		//绘制
		pTempSpr->visit();
		//结束绘制
		this->m_pRenderTexture->end();
		//通过画布拿到这张画布上每个像素点的信息,封装到CCImage中
		CCImage* pImage = this->m_pRenderTexture->newCCImage();

那么CCRenderTexture具体是怎么实现对自己目标纹理的渲染呢
 
其实里面用到了一种技术较FBO(FrameBufferObject),他可以用来把在窗口帧缓冲(framebuffer)的渲染转移到你自己创建的Off screen缓冲中。
 
跟到代码里面
 
OnBegin里显示开启opengl,然后有这样两句话:
  
    glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_oldFBO);
    glBindFramebuffer(GL_FRAMEBUFFER, _FBO);

取出旧的帧缓冲,绑定新的帧缓冲,于是调用完精灵的渲染。纹理信息就被存到了新的帧缓冲中。
OnEnd里
 glBindFramebuffer(GL_FRAMEBUFFER, _oldFBO);
纹理信息保存完了自然要把原先的还原回来,然后当要用的时候再从保存好的缓冲中取出来,于是就有了newImage里的这么两句
 glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_oldFBO);
        glBindFramebuffer(GL_FRAMEBUFFER, _FBO);

先将原本的帧缓冲信息保存起来,然后在绑定上先前保存好的精灵的帧缓冲,把里面的信息拿出来用,
    glPixelStorei(GL_PACK_ALIGNMENT, 1);
    glReadPixels(0,0,savedBufferWidth, savedBufferHeight,GL_RGBA,GL_UNSIGNED_BYTE, tempData);
<span style="font-family:Arial;BACKGROUND-COLOR: #ffffff"></span>
    
偷吃完了要记得插嘴吧,newImage的最后
  glBindFramebuffer(GL_FRAMEBUFFER, _oldFBO);
 
哪里写错,或者写的不好的地方,请大家多点评

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值