How to position the RenderTexture?

i want to save a node into an image. i used RenderTexture, it creates image with node but dimensions are full screen. i want only that part where node is laying.
i tried to give RenderTexture position and size of that node but didn’t get the result i want. Here is the image i get, i want only the white rectangle part. Can someone give me the code snippet.

using cocos2d-x 13.14.1

i have achieved my goal using openCV to crop out the image created by RenderTexture. But i want to minimize this overhead.

The RenderTexture, by default, captures from the bottom-left of the screen and moving it does not affect that.

I don’t have code, but there are 2 ways I can think of doing this. First, when you create the RenderTexture, create it at the size of the Node. Then, either

  1. Move the Node so that its bottom-left corner is at the bottom-left of the screen. Begin the RenderTexture, visit the Node, then end the RenderTexture. If you need to move the Node back to where it was, call Director::getInstance()->getRenderer()->render() to force the Renderer to render and draw to the RenderTexture. (Not 100% about forcing the Renderer, but it should work.) Or,

  2. RenderTexture has a function called setVirtualViewport(). I can’t remember how to use it, but I’m pretty sure I have used it to capture only part of the screen before. Trying experimenting with that.

EDIT:
Ok, so the second option seems to work something like this:

auto winSize = Director::getInstance()->getWinSize();
auto winSizePixels = Director::getInstance()->getWinSizeInPixels();

auto size = node->getBoundingBox().size;
auto ap = node->getAnchorPoint();

renderTexture->setAutoDraw(false);
renderTexture->setKeepMatrix(true);

rt->setVirtualViewport(node->getPosition() - Vec2(size.width * ap.x, size.height * ap.y),
        Rect(0, 0, winSize.width, winSize.height),
        Rect(0, 0, winSizePixels.width, winSizePixels.height));

This will set the RenderTexture to capture the node no matter where on screen it is. Note: It’s possible that the visible origin might cause issues, so you may need to add Director::getInstance()->getVisibleOrigin() to the position of the viewport.

6 Likes

love you man :slight_smile:
that works greatly. improved performance of my app, thank you very much.

it may be rude to ask here but i am having another problem, i have posted it here : Adding library via cocoapods returns Apple Match-O linker error
it will be awesome if you can take a look there and tell me some workaround.

much appreciated

Super useful info :slight_smile: I had my own workarounds to get it to work, but this is a lot cleaner.

I haven’t used CocoaPods, so I won’t be much help, but I will say that usually when you have a linker error like that it usually means it can’t find the implementation of a function, e.g. the .cpp file (for C++ projects.) I would say to make sure all the appropriate source files and library files have been included.

its ok, i achieved my goal without cocoapods. Thanks anyway. :slight_smile:

@grimfate I’m trying to use setVirtualViewport for another problem - I need to render a little wider than the screen size:

25

Green - is lets say 640x1136 iPhone 5 screen and black is part I want to render. In my game there are Sprite's on left and right parts of the screen and so I want to capture them too.
Final rendered image size should be say 700x300, so a bit wider that screen width 640.

But passing for example: Rect(-30.0, 0.0, winSize.width, winSize.height), just renders more only from right, so anyway it’s always renders from 0.0;0.0 and I need from negative coordinates…

@zhangxm Can you comment this too please?

do you found the fix for these issue?
i meet the same problem, in cocos2dx V.2 where rendered saveToFile, its working without problem.
i already try disabling culling but still no luck.

Yes SetVirtualViewport did the job
This is my code to save sprite to a file.

auto winSize = Director::getInstance()->getWinSize();
    auto winSizePixels = Director::getInstance()->getWinSizeInPixels();
    
    log("Root folder : %s",FileUtils::getInstance()->getWritablePath().c_str());
    
    auto size = drawSprite->getBoundingBox().size;
    auto ap = drawSprite->getAnchorPoint();
    
    auto renderTexture = RenderTexture::create(size.width,size.height);
    renderTexture->setAutoDraw(false);
    renderTexture->setKeepMatrix(true);
    
    renderTexture->setVirtualViewport(drawSprite->getPosition() - Vec2(size.width * ap.x, size.height * ap.y), Rect(0, 0, winSize.width, winSize.height),Rect(0, 0, winSizePixels.width,winSizePixels.height));
    //    for(int i = 0; i < 3 ; i++)
    //    {
    renderTexture->beginWithClear(1, 1, 1, 1);

    drawSprite->visit();
    renderTexture->end();


        std::string filename = StringUtils::format("drawImage.jpg");
    
    renderTexture->saveToFile(filename.c_str(), Image::Format::JPG,false,CC_CALLBACK_0(GTWrite::createDrawSprite, this));

do you found the fix for these issue?
i meet the same problem, in cocos2dx V.2 where rendered saveToFile, its working without problem.
i already try disabling culling but still no luck.

sorry i mean problem when save the sprite bigger than screen size

Nope, no solution.

but my code in cocos2dx 2.x is working correctly.

it’s strange if in old cocos working corectly but not in newer version.

YEa, some changes probably were made without proper testing…
Check this also renderTexture saveToFile artifacts

It’s like a bug, and I haven’t faced it with older versions too.