我有一个使用berkelium的OpenGL应用程序。它编译得很好。我已经在应用程序中加载了图像/纹理,并且我可以在OpenGL中绘制纹理到三维对象上。
然而,当我从glut_input
示例中导入berkelium代码(包含在berkelium中)时,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
);
}
和我的地图OnPaintToTexture:
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()));
}
我认为这就是所有相关的部分。当我加载程序时,我只在屏幕上看到一个灰色的正方形。
有人看到我做错了什么吗?
看起来我没有在网页的纹理上调用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
参数添加。为了更健壮,我可以更紧密地遵循berkeliumglut_input
的示例,并实现部分更新。
感谢所有通读我帖子的人。
欢呼