Как установить определенную точку взгляда, используя перспективный вид с матрицами

в настоящее время я изучаю теорию 3D-рендеринга с помощью книги «Изучение современного программирования 3D-графики» и прямо сейчас застрял в одном из заданий «Дальнейшее изучение» по обзору главы 4, особенно последнего задания.

Ответ на третье действие был дан в этом вопросе., понял без проблем. Однако в этом последнем упражнении меня просят сделать все это на этот раз, используя только матрицы.

У меня есть решение, которое частично работает, но мне кажется, что это хакерство и, вероятно, неправильный способ сделать это.

Мое решение третьего вопроса заключалось в том, чтобы осциллировать компоненты x, y и z трехмерного вектора E в произвольном диапазоне и создать куб с увеличением и уменьшением масштаба (растущий снизу слева на исходную точку OpenGL). Я хотел сделать это снова с помощью матриц, это выглядело так:

ss1

ss2

Однако я получаю такие результаты с матрицами (игнорируя изменение цвета фона):

ss3

ss4

Теперь к коду ...

Матрица представляет собой число с плавающей запятой [16], называемое theMatrix, которое представляет собой матрицу 4x4 с данными, записанными в порядке по столбцам, со всеми, кроме следующих элементов, инициализированными нулем:

float fFrustumScale = 1.0f; float fzNear = 1.0f; float fzFar = 3.0f;

theMatrix[0] = fFrustumScale;
theMatrix[5] = fFrustumScale;
theMatrix[10] = (fzFar + fzNear) / (fzNear - fzFar);
theMatrix[14] = (2 * fzFar * fzNear) / (fzNear - fzFar);
theMatrix[11] = -1.0f;

тогда остальная часть кода остается такой же, как matrixPerspective обучающий урок, пока мы не перейдем к void display()функции:

//Hacked-up variables pretending to be a single vector (E)
float x = 0.0f, y = 0.0f, z = -1.0f;

//variables used for the oscilating zoom-in-out
int counter = 0;
float increment = -0.005f;
int steps = 250;

void display()
{
    glClearColor(0.15f, 0.15f, 0.2f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glUseProgram(theProgram);

    //Oscillating values
    while (counter <= steps)
    {
        x += increment;
        y += increment;
        z += increment;

        counter++;

        if (counter >= steps)
        {
            counter = 0;
            increment *= -1.0f;
        }
        break;
    }

    //Introduce the new data to the array before sending as a 4x4 matrix to the shader
    theMatrix[0] = -x * -z;
    theMatrix[5] = -y * -z;

    //Update the matrix with the new values after processing with E
    glUniformMatrix4fv(perspectiveMatrixUniform, 1, GL_FALSE, theMatrix);

    /*
    cube rendering code ommited for simplification
    */

glutSwapBuffers();
glutPostRedisplay();
}

А вот код вершинного шейдера, использующий матрицу:

#version 330

layout(location = 0) in vec4 position;
layout(location = 1) in vec4 color;

smooth out vec4 theColor;

uniform vec2 offset;
uniform mat4 perspectiveMatrix;

void main()
{
        vec4 cameraPos = position + vec4(offset.x, offset.y, 0.0, 0.0);

        gl_Position = perspectiveMatrix * cameraPos;
        theColor = color;
} 

Что я делаю не так или что путаю? Спасибо за то, что вы все это прочитали.


person rlam12    schedule 26.04.2014    source источник
comment
Отредактируйте свой вопрос и правильно добавьте изображения.   -  person 101010    schedule 26.04.2014


Ответы (1)


В OpenGL есть три основные матрицы, о которых вам нужно знать:

  • Матрица модели D: отображает вершины из локальной системы координат объекта в мировую кординатную систему.

  • View Matrix V: отображает вершины из мировой системы координат в систему координат камеры.

  • Матрица проекции P: отображает (или, что более удобно, проецирует) вершины из пространства камеры на экран.

  • Совместное применение модели и матрицы обзора дает нам так называемую Матрицу просмотра модели M, которая отображает вершины из локальных координат объекта в основную систему камеры.

    введите описание изображения здесь

    Матрица представления модели

    Изменение определенных элементов матрицы вида модели приводит к определенным точным преобразованиям камеры.

    Например, 3 матричных элемента в крайнем правом столбце введите здесь описание изображенияпредназначены для преобразования перевода < / сильный>. Диагональные элементы введите описание изображения здесьпредназначены для преобразования масштабирования. Правильное изменение элементов подматрицы

    введите описание изображения здесь

    предназначены для преобразования поворота вдоль оси камеры X, Y и Z.


Вышеупомянутые преобразования в коде C ++ довольно просты и показаны ниже:

  void translate(GLfloat const dx, GLfloat const dy, GLfloat dz, GLfloat *M)
  {
    M[12] = dx; M[13] = dy; M[14] = dz;
  }

  void scale(GLfloat const sx, GLfloat sy, GLfloat sz, GLfloat *M)  
  {
    M[0] = sx; M[5] = sy; M[10] = sz;
  }

  void rotateX(GLfloat const radians, GLfloat *M)  
  {
    M[5] = std::cosf(radians); M[6]  = -std::sinf(radians);
    M[9] = -M[6];              M[10] = M[5];
  }

  void rotateY(GLfloat const radians, GLfloat *M)  
  {
    M[0] = std::cosf(radians); M[2]  = std::sinf(radians);
    M[8] = -M[2];              M[10] = M[0];
  }

  void rotateZ(GLfloat const radians, GLfloat *M)  
  {
    M[0] = std::cosf(radians); M[1] = std::sinf(radians);
    M[4] = -M[1];              M[5] = M[0];
  }

Теперь вам нужно определить матрицу проекции P.

  • Ортографическая проекция:

// These paramaters are lens properties.
// The "near" and "far" create the Depth of Field.
// The "left", "right", "bottom" and "top" represent the rectangle formed
// by the near area, this rectangle will also be the size of the visible area.
GLfloat near   = 0.001, far   = 100.0;
GLfloat left   = 0.0,   right = 320.0; 
GLfloat bottom = 480.0, top   = 0.0;

// First Column
P[0] = 2.0 / (right - left);
P[1] = 0.0;
P[2] = 0.0;
P[3] = 0.0;

// Second Column
P[4] = 0.0;
P[5] = 2.0 / (top - bottom);
P[6] = 0.0;
P[7] = 0.0;

// Third Column
P[8] = 0.0;
P[9] = 0.0;
P[10] = -2.0 / (far - near);
P[11] = 0.0;

// Fourth Column
P[12] = -(right + left) / (right - left);
P[13] = -(top + bottom) / (top - bottom);
P[14] = -(far + near) / (far - near);
P[15] = 1;

  • Перспективная проекция:

// These paramaters are about lens properties.
// The "near" and "far" create the Depth of Field.
// The "angleOfView", as the name suggests, is the angle of view.
// The "aspectRatio" is the cool thing about this matrix. OpenGL doesn't
// has any information about the screen you are rendering for. So the
// results could seem stretched. But this variable puts the thing into the
// right path. The aspect ratio is your device screen (or desired area) width
// divided by its height. This will give you a number < 1.0 the the area 
// has more vertical space and a number > 1.0 is the area has more horizontal 
// space. Aspect Ratio of 1.0 represents a square area.
GLfloat near        = 0.001;
GLfloat far         = 100.0;
GLfloat angleOfView = 0.25 * 3.1415;
GLfloat aspectRatio = 0.75;

// Some calculus before the formula.
GLfloat size   =  near * std::tanf(0.5 * angleOfView); 
GLfloat left   = -size
GLfloat right  =  size;
GLfloat bottom = -size / aspectRatio;
GLfloat top    =  size / aspectRatio;

// First Column
P[0] = 2.0 * near / (right - left);
P[1] = 0.0;
P[2] = 0.0;
P[3] = 0.0;

// Second Column
P[4] = 0.0;
P[5] = 2.0 * near / (top - bottom);
P[6] = 0.0;
P[7] = 0.0;

// Third Column
P[8]  = (right + left) / (right - left);
P[9]  = (top + bottom) / (top - bottom);
P[10] = -(far + near) / (far - near);
P[11] = -1.0;

// Fourth Column
P[12] = 0.0;
P[13] = 0.0;
P[14] = -(2.0 * far * near) / (far - near);
P[15] = 0.0;

Тогда ваш шейдер станет:


#version 330

layout(location = 0) in vec4 position;
layout(location = 1) in vec4 color;

smooth out vec4 theColor;

uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;

void main()
{
  gl_Position = projectionMatrix * modelViewMatrix * position;
  theColor    = color;
} 

Библиография:

http://blog.db-in.com/cameras-on-opengl-es-2-x/

http://www.songho.ca/opengl/gl_transform.html


person 101010    schedule 26.04.2014
comment
Большое спасибо! Насколько я понял, я пытался использовать одну единственную матрицу как в качестве модели, так и в качестве матрицы представления, имея в виду, что теперь код работает, еще раз спасибо! - person rlam12; 27.04.2014
comment
@ rlam12 Всегда рад помочь. Кстати, если вы нашли ответ полезным, вы можете проверить свой вопрос, получив ответ :). - person 101010; 27.04.2014