Well… this is my simple program (sorry for polish comments in code):
#define WIN32_LEAN_AND_MEAN #include "stdafx.h"
#include <windows.h> // standardowy plik nagłówkowy Windows
#include <gl/glaux.h>
////// Zmienne globalne
float angle = 0.0f; // bieżący kąt obrotu
HDC g_HDC; // globalny kontekst urządzenia
bool fullScreen = false; // true = tryb pełnoekranowy; false = tryb okienkowy
////// Zmienne oświetlenia
//float ambientLight[] = { 0.3f, 0.5f, 0.8f, 1.0f }; // światło otoczenia
float ambientLight[] = { 0.5f, 0.5f, 0.5f, 1.0f };
float diffuseLight[] = { 1.0f, 1.0f, 1.0f, 1.0f }; // światło rozproszone
float lightPosition[] = { 0.0f, -1.0f, 0.0f, 0.0f }; // położenie źródła światła
////// Zmienne materiału
//float matAmbient[] = { 1.0f, 0.0f, 0.0f, 1.0f };
//float matDiff[] = { 1.0f, 1.0f, 1.0f, 1.0f};
// Inicjuje
// opis: inicjuje OpenGL
void Initialize()
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // czarny kolor tła
glShadeModel(GL_SMOOTH); // cieniowanie gładkie
glEnable(GL_DEPTH_TEST); // włącza bufor głębi
glEnable(GL_CULL_FACE); // ukrywanie tylnych stron wielokątów
glFrontFace(GL_CCW); // czyli o porządku wierzchołków przeciwnym
// do kierunku ruchu wskazówek zegara
glEnable(GL_LIGHTING); // włącza oświetlenie
// konfiguruje właściwości materiału dla źródła LIGHT0
//glMaterialfv(GL_FRONT, GL_AMBIENT, matAmbient);
//glMaterialfv(GL_FRONT, GL_DIFFUSE, matDiff);
// konfiguruje źródło światła GL_LIGHT0
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight); // składowa otoczenia
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight); // składowa rozproszona
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); // położenie źródła światła
// włącza źródło światła
glEnable(GL_LIGHT0);
}
// DrawCube
// opis: rysuje sześcian na podanej pozycji
// w bieżącym układzie współrzędnych
void DrawCube(float xPos, float yPos, float zPos)
{
glPushMatrix();
glScalef(1.5f, 1.0f, 0.5f);
glTranslatef(xPos, yPos, zPos);
glBegin(GL_POLYGON);
glNormal3f(0.0f, 1.0f, 0.0f); // górna ściana
glVertex3f(0.5f, 0.5f, 0.5f);
glVertex3f(0.5f, 0.5f, -0.5f);
glVertex3f(-0.5f, 0.5f, -0.5f);
glVertex3f(-0.5f, 0.5f, 0.5f);
glEnd();
glBegin(GL_POLYGON);
glNormal3f(0.0f, 0.0f, 1.0f); // przednia ściana
glVertex3f(0.5f, 0.5f, 0.5f);
glVertex3f(-0.5f, 0.5f, 0.5f);
glVertex3f(-0.5f, -0.5f, 0.5f);
glVertex3f(0.5f, -0.5f, 0.5f);
glEnd();
glBegin(GL_POLYGON);
glNormal3f(1.0f, 0.0f, 0.0f); // prawa ściana
glVertex3f(0.5f, 0.5f, 0.5f);
glVertex3f(0.5f, -0.5f, 0.5f);
glVertex3f(0.5f, -0.5f, -0.5f);
glVertex3f(0.5f, 0.5f, -0.5f);
glEnd();
glBegin(GL_POLYGON);
glNormal3f(-1.0f, 0.0f, 0.0f); // lewa ściana
glVertex3f(-0.5f, 0.5f, 0.5f);
glVertex3f(-0.5f, 0.5f, -0.5f);
glVertex3f(-0.5f, -0.5f, -0.5f);
glVertex3f(-0.5f, -0.5f, 0.5f);
glEnd();
glBegin(GL_POLYGON);
glNormal3f(0.0f, -1.0f, 0.0f); // dolna ściana
glVertex3f(-0.5f, -0.5f, 0.5f);
glVertex3f(-0.5f, -0.5f, -0.5f);
glVertex3f(0.5f, -0.5f, -0.5f);
glVertex3f(0.5f, -0.5f, 0.5f);
glEnd();
glBegin(GL_POLYGON);
glNormal3f(0.0f, 0.0f, -1.0f); // tylna ściana
glVertex3f(0.5f, -0.5f, -0.5f);
glVertex3f(-0.5f, -0.5f, -0.5f);
glVertex3f(-0.5f, 0.5f, -0.5f);
glVertex3f(0.5f, 0.5f, -0.5f);
glEnd();
glPopMatrix();
}
// Render
// opis: rysuje scenę
void Render()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // opróżnia bufory ekranu i głębi
glLoadIdentity(); // resetuje macierz modelowania
angle = angle + 0.1f; // zwiększa licznik kąta obrotu
if (angle >= 360.0f)
angle = 0.0f;
glTranslatef(0.0f, 0.0f, -3.0f); // wykonuje przekształcenia
glRotatef(angle, 1.0f, 0.0f, 0.0f);
glRotatef(angle, 0.0f, 1.0f, 0.0f);
glRotatef(angle, 0.0f, 0.0f, 1.0f);
float matAmbient[]={1.0f, 0.0f, 0.0f, 1.0f};
float matDiff[]={0.35f, 0.35f, 0.35f, 1.0f};
glMaterialfv(GL_FRONT, GL_AMBIENT, matAmbient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, matDiff);
DrawCube(0.0f, 0.0f, -1.0f); // rysuje sześcian
float matAmbient1[]={0.0f, 1.0f, 1.0f, 1.0f};
float matDiff1[]={1.0f, 1.0f, 1.0f, 1.0f};
glMaterialfv(GL_FRONT, GL_AMBIENT, matAmbient1);
glMaterialfv(GL_FRONT, GL_DIFFUSE, matDiff1);
auxSolidSphere(0.5);
glFlush();
SwapBuffers(g_HDC); // przełącza bufory
}
// funkcja określająca format pikseli
void SetupPixelFormat(HDC hDC)
{
int nPixelFormat; // indeks formatu pikseli
static PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // rozmiar struktury
1, // domyślna wersja
PFD_DRAW_TO_WINDOW | // grafika w oknie
PFD_SUPPORT_OPENGL | // grafika OpenGL
PFD_DOUBLEBUFFER, // podwójne buforowanie
PFD_TYPE_RGBA, // tryb kolorów RGBA
32, // 32-bitowy opis kolorów
0, 0, 0, 0, 0, 0, // nie specyfikuje bitów kolorów
0, // bez buforu alfa
0, // nie specyfikuje bitu przesunięcia
0, // bez bufora akumulacji
0, 0, 0, 0, // ignoruje bity akumulacji
16, // 16-bit bufor z
0, // bez bufora powielania
0, // bez buforów pomocniczych
PFD_MAIN_PLANE, // główna płaszczyzna rysowania
0, // zarezerwowane
0, 0, 0 }; // ignoruje maski warstw
nPixelFormat = ChoosePixelFormat(hDC, &pfd); // wybiera najbardziej zgodny format pikseli
SetPixelFormat(hDC, nPixelFormat, &pfd); // określa format pikseli dla danego kontekstu urządzenia
}
// procedura okienkowa
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HGLRC hRC; // kontekst tworzenia grafiki
static HDC hDC; // kontekst urządzenia
int width, height; // szerokość i wysokość okna
switch(message)
{
case WM_CREATE: // okno jest tworzone
hDC = GetDC(hwnd); // pobiera kontekst urządzenia dla okna
g_HDC = hDC;
SetupPixelFormat(hDC); // wywołuje funkcję określającą format pikseli
// tworzy kontekst tworzenia grafiki i czyni go bieżącym
hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
return 0;
break;
case WM_CLOSE: // windows is closing
// deselect rendering context and delete it
wglMakeCurrent(hDC, NULL);
wglDeleteContext(hRC);
// send WM_QUIT to message queue
PostQuitMessage(0);
return 0;
break;
case WM_SIZE:
height = HIWORD(lParam); // retrieve width and height
width = LOWORD(lParam);
if (height==0) // unika dzielenie przez 0
{
height=1;
}
glViewport(0, 0, width, height); // nadaje nowe wymiary oknu OpenGL
glMatrixMode(GL_PROJECTION); // wybiera macierz rzutowania
glLoadIdentity(); // resetuje macierz rzutowania
// wyznacza proporcje obrazu
gluPerspective(54.0f,(GLfloat)width/(GLfloat)height,1.0f,1000.0f);
glMatrixMode(GL_MODELVIEW); // wybiera macierz modelowania
glLoadIdentity(); // resetuje macierz modelowania
return 0;
break;
default:
break;
}
return (DefWindowProc(hwnd, message, wParam, lParam));
}
// punkt, w którym rozpoczyna się wykonywanie aplikacji
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
WNDCLASSEX windowClass; // klasa okna
HWND hwnd; // uchwyt okna
MSG msg; // komunikat
bool done; // znacznik zakończenia aplikacji
DWORD dwExStyle; // rozszerzony styl okna
DWORD dwStyle; // styl okna
RECT windowRect;
// zmienne pomocnicze
int width = 800;
int height = 600;
int bits = 32;
//fullScreen = TRUE;
windowRect.left=(long)0; // struktura określająca rozmiary okna
windowRect.right=(long)width;
windowRect.top=(long)0;
windowRect.bottom=(long)height;
// definicja klasy okna
windowClass.cbSize = sizeof(WNDCLASSEX);
windowClass.style = CS_HREDRAW | CS_VREDRAW;
windowClass.lpfnWndProc = WndProc;
windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = 0;
windowClass.hInstance = hInstance;
windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); // domyślna ikona
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW); // domyślny kursor
windowClass.hbrBackground = NULL; // bez tła
windowClass.lpszMenuName = NULL; // bez menu
windowClass.lpszClassName = "MojaKlasa";
windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO); // logo Windows
// rejestruje klasę okna
if (!RegisterClassEx(&windowClass))
return 0;
if (fullScreen) // tryb pełnoekranowy?
{
DEVMODE dmScreenSettings; // tryb urządzenia
memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = width; // szerokość ekranu
dmScreenSettings.dmPelsHeight = height; // wysokość ekranu
dmScreenSettings.dmBitsPerPel = bits; // bitów na piksel
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
//
if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{
// przełączenie trybu nie powiodło się, z powrotem tryb okienkowy
MessageBox(NULL, "Przełączenie trybu wyswietlania nie powiodło się", NULL, MB_OK);
fullScreen=FALSE;
}
}
if (fullScreen) // tryb pełnoekranowy?
{
dwExStyle=WS_EX_APPWINDOW; // rozszerzony styl okna
dwStyle=WS_POPUP; // styl okna
ShowCursor(FALSE); // ukrywa kursor myszy
}
else
{
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // definicja klasy okna
dwStyle=WS_OVERLAPPEDWINDOW; // styl okna
}
AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle); // koryguje rozmiar okna
// tworzy okno
hwnd = CreateWindowEx(NULL, // styl rozszerzony
"MojaKlasa", // nazwa klasy // class name
"Marcin Pilaczyński-proste oświetlenie-OpenGL", // app name
dwStyle | WS_CLIPCHILDREN |
WS_CLIPSIBLINGS,
0, 0, // współrzędne x,y
windowRect.right - windowRect.left,
windowRect.bottom - windowRect.top, // szerokość, wysokość
NULL, // uchwyt okna nadrzędnego
NULL, // uchwyt menu
hInstance, // instancja aplikacji
NULL); // no extra params
// sprawdza, czy utworzenie okna nie powiodło się (wtedy wartość hwnd równa NULL)
if (!hwnd)
return 0;
ShowWindow(hwnd, SW_SHOW); // wyświetla okno
UpdateWindow(hwnd); // aktualizuje okno
done = false; // inicjuje zmienną warunku pętli
Initialize(); // inicjuje OpenGL
// pętla przetwarzania komunikatów
while (!done)
{
PeekMessage(&msg, hwnd, NULL, NULL, PM_REMOVE);
if (msg.message == WM_QUIT) // aplikacja otrzymała komunikat WM_QUIT?
{
done = true; // jeśli tak, to kończy działanie
}
else
{
Render();
TranslateMessage(&msg); // tłumaczy komunikat i wysyła do systemu
DispatchMessage(&msg);
}
}
if (fullScreen)
{
ChangeDisplaySettings(NULL,0); // przywraca pulpit
ShowCursor(TRUE); // i wskaźnik myszy
}
return msg.wParam;
}