我为Windows创建了一个简单的OpenGL应用程序。它创建一个窗口,然后使用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);
}
这是怎么了我打电话从后台线程渲染:
// 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));
}
}
而且这里是我的主要粘合一起:
// 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;
}
好的,您的发布代码与GLFW无关,那么您为什么提到它呢? – InternetAussie
我之前使用过GLFW。为了简化事情,我将其从我的项目中彻底删除(然后我将上面的代码添加到此主题中)。但问题依然存在,无论有无GLFW。 – Boris