#opengl #glsl #shader #projection #glm-math
#opengl #glsl #шейдер #проекция #glm-math
Вопрос:
Недавно, я пытаюсь отобразить треугольник (как показано на рисунке 1) в моем представлении содержимого окна (OSX NSView), используя OpenGL, я создаю «орфографическую проекцию» с помощью функции библиотеки GLM glm:: ortho, после рендеринга все вершины треугольника находятся в неправильном месте, кажется, они смещены по отношению к представлению содержимого окна.
У меня есть 2 вопроса:
-
Я неправильно понял glm :: ortho (основываю следующий код)?
-
При изменении размера окна (увеличение, уменьшение масштаба), как сохранить треугольник в том же месте в окне (т. Е. Верхняя вершина в середине ширины, а нижние вершины в углу)?
Результат следующий:
моя функция рендеринга:
- (void)render
{
float view_width = self.frame.size.width;
float view_height = self.frame.size.height;
glViewport(0, 0, view_width, view_height);
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Using Orthographic Projection Matrix, vertex position
// using view coordinate(pixel coordinate)
float positions[] = {
0.0f, 0.0f, 0.0f, 1.0f,
view_width, 0.0f, 0.0f, 1.0f,
view_width/(float)2.0, view_height, 0.0f, 1.0f,
};
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(positions), positions);
glm::mat4 p = glm::ortho(0.0f, view_width, 0.0f, view_height);
glm::mat4 v = glm::lookAt(glm::vec3(0, 0, 1), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
glm::mat4 m = glm::mat4(1.0f);
// upload uniforms to shader
glUniformMatrix4fv(_projectionUniform, 1, GL_FALSE, amp;p[0][0]);
glUniformMatrix4fv(_viewUniform, 1, GL_FALSE, amp;v[0][0]);
glUniformMatrix4fv(_modelUniform, 1, GL_FALSE, amp;m[0][0]);
glDrawElements(GL_TRIANGLE_STRIP, sizeof(positions) / sizeof(positions[0]),GL_UNSIGNED_SHORT, 0);
[_openGLContext flushBuffer];
}
мой вершинный шейдер:
#version 410
in vec4 position;
uniform highp mat4 projection;
uniform highp mat4 view;
uniform highp mat4 model;
void main (void)
{
gl_Position = position * projection * view * model;
}
Комментарии:
1. Это должно быть
gl_Position = projection * view * model * position;
Ответ №1:
glm
Матрица инициализируется таким же образом, как матрица GLSL. См. Язык затенения OpenGL 4.6, 5.4.2 Векторные и матричные конструкторы, стр. 101 для получения дополнительной информации.
Вектор должен быть умножен на матрицу справа.
См. Программирование на GLSL / векторные и матричные операции:
Обратите внимание, что вектор должен быть умножен на матрицу справа.
Если вектор умножается на матрицу слева, результат соответствует умножению вектора строки слева на матрицу. Это соответствует умножению вектора столбца на транспонированную матрицу справа.
Это означает, что вы должны изменить преобразование вершин в вершинном шейдере:
gl_Position = position * projection * view * model;
gl_Position = projection * view * model * position;
Ответ №2:
@Rabbid76 ответил на мой первый вопрос, это работает! Большое спасибо. Второй вопрос, в OSX, при изменении размера окна (содержащего представление OpenGL), NSOpenGLContext должен обновляться следующим образом:
- (void)setFrameSize:(NSSize)newSize {
[super setFrameSize:newSize];
// update the _openGLContext object
[_openGLContext update];
// reset viewport
glViewport(0, 0, newSize.width*2, newSize.height*2);
// render
[self render];
}