Bor*_*ris 4 c++ opengl multithreading visual-studio
我为Windows创建了一个简单的OpenGL应用程序.它创建一个窗口,然后使用OpenGL命令为其绘制一个三角形.这按预期工作.
稍后我想将我的绘图代码封装到DLL中,以便可以在C#WinForms应用程序中使用它来绘制到WinForm.为此,我将绘图代码移动到一个单独的类和线程.我的想法是,我可以将我的班级"附加"到任何现有的窗口,让我的线程吸引它.
可悲的是,事情似乎并非那么简单.一旦我将窗口创建和绘制内容分离到不同的线程,屏幕就会全黑.绘图调用似乎不再起作用了.
有没有办法让我的绘图完全独立于窗口创建和主UI线程?
编辑:这里有一些代码:-)
这是我的渲染器(从UI线程调用时起作用,从后台线程调用时不起作用):
// Constructor
Renderer::Renderer(HWND hwnd, size_t windowWidth, size_t windowHeight)
:
mContext(hwnd)
{
mWindowWidth = windowWidth;
mWindowHeight = windowHeight;
mHdc = GetDC(hwnd);
// From now on everything is similar to initializing a context on any other hdc
PIXELFORMATDESCRIPTOR pfd;
ZeroMemory(&pfd, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 24;
int iFormat = ChoosePixelFormat(mHdc, &pfd);
SetPixelFormat(mHdc, iFormat, &pfd);
mHrc = wglCreateContext(mHdc);
wglMakeCurrent(mHdc, mHrc);
// Set up OpenGL
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glLoadIdentity();
glViewport(0, 0, windowWidth, windowHeight);
glOrtho(0, windowWidth, windowHeight, 0, -1, 1);
}
// Draws the scene
void Renderer::Draw()
{
wglMakeCurrent(mHdc, mHrc);
glClear(GL_COLOR_BUFFER_BIT);
glColor4f(1, 0, 1, 1);
glBegin(GL_QUADS);
glColor3f(1.0, 1.0, 1.0);
glVertex3f(0.0f, float(mWindowHeight/2), 0.0f);
glVertex3f(float(mWindowWidth/2), float(mWindowHeight/2), 0.0f);
glVertex3f(float(mWindowWidth/2), 0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glEnd();
glFlush();
SwapBuffers(mHdc);
}
Run Code Online (Sandbox Code Playgroud)
这是我从后台线程调用渲染器的方式:
// Constructor
BackgroundRenderer::BackgroundRenderer(HWND hwnd, uint32_t windowWidth, uint32_t windowHeight)
:
mCancelThread(false)
{
// Initialize OpenGL
mRenderer = std::make_shared<Renderer>(hwnd, windowWidth, windowHeight);
// Start rendering thread
mRenderingThread = std::thread(&BackgroundRenderer::BackgroundLoop, this);
}
// Destructor
BackgroundRenderer::~BackgroundRenderer()
{
// Stop rendering thread
mCancelThread = true;
mRenderingThread.join();
}
// The background rendering loop
void BackgroundRenderer::BackgroundLoop()
{
while (!mCancelThread)
{
// Draw stuff
mRenderer->Draw();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的主要内容:
// Message loop
LONG WINAPI WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CLOSE:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
// Window creation
HWND CreateApplicationWindow(char* title, int x, int y, int width, int height, int nCmdShow)
{
HWND hWnd;
WNDCLASS wc;
static HINSTANCE hInstance = 0;
if (!hInstance)
{
hInstance = GetModuleHandle(NULL);
wc.style = CS_OWNDC;
wc.lpfnWndProc = (WNDPROC)WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "OpenGL";
RegisterClass(&wc);
}
hWnd = CreateWindowA("OpenGL", title, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, x, y, width, height, NULL, NULL, hInstance, NULL);
ShowWindow(hWnd, nCmdShow);
return hWnd;
}
// Main entry point of application
int APIENTRY WinMain(HINSTANCE hCurrentInst, HINSTANCE hPreviousInst, LPSTR lpszCmdLine, int nCmdShow)
{
HWND hWnd = CreateApplicationWindow("Test", 0, 0, 640, 480, nCmdShow);
// This renders from another thread (not working)
auto backgroundRenderer = std::make_shared<BackgroundRenderer>(hWnd, 640, 480);
// This would render in the UI thread (works)
//auto renderer = std::make_shared<Renderer>(hWnd, 640, 480);
MSG msg;
while (GetMessage(&msg, hWnd, 0, 0))
{
// This would render in the UI thread (works)
//renderer->Draw();
TranslateMessage(&msg);
DispatchMessage(&msg);
}
DestroyWindow(hWnd);
return msg.wParam;
}
Run Code Online (Sandbox Code Playgroud)
两个基本规则是:
但是,特定OpenGL上下文与特定窗口(使用具有多个窗口的单个OpenGL上下文的Win32测试程序)或特定线程之间没有严格的关联.您始终可以将OpenGL上下文从一个线程迁移到另一个线程.
两种常用方法是:
要么
| 归档时间: |
|
| 查看次数: |
2448 次 |
| 最近记录: |