返回

从点到线:绘制一条直线

Android

从点到线:使用 OpenGL 绘制直线

绘制点的回顾

在上一篇博客中,我们探讨了如何使用 OpenGL 绘制一个点。现在,我们将踏入更复杂的世界,学习如何绘制一条直线。与点不同,一条直线需要两个顶点(点)来定义,因此我们需要更新我们的顶点着色器和片段着色器。

更新顶点着色器

#version 330 core
layout (location = 0) in vec3 position;

void main() {
  gl_Position = vec4(position, 1.0);
}

与绘制点时使用的顶点着色器相比,这里唯一的区别是顶点数据现在是一个包含三个浮点数的向量 vec3,而不是一个包含一个浮点数的向量 vec1。这三个浮点数分别代表顶点的 x、y 和 z 坐标。

片段着色器保持不变

片段着色器与绘制点时使用的片段着色器完全相同,因为它只是简单地将片段的颜色设置为红色:

#version 330 core
out vec4 FragColor;

void main() {
  FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

传递顶点数据

现在我们已经更新了顶点着色器,我们需要将两个顶点的数据传递给 OpenGL。我们可以使用 glVertexAttribPointer() 函数来实现:

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices);

这个函数告诉 OpenGL,我们要使用名为 position 的顶点属性,它是一个包含三个浮点数的向量。这些浮点数存储在 vertices 数组中。

接下来,我们需要启用 position 顶点属性:

glEnableVertexAttribArray(0);

绘制直线

现在,我们可以使用 glDrawArrays() 函数来绘制直线:

glDrawArrays(GL_LINES, 0, 2);

这个函数告诉 OpenGL,我们要绘制两条线段,从顶点数组的第一个顶点开始,到第二个顶点结束。

完整示例

以下是一个完整的示例代码,展示了如何使用 OpenGL 绘制一条直线:

#include <glad/glad.h>
#include <GLFW/glfw3.h>

int main() {
  // 初始化 GLFW
  glfwInit();
  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
  glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

  // 创建 GLFW 窗口
  GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL 直线绘制", NULL, NULL);
  if (window == NULL) {
    glfwTerminate();
    return -1;
  }
  glfwMakeContextCurrent(window);

  // 初始化 GLAD
  if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
    glfwTerminate();
    return -1;
  }

  // 顶点着色器
  const char* vertexShaderSource =
    "#version 330 core\n"
    "layout (location = 0) in vec3 position;\n"
    "void main() {\n"
    "  gl_Position = vec4(position, 1.0);\n"
    "}";

  // 片段着色器
  const char* fragmentShaderSource =
    "#version 330 core\n"
    "out vec4 FragColor;\n"
    "void main() {\n"
    "  FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
    "}";

  // 编译并链接着色器程序
  int vertexShader = glCreateShader(GL_VERTEX_SHADER);
  glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
  glCompileShader(vertexShader);

  int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
  glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
  glCompileShader(fragmentShader);

  int shaderProgram = glCreateProgram();
  glAttachShader(shaderProgram, vertexShader);
  glAttachShader(shaderProgram, fragmentShader);
  glLinkProgram(shaderProgram);

  // 创建顶点数据
  float vertices[] = {
    -0.5f, -0.5f, 0.0f,
     0.5f,  0.5f, 0.0f
  };

  // 创建顶点缓冲对象
  unsigned int VBO;
  glGenBuffers(1, &VBO);

  // 绑定顶点缓冲对象
  glBindBuffer(GL_ARRAY_BUFFER, VBO);

  // 将顶点数据复制到顶点缓冲对象
  glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

  // 启用顶点属性
  glEnableVertexAttribArray(0);

  // 设置顶点属性指针
  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

  // 渲染循环
  while (!glfwWindowShouldClose(window)) {
    // 清除颜色缓冲
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    // 使用着色器程序
    glUseProgram(shaderProgram);

    // 绘制直线
    glDrawArrays(GL_LINES, 0, 2);

    // 交换前后缓冲
    glfwSwapBuffers(window);

    // 处理事件
    glfwPollEvents();
  }

  // 释放资源
  glDeleteVertexArrays(1, &VBO);
  glDeleteProgram(shaderProgram);
  glDeleteShader(fragmentShader);
  glDeleteShader(vertexShader);

  // 终止 GLFW
  glfwTerminate();

  return 0;
}

常见问题解答

1. 我如何更改直线的颜色?

  • 通过在片段着色器中修改 FragColor 变量,您可以更改直线的颜色。

2. 我如何绘制多条直线?

  • 使用 glDrawArrays() 函数并增加最后一个参数,您可以绘制多条直线。

3. 我如何旋转直线?

  • 您可以通过在顶点着色器中使用 mat4 投影矩阵来旋转直线。

4. 我如何平移直线?

  • 与旋转类似,您可以通过在顶点着色器中使用 mat4 平移矩阵来平移直线。

5. 我如何缩放直线?

  • 最后,您可以通过在顶点着色器中使用 mat4 缩放矩阵来缩放直线。

结论

在本文中,我们详细介绍了如何使用 OpenGL 绘制一条直线。我们了解了如何更新顶点着色器、传递顶点数据并使用 glDrawArrays() 函数绘制直线。最后,我们提供了一个完整的示例代码供您参考。我希望本教程对您有用,欢迎提出任何问题或提供反馈。让我们一起探索 OpenGL 的神奇世界,绘制令人惊叹的图形!