OpenGL无法在macOS的QtWidget中绘图

yuvru6vn  于 2022-11-04  发布在  Mac
关注(0)|答案(1)|浏览(334)

我尝试在macOS平台上使用OpenGL和Qt的合并,系统版本是:Monterey。
因为我想自己创建OpenGL上下文,并将渲染线程与UI线程(主线程,这就是我无法使用QOpenglWidget的原因)分开,所以我执行了以下步骤:
1.使用NSOpenGLContext创建openGLContext
1.调用NSOpenGlContext.setView,setView的参数为(NSView*)QWidget::winId()
1.在Qt的showEvent中创建一个线程,用于调用OpenGL API
结果,窗口小部件可以出现,但什么也没有出现。(即使我调用glClear来清除颜色,但颜色不能出现在窗口(视图)中。)
但与此同时,当我在macOS中使用RenderDoc捕捉帧时,我可以正确地获得渲染结果。
我曾怀疑QT改变了默认的帧缓冲区,所以我试着调用glBindFrameBuffer(GL_FRAMEBUFFER,0),但它没有起作用。
然后我在Windows中使用相同的代码(使用wglXXX函数创建OpenGL上下文),它确实工作并正确渲染。
那么我应该如何在QtWidget中使用OpenGL呢?
代码如下:
在macOS中创建OpenGL上下文:

  1. # import <Cocoa/Cocoa.h>
  2. # include "MacosOpenGLContext.h"
  3. # include <iostream>
  4. # include "MacosOpenGLContext.h"
  5. MacosOpenGLContext::MacosOpenGLContext(NSView* winID,SHK::Setting setting){
  6. this->createGLContext(winID,setting);
  7. }
  8. void MacosOpenGLContext::makeCurrent(){
  9. if(this->_openGLContext!=nullptr){
  10. [this->_openGLContext makeCurrentContext];
  11. }
  12. }
  13. void MacosOpenGLContext::flushBuffer(){
  14. if(this->_openGLContext!=nullptr){
  15. [this->_openGLContext flushBuffer];
  16. }
  17. }
  18. void MacosOpenGLContext::setView(WinID id){
  19. if(this->_openGLContext!=nullptr){
  20. [this->_openGLContext setView:(NSView*)id];
  21. }
  22. }
  23. void MacosOpenGLContext::update(){
  24. if(this->_openGLContext!=nullptr){
  25. [this->_openGLContext update];
  26. }
  27. }
  28. bool MacosOpenGLContext::isCreateSuccess(){
  29. return !(this->_openGLContext==nullptr);
  30. }
  31. void MacosOpenGLContext::makeNullCurrent(){
  32. }
  33. void MacosOpenGLContext::createGLContext(NSView* winID,SHK::Setting setting){
  34. _openGLContext=nullptr;
  35. NSOpenGLPixelFormatAttribute attrs[] = {
  36. NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core,
  37. NSOpenGLPFAColorSize,32,
  38. NSOpenGLPFADepthSize,16,
  39. NSOpenGLPFADoubleBuffer,
  40. NSOpenGLPFAAccelerated,
  41. 0
  42. };
  43. NSOpenGLPixelFormat* _pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
  44. _pixelFormat=[[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
  45. if(_pixelFormat==nullptr){
  46. std::cout<<"create macos pixelFormat failed";
  47. return;
  48. }
  49. this->_openGLContext=
  50. [[NSOpenGLContext alloc] initWithFormat: _pixelFormat shareContext: nullptr];
  51. if(this->_openGLContext==nullptr){
  52. std::cout<<"the opengl context create failed";
  53. return;
  54. }
  55. [_pixelFormat release];
  56. _pixelFormat=nullptr;
  57. this->setView((WinID)winID);
  58. // this->makeCurrent();
  59. }
  60. MacosOpenGLContext::MacosOpenGLContext(WinID winID){
  61. SHK::Setting settings;
  62. settings.colorBits = 24;
  63. settings.depthBits = 24;
  64. settings.stencilBits = 8;
  65. settings.majorVersion = 4;
  66. settings.minorVersion = 1;
  67. this->createGLContext((NSView*)winID,settings);
  68. }

小部件代码如下:

  1. # include "TestQtOpenGL.hpp"
  2. # if defined(MACOS)
  3. # include "../platform/Macos/MacosOpenGLContext.h"
  4. # elif defined(WIN)
  5. # include "../platform/Windows/Win32OpenGLContext.hpp"
  6. # endif
  7. # include <GL/glew.h>
  8. # include <iostream>
  9. # include "../Shader.hpp"
  10. const char *vertexShaderSource = "#version 330 core\n"
  11. "layout (location = 0) in vec3 aPos;\n"
  12. "void main()\n"
  13. "{\n"
  14. " gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
  15. "}\0";
  16. const char *fragmentShaderSource = "#version 330 core\n"
  17. "out vec4 FragColor;\n"
  18. "void main()\n"
  19. "{\n"
  20. " FragColor = vec4(0.0f, 1.0f, 0.0f, 1.0f);\n"
  21. "}\n\0";
  22. TestQtOpenGL::TestQtOpenGL()
  23. {
  24. # if defined(MACOS)
  25. _context = std::make_shared<MacosOpenGLContext>((WinID)winId());
  26. # elif defined(WIN)
  27. _context = std::make_shared<Win32OpenGLContext>((HWND)winId());
  28. # endif
  29. }
  30. void TestQtOpenGL::paintEvent(QPaintEvent* event)
  31. {
  32. QWidget::paintEvent(event);
  33. }
  34. void TestQtOpenGL::showEvent(QShowEvent* event)
  35. {
  36. QWidget::showEvent(event);
  37. _thread=std::thread([this](){
  38. this->_context->setView(WinID (this->winId()));
  39. this->_context->update();
  40. this->_context->makeCurrent();
  41. if(!_inited){
  42. if(glewInit()!=GLEW_OK){
  43. std::cout<<"init glew failed"<<std::endl;
  44. }
  45. _inited = true;
  46. }
  47. {
  48. std::shared_ptr<TOOLS::Shader> _shader;
  49. unsigned int _vao, _vbo;
  50. if (glewInit() == GLEW_OK)
  51. {
  52. _shader = std::make_shared<TOOLS::Shader>("TestG3DShader");
  53. {
  54. // this->makeCurrent();
  55. float points[] = {0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
  56. glGenVertexArrays(1, &_vao);
  57. glBindVertexArray(_vao);
  58. glGenBuffers(1, &_vbo);
  59. glBindBuffer(GL_ARRAY_BUFFER, _vbo);
  60. glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
  61. glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
  62. glEnableVertexAttribArray(0);
  63. }
  64. }
  65. while(true){
  66. glBindFramebuffer(GL_FRAMEBUFFER,0);
  67. glViewport(0,0,400,400);
  68. glBindVertexArray(_vao);
  69. glClearColor(0.0f, 0.3f, 0.0f, 1.0f);
  70. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  71. _shader->use();
  72. glDrawArrays(GL_TRIANGLES, 0, 3);
  73. this->_context->flushBuffer();
  74. }
  75. }
  76. });
  77. _thread.detach();
  78. }
  79. void TestQtOpenGL::resizeEvent(QResizeEvent* event)
  80. {
  81. QWidget::resizeEvent(event);
  82. this->_context->update();
  83. }

macOS renderDoc结果如下:renderDoc result
QWidget结果如下:enter image description here

cs7cruho

cs7cruho1#

我也遇到了同样的问题,QWidget不能渲染,但QOpenGlWidget可以,可能是NSView层的问题

相关问题