Array ( )
Вход:




Главная | OpenGL | GLSL | AI | Сеть | Примеры | Библиотека

OpenGL: Создание Скайбокса






Урок показывает, как создать SkyBox. По сути это просто коробка с текстурой,
создающая впечатление, что мы находимся в реальном 3д мире.
Это удобно, т.к. легко программируется и неплохо выглядит.
Используемые текстуры созданы Nick Coombe (http://www.planethalflife.com/crinity
email: crinity@email.com)
Работает всё так: мы создаём коробку, и накладываем на каждую из сторон текстуру.

Исходные коды возьмите из урока "Загрузка текстур", и добавьте класс камеры из последнего
урока "камера".


В файле Init.cpp найдите строку
    gluPerspective(45.0f,(GLfloat)width/(GLfloat)height, .5f ,150.0f);

и замените в ней значение 150.0f на 500.0f. Иначе отсекание будет происходить слишком близко:
    gluPerspective(45.0f,(GLfloat)width/(GLfloat)height, .5f ,500.0f);



Изменяем файл main.h для использования камеры:
// 1) Включите хидер math.h
#include <math.h>

// 2) Перенесите из уроков камеры класс CVector3:
class CVector3 {

public:
    // Дефолтный конструктор
    CVector3() {}

    // Конструктор, инициализирующий данные
    CVector3(float X, float Y, float Z)
    {
        x = X; y = Y; z = Z;
    }
    // Перегружаем оператор +, чтобы прибавлять друг к другу векторы
    CVector3 operator+(CVector3 vVector)
    {
        // Возвращаем +добавленный вектор
        return CVector3(vVector.x + x, vVector.y + y, vVector.z + z);
    }

    // перегружаем оператор -
    CVector3 operator-(CVector3 vVector)
    {
        return CVector3(x-vVector.x, y-vVector.y, z-vVector.z);
    }

    // Перегружаем оператор *
    CVector3 operator*(float num)
    {
        return CVector3(x*num, y*num, z*num);
    }

    // Перегружаем оператор /
    CVector3 operator/(float num)
    {
        return CVector3(x/num,y/num,z/num);
    }

    float x, y, z;              // Просто float для X,Y,Z
};


С этим всё.
Изменяем файл main.cpp:
// Во первых, добавим к инклудам хидер-файл класса камеры:
#include "main.h"
#include "camera.h"
#include "texture.h"


// Установим скорость движения камеры
#define SPEED   0.03f

// Чтобы не запутаться, обозначим ID текстур сторонами куба

#define BACK_ID     1   // ID текстуры для задней части бокса
#define FRONT_ID    2   // Для передней части
#define BOTTOM_ID   3   // Для нижней части
#define TOP_ID      4   // Для верхней части
#define LEFT_ID     5   // Для левой части
#define RIGHT_ID    6   // Для правой части

// Установим количество загружаемых текстур в 6:
TextureImage textures[6] = {0};

// Вместе с обьявлением класса текстур, обьявим класс камеры:
CCamera g_Camera;       // Наша камера
CTexture *Texture;      // Текстурный класс



// Изменим функцию инициализации: инициализируем камеру и загрузим наши текстуры
void Init(HWND hWnd)
{
    g_hWnd = hWnd;
    GetClientRect(g_hWnd, &g_rRect);
    InitializeOpenGL(g_rRect.right, g_rRect.bottom);

    // Инициализируем текстурный класс
    Texture = new CTexture();

    // Ниже мы читаем 6 текстурных карт для сторон нашего скайбокса.
    // ID важны, так что не перепутайте их. У нас есть текстуры для
    // каждой стороны бокса.

    Texture->LoadTexture(IL_BMP, "Back.bmp",    &textures[BACK_ID]);
    Texture->LoadTexture(IL_BMP, "Front.bmp",   &textures[FRONT_ID]);
    Texture->LoadTexture(IL_BMP, "Bottom.bmp",  &textures[BOTTOM_ID]);
    Texture->LoadTexture(IL_BMP, "Top.bmp",     &textures[TOP_ID]);
    Texture->LoadTexture(IL_BMP, "Left.bmp",    &textures[LEFT_ID]);
    Texture->LoadTexture(IL_BMP, "Right.bmp",   &textures[RIGHT_ID]);

    // Дадим камере стартовую точку в мире.
    g_Camera.PositionCamera( 0, 0, 0,   0, 0, 1,    0, 1, 0);
}




///////////////////////////////// CREATE SKY BOX \\\\*
/////               Новая функция!
/////
/////   Создает SkyBox с центром в X,Y,Z.  Вместо окраски каждой вершины применяется
/////   карта текстур для каждой стороны куба. Вы можете задавать ширину, высоту
/////   и длинну скайбокса, чтобы создать разные перспективы для разных
/////   текстур.
/////
///////////////////////////////// CREATE SKY BOX \\\\*

void CreateSkyBox(float x, float y, float z, float width, float height, float length)
{
    // Это самая важная функция в этом уроке. Мы накладываем на каждую сторону текстуру,
    // чтобы создать иллюзию 3д мира. Вы заметите, что я изменил текстурные
    // координаты, чтобы стороны корректно выглядели. Также, в зависимости от
    // ситуации, вершины могут быть перевернуты. В этом уроке такого не будет,
    // но имейте в виду такую возможность.

    // Так как мы хотим, чтобы скайбокс был с центром в x-y-z, мы производим
    // небольшие рассчеты. Просто изменяем X,Y и Z на нужные.

    // Это центрирует скайбокс на X,Y,Z
    x = x - width  / 2;
    y = y - height / 2;
    z = z - length / 2;

    // забиндим заднюю текстуру на заднюю сторону
    glBindTexture(GL_TEXTURE_2D, textures[BACK_ID].texID);
    glBegin(GL_QUADS);

        // Установим текстурные координаты и вершины ЗАДНЕЙ стороны
        glTexCoord2f(1.0f, 0.0f); glVertex3f(x + width, y,z);
        glTexCoord2f(1.0f, 1.0f); glVertex3f(x + width, y + height, z);
        glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + height, z);
        glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y,z);

    glEnd();

    // Биндим ПЕРЕДНЮЮ текстуру на ПЕРЕДНЮЮ сторону бокса
    glBindTexture(GL_TEXTURE_2D, textures[FRONT_ID].texID);

    // Начинаем рисовать сторону
    glBegin(GL_QUADS);

        // Установим текстурные координаты и вершины ПЕРЕДНЕЙ стороны
        glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y, z + length);
        glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y + height, z + length);
        glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y + height, z + length);
        glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y,z + length);
    glEnd();

    // Биндим НИЖНЮЮ текстуру на НИЖНЮЮ сторону бокса
    glBindTexture(GL_TEXTURE_2D, textures[BOTTOM_ID].texID);

    // Начинаем рисовать сторону
    glBegin(GL_QUADS);

        // Установим текстурные координаты и вершины НИЖНЕЙ стороны
        glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y,z);
        glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y,z + length);
        glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y,z + length);
        glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y,z);
    glEnd();

    // Биндим ВЕРХНЮЮ текстуру на ВЕРХНЮЮ сторону бокса
    glBindTexture(GL_TEXTURE_2D, textures[TOP_ID].texID);

    // Начинаем рисовать сторону
    glBegin(GL_QUADS);

        // Установим текстурные координаты и вершины ВЕРХНЕЙ стороны
        glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y + height, z);
        glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y + height, z + length);
        glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y + height,z + length);
        glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y + height,z);

    glEnd();

    // Биндим ЛЕВУЮ текстуру на ЛЕВУЮ сторону бокса
    glBindTexture(GL_TEXTURE_2D, textures[LEFT_ID].texID);

    // Начинаем рисовать сторону
    glBegin(GL_QUADS);

        // Установим текстурные координаты и вершины ЛЕВОЙ стороны
        glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y + height,z);
        glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + height,z + length);
        glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y,z + length);
        glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y,z);

    glEnd();

    // Биндим ПРАВУЮ текстуру на ПРАВУЮ сторону бокса
    glBindTexture(GL_TEXTURE_2D, textures[RIGHT_ID].texID);

    // Начинаем рисовать сторону
    glBegin(GL_QUADS);

        // Установим текстурные координаты и вершины ПРАВОЙ стороны
        glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y,z);
        glTexCoord2f(1.0f, 0.0f); glVertex3f(x + width, y,z + length);
        glTexCoord2f(1.0f, 1.0f); glVertex3f(x + width, y + height,z + length);
        glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y + height,z);
    glEnd();
}




///////////////////////////////////
// В MainLoop() перед RenderScene() добавьте обновление камеры:

    g_Camera.Update(); // Обновим данные камеры
    RenderScene();
///////////////////////////////////



// И наконец RenderScene(). Код её совсем мал, так как вынесен в отдельные функции:
void RenderScene()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();

    // Передадим OpenGL позицию камеры
    g_Camera.Look();

    // Создаем наш скайбокс. Он будет с центром в (0,0,0), с шириной 400,
    // высотой 200, и длинной 400. Вы можете удивится, почему бы не сделать
    // ровный куб? Ну, если мы делаем высоту половиной ширины и длинны,
    // всё выглядит лучше. Попробуйте увеличить высоту до 400 и
    // вы заметите, что всё стало выглядеть хуже. Скайбокс выглядит
    // лучше с разными перспективами и размерами.

    CreateSkyBox(0, 0, 0, 400, 200, 400);

    SwapBuffers(g_hDC);
}
 







Исходные коды к уроку




Комментарии:

Войдите, чтобы оставить комментарий:












Яндекс.Метрика
 Яндекс цитирования.