Array ( )
Вход:




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

OpenGL: OpenGL и тени (матричные)






На самом деле, матричные тени - дело простое. Тут нам и понадобится наш класс матриц
из предыдущего урока. Остальной код (main.cpp. init.cpp, main.h) возьмите из урока
инициализации.


Изменяем только файл main.cpp:

// В начале файла подключите хидер матричного класса:
#include "CMatrix.h"


// Переменные, хранящие угол вращения источника света:
float xRotation = 0.0f;
float yRotation = 0.0f;

// Эта матрица будет использоватся для хранения матрицы тени
CMatrix4x4 ShadowMatrix;

// Следующие переменные очень важны для функционирования теней. Первая - позиция
// источника света, вторая - нормаль поверхности, на которую отбрасывается тень.
CVector4 lightPos(1.5f, 2.3f, -2.0f, 1.0f);
CVector4 planeNormal(0.0f, 1.0f, 0.0f, 0.0f);



/////////////////////////////////////////////////////////////////////
//
//      Функция, отрисовывающая куб
//
/////////////////////////////////////////////////////////////////////

void DrawCube()
{
   // Передний полигон
   glBegin(GL_QUADS);
      glVertex3f(-0.2f, 0.0f, 0.0f);
      glVertex3f(-0.2f, 0.5f, 0.0f);
      glVertex3f(0.3f, 0.5f, 0.0f);
      glVertex3f(0.3f, 0.0f, 0.0f);
   glEnd();

   // Задний полигон
   glBegin(GL_QUADS);
      glVertex3f(-0.2f, 0.0f, -0.5f);
      glVertex3f(-0.2f, 0.5f, -0.5f);
      glVertex3f(0.3f, 0.5f, -0.5f);
      glVertex3f(0.3f, 0.0f, -0.5f);
   glEnd();

   // Левый полигон
   glBegin(GL_QUADS);
      glVertex3f(-0.2f, 0.0f, -0.5f);
      glVertex3f(-0.2f, 0.5f, -0.5f);
      glVertex3f(-0.2f, 0.5f, 0.0f);
      glVertex3f(-0.2f, 0.0f, 0.0f);
   glEnd();

   // Правый полигон
   glBegin(GL_QUADS);
      glVertex3f(0.3f, 0.0f, -0.5f);
      glVertex3f(0.3f, 0.5f, -0.5f);
      glVertex3f(0.3f, 0.5f, 0.0f);
      glVertex3f(0.3f, 0.0f, 0.0f);
   glEnd();

   // Верхний полигон
   glBegin(GL_QUADS);
      glVertex3f(-0.2f, 0.5f, 0.0f);
      glVertex3f(-0.2f, 0.5f, -0.5f);
      glVertex3f(0.3f, 0.5f, -0.5f);
      glVertex3f(0.3f, 0.5f, 0.0f);
   glEnd();

   // Нижний полигон
   glBegin(GL_QUADS);
      glVertex3f(-0.2f, 0.0f, 0.0f);
      glVertex3f(-0.2f, 0.0f, -0.5f);
      glVertex3f(0.3f, 0.0f, -0.5f);
      glVertex3f(0.3f, 0.0f, 0.0f);
   glEnd();
}



///////////////////////////////////////////////////////////////
//
//  Теперь изменим нашу основную функцию:
//
///////////////////////////////////////////////////////////////
 
void RenderScene()
{
 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();

    glTranslatef(0.0f, -1.0f, -5.0f);
    glRotatef(-yRotation, 1.0f, 0.0f, 0.0f);
    glRotatef(-xRotation, 0.0f, 1.0f, 0.0f);

    glColor3f(1.0f, 1.0f, 1.0f);

    // Сначала мы отирсуем поверхность и забудем о ней. Затем я решил
    // нарисовать тень. Чтобы сделать это, мы создадим матрицу тени, основываясь на
    // позиции источника света и нормали поверхности. Создав эту матрицу, мы умножим её
    // на текущую задействованную матрицу. Таким образом всё, что вы отрендерите далее,
    // будет отрисовано плоским на поверхности, в точности как тень от обьекта. В принципе,
    // ничего сложного, верно? Чтобы нарисовать что-то в качестве тени, вы должны закрасить
    // обьект черным цветом и отключить текстуры. Я использовал glPush/PopMatrix, чтобы
    // операции с тенью не затронули остальных обьектов сцены.

    // Рисуем один большой обьект в качестве поверхности.
    glColor3f(0.4f,0.8f,0.4f);
    glBegin(GL_QUADS);
        glTexCoord2f(0.0, 0.0); glVertex3f(15.0f, -0.01f, 15.0f);
        glTexCoord2f(1.0, 0.0); glVertex3f(-15.0f, -0.01f, 15.0f);
        glTexCoord2f(1.0, 1.0); glVertex3f(-15.0f, -0.01f, -15.0f);
        glTexCoord2f(0.0, 1.0); glVertex3f(15.0f, -0.01f, -15.0f);
    glEnd();

    // Создадим матрицу тени на основе нормали поверхности и позиции источника света
    ShadowMatrix.CreateShadowMatrix(planeNormal, lightPos);

    // Теперь рисуем тень...
    glDisable(GL_DEPTH_TEST);

    glPushMatrix();

        // Одно то, что мы создали матрицу тени, ещё ничего не значит. Теперь нужно
        // умножить её на текущую матрицу:
        glMultMatrixf(ShadowMatrix.matrix);
        glColor3f(0.0f, 0.0f, 0.0f);
       
        // Нарисуем куб как обычно. Новая матрица сделает его плоским.
        DrawCube();
    glPopMatrix();

    glEnable(GL_DEPTH_TEST);

    // Теперь мы можем нарисовать обычный куб.
    glColor3f(0.8f, 0.5f, 0.5f);
    DrawCube();

    // Теперь нарисуем источник света
    glColor3f(1.0f, 1.0f, 0.0f);
    glTranslatef(lightPos.x, lightPos.y, lightPos.z);
   
    GLUquadricObj *pObj = gluNewQuadric();
    gluSphere(pObj, 0.05f, 6,6);
 
    SwapBuffers(g_hDC);
}


//////////////////////////////////////////////////////////////////////
//
// И последнее, что осталось сделать - написать обработку клавиш:
//

            case VK_UP:
                lightPos.z -= 0.05f;
                break;

            case VK_DOWN:
                lightPos.z += 0.05f;
                break;

            case VK_LEFT:
                lightPos.x -= 0.05f;
                break;

            case VK_RIGHT:
                lightPos.x += 0.05f;
                break;





Вот и всё. У нас есть тень, которая следует всллед за движениями "солнца".
Чтобы создать тень с помощью этой техники, сначала создаётся матрица тени. Затем
вы отрисовываете обьект дважды, один раз используя матрицу, второй раз нет. Но учитывайте
и то, что при использовании этого способа значительно возрастает и нагрузка, так что
для крупного проекта она может и не подойти.






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




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

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












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