您当前的位置: 首页 >  ar

龚建波

暂无认证

  • 4浏览

    0关注

    312博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

LearnOpenGL学习笔记:第一个三角形

龚建波 发布时间:2019-11-07 17:13:17 ,浏览量:4

( 本文对应学习章节:https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/ )

0.前言

本章节主要介绍了VAO/VBO以及顶点着色器/片段着色器,并绘制了一个三角形。

1.重要的东西

在OpenGL中,任何事物都在3D空间中,而屏幕和窗口却是2D像素数组,这导致OpenGL的大部分工作都是关于把3D坐标转变为适应你屏幕的2D像素。3D坐标转为2D坐标的处理过程是由OpenGL的图形渲染管线(Graphics Pipeline)管理的。图形渲染管线接受一组3D坐标,然后把它们转变为你屏幕上的有色2D像素输出。图形渲染管线可以被划分为几个阶段,每个阶段将会把前一个阶段的输出作为输入。

由于我这里只是应用型的学习,就不深入讲解(好吧,毕竟我也还没学会),具体的渲染流程请参考前言中的链接。对于应用,主要关注顶点着色器(Vertex Shader)和片段着色器(Fragment Shader)就行了。而且,在现代OpenGL中,我们必须定义至少一个顶点着色器和一个片段着色器(因为GPU中没有默认的顶点/片段着色器)。顶点着色器可用于传统的基于顶点操作,例如通过矩阵变换位置、计算照明方程式以生成逐顶点的颜色以及生成或者变换纹理坐标。片段着色器的主要目的是计算一个像素的最终颜色,这也是所有OpenGL高级效果产生的地方。通常,片段着色器包含3D场景的数据(比如光照、阴影、光的颜色等等),这些数据可以被用来计算最终像素的颜色。着色器需要用着色器语言GLSL(OpenGL Shading Language)编写,语法类似C语言,这个是后面章节的内容。

另外一个重点是VAO(顶点数组对象:Vertex Array Object)和VBO(顶点缓冲对象:Vertex Buffer Object)。VAO是一个对象,其中包含一个或者更多的Vertex Buffer Objects。而VBO是Graphics Card中的一个内存缓冲区,用来保存顶点信息,颜色信息,法线信息,纹理坐标信息和索引信息等等。一个VAO有多个VBO,它们之间通过上下文关联,只有唯一的激活VAO,在VAO后配置的VBO都属于该VAO(要在配置顶点属性glVertexAttribPointer之前,而glEnableVertexAttribArray在glVertexAttribPointer前后调用都可以)。不过有点没懂的是一开始我把VBO配置完了才去创建VAO,也是正常的。

还有就是顶点中的坐标,使用的标准化设备坐标(Normalized Device Coordinates, NDC)。与通常的屏幕坐标不同,y轴正方向为向上,(0, 0)坐标是这个图像的中心,而不是左上角。

还有就是顶点着色器中的 layout(location = 0) 这个输入偏移怎么来的,学到后半部分才看到是使用glVertexAttribPointer函数告诉OpenGL该如何解析顶点数据。每个顶点属性从一个VBO管理的内存中获得它的数据,而具体是从哪个VBO(程序中可以有多个VBO)获取则是通过在调用glVertexAttribPointer时绑定到GL_ARRAY_BUFFER的VBO决定的。

(对于VAO/VBO或者着色器的操作流程还有疑问可以参考教程的参考http://antongerdelan.net/opengl/hellotriangle.html)

2.第一个三角形

代码中着色器应用流程:

  1. glCreateShader  创建着色器对象
  2. glShaderSource  把着色器代码附加到着色器对象上
  3. glCompileShader  编译着色器
  4. glGetShaderiv  检测是否编译成功
  5. glCreateProgram  创建程序对象
  6. glAttachShader  把顶点和片段着色器附加到程序对象
  7. glLinkProgram  链接程序对象
  8. glGetProgramiv  检测是否链接成功
  9. glDeleteShader  删除着色器对象(附加到了程序对象,后面不需要了)
  10. glUseProgram  每次渲染时使用,使程序对象作为当前渲染状态的一部分

代码中VAO/VBO应用流程: 

  1. glGenVertexArrays  创建VAO
  2. glGenBuffers  创建VBO
  3. glBindVertexArray  绑定VAO
  4. glBindBuffer  绑定VBO
  5. glBufferData  把定义的顶点数据复制到缓冲的内存中
  6. glVertexAttribPointer  定义通用顶点属性数据的数组
  7. glEnableVertexAttribArray  使能顶点属性数组
  8. glBindVertexArray  每次渲染时使用,绑定一个顶点数组对象
  9. glDrawArrays  每次渲染时使用,绘制图元
  10. glDeleteVertexArrays  退出时删除VAO
  11. glDeleteBuffers  退出时删除VBO

从这些接口有点理解了OpenGL是以状态机来实现的。

#include 

#include 
#include 

void error_callback(int error, const char* description); //声明
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
void bufferresize_callback(GLFWwindow* window, int width, int height);

//顶点着色器程序,着色器语言GLSL下一节才学
//为了设置顶点着色器的输出,我们必须把位置数据赋值给预定义的gl_Position变量
//layout对应glVertexAttribPointer中的参数1
static const char* vertex_code = R"(
#version 330 core
layout(location=0) in vec3 aPos;

void main()
{
	gl_Position = vec4(aPos,1.0f);
}
)";

//片段着色器代码
//片段着色器所做的是计算像素最后的颜色输出
static const char* frag_code = R"(
#version 330 core
out vec4 FragColor;

void main()
{
	FragColor = vec4(0.1f,1.0f,0.1f,1.0f);
}
)";

int main()
{
	if (!glfwInit()) {
		return -1; //初始化GLFW库失败
	}
	//注册错误回调,大多数事件都是通过回调报告的
	glfwSetErrorCallback(error_callback);
	//设置最低主版本号
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	//设置最低次版本号
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	//设置为核心模式
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); //mac系统加这一句
	//创建窗口对象,如果要销毁窗口则glfwDestroyWindow(window)
	GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
	//创建失败则返回NULL,退出程序
	if (window == NULL)
	{
		std::cout             
关注
打赏
1655829268
查看更多评论
0.0954s