Доброго времени суток,
Код от NeHe, убран fullscreen и keys.
Компилируется, линкуется. Cygwin GCC.
Сабж - ничего не рисуется, чёрный экран и всё.
Пробовал запускать на OpenGL 1.1 и 3.х (не помню точно какая).
После запуска на 3.х думаю что косяк в коде. Посмотрите, пожалуйста, мб что увидите.
stcpp.h:Код:
#ifndef STCPP_H_
#define STCPP_H_
#include <iostream>
#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glaux.h>
extern HGLRC hRC; // Постоянный контекст рендеринга
extern HDC hDC; // Приватный контекст устройства GDI
extern HWND hWnd; // Здесь будет хранится дескриптор окна
extern HINSTANCE hInstance; // Здесь будет хранится дескриптор приложения
extern bool active;
int DrawGLScene( void );
int InitGL( void );
void ReSizeGLScene( GLsizei, GLsizei );
void KillGLWindow( void );
BOOL CreateGLWindow(char *, int, int, int);
LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ); // Прототип функции WndProc
#endif // STCPP_H_
stcpp.cpp:Код:
#include "stcpp.h"
HGLRC hRC = NULL; // Постоянный контекст рендеринга
HDC hDC = NULL; // Приватный контекст устройства GDI
HWND hWnd = NULL; // Здесь будет хранится дескриптор окна
HINSTANCE hInstance = NULL; // Здесь будет хранится дескриптор приложения
bool active = false;
int DrawGLScene( void ) // Здесь будет происходить вся прорисовка
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // Очистить экран и буфер глубины
glLoadIdentity(); // Сбросить текущую матрицу
glTranslatef(-1.5f,0.0f,-6.0f); // Сдвинемся влево на 1.5 единицы и
glBegin(GL_TRIANGLES);
glColor3f(1.0f,0.0f,0.0f); // Красный цвет
glVertex3f( 0.0f, 1.0f, 0.0f); // Вверх
glColor3f(0.0f,1.0f,0.0f); // Зеленный цвет
glVertex3f(-1.0f,-1.0f, 0.0f); // Слева снизу
glColor3f(0.0f,0.0f,1.0f); // Синий цвет
glVertex3f( 1.0f,-1.0f, 0.0f); // Справа снизу
glEnd();
glTranslatef(3.0f,0.0f,0.0f); // Сдвинем вправо на 3 единицы
glBegin(GL_QUADS);
glVertex3f(-1.0f, 1.0f, 0.0f); // Слева вверху
glVertex3f( 1.0f, 1.0f, 0.0f); // Справа вверху
glVertex3f( 1.0f,-1.0f, 0.0f); // Справа внизу
glVertex3f(-1.0f,-1.0f, 0.0f); // Слева внизу
glEnd();
return true; // Прорисовка прошла успешно
}
int InitGL( void ) // Все установки касаемо OpenGL происходят здесь
{
glShadeModel( GL_SMOOTH ); // Разрешить плавное цветовое сглаживание
glClearColor(0.2f, 0.0f, 0.3f, 0.5f); // Очистка экрана в черный цвет
glClearDepth( 1.0f ); // Разрешить очистку буфера глубины
glEnable( GL_DEPTH_TEST ); // Разрешить тест глубины
glDepthFunc( GL_LEQUAL ); // Тип теста глубины
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ); // Улучшение в вычислении перспективы
std::cout << "Init done\n";
return true; // Инициализация прошла успешно
}
void ReSizeGLScene( GLsizei width, GLsizei height ) // Изменить размер и инициализировать окно GL
{
if( height == 0 ) height = 1; // Предотвращение деления на ноль
glViewport( 0, 0, width, height ); // Сброс текущей области вывода
glMatrixMode( GL_PROJECTION ); // Выбор матрицы проекций
glLoadIdentity(); // Сброс матрицы проекции
// Вычисление соотношения геометрических размеров для окна
gluPerspective( 45.0f, (GLfloat)width/(GLfloat)height, 0.1f, 100.0f );
glMatrixMode( GL_MODELVIEW ); // Выбор матрицы вида модели
glLoadIdentity(); // Сброс матрицы вида модели
std::cout << "Resize done\n";
}
void KillGLWindow( void ) // Корректное разрушение окна
{
if( hRC ) // Существует ли Контекст Рендеринга?
{
if( !wglMakeCurrent( NULL, NULL ) )
MessageBox( NULL, "Release Of DC And RC Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION ); // Возможно ли освободить RC и DC?
if( !wglDeleteContext( hRC ) )
MessageBox( NULL, "Release Rendering Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION ); // Возможно ли удалить RC?
hRC = NULL; // Установить RC в NULL
}
if( hDC && !ReleaseDC( hWnd, hDC ) ) // Возможно ли уничтожить DC?
{
MessageBox( NULL, "Release Device Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION );
hDC=NULL; // Установить DC в NULL
}
if(hWnd && !DestroyWindow(hWnd)) // Возможно ли уничтожить окно?
{
MessageBox( NULL, "Could Not Release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION );
hWnd = NULL; // Установить hWnd в NULL
}
if( !UnregisterClass( "OpenGL", hInstance ) ) // Возможно ли разрегистрировать класс
{
MessageBox( NULL, "Could Not Unregister Class.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
hInstance = NULL; // Установить hInstance в NULL
}
}
BOOL CreateGLWindow(char *title, int width, int height, int bits )
{
std::cout << "Let's create GL window!\n";
GLuint PixelFormat; // Хранит результат после поиска
WNDCLASS wc; // Структура класса окна
DWORD dwExStyle; // Расширенный стиль окна
DWORD dwStyle; // Обычный стиль окна
RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values
WindowRect.left=(long)0; // Установить левую составляющую в 0
WindowRect.right=(long)width; // Установить правую составляющую в Width
WindowRect.top=(long)0; // Установить верхнюю составляющую в 0
WindowRect.bottom=(long)height; // Установить нижнюю составляющую в Height
hInstance = GetModuleHandle(NULL); // Считаем дескриптор нашего приложения
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Перерисуем при перемещении и создаём скрытый DC
wc.lpfnWndProc = (WNDPROC) WndProc; // Процедура обработки сообщений
wc.cbClsExtra = 0; // Нет дополнительной информации для окна
wc.cbWndExtra = 0; // Нет дополнительной информации для окна
wc.hInstance = hInstance; // Устанавливаем дескриптор
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Загружаем иконку по умолчанию
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Загружаем указатель мышки
wc.hbrBackground = NULL; // Фон не требуется для GL
wc.lpszMenuName = NULL; // Меню в окне не будет
wc.lpszClassName = "OpenGL"; // Устанавливаем имя классу
if( !RegisterClass( &wc ) ) // Пытаемся зарегистрировать класс окна
{
MessageBox( NULL, "Failed To Register The Window Class.", "ERROR", MB_OK | MB_ICONEXCLAMATION );
return false; // Выход и возвращение функцией значения false
}
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Расширенный стиль окна
dwStyle = WS_OVERLAPPEDWINDOW; // Обычный стиль окна
AdjustWindowRectEx( &WindowRect, dwStyle, false, dwExStyle ); // Подбирает окну подходящие размеры
if( !( hWnd = CreateWindowEx( dwExStyle, // Расширенный стиль для окна
"OpenGL", // Имя класса
title, // Заголовок окна
WS_CLIPSIBLINGS | // Требуемый стиль для окна
WS_CLIPCHILDREN | // Требуемый стиль для окна
dwStyle, // Выбираемые стили для окна
0, 0, // Позиция окна
WindowRect.right-WindowRect.left, // Вычисление подходящей ширины
WindowRect.bottom-WindowRect.top, // Вычисление подходящей высоты
NULL, // Нет родительского
NULL, // Нет меню
hInstance, // Дескриптор приложения
NULL )
) ) // Не передаём ничего до WM_CREATE (???)
{
KillGLWindow(); // Восстановить экран
MessageBox( NULL, "Window Creation Error.", "ERROR", MB_OK | MB_ICONEXCLAMATION );
return false; // Вернуть false
}
static PIXELFORMATDESCRIPTOR pfd = {0}; // pfd сообщает Windows каким будет вывод на экран каждого пикселя
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); // Размер дескриптора данного формата пикселей
pfd.nVersion = 1; // Номер версии
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; // Формат для Окна и Формат для OpenGL и Формат для двойного буфера
pfd.iPixelType = PFD_TYPE_RGBA; // Требуется RGBA формат
pfd.cColorBits = bits; // Выбирается бит глубины цвета
pfd.cDepthBits = 32;
pfd.iLayerType = PFD_MAIN_PLANE; // Главный слой рисования
if(!(hDC = GetDC(hWnd))) // Можем ли мы получить Контекст Устройства?
{
KillGLWindow(); // Восстановить экран
MessageBox(NULL, "Can't Create A GL Device Context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
return false; // Вернуть false
}
if(!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) // Найден ли подходящий формат пикселя?
{
KillGLWindow(); // Восстановить экран
MessageBox(NULL, "Can't Find A Suitable PixelFormat.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
return false; // Вернуть false
}
if(!SetPixelFormat(hDC, PixelFormat, &pfd)) // Возможно ли установить Формат Пикселя?
{
KillGLWindow(); // Восстановить экран
MessageBox(NULL, "Can't Set The PixelFormat.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
return false; // Вернуть false
}
if(!(hRC = wglCreateContext(hDC))) // Возможно ли установить Контекст Рендеринга?
{
KillGLWindow(); // Восстановить экран
MessageBox(NULL, "Can't Create A GL Rendering Context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
return false; // Вернуть false
}
if(!wglMakeCurrent(hDC, hRC)) // Попробовать активировать Контекст Рендеринга
{
KillGLWindow(); // Восстановить экран
MessageBox(NULL, "Can't Activate The GL Rendering Context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
return false; // Вернуть false
}
ShowWindow(hWnd, SW_SHOW); //Показать окно
SetForegroundWindow(hWnd); // Слегка повысим приоритет
SetFocus(hWnd); // Установить фокус клавиатуры на наше окно
ReSizeGLScene(width, height); // Настроим перспективу для нашего OpenGL экрана.
if(!InitGL()) // Инициализация только что созданного окна
{
KillGLWindow(); // Восстановить экран
MessageBox(NULL, "Initialization Failed.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
return false; // Вернуть false
}
std::cout << "Create GL window done\n";
return true; // Всё в порядке!
}
int WINAPI WinMain( HINSTANCE hInstance, // Дескриптор приложения
HINSTANCE hPrevInstance, // Дескриптор родительского приложения
LPSTR lpCmdLine, // Параметры командной строки
int nCmdShow ) // Состояние отображения окна
{
MSG msg; // Структура для хранения сообщения Windows
BOOL done = false; // Логическая переменная для выхода из цикла
// Создать наше OpenGL окно
if( !CreateGLWindow( "OpenGL window", 800, 600, 32 ) )
return 0; // Выйти, если окно не может быть создано
while( !done ) // Цикл продолжается, пока done не равно true
{
if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) // Есть ли в очереди какое-нибудь сообщение?
{
if( msg.message == WM_QUIT ) // Мы поучили сообщение о выходе?
done = true; // Если так, done=true
else // Если нет, обрабатывает сообщения
{
TranslateMessage( &msg ); // Переводим сообщение
DispatchMessage( &msg ); // Отсылаем сообщение
}
}
else // Если нет сообщений
{
// Прорисовываем сцену.
if( active ) // Активна ли программа?
{
DrawGLScene(); // Рисуем сцену
SwapBuffers( hDC ); // Меняем буфер (двойная буферизация)
}
}
}
// Shutdown
KillGLWindow(); // Разрушаем окно
return ( msg.wParam ); // Выходим из программы
}
LRESULT CALLBACK WndProc( HWND hWnd, // Дескриптор нужного окна
UINT uMsg, // Сообщение для этого окна
WPARAM wParam, // Дополнительная информация
LPARAM lParam) // Дополнительная информация
{
switch (uMsg) // Проверка сообщения для окна
{
case WM_ACTIVATE: // Проверка сообщения активности окна
{
if( !HIWORD( wParam ) ) // Проверить состояние минимизации
{
active = true; // Программа активна
}
else
{
active = false; // Программа теперь не активна
}
return 0; // Возвращаемся в цикл обработки сообщений
}
case WM_SYSCOMMAND: // Перехватываем системную команду
{
switch ( wParam ) // Останавливаем системный вызов
{
case SC_SCREENSAVE: // Пытается ли запустится скринсейвер?
case SC_MONITORPOWER: // Пытается ли монитор перейти в режим сбережения энергии?
return 0; // Предотвращаем это
}
break; // Выход
}
case WM_CLOSE: // Мы получили сообщение о закрытие?
{
PostQuitMessage( 0 ); // Отправить сообщение о выходе
return 0; // Вернуться назад
}
case WM_SIZE: // Изменены размеры OpenGL окна
{
std::cout << "ReSizeGLScene()\n";
ReSizeGLScene( LOWORD(lParam), HIWORD(lParam) ); // Младшее слово=Width, старшее слово=Height
return 0; // Возвращаемся
}
}
// пересылаем все необработанные сообщения DefWindowProc
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}