我正在尝试通过使用OpenGL版本3.3将矩形的最小和最大点作为输入(在屏幕坐标中)来实现一个简单的API在屏幕上绘制矩形。 例如
void Rect(xmin, ymin, xmax, ymax);
OpenGL 2.x Rect()提供的类似API
我假设屏幕坐标不过是像素位置,其原点位于屏幕的左上角。 (OpenGL的原点在左下方)
通常,我们在顶点着色器中将局部空间点转换为NDC(通过世界,摄影机并最终裁剪空间),
gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * pointInLocalSpace;
我将矩形的最小和最大点(屏幕坐标,在我的情况下实际上是鼠标光标的位置)作为着色器中的均匀变量,以方便使用此API。
我当前的实现方式假定我们传递屏幕点时,它们在视图空间中(如果我错了,请纠正我)。并且我仅应用投影矩阵将其转换为NDC,
gl_Position = ProjectionMatrix * vec4(screen.x, screen.y, 0.0, 1.0);
我正在使用透视投影,并且正在准备线条以在几何着色器中绘制矩形。我在VBO中仅设置了一个顶点(0,0,0),并且没有在任何地方使用它。 (这种方法不是问题,因为我已经在其他情况下成功实现了该方法。)
问题是,我没有在屏幕上绘制任何矩形。
如果坐标转换不正确或我做错了什么,请问有人可以帮助我理解坐标转换吗? 不用着色器就可以画出这么简单的东西吗?
以下是我正在处理的代码段。
顶点着色器
#version 330 core
layout (location = 0) in vec3 aPos;
void main()
{
gl_Position = vec4(aPos, 1.0);
}
几何着色器
#version 330 core
layout (points) in;
layout (line_strip, max_vertices = 8) out;
out vec3 fColor;
uniform mat4 Projection;
uniform vec4 rect; // min.x = rect.x, min.y = rect.y, max.x = rect.z, max.y = rect.w
void main()
{
vec4 position = gl_in[0].gl_Position;
fColor = vec3(0.80, 0.0, 0.0);
gl_Position = Projection * vec4(rect.x, rect.y, 1.0, 1.0);
EmitVertex();
gl_Position = Projection * vec4(rect.z, rect.y, 1.0, 1.0);
EmitVertex();
EndPrimitive();
gl_Position = Projection * vec4(rect.z, rect.y, 1.0, 1.0);
EmitVertex();
gl_Position = Projection * vec4(rect.z, rect.w, 1.0, 1.0);
EmitVertex();
EndPrimitive();
gl_Position = Projection * vec4(rect.z, rect.w, 1.0, 1.0);
EmitVertex();
gl_Position = Projection * vec4(rect.x, rect.w, 1.0, 1.0);
EmitVertex();
EndPrimitive();
gl_Position = Projection * vec4(rect.x, rect.w, 1.0, 1.0);
EmitVertex();
gl_Position = Projection * vec4(rect.x, rect.y, 1.0, 1.0);
EmitVertex();
EndPrimitive();
}
片段着色器
#version 330 core
out vec4 FragColor;
in vec3 fColor;
void main()
{
FragColor = vec4(fColor, 1.0);
}
Cpp
// set up opengl
float points[] = {0.0f, 0.0f, 0.0f};
unsigned int VAO, VBO;
glGenBuffers(1, &VBO);
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(points), &points, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
glBindVertexArray(0);
.
.
//read and compile shaders (_rectangleDrawShader)
.
.
glm::mat4 projectionMatrix = glm::perspective(glm::radians(45.0), (float)width / (float)height, 0.1f, 100.0f);
while (!glfwWindowShouldClose(window))
{
.
.
// some stuff to clear the color, depth buffers.
.
.
glm::vec2 min(50,50), max(150, 150)
_rectangleDrawShader->use();
_rectangleDrawShader->setMat4("Projection", projectionMatrix);
_rectangleDrawShader->setVec4("rect", glm::vec4(min.x, min.y, max.x, max.y));
glBindVertexArray(VAO);
glDrawArrays(GL_POINTS, 0, 1);
glfwSwapBuffers(window);
glfwPollEvents();
}