使用OpenGL绘制三角形:如何使用两个类进行管理
Posted
技术标签:
【中文标题】使用OpenGL绘制三角形:如何使用两个类进行管理【英文标题】:Triangle drawing with OpenGL: how to manage with two classes 【发布时间】:2016-04-30 12:32:16 【问题描述】:我对这段代码有疑问。没有错误或警告,但仅在调整窗口大小时会出现三角形。
我需要纠正这个问题。头文件包含这两个类:Window 和 WindowGL(基于类的继承)。这段代码有什么问题?
#ifndef OPENGL_H
#define OPENGL_H
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
class Window
protected:
HWND hwnd;
long clientWidh;
long clientHeight;
public:
Window() :hwnd(NULL);
LRESULT WndProc(HWND , UINT , WPARAM , LPARAM );
bool Initialize(HINSTANCE appHandle, POINT windowPosition, POINT windowSize);
WPARAM Run();
;
class WindowGL : public Window
private:
HGLRC handleRC;
HDC handleDC;
bool InitWGL(HWND hwnd);
void DestroyWGL();
void SetScene(bool isometricProjection);
void Render();
public:
WindowGL() :Window(), handleRC(NULL), handleDC(NULL);
LRESULT WndProc(HWND, UINT , WPARAM, LPARAM );
bool SetPixels(HDC) const;
window;
#endif
还有.cpp文件:
#include "myHeaderGL.h"
#include <cstdlib>
#include <gl/GL.h>
#include <gl/GLU.h>// not used in this example
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
return window.WndProc(hWnd, message, wParam, lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
POINT windowPosition = 100, 100 ;
POINT windowSize = 800, 600 ;
if (!window.Initialize(hInstance, windowPosition, windowSize))
MessageBox(NULL, "Initialisation fail.", "OpenGL Application", MB_OK | MB_ICONERROR);
return EXIT_FAILURE;
else return window.Run();
LRESULT Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
switch (message)
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_PAINT:
RECT rect;
GetClientRect(hWnd, &rect);
clientWidh = rect.right - rect.left;
clientHeight = rect.bottom - rect.top;
break;
default:
return(DefWindowProc(hWnd, message, wParam, lParam));
return 0L;
LRESULT WindowGL::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
long result = Window::WndProc(hWnd, message, wParam, lParam);
switch (message)
case WM_CREATE:
if (!InitWGL(hWnd))
MessageBox(NULL, "Render context fail to load", "My OpenGL", MB_OK | MB_ICONERROR);
return EXIT_FAILURE;
SetScene(false);
break;
case WM_DESTROY:
DestroyWGL();
break;
case WM_SIZE:
SetScene(false);
break;
case WM_PAINT:
Render();
ValidateRect(hWnd, NULL);
break;
//default:
//return (DefWindowProc(hWnd, message, wParam, lParam));
return result;
bool Window::Initialize(HINSTANCE appHandle, POINT windowPosition, POINT windowSize)
char windowName[] = "My 1 OpenGL";
WNDCLASSEX wc;
wc.cbSize = sizeof(wc);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = (WNDPROC)::WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = appHandle;
wc.hIcon = NULL;
wc.hIconSm = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = windowName;
if (RegisterClassEx(&wc) == 0) return false;
hwnd = CreateWindow(
windowName,
windowName,
WS_OVERLAPPEDWINDOW,
windowPosition.x, windowPosition.y,
windowSize.x, windowSize.y,
NULL,
NULL,
appHandle,
NULL
);
if (!hwnd) return false;
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
return true;
WPARAM Window::Run()
MSG msg = 0;
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
TranslateMessage(&msg);
DispatchMessage(&msg);
else
window.Render();
return msg.wParam;
bool WindowGL::SetPixels(HDC handleDC) const
PIXELFORMATDESCRIPTOR pfd;
ZeroMemory(&pfd, sizeof(pfd));
pfd.nVersion = 1;
pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 32;
pfd.iLayerType = PFD_MAIN_PLANE;
int pixFormat = ChoosePixelFormat(handleDC, &pfd);
if (pixFormat == 0) return false;
if (!SetPixelFormat(handleDC, pixFormat, &pfd)) return false;
return true;
bool WindowGL::InitWGL(HWND hwnd)
handleDC= ::GetDC(hwnd);
if (!SetPixels(handleDC)) return false;
handleRC = wglCreateContext(handleDC);
if (handleRC == NULL) return false;
if (!wglMakeCurrent(handleDC, handleRC)) return false;
return true;
void WindowGL::SetScene(bool isometricProjection)
glViewport(0, 0, clientWidh, clientHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float wsp = clientHeight / (float)clientWidh;
if (!isometricProjection)
glFrustum(-1.0f, 1.0f, wsp*-1.0f, wsp*1.0f, 1.0f, 10.0f);
else
glOrtho(-1.0f, 1.0f, wsp*-1.0f, wsp*1.0f, 1.0f, 10.0f);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_DEPTH_TEST);
void WindowGL::DestroyWGL()
wglMakeCurrent(NULL, NULL);
wglDeleteContext(handleRC);
::ReleaseDC(hwnd, handleDC);
void WindowGL::Render()
const float x0 = 1.0f;
const float y0 = 1.0f;
const float z0 = 1.0f;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -3.0f);
glColor4f(1.0f, 1.0f, 0.0f, 1.0f);
glBegin(GL_TRIANGLES);
glVertex3f(-x0, -y0, 0.0f);
glVertex3f( x0, -y0, 0.0f);
glVertex3f(0.0f, y0, 0.0f);
glEnd();
SwapBuffers(handleDC);
【问题讨论】:
【参考方案1】:您仅在发送WM_PAINT
时才调用Render()
,请尝试每隔几毫秒在Run()
中调用它一次。
使用 PeekMessage 更改 GetMessage 以防止代码停滞,然后仅在有要读取的消息时使用 GetMessage。
编辑
while(msg.message != WM_QUIT)
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
TranslateMessage(&msg);
DispatchMessage(&msg);
Render();
sleep(10); // If you don't want to update the screen too fast
编辑 2
LRESULT Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
switch (message)
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_SIZE || WM_PAINT: // <- the problem was here
RECT rect;
GetClientRect(hWnd, &rect);
clientWidh = rect.right - rect.left;
clientHeight = rect.bottom - rect.top;
break;
default:
return(DefWindowProc(hWnd, message, wParam, lParam));
return 0L;
【讨论】:
抱歉。我已经更新了 Run() 函数。但仍然是同样的问题。不改变窗口大小就没有三角形。 我编辑了代码,它应该给你正确的想法。 是的,我之前编辑了上面的代码 - 并用“更好的”函数 PeekMessage() 更改了 Run() 但仍然没有效果。头类是这样构建的,我什至不能在 Run() 中调用 Render()。相反,我可以调用:window. Render() 但它不会改变任何东西。代码来自物理学家写的书,但作者没有提供源代码。你能试着在你的机器上编译这些东西吗?感谢您的帮助。 非常感谢您 FedeWar。我检查了我的书,发现了什么?有一个错误。我可能会把它寄回商店。再次感谢,我该如何奖励您? 不客气,奖励我选择这个答案为最佳。以上是关于使用OpenGL绘制三角形:如何使用两个类进行管理的主要内容,如果未能解决你的问题,请参考以下文章