OpenGl 显示2D图像

  • Opengl的认识

Opengl 显示2D图像相对于在平台采用接口的方式,效率上是高一些的,因为使用了较少的CPU运行时间。

学习Opengl时间不长,仅仅对管道的方法有所了解,Shade的方法有时间再去学习;Opengl的 版本有比较多,Qt对Opengl有相应的模块,不过使用起来和常见的Win32程序有所区别,在Qt中包含了两个窗口类来支持Opengl,QGLWidget和QOpenglWidget,前者是较为老的版本,后者是更为新的类,其实都差别不大。

void initializeGL();用于初始化,
void paintGL();用于绘制各种图元以及纹理贴图

  • 纹理贴图的方法

初始化纹理尺寸的代码:

unsigned char* image_data = nullptr;
	int pixel_count = CImageW * CImageH;
	DATA_SIZE = pixel_count * 4;
	DATA_SIZE3 = pixel_count * 3;
	image_data = (unsigned char*)malloc(sizeof(unsigned char) * DATA_SIZE);
	for (int i = 0; i < pixel_count; i++) {
		image_data[i * 4 + 0] = 255;
		image_data[i * 4 + 1] = 255;
		image_data[i * 4 + 2] = 255;
		image_data[i * 4 + 3] = 255;
	}
	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	
	/* 设置纹理选项 */
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA, CImageW, CImageH, 0, GL_BGRA, GL_UNSIGNED_BYTE, image_data);
	free(image_data);
	

如果采用交换缓存区的方法来纹理贴图,还需要进一步绑定两个“乒乓”buffer,相关知识点:http://www.songho.ca/opengl/gl_pbo.html

OpenGl 显示2D图像_第1张图片

glGenBuffersARB(2, pboIds);
	glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, pboIds[0]);
	glBufferDataARB(GL_PIXEL_UNPACK_BUFFER, DATA_SIZE3, 0, GL_STREAM_DRAW);
	glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, pboIds[1]);
	glBufferDataARB(GL_PIXEL_UNPACK_BUFFER, DATA_SIZE3, 0, GL_STREAM_DRAW);
	glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, 0);

实际上测试,并没有官方说的提高得很明显,尽管glTexImage2D函数几乎不耗时,绑定缓存的效率也并非很高。

另外有一些笔记本电脑的显卡好像是不支持的这中方法的,也就是glTexImage2D函数的调用依然很耗时。

显示函数代码:

如果是简单的直接显示

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (GLsizei)HwManager.getImageWidth(), (GLsizei)HwManager.getImageHeight(), GL_BGR, GL_UNSIGNED_BYTE, pGLBuffer);
GLenum result = glGetError();
qDebug() << "GLenum:" << result;
GLdouble viewMatrix[16];
glGetDoublev(GL_MODELVIEW_MATRIX, viewMatrix);
GLdouble projectionMatrix[16];
glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix);
GLint    viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);


glBindTexture(GL_TEXTURE_2D, texture);
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, pboIds[index]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (GLsizei)HwManager.getImageWidth(), (GLsizei)HwManager.getImageHeight(), GL_BGR, GL_UNSIGNED_BYTE, 0);
// start to modify pixel values ///////////////////
// bind PBO to update pixel values
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, pboIds[nextIndex]);
// map the buffer object into client's memory
// Note that glMapBuffer() causes sync issue.
// If GPU is working with this buffer, glMapBuffer() will wait(stall)
// for GPU to finish its job. To avoid waiting (stall), you can call
// first glBufferData() with NULL pointer before glMapBuffer().
// If you do that, the previous data in PBO will be discarded and
// glMapBuffer() returns a new allocated pointer immediately
// even if GPU is still working with the previous data.
glBufferDataARB(GL_PIXEL_UNPACK_BUFFER, DATA_SIZE3, 0, GL_STREAM_DRAW);
ptr = (GLubyte*)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
if (ptr)
{
	//
	if (pGLBuffer != NULL)
	{
		mutex.lock();
		memcpy(ptr, pGLBuffer, DATA_SIZE3);
		//ptr = pGLBuffer;
		mutex.unlock();
	}
	glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER);  // release pointer to mapping buffer
}
glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER);  // release pointer to mapping buffer
// measure the time modifying the mapped buffer
// it is good idea to release PBOs with ID 0 after use.
// Once bound with 0, all pixel operations behave normal ways.
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, 0);

Qt 中使用拓展函数需要窗口类区继承一些Qt的封装类。

class myQtOpenglWindow :public QGLWidget,protected QOpenGLFunctions, protected QOpenGLExtension_ARB_vertex_buffer_object
{
...

}

 

你可能感兴趣的:(图形学,C/C++)