又一种Qt + OpenGL 的离屏渲染方法
来源:互联网 发布:mac 上的游戏 编辑:程序博客网 时间:2024/05/23 14:00
前面的博客《Qt + OpenGL + 离屏渲染》介绍了一种离屏渲染的办法:先在framebuffer里面绘制,然后把绘制的结果转化为QImage。但是这样做涉及到从显存(framebuffer)到内存QImage的传递,降低效率。本博客介绍一种新办法,从显存到显存,不必经由内存。
本文受了
http://www.cppblog.com/init/archive/2012/02/16/165778.aspx
的启发。
上代码:
pro文件
#-------------------------------------------------## Project created by QtCreator 2017-12-16T21:21:01##-------------------------------------------------QT += core gui openglgreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsTARGET = frmBuffTEMPLATE = appSOURCES += main.cpp\ mainwindow.cppHEADERS += mainwindow.hLIBS += -lopengl32 -lGLU32
h文件
#ifndef MAINWINDOW_H#define MAINWINDOW_H#include <QOpenGLWidget>#include <QOpenGLFunctions>//#include <gl/GLU.H>class MainWindow : public QOpenGLWidget, protected QOpenGLFunctions{ Q_OBJECTpublic: MainWindow(QWidget *parent = 0); ~MainWindow(); GLuint m_uiFBO; GLuint m_uiDepthBuff; GLuint m_uiTex;protected: void initializeGL(); void resizeGL(int, int); void paintGL();};#endif // MAINWINDOW_H
cpp文件
#include "mainwindow.h"#include <QMessageBox>MainWindow::MainWindow(QWidget *parent) : QOpenGLWidget(parent){}MainWindow::~MainWindow(){}void MainWindow::initializeGL(){ initializeOpenGLFunctions(); glGenFramebuffers(1, &m_uiFBO); glBindFramebuffer(GL_FRAMEBUFFER, m_uiFBO); glGenRenderbuffers(1, &m_uiDepthBuff); glBindRenderbuffer(GL_RENDERBUFFER, m_uiDepthBuff); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 256, 256); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_uiDepthBuff); glGenTextures(1,&m_uiTex); glBindTexture(GL_TEXTURE_2D, m_uiTex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,256,256,0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glGenerateMipmap(GL_TEXTURE_2D); glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,m_uiTex,0); GLenum status = glCheckFramebufferStatus( GL_FRAMEBUFFER); QMessageBox msg; switch( status ) { case GL_FRAMEBUFFER_UNSUPPORTED_EXT: msg.setText("GL_FRAMEBUFFER_UNSUPPORTED_EXT!"); msg.exec(); break; }}void MainWindow::paintGL(){ glBindFramebuffer(GL_FRAMEBUFFER, m_uiFBO); glPushAttrib(GL_VIEWPORT_BIT); glViewport(0,0,256,256); glClearColor(0.0,1.0,0.0,0.0);//frambuffer black glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, m_uiTex); glPopAttrib(); glBindFramebuffer(GL_FRAMEBUFFER,0); glClearColor( 0.9f, 0.2f, 0.2f, 1.0f ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, m_uiTex); GLfloat arrCubeVertices[] = { 0,0, 0,0,0, 0,1, 0,0.5,0, 1,1, 0.5,0.5,0, 1,0, 0.5,0,0, }; glInterleavedArrays( GL_T2F_V3F, 0, arrCubeVertices ); glDrawArrays( GL_QUADS, 0, 20 );}void MainWindow::resizeGL(int w, int h){}
上面 的 例子 画出来 的 纹理不稳定--几乎 每次最小化窗口都会改变纹理的外观。下面给出另一种更稳定的绘制办法:
#include "mainwindow.h"#include <QMessageBox>MainWindow::MainWindow(QWidget *parent) : QOpenGLWidget(parent){}MainWindow::~MainWindow(){}void MainWindow::initializeGL(){ initializeOpenGLFunctions(); glGenFramebuffers(1, &m_uiFBO); glBindFramebuffer(GL_FRAMEBUFFER, m_uiFBO); glGenRenderbuffers(1, &m_uiDepthBuff); glBindRenderbuffer(GL_RENDERBUFFER, m_uiDepthBuff); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 256, 256); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_uiDepthBuff); glGenTextures(1,&m_uiTex); glBindTexture(GL_TEXTURE_2D, m_uiTex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,256,256,0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glGenerateMipmap(GL_TEXTURE_2D); glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,m_uiTex,0); GLenum status = glCheckFramebufferStatus( GL_FRAMEBUFFER); QMessageBox msg; switch( status ) { case GL_FRAMEBUFFER_UNSUPPORTED_EXT: msg.setText("GL_FRAMEBUFFER_UNSUPPORTED_EXT!"); msg.exec(); break; }glPushAttrib(GL_VIEWPORT_BIT); glViewport(0,0,256,256); glClearColor(0.0,1.0,0.0,0.0);//frambuffer black glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glPopAttrib();glBindTexture(GL_TEXTURE_2D, 0);glBindFramebuffer(GL_FRAMEBUFFER, 0);}void MainWindow::paintGL(){ glClearColor( 0.9f, 0.2f, 0.2f, 1.0f ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glLoadIdentity();GLfloat arrTex[] = {0.0,0.0,1.0, 0.0,1.0, 1.0, 0.0, 1.0};GLfloat arrVertex[] = {0.0,0.0, 50.0, 0.0, 50.0, 50.0, 0.0, 50.0}; glBindTexture(GL_TEXTURE_2D, m_uiTex); /*GLfloat arrCubeVertices[] = { 0,0, 0,0,0, 0,1, 0,50,0, 1,1, 50,50,0, 1,0, 50,0,0, };*/ //glInterleavedArrays( GL_T2F_V3F, 0, arrCubeVertices ); //glDrawArrays( GL_QUADS, 0, 20 );//glBindTexture(GL_TEXTURE_2D, 0);glEnable(GL_TEXTURE_2D);glEnableClientState(GL_VERTEX_ARRAY);glEnableClientState(GL_TEXTURE_COORD_ARRAY);glTexCoordPointer(2, GL_FLOAT, 0, arrTex);glVertexPointer(2, GL_FLOAT, 0, &arrVertex[0]); glDrawArrays(GL_QUADS, 0, 4);glDisableClientState(GL_VERTEX_ARRAY);glDisableClientState(GL_TEXTURE_COORD_ARRAY);glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D);}void MainWindow::resizeGL(int w, int h){glViewport(0,0,w,h);glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-50.0, 50.0, -50.0, 50.0, -1.0, 1.0); glMatrixMode(GL_MODELVIEW);}
在上面的例子里,我建立了framebuffer m_uiFBO,然后建立renderbuffer m_uiDepthBuff 和 纹理 m_uiTex。
在paintGL()函数里,我先利用 语句 glBindFrameBuffer(GL_FAMEBUFFER, m_uiFBO),指定纹理作为绘制对象,把纹理填为绿色。然后调用glBindFrameBuffer(GL_FAMEBUFFER, 0),把绘制对象变更为当前窗体。此时只要把纹理的内容通过 glInterleaveArrays() 和 glDrawArrays() 绘制到屏幕右上角即可。而屏幕自身的颜色由函数glClearColor(0.9, 0.2, 0.2, 1.0);决定。
效果:
阅读全文
0 0
- 又一种Qt + OpenGL 的离屏渲染方法
- Qt + OpenGL + 离屏渲染
- 基于 qt 的 Opengl 渲染 YUV
- OpenGL离屏渲染
- opengl离屏渲染
- Qt OpenGL渲染文字
- 如何将OpenGL渲染的图片保存到本地(正常渲染和离屏渲染)
- opengl离屏渲染图片
- Android OpenGL离屏渲染
- QT下使用OpenGL渲染Mesh的框架
- 适用于OpenGL离屏渲染上下文的初始化代码
- OpenGL基于帧缓存FBO的离屏渲染
- OpenGL 的渲染流水线
- OpenGL 的渲染流水线
- OpenGL 的渲染流水线
- OpenGL 的渲染流水线
- OpenGL 的渲染流水线
- OpenGL 的渲染流水线
- IO设计模式:Reactor和Proactor对比
- Q-1-HTML-1
- mysql常用操作
- hdu 1372 Knight Moves(骑士遍历/跳马问题)
- mongo安全:增加用户名密码
- 又一种Qt + OpenGL 的离屏渲染方法
- el详解
- 基于ACE Proactor框架下高并发、大容量吞吐程序设计既最近的一个产品开发总结
- golang开发环境(2016.9.16)
- Git 初接触 (三) Git的撤销操作 git reset HEAD -- <file>
- Golang里面使用protobuf(proto3)
- numpy基础教程—数组(向量)的属性和方法
- visual studio code
- 凑单助手1.0