最近,我试图使用OpenGL在我的Window Content View(OSX NSView)中渲染一个三角形(如图1所示),我使用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, &p[0][0]);
glUniformMatrix4fv(_viewUniform, 1, GL_FALSE, &v[0][0]);
glUniformMatrix4fv(_modelUniform, 1, GL_FALSE, &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;
}
答案 0 :(得分:1)
glm
矩阵的初始化方法与GLSL矩阵相同。有关更多信息,请参见The OpenGL Shading Language 4.6, 5.4.2 Vector and Matrix Constructors, page 101。
向量必须从右边乘以矩阵。
请参见GLSL Programming/Vector and Matrix Operations:
请注意,向量必须从右边乘以矩阵。
如果将向量从左侧乘以矩阵,则结果对应于将行向量从左侧乘以矩阵。这相当于将列向量从右边乘以转置矩阵。
这意味着您必须在顶点着色器中更改顶点变换:
gl_Position = position * projection * view * model;
gl_Position = projection * view * model * position;
答案 1 :(得分:0)
@ 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];
}