1

我有一个使用 berkelium 的 OpenGL 应用程序。它编译得很好。我已经将图像加载/纹理添加到应用程序中,并且可以在 OpenGL 中将纹理绘制到 3d 对象上。

但是,当我从glut_input示例中导入 berkelium 代码(包含在 berkelium 中)时,来自的代码mapOnPaintToTexture(..)似乎没有获取图像并将其正确加载到 OpenGL 纹理中……至少,我无法让它工作。它在 berkelium 提供的示例中确实有效,所以我确定这是我正在做的事情。

如果我从示例中复制代码ppmrender(此示例获取网页并将其“渲染”为图像,然后将其保存到磁盘),我可以让它毫无问题地将 .ppm 文件保存到 /tmp 中(我也可以加载那些图像并将它们渲染为 3d 对象)。

onPaint(..)的委托中的方法正在被调用,mapOnPaintToTexture(..)方法也是如此。

这是我的onPaint:

// gets called when berkelium has stuff we need to paint
onPaint(Berkelium::Window* wini,
    const unsigned char *bitmap_in, const Berkelium::Rect &bitmap_rect,
    size_t num_copy_rects, const Berkelium::Rect* copy_rects,
    int dx, int dy, const Berkelium::Rect& scroll_rect) {
        bool updated = mapOnPaintToTexture(
            wini, bitmap_in, bitmap_rect, num_copy_rects, copy_rects,
            dx, dy, scroll_rect,
            web_texture, width, height, false, scroll_buffer
        );
}

和我的 mapOnPaintToTexture:

mapOnPaintToTexture(
    Berkelium::Window *wini,
    const unsigned char* bitmap_in, const Berkelium::Rect& bitmap_rect,
    size_t num_copy_rects, const Berkelium::Rect *copy_rects,
    int dx, int dy,
    const Berkelium::Rect& scroll_rect,
    unsigned int dest_texture,
    unsigned int dest_texture_width,
    unsigned int dest_texture_height,
    bool ignore_partial,
    char* scroll_buffer) {

    BOOST_LOG_TRIVIAL(debug) << "mapOnPaintToTexture: " << dest_texture_width << "x" << dest_texture_width << " dest_texture: " << dest_texture;

    glBindTexture(GL_TEXTURE_2D, dest_texture);

    const int kBytesPerPixel = 4;

    // If we've reloaded the page and need a full update, ignore updates
    // until a full one comes in.  This handles out of date updates due to
    // delays in event processing.
    if (ignore_partial) {
        if (bitmap_rect.left() != 0 ||
            bitmap_rect.top() != 0 ||
            bitmap_rect.right() != dest_texture_width ||
            bitmap_rect.bottom() != dest_texture_height) {
            return false;
        }

        glTexImage2D(GL_TEXTURE_2D, 0, kBytesPerPixel, dest_texture_width, dest_texture_height, 0,
            GL_BGRA, GL_UNSIGNED_BYTE, bitmap_in);
        ignore_partial = false;
        return true;
    }

    BOOST_LOG_TRIVIAL(debug) << "mapOnPaintToTexture: here 1";


    // Now, we first handle scrolling. We need to do this first since it
    // requires shifting existing data, some of which will be overwritten by
    // the regular dirty rect update.
    if (dx != 0 || dy != 0) {
        // scroll_rect contains the Rect we need to move
        // First we figure out where the the data is moved to by translating it
        Berkelium::Rect scrolled_rect = scroll_rect.translate(-dx, -dy);
        // Next we figure out where they intersect, giving the scrolled
        // region
        Berkelium::Rect scrolled_shared_rect = scroll_rect.intersect(scrolled_rect);
        // Only do scrolling if they have non-zero intersection
        if (scrolled_shared_rect.width() > 0 && scrolled_shared_rect.height() > 0) {
            // And the scroll is performed by moving shared_rect by (dx,dy)
            Berkelium::Rect shared_rect = scrolled_shared_rect.translate(dx, dy);

            int wid = scrolled_shared_rect.width();
            int hig = scrolled_shared_rect.height();

            if (DEBUG_PAINT) {
              std::cout << "Scroll rect: w=" << wid << ", h=" << hig << ", ("
                        << scrolled_shared_rect.left() << "," << scrolled_shared_rect.top()
                        << ") by (" << dx << "," << dy << ")" << std::endl;
            }

            int inc = 1;
            char *outputBuffer = scroll_buffer;
            // source data is offset by 1 line to prevent memcpy aliasing
            // In this case, it can happen if dy==0 and dx!=0.
            char *inputBuffer = scroll_buffer+(dest_texture_width*1*kBytesPerPixel);
            int jj = 0;
            if (dy > 0) {
                // Here, we need to shift the buffer around so that we start in the
                // extra row at the end, and then copy in reverse so that we
                // don't clobber source data before copying it.
                outputBuffer = scroll_buffer+(
                    (scrolled_shared_rect.top()+hig+1)*dest_texture_width
                    - hig*wid)*kBytesPerPixel;
                inputBuffer = scroll_buffer;
                inc = -1;
                jj = hig-1;
            }

            // Copy the data out of the texture
            glGetTexImage(
                GL_TEXTURE_2D, 0,
                GL_BGRA, GL_UNSIGNED_BYTE,
                inputBuffer
            );

            // Annoyingly, OpenGL doesn't provide convenient primitives, so
            // we manually copy out the region to the beginning of the
            // buffer
            for(; jj < hig && jj >= 0; jj+=inc) {
                memcpy(
                    outputBuffer + (jj*wid) * kBytesPerPixel,
//scroll_buffer + (jj*wid * kBytesPerPixel),
                    inputBuffer + (
                        (scrolled_shared_rect.top()+jj)*dest_texture_width
                        + scrolled_shared_rect.left()) * kBytesPerPixel,
                    wid*kBytesPerPixel
                );
            }

            // And finally, we push it back into the texture in the right
            // location
            glTexSubImage2D(GL_TEXTURE_2D, 0,
                shared_rect.left(), shared_rect.top(),
                shared_rect.width(), shared_rect.height(),
                GL_BGRA, GL_UNSIGNED_BYTE, outputBuffer
            );
        }
    }

    BOOST_LOG_TRIVIAL(debug) << "mapOnPaintToTexture: here 2";
    if (DEBUG_PAINT) {
      std::cout << (void*)wini << " Bitmap rect: w="
                << bitmap_rect.width()<<", h="<<bitmap_rect.height()
                <<", ("<<bitmap_rect.top()<<","<<bitmap_rect.left()
                <<") tex size "<<dest_texture_width<<"x"<<dest_texture_height
                <<std::endl;
    }


    for (size_t i = 0; i < num_copy_rects; i++) {
        int wid = copy_rects[i].width();
        int hig = copy_rects[i].height();
        int top = copy_rects[i].top() - bitmap_rect.top();
        int left = copy_rects[i].left() - bitmap_rect.left();

        if (DEBUG_PAINT) {
            std::cout << (void*)wini << " Copy rect: w=" << wid << ", h=" << hig << ", ("
                      << top << "," << left << ")" << std::endl;
        }

        for(int jj = 0; jj < hig; jj++) {
            memcpy(
                scroll_buffer + jj*wid*kBytesPerPixel,
                bitmap_in + (left + (jj+top)*bitmap_rect.width())*kBytesPerPixel,
                wid*kBytesPerPixel
                );
        }

        // Finally, we perform the main update, just copying the rect that is
        // marked as dirty but not from scrolled data.
        glTexSubImage2D(GL_TEXTURE_2D, 0,
                        copy_rects[i].left(), copy_rects[i].top(),
                        wid, hig,
                        GL_BGRA, GL_UNSIGNED_BYTE, scroll_buffer
            );
    }
    BOOST_LOG_TRIVIAL(debug) << "mapOnPaintToTexture: here 3";

    glBindTexture(GL_TEXTURE_2D, 0);

    return true;
}

我的渲染代码如下所示:

testDrawTestBerkelium() {
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable( GL_TEXTURE_2D );
    glBindTexture(GL_TEXTURE_2D, web_texture);

    // display   
    glBegin(GL_QUADS);
        glTexCoord2f(0.f, 0.f); glVertex3f(-10.f, -10.f, 0.f);
        glTexCoord2f(0.f, 1.f); glVertex3f(-10.f,  10.f, 0.f);
        glTexCoord2f(1.f, 1.f); glVertex3f( 10.f,  10.f, 0.f);
        glTexCoord2f(1.f, 0.f); glVertex3f( 10.f, -10.f, 0.f);
    glEnd();

    Berkelium::update();
}

我的初始化函数如下所示:

initialize() {
    if (!Berkelium::init(Berkelium::FileString::empty())) {
        BOOST_LOG_TRIVIAL(debug) << "Failed to initialize berkelium!";
        return -1;
    }

    scroll_buffer = new char[width*(height+1)*4];

    // Create texture to hold rendered view
    glGenTextures(1, &web_texture);
    glBindTexture(GL_TEXTURE_2D, web_texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    Berkelium::Context* context = Berkelium::Context::create();
    Berkelium::Window* window = Berkelium::Window::create(context);
    delete context;

    width = 600;
    height = 600;

    //MyDelegate* delegate = new MyDelegate();
    window->setDelegate(this);
    window->resize(width, height);
    std::string url = "http://yahoo.ca";
    window->navigateTo(Berkelium::URLString::point_to(url.data(), url.length()));
}

我认为这就是所有相关的部分。当我加载程序时,我只在屏幕上看到一个灰色方块。

有没有人看到我做错了什么明显的事情?

4

1 回答 1

1

看起来我没有调用glTexImage2D(..)网页的纹理。

我需要onPaint(..)像这样修改:

bool updated = mapOnPaintToTexture(
            wini, bitmap_in, bitmap_rect, num_copy_rects, copy_rects,
            dx, dy, scroll_rect,
            web_texture, width, height, true, scroll_buffer
        ); 

trueignore_partial参数添加。为了更健壮,我可以glut_input更密切地遵循 berkelium 示例并实现部分更新。

感谢所有阅读我帖子的人。

干杯

于 2012-11-20T01:46:57.413 回答