Last active
March 6, 2019 21:47
-
-
Save fegemo/1f534a2a59d7d289ec48 to your computer and use it in GitHub Desktop.
Um Hello World em OpenGL usando C e a biblioteca windows.h.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <windows.h> | |
#include <GL/gl.h> | |
char *className = "OpenGL"; | |
char *windowName = "Hello World"; | |
int winX = 0, winY = 0; | |
int winWidth = 500, winHeight = 500; | |
HDC hDC; | |
HGLRC hGLRC; | |
HPALETTE hPalette; | |
void desenhaMinhaCena() | |
{ | |
glClearColor(1, 1, 1, 1); | |
glClear(GL_COLOR_BUFFER_BIT); | |
// desenha um quadrado | |
glBegin(GL_TRIANGLE_FAN); | |
glVertex3f(-0.5, -0.5, 0.0); | |
glVertex3f( 0.5, -0.5, 0.0); | |
glVertex3f( 0.5, 0.5, 0.0); | |
glVertex3f(-0.5, 0.5, 0.0); | |
glEnd(); | |
glFlush(); | |
SwapBuffers(hDC); | |
} | |
void redimensiona() | |
{ | |
// define a tela de pintura como a janela toda | |
glViewport(0, 0, winWidth, winHeight); | |
} | |
void setupPixelFormat(HDC hDC) | |
{ | |
PIXELFORMATDESCRIPTOR pfd = { | |
sizeof(PIXELFORMATDESCRIPTOR), // tamanho | |
1, // versão | |
PFD_SUPPORT_OPENGL | | |
PFD_DRAW_TO_WINDOW | | |
PFD_DOUBLEBUFFER, // buffer dpulo | |
PFD_TYPE_RGBA, // formato da cor | |
16, // profundidade da cor | |
0, 0, 0, 0, 0, 0, // bits de cor (ignorado) | |
0, // sem alfa buffer | |
0, // bits de alfa (ignorado) | |
0, // sem accumulation buffer | |
0, 0, 0, 0, // bits de acumulação (ignorado) | |
16, // buffer de profundidade | |
0, // sem stencyl buffer | |
0, // sem buffers auxiliares | |
PFD_MAIN_PLANE, // camada principal | |
0, // reservado | |
0, 0, 0, | |
}; | |
int pixelFormat; | |
pixelFormat = ChoosePixelFormat(hDC, &pfd); | |
if (pixelFormat == 0) { | |
MessageBox(WindowFromDC(hDC), "ChoosePixelFormat falhou.", "Erro", | |
MB_ICONERROR | MB_OK); | |
exit(1); | |
} | |
if (SetPixelFormat(hDC, pixelFormat, &pfd) != TRUE) { | |
MessageBox(WindowFromDC(hDC), "SetPixelFormat falhou.", "Erro", | |
MB_ICONERROR | MB_OK); | |
exit(1); | |
} | |
} | |
void setupPalette(HDC hDC) | |
{ | |
int pixelFormat = GetPixelFormat(hDC); | |
PIXELFORMATDESCRIPTOR pfd; | |
LOGPALETTE* pPal; | |
int paletteSize; | |
DescribePixelFormat(hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); | |
if (pfd.dwFlags & PFD_NEED_PALETTE) { | |
paletteSize = 1 << pfd.cColorBits; | |
} else { | |
return; | |
} | |
pPal = (LOGPALETTE*) | |
malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY)); | |
pPal->palVersion = 0x300; | |
pPal->palNumEntries = paletteSize; | |
// constrói uma paleta RGB | |
{ | |
int redMask = (1 << pfd.cRedBits) - 1; | |
int greenMask = (1 << pfd.cGreenBits) - 1; | |
int blueMask = (1 << pfd.cBlueBits) - 1; | |
int i; | |
for (i=0; i<paletteSize; ++i) { | |
pPal->palPalEntry[i].peRed = | |
(((i >> pfd.cRedShift) & redMask) * 255) / redMask; | |
pPal->palPalEntry[i].peGreen = | |
(((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask; | |
pPal->palPalEntry[i].peBlue = | |
(((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask; | |
pPal->palPalEntry[i].peFlags = 0; | |
} | |
} | |
hPalette = CreatePalette(pPal); | |
free(pPal); | |
if (hPalette) { | |
SelectPalette(hDC, hPalette, FALSE); | |
RealizePalette(hDC); | |
} | |
} | |
LRESULT APIENTRY WndProc( | |
HWND hWnd, | |
UINT message, | |
WPARAM wParam, | |
LPARAM lParam) | |
{ | |
switch (message) { | |
case WM_CREATE: | |
// inicializa renderização em OpenGL | |
hDC = GetDC(hWnd); | |
setupPixelFormat(hDC); | |
setupPalette(hDC); | |
hGLRC = wglCreateContext(hDC); | |
wglMakeCurrent(hDC, hGLRC); | |
return 0; | |
case WM_DESTROY: | |
// finaliza renderização em OpenGL | |
if (hGLRC) { | |
wglMakeCurrent(NULL, NULL); | |
wglDeleteContext(hGLRC); | |
} | |
if (hPalette) { | |
DeleteObject(hPalette); | |
} | |
ReleaseDC(hWnd, hDC); | |
PostQuitMessage(0); | |
return 0; | |
case WM_SIZE: | |
// o tamanho da janela foi alterado | |
if (hGLRC) { | |
winWidth = (int) LOWORD(lParam); | |
winHeight = (int) HIWORD(lParam); | |
redimensiona(); | |
return 0; | |
} | |
case WM_PALETTECHANGED: | |
// ativa a paleta de cores escolhida | |
if (hGLRC && hPalette && (HWND) wParam != hWnd) { | |
UnrealizeObject(hPalette); | |
SelectPalette(hDC, hPalette, FALSE); | |
RealizePalette(hDC); | |
desenhaMinhaCena(); | |
break; | |
} | |
break; | |
case WM_QUERYNEWPALETTE: | |
// reativa a paleta de cores | |
if (hGLRC && hPalette) { | |
UnrealizeObject(hPalette); | |
SelectPalette(hDC, hPalette, FALSE); | |
RealizePalette(hDC); | |
desenhaMinhaCena(); | |
return TRUE; | |
} | |
break; | |
case WM_PAINT: | |
// desenha a cena | |
{ | |
PAINTSTRUCT ps; | |
BeginPaint(hWnd, &ps); | |
if (hGLRC) { | |
desenhaMinhaCena(); | |
} | |
EndPaint(hWnd, &ps); | |
return 0; | |
} | |
break; | |
case WM_CHAR: | |
// o teclado foi pressionado (alguma tecla) | |
switch ((int)wParam) { | |
case VK_ESCAPE: | |
DestroyWindow(hWnd); | |
return 0; | |
default: | |
break; | |
} | |
break; | |
default: | |
break; | |
} | |
return DefWindowProc(hWnd, message, wParam, lParam); | |
} | |
int APIENTRY | |
WinMain( | |
HINSTANCE hCurrentInst, | |
HINSTANCE hPreviousInst, | |
LPSTR lpszCmdLine, | |
int nCmdShow) | |
{ | |
WNDCLASS wndClass; | |
HWND hWnd; | |
MSG msg; | |
// registra a classe da janela | |
wndClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; | |
wndClass.lpfnWndProc = WndProc; | |
wndClass.cbClsExtra = 0; | |
wndClass.cbWndExtra = 0; | |
wndClass.hInstance = hCurrentInst; | |
wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); | |
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); | |
wndClass.hbrBackground = GetStockObject(BLACK_BRUSH); | |
wndClass.lpszMenuName = NULL; | |
wndClass.lpszClassName = className; | |
RegisterClass(&wndClass); | |
// cria a janela | |
hWnd = CreateWindow( | |
className, windowName, | |
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, | |
winX, winY, winWidth, winHeight, | |
NULL, NULL, hCurrentInst, NULL); | |
// mostra a janela | |
ShowWindow(hWnd, nCmdShow); | |
UpdateWindow(hWnd); | |
// entra em loop para ficar processando os eventos | |
while (GetMessage(&msg, NULL, 0, 0) == TRUE) { | |
TranslateMessage(&msg); | |
DispatchMessage(&msg); | |
} | |
return msg.wParam; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment