Как отобразить 2 или более объектов в openGL (модель - вид - матрицы проекций и шейдеры) - PullRequest
6 голосов
/ 29 февраля 2012

Все нормально, когда я хочу нарисовать один объект, например, куб.Я создаю вершины для куба, я создаю буфер, я создаю матрицу MVP и отправляю ее в шейдер, и она хорошо работает.

Но, что делать, когда я хочу нарисовать 2 или более объектов например куб и треугольник?Я считаю, что матрицы вида и проекции должны быть одинаковыми как для треугольника, так и для куба, мне нужны только разные матрицы моделей, верно?Значит, у меня будет два MVP?

//Example (using GLM):

glm::mat4 MVPC = Projection * View * ModelCube; 
glm::mat4 MVPT = Projection * View * ModelTriangle; 

Так что мне теперь делать с этими двумя?Это вершинный шейдер, который хорошо работает для куба

//vertex shader
#version 330 core

layout(location = 0) in vec3 verticesCube;

uniform mat4 MVPC;

void main(){

     gl_Position =  MVPC * vec4(verticesCube,1);

}

И что мне делать с MVPT (треугольником) в шейдере, я пытался возиться с разными вещами, но не могу заставить его работать,я не могу одновременно отображать куб и треугольник.

Ответы [ 4 ]

7 голосов
/ 30 августа 2013

Путаница возникает из-за того, что шейдер управляет несколькими массивами вершин одновременно, когда его следует рассматривать как универсальную сущность. Массив вершин передается шейдеру, затем объект рисуется. И процесс повторяется.

Например, допустим, мы присвоили переменную matrixID униформе MVP :

    // get handle for our "MVP" uniform
    GLuint matrixID = glGetUniformLocation(programID, "MVP");

Когда мы готовы нарисовать объект, мы устанавливаем matrixID для MVP объекта:

    glUniformMatrix4fv(matrixID, 1, GL_FALSE, &cubeMVP[0][0]);

Затем свяжите буфер вершин, установите указатель атрибута и нарисуйте его:

    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, cubeVerteciesBuffer);

    glVertexAttribPointer(
            0,      // shader layout location
            3,
            GL_FLOAT,
            GL_FALSE,
            0,
            (void *)0
    );
    glDrawArrays(GL_TRIANGLES, 0, 12*3);    // draw cube

Теперь мы переходим к треугольнику и повторяем процесс - установите matrixID на MVP объекта, привяжите буфер вершин, установите указатель атрибута и нарисуйте его:

    glUniformMatrix4fv(matrixID, 1, GL_FALSE, &triMVP[0][0]);

    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, triangleVerteciesBuffer);

    glVertexAttribPointer(
            0,      // shader layout location
            3,
            GL_FLOAT,
            GL_FALSE,
            0,
            (void *)0
    );
    glDrawArrays(GL_TRIANGLES, 0, 3);   // draw triangle

Соответствующий код вершинного шейдера:

#version 330 core
// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertecies_modelspace;

uniform mat4 MVP;

void main(){
    gl_Position = MVP * vec4(vertecies_modelspace, 1);
}
3 голосов
/ 29 февраля 2012

OpenGL не является графом сцены.Он рисует вещи в соответствии с текущим состоянием, а затем забывает об этом.

Так что, если вы хотите нарисовать разные геометрии, с разными преобразованиями просто установите соответствующую матрицу преобразования (равномерную), нарисуйте объект и повторите это для каждогообъект, который вы хотите нарисовать.После отрисовки геометрии следующие операции больше не будут на нее влиять, кроме того, что она может быть отменена.

2 голосов
/ 11 ноября 2015

Альтернативой, которая также может работать, было бы выполнение вычисления матрицы «ModelViewProjection» в вершинном шейдере.Это можно сделать, создав матричные переменные модель , view и projection в вершинном шейдере.Затем вы можете глобально рассчитать просмотр и проекции матриц и отправить их в шейдер.Затем вы можете просто рассчитать матрицу модели для своего куба и треугольника (или любых объектов, которые вам нужно визуализировать) и отправить эти матрицы модели также в шейдер.


Просмотр и вычисления матрицы проекции;это может быть отдельный класс «камеры»:

glm::mat4 viewMatrix = glm::lookAt(
  glm::vec3(0, -5, 0), // camera location in world
  glm::vec3(0, 0, 0), // point camera is looking at
  glm::vec3(0, 1, 0) // orientation of camera, change 1 to -1 to flip camera upside down
);

glm::mat4 projectionMatrix = glm::perspective(35.0f, displayWidth / displayHeight, 0.1f, 100.0f);

// send view and projection matrices to the shader
glUseProgram(shaderProgram);
GLint viewMatrixId = glGetUniformLocation(shaderProgram, "view");
GLint projectionMatrixId = glGetUniformLocation(shaderProgram, "projection");

glUniformMatrix4fv(viewMatrixId, 1, GL_FALSE, &viewMatrix[0][0]);
            glUniformMatrix4fv(projectionMatrixId, 1, GL_FALSE, &projectionMatrix[0][0]);
glUseProgram(0);

Расчет матрицы модели;этот код может входить в отдельный класс, и вы можете создать его экземпляр для каждого объекта, который хотите визуализировать:

// this can go after where you initialize your cube or triangle vertex information
glUseProgram(shaderProgram);
modelMatrixId = glGetUniformLocation(shaderProgram, "model"); //modelMatrixId can be a global GLint
glUniformMatrix4fv(modelMatrixId, 1, GL_FALSE, &modelMatrix[0][0]); //modelMatrix can be a global glm::mat4
glUseProgram(0);

//use this for every render frame
glUseProgram(shaderProgram);
glUniformMatrix4fv(modelMatrixId, 1, GL_FALSE, &modelMatrix[0][0]);

// code to bind vertices and draw you objects goes here

glUseProgram(0);

Новый вершинный шейдер:

//vertex shader
#version 330 core

layout(location = 0) in vec3 vertices;

uniform mat4 model, view, projection;

void main(){

     gl_Position =  projection * view * model * vec4(vertices, 1.0);

}
0 голосов
/ 08 мая 2013

Имеют два массива вершин.Давайте скажем массив1 для куба, массив2 для круга.Создайте 2 vaos и 2 vbos.vao1 и vbo1 для куба.vao2 и vbo2 для круга.

Привязка vao1, привязка vbo1, заполнение буфера vbo1 массивом1.glUserProgram (программа), которая является программой для шейдеров, настраивает vertexattripointer.

вызовите glDrawArray ()

Сделайте то же самое для других vao и vbo.

...