Berkelium рендер текстуры

У меня есть приложение OpenGL, использующее берклий. Компилируется нормально. Я загрузил изображения / текстуры в приложение, и я могу заставить текстуры рисовать на 3D-объектах в OpenGL.

Однако, когда я импортировал код берклия из glut_input пример (в комплекте с берклием), код из mapOnPaintToTexture(..) не получается получить изображение и загрузить его в текстуру OpenGL должным образом... по крайней мере, я не могу заставить его работать. Это работает в примере с берклием, так что я уверен, что это то, что я делаю.

Если я скопирую код из 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()));
}

Я думаю, что это все соответствующие биты. Когда я загружаю программу, я просто вижу серый квадрат на экране.

Кто-нибудь видит что-нибудь очевидное, что я делаю не так?

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
        ); 

Добавлено в true для ignore_partial параметр. Чтобы быть более крепким, я мог бы следовать за Berkelium glut_input Пример более тесно и реализовать частичное обновление.

Спасибо всем, кто прочитал мой пост.

ура

Другие вопросы по тегам