Сама программа :
http://pmg.org.ru/nehe/nehe38.htm
Или вот :
#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glaux.h>
#include "NeHeGL.h"
#include "resource.h"
#pragma comment( lib, "opengl32.lib" )
#pragma comment( lib, "glu32.lib" )
#pragma comment( lib, "glaux.lib" )
#ifndef CDS_FULLSCREEN
#define CDS_FULLSCREEN 4
#endif
GL_Window* g_window;
Keys* g_keys;
// Пользовательские переменные
GLuint texture[3]; // Место для хранения 3 текстур
struct object // Структура объекта
{
int tex; // Текстура
float x; // X позиция
float y; // Y позиция
float z; // Z позиция
float yi; // Y скорость падения
float spinz; // Z вращение
float spinzi; // Z скорость вращения
float flap; // Хлопающие треугольники
float fi; // Направление хлопанья
};
object obj[50]; // Создается 50 объектов
void SetObject(int loop) // Инициализация объекта (случайная)
{
obj[loop].tex=rand()%3; // Текстура
obj[loop].x=rand()%34-17.0f; // x от -17.0f до 17.0f
obj[loop].y=18.0f; // Y равно 18 (чуть выше экрана)
obj[loop].z=-((rand()%30000/1000.0f)+10.0f);// z от -10.0f до -40.0f
obj[loop].spinzi=(rand()%10000)/5000.0f-1.0f;// spinzi от -1.0f до 1.0f
obj[loop].flap=0.0f; // вначале хлопанье равно 0.0f;
obj[loop].fi=0.05f+(rand()%100)/1000.0f; // fi от 0.05f до 0.15f
obj[loop].yi=0.001f+(rand()%1000)/10000.0f; // yi от 0.001f до 0.101f
}
void LoadGLTextures() // Создание текстур из изображений, которые в ресурсе
{
HBITMAP hBMP; // Указатель на изображение
BITMAP BMP; // структура изображения
// Три ID для изображений, которые мы хотим загрузить из файла ресурсов
byte Texture[]={ IDB_BUTTERFLY1, IDB_BUTTERFLY2, IDB_BUTTERFLY3 };
glGenTextures(sizeof(Texture), &texture[0]); // создаем 3 текстуры (sizeof(Texture)=3 ID's)
for (int loop=0; loop<sizeof(Texture); loop++) // цикл по всем ID (изображений)
{
hBMP=(HBITMAP)LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(Texture[loop]), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
if (hBMP) // существует ли изображение?
{ // если да …
GetObject(hBMP,sizeof(BMP), &BMP); // получить объект
// hBMP: указатель на графический объект
// sizeof(BMP): размер буфера для информации по объекту
// BMP - Буфер информации по объекту
// режим сохранения пикселей (равнение по двойному слову / 4 Bytes)
glPixelStorei(GL_UNPACK_ALIGNMENT,4);
glBindTexture(GL_TEXTURE_2D, texture[loop]); // связываемся с нашей текстурой
// линейная фильтрация
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
// линейная фильтрация Mipmap
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
// генерация Mipmapped текстуры (3 байта, ширина, высота и данные из BMP)
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, BMP.bmWidth, BMP.bmHeight,
GL_BGR_EXT, GL_UNSIGNED_BYTE, BMP.bmBits);
DeleteObject(hBMP); // удаление объекта изображения
}
}
}
// весь код для инициализации GL и все инициализации пользователя происходят здесь
BOOL Initialize (GL_Window* window, Keys* keys)
{
g_window = window;
g_keys = keys;
// Start Of User Initialization
LoadGLTextures(); // Загрузка текстуры из нашего файла ресурсов
glClearColor (0.0f, 0.0f, 0.0f, 0.5f); // цвет фона - черный
glClearDepth (1.0f); // Параметры буфера глубины
glDepthFunc (GL_LEQUAL); // Тип проверки глубины (меньше или равно)
glDisable(GL_DEPTH_TEST); // Выключить проверку глубины
glShadeModel (GL_SMOOTH); // выберем плавное сглаживание
glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // установим вычисление перспективы в режим наибольшей точности
glEnable(GL_TEXTURE_2D); // включим отрисовку текстуры
glBlendFunc(GL_ONE,GL_SRC_ALPHA); // зададим режим смешения (простой и быстрый)
glEnable(GL_BLEND); // включим смешение
for (int loop=0; loop<50; loop++) // цикл для инициализации 50 объектов
{
SetObject(loop); // вызов SetObject для задания новых случайных значений
}
return TRUE; // возврат TRUE (успешная инициализация)
}
void Deinitialize (void) // все деинициализации пользователя находятся здесь
{
}
void Update (DWORD milliseconds) // здесь происходит перерасчет движения
{
if (g_keys->keyDown [VK_ESCAPE] == TRUE) // была ли нажата клавиша ESC?
{
TerminateApplication (g_window); // остановить программу
}
if (g_keys->keyDown [VK_F1] == TRUE) // была ли нажата клавиша F1?
{
ToggleFullscreen (g_window); // переключить или на полный экран и на первоначальный
}
}
void Draw (void) // отрисовка сцены
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // очистка экрана и буфера глубины
for (int loop=0; loop<50; loop++) // цикл по 50 (рисуем 50 обьектов)
{
glLoadIdentity (); // сброс матрицы просмотра объекта
glBindTexture(GL_TEXTURE_2D, texture[obj[loop].tex]); // связывание с нашей текстурой glTranslatef(obj[loop].x,obj[loop].y,obj[loop].z); // помещение объекта glRotatef(45.0f,1.0f,0.0f,0.0f); // вращение по оси X
glRotatef((obj[loop].spinz),0.0f,0.0f,1.0f); // вращение по оси Z
glBegin(GL_TRIANGLES); // начала рисования треугольников
// первый треугольник
glTexCoord2f(1.0f,1.0f); glVertex3f( 1.0f, 1.0f, 0.0f); // точка 1 (верхняя правая)
glTexCoord2f(0.0f,1.0f); glVertex3f(-1.0f, 1.0f, obj[loop].flap); // точка 2 (верхняя левая)
glTexCoord2f(0.0f,0.0f); glVertex3f(-1.0f,-1.0f, 0.0f); // точка 3 (нижняя левая)
// второй треугольник
glTexCoord2f(1.0f,1.0f); glVertex3f( 1.0f, 1.0f, 0.0f); // точка 1 (вверху справа)
glTexCoord2f(0.0f,0.0f); glVertex3f(-1.0f,-1.0f, 0.0f); // точка 2 (внизу слева)
glTexCoord2f(1.0f,0.0f); glVertex3f( 1.0f,-1.0f, obj[loop].flap); // точка 3 (внизу справа)
glEnd();
obj[loop].y-=obj[loop].yi; // двигаем объект вниз по экрану
obj[loop].spinz+=obj[loop].spinzi; // увеличиваем вращение по Z на величину spinzi
obj[loop].flap+=obj[loop].fi; // увеличиваем значение хлопанья на fi
if (obj[loop].y<-18.0f) // объект вне экрана?
{
SetObject(loop); // если да – перезадай новые параметры
if ((obj[loop].flap>1.0f) || (obj[loop].flap<-1.0f)) // изменяем направление хлопанья?
{
obj[loop].fi=-obj[loop].fi; // сменим направление fi = -fi
}
}
Sleep(15); // короткая задержка (15 Milliseconds)
glFlush (); // сброс линии отрисовки GL
}