RenderTexture not rendering small sprites on the left

RenderTexture not rendering small sprites on the left
0

#1

Day of bugs, really:

string filename = "test.png";
auto renderTexture = RenderTexture::create(300, 240, Texture2D::PixelFormat::RGBA8888);
renderTexture->clear(0,0,0,0);
renderTexture->begin();
auto sprite = Sprite::create("0.png");
sprite->setPosition(Vec2(39, sprite->getContentSize().height * 0.5f));
sprite->visit();
renderTexture->end();
renderTexture->saveToFile(filename, Image::Format::PNG);
Director::getInstance()->getRenderer()->render();

It doesn’t render anything. If I change 39 to 40 it magically works (or add bigger image, big enough can be even at 0, 0). I’ve discovered that if image right side is below a certain value it won’t render to the renderTexture. Y position and height doesn’t matter.

Why?!

I’ve also tested this with DrawNode instead (using drawDot to render a simple dot) and it works fine.

Director::getInstance()->getRenderer()->render(); is suggested, but removing it doesn’t help.

Testing image (0.png) is 28x33. I’m attaching it to this post.

0


Draw sprite on Image?
#2

What platform (win/mac/ios) and cocos2d version?
It works for me using your image on Mac w/ver 3.17 cocos new project.

Note: the image is .jpeg on this forum so I did open it in an image editor to re-save as .png, not sure if there’s an issue with your original image.


#3

iOS 12.1 running on iPad Pro 10.5, cocos2d-x 3.17.

image is a png on my machine, also I’ve got another one, just swapped with it for testing.

I’ve also uploaded it here, just in case: https://www113.zippyshare.com/v/vMkE0XeS/file.html


#4

Okay, this is strange!

Today, I’ve made more tests.

  1. I’ve created fresh project and copy-pasted code here - it worked!
  2. I thought there may be a problem with some stuff in AppDelegate (mine is very custom), but nope, still worked
  3. I’ve copy-pasted HelloWorld scene to my existing project - it worked!
    Also I’ve added a quick code to preview saved file.

It looks like this:

string testPath = FileUtils::getInstance()->getWritablePath() + filename;
auto check = Sprite::create(testPath);
check->setPosition(Vec2(240, 160));
addChild(check);
  1. I’ve launched my old class with the same code again, but called it on init() - it worked!
  2. I’ve launched it using scheduleOnce() (5 seconds later) - still worked!
  3. In the non-working case I’ve called it when clicked a button (ui::Button class) - it still didn’t work - but I’ve added scheduleOnce with 0.0 time and guess what - it worked!

That’s very strange, because I don’t think addTouchEventListener works on different thread. However, as you can see, running it on the next frame fixes the issue.

  1. Then I’ve remembered - hey - let’s try default AppDelegate - and it worked! So I thought there’s something wrong with my AppDelegate. I’ve removed all unnecessary code and I ended up with pretty much the same. The only difference was the default designResolutionSize. Mine was 960x640, while default is 480x320.

I’ve created a new test project to show you how to reproduce this bug.

Classes.zip (6.6 KB)

Just create an empty cocos2d-x project, replace Classes and copy previously attached 0.png file (or use any other small png, it should work as well).


#5

I haven’t looked at your new test project yet, but the “next frame” issue may just be due to the button event occurring before the render target save to file executes.

If so that’s not technically a bug, but more of a feature request, in the sense that it’d be working as intended, but is not the behavior you want? Or you just need to work within the behavior of the engine.

Anyway, I’ll take a look sometime in the next day or two, but will also watch this thread.


#6

Strange. I tested the following changed code on iPhone SE, not an iPad, but still running iOS 12. I do believe with the code you had it did appear to not display with the top button (without scheduleOnce), but would display correct with bottom button (with scheduleOnce). However, I added and changed the test a bit to better display what’s going on and it appears to work fine with the following…???

I’m going to re-test your original code and do some further investigation.

void HelloWorld::runTest()
{
    static int i = 0;
    i = i + 1;
    i = i % 20;

    string filename = "test.png";
    auto renderTexture = RenderTexture::create(300, 240, Texture2D::PixelFormat::RGBA8888);
    renderTexture->beginWithClear(.5f, 0, .7f, 1);

    {
        float x = (i+1) * 10.f;
        float y = 0;
        auto sprite = Sprite::create("res/0.png");
        //auto sprite = Sprite::create("HelloWorld.png");
        auto size = renderTexture->getContentSize();
        sprite->setPosition(Vec2(40 + x, 40 + y));
        sprite->setColor(Color3B::RED);
        sprite->visit();
    }
    {
        float x = 0;
        float y = (i+1) * 5.f;
        //auto sprite = Sprite::create("HelloWorld.png");
        auto sprite = Sprite::create("res/0.png");
        sprite->setPosition(Vec2(40 + x, 40 + y));
        sprite->setColor(Color3B::GREEN);
        sprite->visit();
    }
    {
        float x = (i+1) * 10.f;
        float y = (i+1) * 5.f;
        auto sprite = Sprite::create("res/0.png");
        //auto sprite = Sprite::create("HelloWorld.png");
        auto size = renderTexture->getContentSize();
        sprite->setPosition(Vec2(40 + x, 40 + y));
        sprite->setColor(Color3B::BLUE);
        sprite->visit();
    }

    renderTexture->end();
    renderTexture->saveToFile(filename, Image::Format::PNG, true, [](RenderTexture* rt, const std::string& str) {
        CCLOG("str = %s", str.data());
    });
    Director::getInstance()->getRenderer()->render();

    string testPath = FileUtils::getInstance()->getWritablePath() + filename;
    auto texCache = Director::getInstance()->getTextureCache();
    texCache->removeTextureForKey(testPath); //remove old texture from cache

    static float offset = 10.f;
    offset += 10.f;
    offset = fmodf(offset, 200);

    auto check = Sprite::create(testPath);
    check->setTag(101); //use a tag
    check->setPosition(Vec2(400 + offset, 200));
    removeChildByTag(101); //remove old sprite before adding a new one
    addChild(check);
}

#7
sprite->setPosition(Vec2(40 + x, 40 + y));

This line matters. Replace 40 + x with just x and you’ll see.


#8

Yeah, apparently. Strange. I’ll take a final brief look at it tomorrow and if we don’t find the root cause then should be moved to github issue.


#9

Thanks, altought I’ve found a workaround (scheduleOnce) I’m very curious what’s the issue. I bet on sprite batching.


#10

Have you found what’s the issue or should I report a bug on github?


#11

Sorry, didn’t get back to this until now. I’ll report anything tomorrow, otherwise yeah report a bug.


#12

Weirdly enough now I can’t reproduce the issue that we’ve discussed with the same project that I’m pretty sure I noticed the issue at least once or twice. **sigh**

Anyway, feel free to make an issue.