目录

  • 前言
  • 创建简单的应用
    • 创建脚本
    • 渲染底色
    • 渲染底色plus
  • 使用着色器(shader)
    • 什么是着色器(shader)
    • GLSL
    • OpenGL的着色阶段
    • 编写着色器
      • 顶点着色器
      • 片段着色器
      • shader对象的创建
      • 执行程序的创建
      • 删除无用的shader
    • 顶点数组对象VAO
    • 清理VAO和Program
    • 使用和展示着色器效果
      • 效果
  • 绘制三角形
  • 推送
  • 结语

前言

  • 2.1 创建简单的应用
  • 2.2 使用着色器
  • 2.3 绘制我们的第一个三角形
  • 2.4 总结

本篇文章将学习超级宝典的第二章内容,根据演示示例制作我们第一个OpenGL程序

创建简单的应用

第一小节,我们需要学习如何去编译运行我们第一个OpenGl程序

创建脚本

  • 创建新类

第一步我们需要去创建一个新的C++类,该类位于我们启动项的Source Files文件下

  • 继承application
    #include <sb7.h>class singlepoint_app_test : public sb7::application{virtual void startup(){}virtual void render(double currentTime){}};DECLARE_MAIN(singlepoint_app_test)

内容相当的简单,我们继承application类,然后通过宏DECLARE_MAIN去创建新类的实例,创建后会调用默认的run方法,实现一个窗体应用

  • startup方法

初始化的时候被调用

  • render方法

编辑渲染逻辑,参数currentTime是运行经过的秒数

  • 注释原有的宏

因为老代码我们并没有删,所以我们把原来的宏给注释了,一个解决方案内只能存在一个主循环,保留我们新定义的实例即可

  • 运行效果

创建的窗体,一个啥也没有的黑色窗口

渲染底色

现在我们要给单调的窗口添加一个纯色背景,在render里面书写代码

  • glClearBufferfv
virtual void render(double currentTime)
{const GLfloat red[] = { 1.0f, 0.0f, 0.0f, 1.0f };glClearBufferfv(GL_COLOR, 0, red);
}

当前代码的作用就是让窗口的底色变为红色

要点1: 我们生命了一个浮点向量red[],四个浮点值分别代表RGBA四个值,1.0f即255,0就是0,当前数值代表三原色的红色
要点2: glClearBufferfv,OpenGL的一个函数,作用是清除第一个参数GL_COLOR的缓存为第三个参数red,可能存在多个输出缓存可清除的情况,第二个参数代表清除缓存的下标,当前只有一个缓存所以是0
要点3: 所有OpenGL的函数都是gl开头的
要点4: 后缀fv表示该函数使用一组向量浮点值

  • 效果

渲染底色plus

我们已经可以给窗体设置底色了,现在来个进阶版,根据render的参数currentTime设置个动态变色

virtual void render(double currentTime)
{const GLfloat red[] = { (float)sin(currentTime) * 0.5f,(float)cos(currentTime) * 0.5f,0.0f, 1.0f };glClearBufferfv(GL_COLOR, 0, red);
}
  • 效果

随着时间不短的变换窗口底色


使用着色器(shader)

什么是着色器(shader)

  • 百度百科
https://baike.baidu.com/item/%E7%9D%80%E8%89%B2%E5%99%A8/411001?fr=aladdin

简而言之,就是让我们可以编辑去实现特定效果的一段程序

GLSL

GLSL就是OpenGL的着色语言,OpenGL内置了对GLSL的编译器,语法和C类似

  • 百度百科
https://baike.baidu.com/item/GLSL?fromModule=lemma_search-box

OpenGL的着色阶段

OpenGL的着色分一下几个阶段

  1. 顶点着色器
  2. 细分曲面控制和评价着色器
  3. 评价着色器
  4. 几何着色器
  5. 片段着色器
  6. 计算着色器

要点: 平常需要我们手动去编写的只有顶点着色器片段着色器

编写着色器

以下是一个用来获取执行程序Program的方法,我们一点点来分析

GLuint compile_shaders(void)
{GLuint vertex_shader;GLuint fragment_shader;GLuint program;//顶点着色器static const char * vs_source[] ={"#version 420 core                             \n""                                              \n""void main(void)                               \n""{                                             \n""    gl_Position = vec4(0.0, 0.0, 0.5, 1.0);   \n""}                                             \n"};//片段着色器static const char * fs_source[] ={"#version 420 core                             \n""                                              \n""out vec4 color;                               \n""                                              \n""void main(void)                               \n""{                                             \n""    color = vec4(0.0, 0.8, 1.0, 1.0);         \n""}                                             \n"};vertex_shader = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertex_shader, 1, vs_source, NULL);glCompileShader(vertex_shader);fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragment_shader, 1, fs_source, NULL);glCompileShader(fragment_shader);program = glCreateProgram();glAttachShader(program, vertex_shader);glAttachShader(program, fragment_shader);glLinkProgram(program);glDeleteShader(vertex_shader);glDeleteShader(fragment_shader);return program;
}

顶点着色器

嵌入在代码中的点点着色器,本质就是一段GLSL代码的字符串,顶点着色器用来输出顶点位置

static const char * vs_source[] =
{"#version 420 core                             \n""                                              \n""void main(void)                               \n""{                                             \n""    gl_Position = vec4(0.0, 0.0, 0.5, 1.0);   \n""}                                             \n"
};

要点1: #version 420 core,420代表的含义是使用着色语言的4.2版本,core指的是我们只想要用OpenGL核心模式所支持的特性
要点2: gl_开始的变量都是OpenGL的一部分
要点3: gl_position表示顶点输出的部分

上述顶点着色器代码意指,所有使用该顶点着色器的顶点输出位置都在屏幕正中央

片段着色器

片段着色器和顶点着色器类似,功能不同,片段着色器用来输出颜色

static const char * fs_source[] =
{"#version 420 core                             \n""                                              \n""out vec4 color;                               \n""                                              \n""void main(void)                               \n""{                                             \n""    color = vec4(0.0, 0.8, 1.0, 1.0);         \n""}                                             \n"
};

要点1: out关键字定义color作为一个输出变量
要点2: 设置给color变量的浮点值,最终会作为顶点颜色输出在屏幕上

当前片段着色器,意指所有只用该着色器的顶点颜色均是青色

shader对象的创建

我们写的着色器本质就是一段字符串,我们需要将写好的字符串编译成可被执行的shader代码

GLuint vertex_shader;
GLuint fragment_shader;vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, vs_source, NULL);
glCompileShader(vertex_shader);fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, fs_source, NULL);
glCompileShader(fragment_shader);

要点1: glCreateShader,OpenGL内置结构,意指创建一个空的shader对象
要点2: glShaderSource,将我们写的字符串着色器代码传给shader对象,保留副本
要点3: glCompileShader,将shader对象中我们传入的字符源码进行编译

执行程序的创建

shader只是业务逻辑,我们需要创建一个程序对象来取执行逻辑

program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);

要点1: glCreateProgram,创建一个空的执行程序Program
要点2: glAttactShader,将shader对象附加给执行程序
要点3: glLinkPrigram,将各对象一起连接到可在图形处理器上运行的代码中

删除无用的shader

在通过glAttachShader附加shader到program的时候,会在program内保留shader副本,原shader无用,可删

glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);

要点1: glDeleteShader,删除shader对象

顶点数组对象VAO

什么是顶点数组对象?

博主刚看到这里对这个东西的理解还不是特别清楚,当前理解的大意就是,所有对顶点的操作都会缓存在这个数组内,顶点着色器的数据都来自这个数组,如果想显示渲染结果,VAO是必不可少的

virtual void startup()
{program = compile_shaders();glGenVertexArrays(1, &vao);glBindVertexArray(vao);
}

要点1: glGnVertexArrays,创建VAO,生成一个顶点数组对象,存储到vao内
要点2: glBindVertexArray,将赋值过得vao对象链接到上下文,让OpenGL能获取到
要点3: 我们在startup中获取了刚才附加shader的程序对象program

我们在startup内去创建VAO,并绑定到上下文

清理VAO和Program

我们在start的时候创建了vao和program,同理的我们应该在程序结束把他们删除掉

void shutdown()
{glDeleteVertexArrays(1, &vao);glDeleteProgram(program);
}

要点1: shutdown方法重写自基类,在程序结束时调用
要点2: glDeleteVertexArrays,删除VAO
要点3: glDeleteProgram,删除program

使用和展示着色器效果

最终展示效果当然要写在render方法内了

virtual void render(double currentTime)
{const GLfloat red[] = { (float)sin(currentTime) * 0.5f,(float)cos(currentTime) * 0.5f,0.0f, 1.0f };glClearBufferfv(GL_COLOR, 0, red);glUseProgram(program);glDrawArrays(GL_POINTS,0,1);glPointSize(40.0f);
}

要点1: glUseProgram,告诉OpenGL用哪个program去进行渲染
要点2: glDrawArrays,执行绘图命令

  • 参数1:告诉OpenGL想要渲染何种图元
  • 参数2:从数组缓存中的哪一位开始绘制,一般为0
  • 参数2:数组中顶点的数量

要点3: glPointSize,设置绘制顶点的大小

效果


绘制三角形

绘制三角形肯定需要三个点,结合我们之前了解到到的内容,顶点着色器设置顶点的位置,所以我们需要修改顶点着色器,设置三个顶点,就可以绘制三角形

  • 顶点着色器
static const char * vs_source[] =
{"#version 420 core                                                 \n""                                                                  \n""void main(void)                                                   \n""{                                                                 \n""    const vec4 vertices[] = vec4[](vec4( 0.25, -0.25, 0.5, 1.0),  \n""                                   vec4(-0.25, -0.25, 0.5, 1.0),  \n""                                   vec4( 0.25,  0.25, 0.5, 1.0)); \n""                                                                  \n""    gl_Position = vertices[gl_VertexID];                          \n""}                                                                 \n"
};

要点1: gl_VertexID,此时正在被处理的顶点索引

创建了一个包含三个顶点位置的浮点向量数组,然后通过gl_VertexID索引来设置顶点位置

  • 绘制命令glDrawArrays

既然要绘制三角形,我们的绘制图元肯定不能是点了,需要修改

glDrawArrays(GL_TRIANGLES, 0, 3);

要点1: GL_TRIANGLES代表绘制三角形
要点2: 参数3,代表要绘制3个顶点,从下标0开始,对应输出给顶点着色器的gl_VertexID变量

  • 效果


推送

  • Github
https://github.com/KingSun5

结语

本篇作为OpenGL学习的第二篇,学习了如何去绘制点和三角形,认识了shader和Program和部分OpenGL的API,源码都在官方示例里面,这里就不完整贴出来了,若是觉得博主的文章写的不错,不妨关注一下博主,点赞一下博文,另博主能力有限,若文中有出现什么错误的地方,欢迎各位评论指摘。
本文属于原创文章,转载请著名作者出处并置顶!!

(第二章)OpGL超级宝典学习:创建我们第一个OpenGL程序,绘制一个点和三角形相关推荐

  1. OpenGL学习笔记:第一个OpenGL程序完全注释

    运行环境: CentOS7 g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-16) OpenGL实现厂商的名字:VMware, Inc. 渲染器标识符:Gallium ...

  2. OpenGL超级宝典学习笔记——操作矩阵

    为了更强大的功能和灵活性,我们有时需要直接操作矩阵.在OpenGL中4x4的矩阵用包含16个浮点数值的一维数组来表示,而不是用二维的4x4的数组来表示.OpenGL之所以这么做,因为使用一维数组更高效 ...

  3. 鸟哥的Linux私房菜(基础篇)-第二章、 Linux 如何学习(二.5. 重点回顾)

    第二章. Linux 如何学习 最近更新日期:2009/08/06 5. 重点回顾 6. 本章习题 7. 针对本文的建议:http://phorum.vbird.org/viewtopic.php?t ...

  4. 鸟哥的Linux私房菜(基础篇)-第二章、 Linux 如何学习(二.4. 鸟哥的建议(重点在solution的学习))

    第二章. Linux 如何学习 最近更新日期:2009/08/06 4. 鸟哥的建议(重点在solution的学习) 鸟哥的建议(重点在Solution的学习): 除了上面的学习建议之外,还有其他的建 ...

  5. 鸟哥的Linux私房菜(基础篇)-第二章、 Linux 如何学习(二.3. 有心朝Linux作业系统学习者的学习态度)

    第二章. Linux 如何学习 最近更新日期:2009/08/06 3. 有心朝Linux作业系统学习者的学习态度 3.1 从头学习Linux基础 3.2 选择一本易读的工具书 3.3 实作再实作 3 ...

  6. 鸟哥的Linux私房菜(基础篇)-第二章、 Linux 如何学习(二.2. 鸟哥的Linux苦难经验全都录)

    第二章. Linux 如何学习 最近更新日期:2009/08/06 2. 鸟哥的Linux苦难经验全都录 2.1 鸟哥的Linux学习之路 2.2 学习心态的分别 2.3 X window的学习 鸟哥 ...

  7. 计算机图形学基础(第二版)陆枫 何云峰(2)我的第一个OpenGL程序

    实际这已经不是我第一次敲这个程序了,但是基于老师在给我们上这门课时实在没搞懂,还是决定自己在敲几遍,方便期末复习. 下面开始绘制矩形啦! /* * *       我使用的IDE是Code::Bloc ...

  8. 【3DMax简易入门教程】(二) 第二章 ·3DMax下的基本体创建

    3dMax第二章:基本体创建 1.标准基本体与扩展基本体组成了图形构建的主要内容,可以利用基本体内容创建桌子.电脑.沙发.凳子.门窗等内容.这里我用线条创建一个窗户框架和垃圾桶. 2.利用样条线创建一 ...

  9. OpenGL超级宝典学习笔记:着色器存储区块、原子内存操作、内存屏障

    前言 本篇在讲什么 本篇为蓝宝书学习笔记 着色器存储区块 原子内存操作 内存屏障 本篇适合什么 适合初学Open的小白 本篇需要什么 对 C++语法有简单认知 对 OpenGL有简单认知 最好是有 O ...

最新文章

  1. elasticsearch常见报错总结
  2. 用java做出32选7_用java做的一个彩票32选7的简单程序
  3. SLAM-ch2-cmake中使用库
  4. oracle 叠加代码写法,利用st_geometry进行图形叠加分析
  5. 大佬分享:程序员必知的干货
  6. 曲线 神经网络_神经网络的数学基础-8(完结)
  7. Linux内核:Gigantic巨页与CMA的结合的PATCH补丁提交
  8. Pytorch常用技巧记录
  9. virtualbox中给CentOS根分区扩容的方法
  10. 【6】python生成数据曲线平滑处理——(Savitzky-Golay 滤波器、convolve滑动平均滤波)方法介绍,推荐玩强化学习的小伙伴收藏
  11. 实木地板被机器人弄成坑_“实木地板”真的好?这些不搞明白,小心被商家坑了...
  12. Flask-SQLAlchemy relationship中的 lazy屬性
  13. 考研一年到底需要花多少钱?这个你必须要知道!!!
  14. win10的C盘满了清理方法
  15. 普通数字到科学计数法的转换
  16. 基于SOLIDWORKS Simulation 实现对零件,装配体的静应力分析 ૮ ฅ‘ㅅ‘ฅ ა
  17. 锐龙7000PBO温度墙设置
  18. 【第53题】输入、输出系列1-查找文件和替换文件内容
  19. 如何提取公众号文章封面图
  20. 解决Mac的奇葩痛点,不妨试试开源小众软件

热门文章

  1. R语言文本挖掘相关包介绍
  2. 2022-2028全球与中国成像色度计市场现状及未来发展趋势
  3. 万万没想到:用理工科思维理解世界
  4. 方差齐性检验python实现
  5. 软件设计师2017上半年
  6. 传统系统架构与中台架构的区别和联系
  7. php前台限制输入text字符,限制字符输入数功能(jquery版和原生JS版)
  8. 【机器学习】随机森林 – Random forest
  9. C# Development 13 Things Every C# Developer Should Know--C#开发人员应该知道的13件事情
  10. 差异表达基因热图怎么看_陈根:从基因层面看衰老本质,被误会的端粒差异