I want to do offscreen rendering, but have no luck
These are the codes, I have no any idea why the FBO(frame buffer object)
always give me a blank image

What I want to do is, the texture after render will write to the FBO
after that, I could transfer the data of fbo into QImage by toImage()

.hpp
Qt Code:
  1. #ifndef OFFSCREENEXP_HPP
  2. #define OFFSCREENEXP_HPP
  3.  
  4. #include <QOpenGLFunctions>
  5. #include <QWindow>
  6.  
  7. class QImage;
  8. class QOpenGLContext;
  9.  
  10. class offScreenExp : public QWindow, protected QOpenGLFunctions
  11. {
  12. public:
  13. explicit offScreenExp(QWindow *parent = 0);
  14.  
  15. QImage render();
  16.  
  17. private:
  18. QOpenGLContext *context_;
  19. };
  20.  
  21. #endif // OFFSCREENEXP_HPP
To copy to clipboard, switch view to plain text mode 

.cpp
Qt Code:
  1. #include <QImage>
  2. #include <QOpenGLBuffer>
  3. #include <QOpenGLContext>
  4. #include <QOpenGLFramebufferObject>
  5. #include <QOpenGLShaderProgram>
  6. #include <QString>
  7. #include <QWidget>
  8.  
  9. #include <QDebug>
  10.  
  11. #include "offScreenExp.hpp"
  12.  
  13. offScreenExp::offScreenExp(QWindow *parent) :
  14. QWindow(parent),
  15. context_(nullptr)
  16. {
  17. setSurfaceType(QWindow::OpenGLSurface);
  18. setFormat(QSurfaceFormat());
  19. create();
  20. }
  21.  
  22. QImage offScreenExp::render()
  23. {
  24. //create the context
  25. if (!context_) {
  26. context_ = new QOpenGLContext(this);
  27. QSurfaceFormat format;
  28. context_->setFormat(format);
  29.  
  30. if (!context_->create())
  31. qFatal("Cannot create the requested OpenGL context!");
  32. }
  33.  
  34. context_->makeCurrent(this);
  35. initializeOpenGLFunctions();
  36.  
  37. //load image
  38. QString const prefix("/Users/Qt/program/experiment_apps_and_libs/openGLTest/simpleGPGPU/");
  39. QImage img(prefix + "images/emili.jpg");
  40. if(img.isNull()){
  41. qFatal("image is null");
  42. }
  43.  
  44. //if(glCheckFramebufferStatus(fbo.handle()) != GL_FRAMEBUFFER_COMPLETE){
  45. // qDebug()<<"frame buffer error";
  46. //}
  47. qDebug()<<"has opengl fbo : "<<QOpenGLFramebufferObject::hasOpenGLFramebufferObjects();
  48.  
  49. //use two triangles two cover whole screen
  50. std::vector<GLfloat> const vertex{
  51. -1.0f, 1.0f, 0.0f, 1.0f,
  52. 1.0f, 1.0f, 0.0f, 1.0f,
  53. -1.0f, -1.0f, 0.0f, 1.0f,
  54. 1.0f, 1.0f, 0.0f, 1.0f,
  55. 1.0f, -1.0f, 0.0f, 1.0f,
  56. -1.0f, -1.0f, 0.0f, 1.0f,
  57. };
  58.  
  59. //initialize vbo
  60. QOpenGLBuffer buffer(QOpenGLBuffer::VertexBuffer);
  61. buffer.create();
  62. buffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
  63. buffer.bind();
  64. buffer.allocate(&vertex[0], vertex.size() * sizeof(GLfloat) );
  65. buffer.release();
  66.  
  67. //create texture
  68. GLuint rendered_texture;
  69. glGenTextures(1, &rendered_texture);
  70.  
  71. // "Bind" the newly created texture : all future texture functions will modify this texture
  72. glBindTexture(GL_TEXTURE_2D, rendered_texture);
  73.  
  74. //naive solution, better encapsulate the format in a function
  75. if(img.format() == QImage::Format_Indexed8){
  76. glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, img.width(), img.height(), 0, GL_RED, GL_UNSIGNED_BYTE, img.scanLine(0));
  77. }else if(img.format() == QImage::Format_RGB888){
  78. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.width(), img.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, img.scanLine(0));
  79. }else{
  80. QImage temp = img.convertToFormat(QImage::Format_RGB888);
  81. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.width(), img.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, temp.scanLine(0));
  82. }
  83.  
  84. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  85. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  86. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  87. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  88.  
  89. glBindTexture(GL_TEXTURE_2D, 0);
  90.  
  91. //compile and link program
  92. QOpenGLShaderProgram program;
  93. if(!program.addShaderFromSourceCode(QOpenGLShader::Vertex,
  94. "attribute highp vec4 qt_Vertex;"
  95. "varying highp vec2 qt_TexCoord0;"
  96.  
  97. "void main(void)"
  98. "{"
  99. " gl_Position = qt_Vertex;"
  100. " qt_TexCoord0 = (qt_Vertex.xy + vec2(1.0)) * 0.5;"
  101. "}")){
  102. qDebug()<<"QOpenGLShader::Vertex error : " + program.log();
  103. }
  104.  
  105. // Compile fragment shader
  106. if (!program.addShaderFromSourceCode(QOpenGLShader::Fragment,
  107. "uniform sampler2D source;"
  108. "varying highp vec2 qt_TexCoord0;"
  109.  
  110. "vec3 toGray(vec3 rgb)"
  111. "{"
  112. " return vec3(rgb.r * 0.299 + rgb.g * 0.587 + rgb.b * 0.114);"
  113. "}"
  114.  
  115. "void main(void)"
  116. "{"
  117. "vec3 gray = toGray(texture2D(source, qt_TexCoord0).rgb);"
  118. "gl_FragColor = vec4(gray, 0.0);"
  119. "}"
  120. )){
  121. qDebug()<<"QOpenGLShader::Fragment error : " + program.log();
  122. }
  123.  
  124. // Link shader pipeline
  125. if (!program.link()){
  126. qDebug()<<"link error : " + program.log();
  127. }
  128.  
  129. //render the texture as usual
  130. glClearColor(0, 0, 0, 1);
  131. glClear(GL_COLOR_BUFFER_BIT);
  132. glViewport(0, 0, img.width(), img.height());
  133.  
  134. program.bind();
  135. buffer.bind();
  136. program.enableAttributeArray("qt_Vertex");
  137. program.setAttributeBuffer( "qt_Vertex", GL_FLOAT, 0, 4);
  138.  
  139. glActiveTexture(GL_TEXTURE0);
  140. glBindTexture(GL_TEXTURE_2D, rendered_texture);
  141.  
  142. //bind and create fbo
  143. QOpenGLFramebufferObject fbo(img.size());
  144. qDebug()<<"bind success? : "<<fbo.bind();
  145.  
  146. glDrawArrays(GL_TRIANGLES, 0, buffer.size());
  147.  
  148. program.disableAttributeArray("qt_Vertex");
  149. program.release();
  150. glActiveTexture(0);
  151. glBindTexture(GL_TEXTURE_2D, 0);
  152. buffer.release();
  153.  
  154. QImage result = fbo.toImage();
  155. fbo.release();
  156. context_->doneCurrent();
  157.  
  158. return result;
  159. }
To copy to clipboard, switch view to plain text mode