Synchronous glReadPixel in cocos2d-x-v3

Continuing the discussion from Pixel perfect touch detection:

Since the new renderer does all the actual rendering asynchronously is there any way to create a RenderTexture, render something in there and use glReadPixel to check a pixel’s value without resorting to lambdas and async behavior?

I am asking this because I would like to implement a pixel perfect touch detection that ignores touches on invisible pixels for a given sprite and so I need to return immediately whether or not the touch was acknowledged from the onTouchBegan method.

Yes, you could call Renderer::render() function manually, which will execute the current render que, and the only thing in the render que at that moment should only be the stuff you manually called visit inside the rendertexture begin / end

Yes, exactly, I have managed to make it work, thank you.

So, to give a concrete example, we could use some kind of “pixel reader” node like:

class CC_DLL KBRPixelReadNode : public cocos2d::Node
{
public:
    
    static KBRPixelReadNode* create(const cocos2d::Vec2& readPoint);
    ...
    virtual void draw(cocos2d::Renderer *renderer, const cocos2d::Mat4& transform, uint32_t flags);
    Byte* getPixelColor() {return _pixelColorRead; };
    
protected:
    void onDraw();
    cocos2d::CustomCommand _readPixelsCommand;
    cocos2d::Vec2 _readPoint;
    Byte _pixelColorRead[4];
};

void KBRPixelReadNode::draw(Renderer *renderer, const Mat4& transform, uint32_t flags) {
    _readPixelsCommand.init(_globalZOrder);
    _readPixelsCommand.func = CC_CALLBACK_0(KBRPixelReadNode::onDraw, this);
    renderer->addCommand(&_readPixelsCommand);
}


void KBRPixelReadNode::onDraw() {
    glReadPixels(_readPoint.x,
                 _readPoint.y,
                 1,
                 1,
                 GL_RGBA,
                 GL_UNSIGNED_BYTE,
                 &_pixelColorRead[0]);
}

and then

//having pRenderer and sprite created    
KBRPixelReadNode* pixelReadNode = KBRPixelReadNode::create(testPoint);
pRenderer->begin();
sprite->visit();
pixelReadNode->visit();
pRenderer->end();
Director::getInstance()->getRenderer()->render();
//access pixelReadNode->getPixelColor();

Hi,

Sorry to bump this thread but I have exactly the same problem even after having used render() after the end() call.

I used a RenderTexture, call begin(), visit my sprites, call glReadPixels into a private buffer, then call end().

And whatever I do, the buffer contains the sub part of my game scene image, not the sub part of the render texture one.

Any idea of what I could miss ?
I’m using Cocos2d-x v3.3

Thanks

Edit: OK I did it by using this home-made KBRPixelReadNode, I though it was the same to call directly glReadPixels but it isn’t !

you have to call Renderer::render() before you read pixel, because the visits and draw inside begin and end are just adding commands to the renderqueue

Please, I really need help with it. I want to verify the touch with pixel perfect detection, but I can’t understand the code and how it works. Can someone help me with it? I have no idea how to do it.

ps: the Byte class is showing error here.