Programação com OpenGL/Modern OpenGL Tutorial 04: diferenças entre revisões

Origem: Wikilivros, livros abertos por um mundo aberto.
[edição não verificada][edição não verificada]
Conteúdo apagado Conteúdo adicionado
Linha 2: Linha 2:


== Configurando as matrizes ==
== Configurando as matrizes ==
{{wikibooks|GLSL_Programming/Vertex_Transformations{{!}}section about Vertex Transformations in the GLSL Programming }}

{{wikibooks|GLSL_Programming/Vertex_Transformations{{!}} seção sobre transformação de vertices na linguaguem GLSL}}
Aqui estão algumas dicas para se lembrar quando se trabalha com matrizes:
Aqui estão algumas dicas para se lembrar quando se trabalha com matrizes:
* Transformações são aplicados pela multiplicação de matrizes 4X4 na ordem inversa. O <code> M = M_translation * M_rotation</code> diz para rodar primeiro, e depois movimentar.
* Transformações são aplicados pela multiplicação de matrizes 4X4 na ordem inversa. O <code> M = M_translation * M_rotation</code> diz para rodar primeiro, e depois movimentar.

Revisão das 23h42min de 10 de maio de 2013

Neste tutorial nśo vamos mergulhar no mundo da transformação de matrizes, assim nós poderemos movimentar, rotacionar e mudar a escala do nosso triangulo.

Configurando as matrizes

Predefinição:Wikibooks Aqui estão algumas dicas para se lembrar quando se trabalha com matrizes:

  • Transformações são aplicados pela multiplicação de matrizes 4X4 na ordem inversa. O M = M_translation * M_rotation diz para rodar primeiro, e depois movimentar.
  • A Matriz é a matriz de identidade que não faz nada - absolutamente nenhuma movimentação.
  • Para transformar um vertex, nós multiplicaremos ele pela matriz: v' = M * v
  • As matrizes 4x4 pode ser aplicadas somente para vetores 4X1, que obtemos usando uma das quatro dimensões da vertice: (x, y, z, 1).

Para estas multiplicações, nós vamos precisar de bibliotecas aritmética(math). os Shader já possuem inclusas, um facil suporte para operações de matrizes, mas nós precisaremos manipular-las na linguaguem C. é também mais eficiente, porque os shaders são executados em cada vertice, então é melhor cacularmos as matrizes de antemão.

Neste tutorial nós usaremos OpenGL Mathematics A biblioteca GLM, que esta escrita em C++. A GLM usa algumas convenções da GLSL, e então será facil nós começarmos. Esta documentação tambem mostrar substitutos para a defassada OpenGL 1.x e funções da GLU, como o glRotate, glFrustum ou gluLookAt, que vem a calhar se você já usou eles.

Existem alternativas, como libSIMDx86 (que também trabalham em processador que não são da familia x86). você pode também escrever seus próprio códigos de matrizes, desde que não seja muito grande, veja o exemplo mesa-demos-8.0.1/src/egl/opengles2/tri.c no demos que vem no Mesa3D.

Nota: a partir de agora usaremos C++, vamos precisar mudar nosso programa para C++ - desculpe por isto, vamos então editar nosso primeiro tutorial para iniciarmos. Na verdade você só precisa mudar o nome triangle.c para triangle.cpp

O GLM é uma biblioteca header-only, então você não precisa modificar o Makefile, contando que os header esteja configurado no standard path. Para instalar o GLM no Debian ou no Ubuntu:

apt-get install libglm-dev

Agora nós podemos adicionar os cabeçalhos da GLM:

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

Usando 3D Points

Nossa matriz de transformação são para vertices em 3D. Mesmo que nós estejamos em 2D, vamos descrever nosso triângulo com um ponto 3D com Z = 0. de qualquer maneiro vamos mudar nosso objeto para 3D no próximo tutorial :)

Vamos definir ele (3 elementos por verticés) para OpenGL no triangle.cpp:

struct attributes {
  GLfloat coord3d[3];
  GLfloat v_color[3];
};

Agora, no init_resources()

  struct attributes triangle_attributes[] = {
    {{ 0.0,  0.8, 0.0}, {1.0, 1.0, 0.0}},
    {{-0.8, -0.8, 0.0}, {0.0, 0.0, 1.0}},
    {{ 0.8, -0.8, 0.0}, {1.0, 0.0, 0.0}}
  };

...

  attribute_name = "coord3d";
  attribute_coord3d = glGetAttribLocation(program, attribute_name);
  if (attribute_coord3d == -1) {
    fprintf(stderr, "Could not bind attribute %s\n", attribute_name);
    return 0;
  }

Mudaremos a configuração do array de vértices em onDisplay()

  glVertexAttribPointer(
    attribute_coord3d,   // atributo
    3,                   // numero de elementos por vértice, que é (x,y,z)
    GL_FLOAT,            // o tipo de elemento
    GL_FALSE,            // o valor que ele está
    sizeof(struct attributes),  // o próximo coord3d aparecerá a cada 6 flots.
    0                    // deslocamento do primeiro elemento.
  );

substitua as outras ocorrências de 'attribute_coord2d' correspondente e chame o shader usando a nova coordenada.

attribute vec3 coord3d;
[...]
void main(void) {
  gl_Position = vec4(coord3d, 1.0);

Criando uma matriz de transformação

No GLM vem inclusivo funções para calcular rotações, movimentação e escalas das matrizes. Vamos colocar nossa matriz de transformação em onIdle(), que calculará uma rotação progressiva combinado com movimentos:

void onIdle() {
  float move = sinf(glutGet(GLUT_ELAPSED_TIME) / 1000.0 * (2*3.14) / 5); // -1<->+1 a cada 5 segundos
  float angle = glutGet(GLUT_ELAPSED_TIME) / 1000.0 * 45;  // 45° por segundo
  glm::vec3 axis_z(0, 0, 1);
  glm::mat4 m_transform = glm::translate(glm::mat4(1.0f), glm::vec3(move, 0.0, 0.0))
    * glm::rotate(glm::mat4(1.0f), angle, axis_z);
  [...]

Passando para matriz de transformação

Assim como vimos no tutorial anterior, vamos adicionar um novo uniform, com glUniformMatrix4fv:

  /* Global */
  #include <glm/gtc/type_ptr.hpp>
  GLint uniform_m_transform;
  /* init_resources() */
  uniform_name = "m_transform";
  uniform_m_transform = glGetUniformLocation(program, uniform_name);
  if (uniform_m_transform == -1) {
    fprintf(stderr, "Could not bind uniform %s\n", uniform_name);
    return 0;
  }
  /* onIdle() */
  glUniformMatrix4fv(uniform_m_transform, 1, GL_FALSE, glm::value_ptr(m_transform));

Se você não está usando o GLM, é bom passar um ponteiro para uma array GLfloat[16], deste jeito:

  GLfloat matrix[16] = {...};
  glUniformMatrix4fv(uniform_m_transform, 1, GL_FALSE, matrix);

O vertex shader apenas tem que multiplicar o vertex pela matrix, como mostraremos abaixo:

uniform mat4 m_transform;
void main(void) {
  gl_Position = m_transform * vec4(coord3d, 1.0);
  [...]


Nosso triangulo, transformado

Nós notaremos que ainda que temos o problema em relação ao aspecto, (caso venhamos a ver em um monitor de 16:9) Nós corrigiremos isto no próximo tutorial de matrizes de Model-View-Projection(Modelo, visualização e Projeção)

Experimentando

Lembre que nós mencionamos sobre como aplicar matrizes na ordem contrária? em nosso exemplo, nos rodamos primeiro e depois movimentamos.

Tente fazer em outra direção: você vai fazer que o triangulo rotacione depois ele vai movimentar, o que significa que ele irá rodar sobre sua origem ao invés de rodar sobre seu próprio centro.

Navegue e baixe os códigos completos