我尝试在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上下文:
# import <Cocoa/Cocoa.h>
# include "MacosOpenGLContext.h"
# include <iostream>
# include "MacosOpenGLContext.h"
MacosOpenGLContext::MacosOpenGLContext(NSView* winID,SHK::Setting setting){
this->createGLContext(winID,setting);
}
void MacosOpenGLContext::makeCurrent(){
if(this->_openGLContext!=nullptr){
[this->_openGLContext makeCurrentContext];
}
}
void MacosOpenGLContext::flushBuffer(){
if(this->_openGLContext!=nullptr){
[this->_openGLContext flushBuffer];
}
}
void MacosOpenGLContext::setView(WinID id){
if(this->_openGLContext!=nullptr){
[this->_openGLContext setView:(NSView*)id];
}
}
void MacosOpenGLContext::update(){
if(this->_openGLContext!=nullptr){
[this->_openGLContext update];
}
}
bool MacosOpenGLContext::isCreateSuccess(){
return !(this->_openGLContext==nullptr);
}
void MacosOpenGLContext::makeNullCurrent(){
}
void MacosOpenGLContext::createGLContext(NSView* winID,SHK::Setting setting){
_openGLContext=nullptr;
NSOpenGLPixelFormatAttribute attrs[] = {
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core,
NSOpenGLPFAColorSize,32,
NSOpenGLPFADepthSize,16,
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAAccelerated,
0
};
NSOpenGLPixelFormat* _pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
_pixelFormat=[[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
if(_pixelFormat==nullptr){
std::cout<<"create macos pixelFormat failed";
return;
}
this->_openGLContext=
[[NSOpenGLContext alloc] initWithFormat: _pixelFormat shareContext: nullptr];
if(this->_openGLContext==nullptr){
std::cout<<"the opengl context create failed";
return;
}
[_pixelFormat release];
_pixelFormat=nullptr;
this->setView((WinID)winID);
// this->makeCurrent();
}
MacosOpenGLContext::MacosOpenGLContext(WinID winID){
SHK::Setting settings;
settings.colorBits = 24;
settings.depthBits = 24;
settings.stencilBits = 8;
settings.majorVersion = 4;
settings.minorVersion = 1;
this->createGLContext((NSView*)winID,settings);
}
小部件代码如下:
# include "TestQtOpenGL.hpp"
# if defined(MACOS)
# include "../platform/Macos/MacosOpenGLContext.h"
# elif defined(WIN)
# include "../platform/Windows/Win32OpenGLContext.hpp"
# endif
# include <GL/glew.h>
# include <iostream>
# include "../Shader.hpp"
const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(0.0f, 1.0f, 0.0f, 1.0f);\n"
"}\n\0";
TestQtOpenGL::TestQtOpenGL()
{
# if defined(MACOS)
_context = std::make_shared<MacosOpenGLContext>((WinID)winId());
# elif defined(WIN)
_context = std::make_shared<Win32OpenGLContext>((HWND)winId());
# endif
}
void TestQtOpenGL::paintEvent(QPaintEvent* event)
{
QWidget::paintEvent(event);
}
void TestQtOpenGL::showEvent(QShowEvent* event)
{
QWidget::showEvent(event);
_thread=std::thread([this](){
this->_context->setView(WinID (this->winId()));
this->_context->update();
this->_context->makeCurrent();
if(!_inited){
if(glewInit()!=GLEW_OK){
std::cout<<"init glew failed"<<std::endl;
}
_inited = true;
}
{
std::shared_ptr<TOOLS::Shader> _shader;
unsigned int _vao, _vbo;
if (glewInit() == GLEW_OK)
{
_shader = std::make_shared<TOOLS::Shader>("TestG3DShader");
{
// this->makeCurrent();
float points[] = {0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
glGenVertexArrays(1, &_vao);
glBindVertexArray(_vao);
glGenBuffers(1, &_vbo);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
}
}
while(true){
glBindFramebuffer(GL_FRAMEBUFFER,0);
glViewport(0,0,400,400);
glBindVertexArray(_vao);
glClearColor(0.0f, 0.3f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_shader->use();
glDrawArrays(GL_TRIANGLES, 0, 3);
this->_context->flushBuffer();
}
}
});
_thread.detach();
}
void TestQtOpenGL::resizeEvent(QResizeEvent* event)
{
QWidget::resizeEvent(event);
this->_context->update();
}
macOS renderDoc结果如下:renderDoc result
QWidget结果如下:enter image description here
1条答案
按热度按时间cs7cruho1#
我也遇到了同样的问题,QWidget不能渲染,但QOpenGlWidget可以,可能是NSView层的问题