OPenGL学习记录1-渲染管线和第一个三角形

引擎初学者
发布于

这一部分应该是我好几周之前实现的了,这次写这篇文章也算是复习了。

这篇文章是站在已经配置好OPenGl的环境,用VS创建一共空项目为前提了。

首先是根据我看到的视频教程或者papers,都有说到其实渲染分成传统的光栅化和近些年的光线追踪。首先此处的渲染指的是从数据开始制造一张图片,

光栅化:这个我写过代码看过论文和视频教程,我个人的理解其实光栅化的核心就是投影(MVP)这个矩阵。说白了就是:你现在有一个三维模型的数据(处于某种坐标系下),然后你需要根据这些数据,再加上你设置的视点等通过投影把这个三维模型投影到二维平面上。

   这个图就是OPenGL官网上的图形渲染管线图。是一个光栅化的过程,其中三个着色器为蓝色,意思是可编程,就是我们可以干预的过程。

光线追逐:这个是一个模拟场景中光线进入人眼睛的过程,我感觉这个核心是在计算每一个像素的颜色贡献值上面,简单理解就是这个像素接受到的光线越多就会越亮,所以光线追踪的效果会好一点,当然渲染时间也对应久一点,关于光追这一块我目前代码写的不多,论文和相关资料只是有些接触,所以就不多说了,以后有机会我再专门写有关光线追踪的文章吧!


开始画三角形吧!

第一步:开一个窗口,在main函数中使用如下代码:

1、初始化窗口的参数:

   glfwInit();

   glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);

   glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);

   glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);

2、生成一个窗口:

    GLFWwindow* window = glfwCreateWindow(800, 600, "MyLearnOpenGL", NULL, NULL);

3、GLFW允许用户创建OpenGL上下文、定义窗口参数以及处理用户输入。初始化这个库

   glfwTerminate();

4、创建OpenGl上下文

   glfwMakeContextCurrent(window);

到这里就可以呼出一共OPenGL的800*600的窗口了。然后就可以快乐的在里面绘制你想的画面了。

第二步:三角形数据准备,在main函数中使用如下代码:

懒得手打了,直接截图吧,下面是代码,画一个三角形目前只用VAO和VBO足够。

    unsigned int VAO,VBO; //这个可以理解为一共索引的标志

    glGenVertexArrays(1, &VAO); //可以理解为生成一个存储数据的数组

    glBindVertexArray(VAO);

   //这个可以填多个模型。多个模型的用法

   //unsigned int VBO[10];

   //glGenVertexArrays(10, VBO);

   glGenBuffers(1,&VBO);

   glBindBuffer(GL_ARRAY_BUFFER,VBO);

   glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

//vertices是事先声明好的一组float类型的数据

(对于多个模型可以用EBO,然后接下来本应该是对顶点,颜色,UV,纹理的处理,但是画一个三角形不需要,只用对位置信息进行处理)

   glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);

   glEnableVertexAttribArray(0);//此处的0代表的是顶点数据,可以给0-15,不能是16.这0-15就可以代表顶点,法线,uv坐标等。

进入下一步:

第三部:写着色器

基础的顶点着色器:

#version 330 core

layout (location = 0) in vec3 aPos;

void main() { gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0); }

可以理解这个0对应上文中的 glVertexAttribPointer里面的参数0.

基础的片段着色器,(这个小三角不需要几何着色器):

#version 330 core

out vec4 FragColor;

void main() { FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f); }

//设置的颜色

第四步:设置MVP矩阵和渲染回圈

写到这里,属实累了,,,

下面是MVP中的M和P。

   glm::mat4 model;

   model = glm::rotate(model, glm::radians(-55.0f), glm::vec3(1.0f, 0.0f, 0.0f));

   glm::mat4 proj = glm::perspective(glm::radians(45.0f), (float)800 / (float)600, 0.1f, 100.0f);

V矩阵在渲染回圈中获取,这个循环的意思就是每一帧屏幕回更新一下,View矩阵写在里面的好处是将来如果我们控制画面里面的视点移动,他会随着这个循环更新。

glm::mat4 view;

       view = camera.GetViewMatrix();代码很简单。

渲染回圈是这样写的,很简单得嘞!

循环里面首先包括:

 glClearColor(0.2f, 0.3f, 0.3f, 1.0f);//先设置清屏颜色

       glClear(GL_COLOR_BUFFER_BIT);

然后是对于我们设置的MVP矩阵绑定到我们的shader上面。

glUniformMatrix4fv(glGetUniformLocation(myShader->ID, "model"), 1, GL_FALSE, glm::value_ptr(model2));

           glUniformMatrix4fv(glGetUniformLocation(myShader->ID, "view"), 1, GL_FALSE, glm::value_ptr(view));

           glUniformMatrix4fv(glGetUniformLocation(myShader->ID, "proj"), 1, GL_FALSE, glm::value_ptr(proj));


很无语,写到这个地方发现自己搞错了,其实画一个三角形就不需要MVP矩阵,我们上文设置的vertices数据其实就是直接是在屏幕坐标上设置的了。我真的栓q、

好吧,请大家先忽略上文有关MVP的代码,其实渲染回圈里面只需要下面代码即可:

processInput(window);加上上面的glclear那几个函数

//使用我们的渲染器

 glUseProgram(shaderProgram);

好吧在数据准备完成之后应该先调用我们写好的着色器了。这一部分我下篇给补上吧!!!啊啊啊

 glBindVertexArray(VAO);

 glDrawArrays(GL_TRIANGLES, 0, 3);

到这里就画出来了,然后是交换缓存,可以理解为每一次循环的更新。

glfwSwapBuffers(window);

       glfwPollEvents();

跳出这个渲染回圈:

glfwTerminate();//上文初始化的这个库不要忘记给他清除了。

   return 0;

行文至此,落笔之处皆是思念,哈哈哈,好吧,最近师兄师姐快毕业,估计他们会用到。

个人第一次写类似的文章,会有很多不足,希望大家多多包容,下一期我尽量让思路更通畅一些。包括刚刚写的时候发现的两个问题,其中一个还没有补全,如果有大佬发现其他问题,可以批评指出,万分感谢,最后十分感谢Piccolo这个社区平台。

上一篇文章中有个小伙伴让我分享一些学习OPENGL的心得:

目前学习这么多时间,我个人决定OPENGL这个语言,还是需要多练习,然后去揣摩当初为什么这样设计的,我现在还处于练习期,心得谈不上,只能说这个语言基本上能够满足科研的很多需求了。

在这里我今天发现我们社区有一位大佬开始更新有关Vulkan的教程,樱粉花蜜糖 支持一波!


4
评论 1
收藏
  • MR7
    MR7
    感谢分享~