Skip to content

Instantly share code, notes, and snippets.

@fegemo
Last active March 6, 2019 21:47
Show Gist options
  • Save fegemo/1f534a2a59d7d289ec48 to your computer and use it in GitHub Desktop.
Save fegemo/1f534a2a59d7d289ec48 to your computer and use it in GitHub Desktop.
Um Hello World em OpenGL usando C e a biblioteca windows.h.
#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