> 文章列表 > OpenGL入门之 深入三角形

OpenGL入门之 深入三角形

想在3D世界里大展身手?别急,先别想着什么惊天动地的模型,先从三角形开始!这不,咱们用OpenGL画个三角形,简单得跟吃早餐一样。但别小看这个三角形,它可是3D世界里的“乐高积木”,没它还真不行。想画个房子?拆解成三角形,简单!想做个动画角色?还是用三角形来拼。所以,三角形才是基础,是王道!

那问题来了,为什么必须从三角形开始?因为三角形简单,容易处理。每个顶点都能精确控制,非常适合学习如何操作顶点数据和变换。再说了,复杂的模型,比如你手机里的游戏人物,哪个不是由无数个三角形拼凑而成?学会了画三角形,就能理解顶点缓冲、着色器的工作原理,这些都是3D渲染的核心。

那怎么一步步来呢?首先,得初始化GLFW,就像搭积木前得先整理好工具。设置窗口属性,选对OpenGL版本,确保兼容性。然后,创建顶点缓冲对象和顶点数组对象,这是用来存放三角形的坐标信息。编译顶点和片段着色器,赋予三角形颜色和形态。最后,把所有东西装进渲染循环,就能看到成果啦!

想让三角形动起来?别急,先得学会让它静止地展现。掌握这些基础,以后再学顶点动画、纹理贴图就轻松了。所以,从三角形开始,就是从零到英雄的第一步!

OpenGL入门之 深入三角形

一、引言

 本教程使用GLEWGLFW库。
 通过本教程,你能轻松的、深入的理解OpenGL如何绘制一个三角形
 如果你不了解OpenGL是什么,可以阅读OpenGL深入理解。

二、基本函数和语句介绍

 通过阅读以下的函数,你的大脑里能留下关于OpenGL基本函数的一个大致印象。(不需深入理解,可忽略此节)

  • glfwInit ()
     初始化glfw,为一些空指针赋值 。
  • glfwWindowHint(name, value)
     设置glfw库的一些属性,name为属性字段,value为设置的值。
     GLFW_CONTEXT_VERSION_MAJOR指OpenGL主版本号。
     GLFW_CONTEXT_VERSION_MINOR指OpenGL次版本号。
     GLFW_OPENGL_PROFILE指渲染模式, GLFW_OPENGL_CORE_PROFILE为核心模式。
     GLFW_RESIZABLE表示窗口可调性, GL_FALSE代表不可调。
  • glfwCreateWindow(width, height, title, NULL, NULL)
     创建一个glfw窗口,参数为:宽、高、窗口标题。返GLFWwindow* 类型。
  • glfwMakeContextCurrent(window)
     通知GLFW将窗口window的上下文设置为当前线程的主上下文。
  • glfwSetKeyCallback(window, callback)
     通过GLFW注册函数至合适的回调,callback为函数名。
  • glewExperimental = GL_TRUE
     让GLEW在管理OpenGL的函数指针时更多地使用现代化的技术,如果把它设置为GL_FALSE的话可能会在使用OpenGL的核心模式时出现一些问题。
  • glewInit()
     初始化glew。
  • glfwGetFramebufferSize(window, &width, &height);
     获取窗口window的大小width和height。
  • glViewport(x, y, width, height)
     设置视口位置,x、y表示视口左下角在窗口中的位置,width和height表示视口大小。
  • glCreateShader(shader)
     创建一个shader着色器,返回shader的引用。
     shader值有GL_VERTEX_SHADER和GL_FRAGMENT_SHADER。
  • glShaderSource(shader, n, &shaderSource, NULL)
     绑定shader着色器的源码,n为源代码中字符串数量,shaderSource为源代码字符串。
  • glCompileShader(shader)
     编译shader着色器。
  • glGetShaderiv(shader, GL_COMPILE_STATUS, &success)
     检查着色器shader编译是否成功编译,success为GLint类型。
  • glGetShaderInfoLog(shader, length, NULL, infoLog)
     获取错误信息并存储与infoLog字符数组中,length为数组长度。
  • glCreateProgram()
     创建一个着色器程序,返回其引用。
  • glAttachShader(shaderProgram, shader)
     将着色器shader添加到着色器程序shaderProgram中。
  • glLinkProgram(shaderProgram)
     链接着色器程序。
  • glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success)
     检测链接着色器程序是否成功。
  • glGetProgramInfoLog(shaderProgram, length, NULL, infoLog)
     获取链接着色器程序
  • glUseProgram(shaderProgram)
     激活着色器程序,激活后每个着色器调用和渲染调用都会使用这个程序对象。
  • glDeleteShader(shader)
     删除着色器对象。当把着色器对象链接到程序对象后,要删除着色器对象。
  • glGenVertexArrays(n, &VAO)
     返回一个顶点数组对象(Vertex Array Object, VAO)的引用。同样当n≥2时,返回的是一个引用的数组。
  • glGenBuffers(1, &VBO)
     返回一个顶点缓冲对象(Vertex Buffer Objects, VBO)的引用。同样当n≥2时,返回的是一个引用的数组。
  • glBindVertexArray(VAO)
     绑定VAO。
  • glBindBuffer(GL_ARRAY_BUFFER, VBO)
     绑定VBO。
  • glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW)
     专门用来把用户定义的数据复制到当前绑定缓冲的函数。
     第一个参数是目标缓冲的类型,第二个参数指定传输数据的大小(以字节为单位),第三个参数是我们希望发送的实际数据,第四个参数指定了我们希望显卡如何管理给定的数据。它有三种形式:
     GL_STATIC_DRAW : 数据不会或几乎不会改变。
     GL_DYNAMIC_DRAW:数据会被改变很多。
     GL_STREAM_DRAW : 数据每次绘制时都会改变。
  • glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0)
     进行顶点缓冲对象与顶点属性的链接。
  • glEnableVertexAttribArray(0)
     以顶点属性位置值作为参数,启用顶点属性(顶点属性默认是禁用的)。
  • glfwWindowShouldClose(window)
     检查GLFW是否被要求退出。
  • glfwPollEvents()
     检查事件
  • glClearColor(0.2f, 0.3f, 0.3f, 1.0f)
     设置清空屏幕所用的颜色。
  • glClear(GL_COLOR_BUFFER_BIT)
     清空屏幕的颜色缓冲。
  • glfwSwapBuffers(window)
     交换窗口的缓冲区。
  • glDeleteVertexArrays(1, &VAO)
     删除对应的VAO对象。
  • glDeleteBuffers(1, &VBO)
     删除对于的VBO对象。
  • glfwTerminate()
     释放GLFW分配的内存

三、重要语句模块

OpenGL渲染程序的大体框架是固定的,在本节你将会学习到一个个完整且独立的模块
 当我们学习完这些基本模块后,我们把模块拼接起来即可构成一个完整的OpenGL的程序。
 如果你对于文章整体脉络感到困惑,可以参考文章目录。
 如果你对片段化的模块代码感到头疼,可以往下阅读,在每个阶段我会展现完整的代码。
 如果在你读到模块代码时感到看困惑,请不要停止阅读,因为模块代码后会有小节专门解释。

1 GLFW和GLEW头文件的引用

宏定义表示glew是静态链接的

// GLEW的导入
#define GLEW_STATIC
#include <GL/glew.h>// GLFW的导入
#include <GLFW/glfw3.h>

OpenGL中的基元类型

 使用OpenGL时,建议使用OpenGL定义的基元类型比如使用float时我们加上前缀GL(因此写作GLfloat)。int、uint、char、bool等等也类似。OpenGL定义的这些GL基元类型的内存布局是与平台无关的,而int等基元类型在不同操作系统上可能有不同的内存布局。使用GL基元类型可以保证你的程序在不同的平台上工作一致。

2 GLFW的初始化和配置

2.1 模块代码

 	// 初始化 GLFWglfwInit();// 设置GLFW的使用 OpenGL的版本 为3.3glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);// 设置GLFW使用OpenGL的 核心模型glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);// 设置GLFW窗口大小的可调整性为:否glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);// 创建一个宽为WIDTH、高为HEIGHT、标题为"LearnOpenGL"的窗口GLFWwindow* window