Galoisplusplus

A fan of science, technology and Classical music.

Cocos2d-x V3.x不规则按钮-续篇

| Comments

之前曾经在cocos2d-x V3.x不规则按钮探讨过在cocos2d-x 3.x版本实现不规则按钮的方法,后来本渣又琢磨了下仿照RenderTexture类调用OpenGL ES API来获取图片像素信息的方式。这种方式由于按钮图片的Texture已在内存中,且不需要解析图片文件格式,因此相比之前用Image::initWithImageFile还是要快一些的。

重写的loadNormalTransparentInfo函数如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
void IrregularButton::loadNormalTransparentInfo()
{
#ifdef DEBUG
    auto start = std::chrono::steady_clock::now();
#endif

    Sprite* normalRenderer = static_cast<Sprite*>(_buttonNormalRenderer);
    auto normalTexture = normalRenderer->getTexture();
    const Size& s = normalTexture->getContentSizeInPixels();

    int savedBufferWidth = (int)s.width;
    int savedBufferHeight = (int)s.height;

    GLubyte *buffer = nullptr;

    // the FBO which cocos2dx used is not window-system-provided (non-zero id)
    GLint oldFBO;
    glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldFBO);

    GLuint framebuffer;
    glGenFramebuffers(1, &framebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);

    glBindTexture(GL_TEXTURE_2D, normalTexture->getName());
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, savedBufferWidth, savedBufferHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, normalTexture->getName(), 0);

    CCASSERT(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Could not attach texture to framebuffer");

    buffer = new (std::nothrow) GLubyte[savedBufferWidth * savedBufferHeight * 4];

    glPixelStorei(GL_PACK_ALIGNMENT, 1);
    glReadPixels(0, 0, savedBufferWidth, savedBufferHeight, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
    glBindFramebuffer(GL_FRAMEBUFFER, oldFBO);

    auto dataLen = savedBufferWidth * savedBufferHeight * 4;
    if (normalTransparent_ != nullptr) {
        delete[] normalTransparent_;
    }
    normalImageWidth_ = savedBufferWidth;
    normalImageHeight_ = savedBufferHeight;
    normalTransparent_ = new bool[dataLen / (sizeof(unsigned char) * 4)];
    for (auto i = 0; i < normalImageHeight_; i++) {
        for (auto j = 0; j < normalImageWidth_; j++) {
            normalTransparent_[i * normalImageWidth_ + j] = (buffer[(i * normalImageWidth_ + j) * 4 + 3] == 0);
        }
    }

    CC_SAFE_DELETE_ARRAY(buffer);

#ifdef DEBUG
    auto end = std::chrono::steady_clock::now();
    auto totalTime = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    printf("load from memory: %lld ms\n", totalTime.count());
#endif
}

完整代码请参考: cocos2d-x-irregular-button

Comments