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

news2024/11/18 19:59:06

目录

  • 前言
  • 创建简单的应用
    • 创建脚本
    • 渲染底色
    • 渲染底色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,源码都在官方示例里面,这里就不完整贴出来了,若是觉得博主的文章写的不错,不妨关注一下博主,点赞一下博文,另博主能力有限,若文中有出现什么错误的地方,欢迎各位评论指摘。
本文属于原创文章,转载请著名作者出处并置顶!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/111109.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

跨孔CT交叉梯度联合反演算法

跨孔CT交叉梯度联合反演算法 利用交叉梯度函数的结构约束作用实现多种跨孔CT的联合反演。 文章目录跨孔CT交叉梯度联合反演算法1、跨孔CT原理2、跨孔CT正演算法2.1 多模块快速推进算法2.2 最短路径法弯曲射线追踪2.3 胖射线追踪2.4 直射线追踪3、跨孔CT正演模型4、交叉梯度联合…

Matlab渐变色生成/编辑器专业版—ColorMapPro

渐变配色在科研绘图时十分常用&#xff0c;比如三维柱状图、特征渲染散点图、热图、曲面图、等高线填充图等等&#xff0c;都需要使用渐变配色。 虽说现成的渐变配色有很多&#xff0c;比如&#xff0c;在TheColor配色工具的渐变颜色库中便集成了近千种的渐变色&#xff1a; 然…

Lambda Python 创建和使用 Layer

目标 由于 Python 代码中需要用到第三方的库, 在 Lambda 中可以通过创建自定义层(Layer)的方式来将这些依赖提供给 Lambda 运行环境. 下面演示创建一个包含第三方库 requests 的层, 以及如何在 Lambda 中调用 准备 zip 文件 首先在本地电脑上将相关依赖下载到名为 python 的…

32.多输入多输出通道

通道数是一个重要的超参数&#xff0c;通常是会仔细设计的。 在之前&#xff0c;我们仅展示了单个输入和单个输出通道的简化例子。 这使得我们可以将输入、卷积核和输出看作二维张量。 当我们添加通道时&#xff0c;我们的输入和隐藏的表示都变成了三维张量。例如&#xff0c…

OpenPCDet详细安装指南+单/多GPU训练演示

OpenPCDet详细安装指南单/多GPU训练演示前言个人环境一览安装环境安装的各版本1. 创建conda虚拟环境2. 安装PyTorch3. 安装spconv4. 安装PCDet5. 训练单GPU训练多GPU训练前言 本人总共花了两个晚上一个下午安装&#xff0c;中间因为各种版本错误、版本不兼容报各种奇奇怪怪的错…

Windows 下使用 Docker + MySQL 安装 Wiki.js

Windows 下使用 Docker MySQL 安装 Wiki.jsIntroductionChapter 1 配置数据库Part 1 数据库安装Part 2 创建 Wiki 相关配置并修改权限Chapter 2 配置 Wiki.jsPart 1 安装Part 2 配置 WikiIntroduction Wiki 是一种在网络上开放且可供多人协同创作的系统&#xff0c;比较著名的…

【触摸屏功能测试】昆仑通态MCGS——测试通过HJ212_TCPIP驱动4G功能发送212报文

1、触摸屏功能测试 型号&#xff1a;TPC7022Ni 测试内容&#xff1a; 实现4G触摸屏&#xff0c;通过自带的4G卡向平台发送HJ212报文 2、HJ212_TCPIP 驱动说明 2.1、驱动介绍 本驱动构件用于MCGS软件,通过污染物在线监控(监测)系统数据传输标准协议向下位机数采仪发送各类指…

MCU-51:静态数码管显示

目录一、数码管介绍2.1 介绍2.2 数码管引脚定义2.3 原理图二、要用到的C语言知识2.1 数组2.2 子函数三、数码管显示3.1 单个数码管显示3.2 通过定位函数实现数码管显示四、动态数码管显示一、数码管介绍 2.1 介绍 LED数码管&#xff1a;数码管是一种简单、廉价的显示器&#…

Word表格常见设置汇总

Word表格常见设置汇总 总结一些Word中常用的关于表格的设置问题。 文章目录1.居中设置2.隔页显示表格首行设置3.边框边线粗细及显示设置4.表格斜线设置5.单元格合并与拆分设置1.居中设置 全选要居中显示部分→布局→选择居中类型。 2.隔页显示表格首行设置 选择表格→表格属性→…

idea插件之自动生成时序图(Sequence Diagram)

前言 小伙们&#xff0c;你们有没有发现&#xff0c;身边经常有这样一些人&#xff0c;看着平时没怎么干活&#xff0c;到关键时候需要展示工作成果&#xff0c;会发现这些人也有工作成果&#xff0c;甚至比辛苦在干的人可能还要多一些。按常理推测&#xff0c;这绝对不是一件科…

【小程序】案例 - 本地生活(首页)

1. 首页效果以及实现步骤 新建项目并梳理项目结构 配置导航栏效果 配置 tabBar 效果 实现轮播图效果 实现九宫格效果 实现图片布局 2. 接口地址 获取轮播图数据列表的接口 【GET】 https://www.escook.cn/slides 获取九宫格数据列表的接口 【GET】 https://www.esco…

XXE工具——XXEinjection安装与使用

今天继续给大家介绍渗透测试相关知识&#xff0c;本文主要内容是XXE工具——XXEinjection安装与使用。 免责声明&#xff1a; 本文所介绍的内容仅做学习交流使用&#xff0c;严禁利用文中技术进行非法行为&#xff0c;否则造成一切严重后果自负&#xff01; 再次强调&#xff1…

直播推流神器 Kplayer 手把手教你在B站7*24h全天直播

开始前的准备工作 Linux服务器 (1)KPlayer目前仅支持Linux环境并需要满足x86_64(amd64)与aarch64(arm64)CPU架构的硬件环境上运行&#xff0c;我们已经将相关依赖库静态链接至主程序中&#xff0c;这意味着你不需要额外的安装任何的第三方库来支持KPlayer的运行。 在后续的迭代…

【数据预处理】基于Pandas的数据预处理技术【前七个任务】

文章目录一.需求分析二.需求解决2.1 本次实验以california_housing加州房价数据集为例&#xff0c;下载数据集2.2 查看数据集的描述、特征及目标数据名称、数据条数、特征数量2.3 将数据读入pandas的DataFrame并转存到csv文件2.4 查看数据集各个特征的类型以及是否有空值2.5 对…

五年经验的前端社招被问:CPU 和 GPU 有什么区别?

CPU 和 GPU 的设计目标和整体架构的区别分析&#xff0c;并在全文最后使用通俗的例子做比喻帮助理解。 首先来看 CPU 和 GPU 的百科解释&#xff1a; CPU&#xff08;Central ProcessingUnit&#xff0c;中央处理器&#xff09;&#xff1a;功能主要是解释计算机指令以及处理计…

【工作流Activiti7】2、Activiti7 与 Spring Boot 及 Spring Security 整合

1. 前言 其实&#xff0c;选择用Activiti7没别的原因&#xff0c;就是因为穷。但凡是有钱&#xff0c;谁还用开源版的啊&#xff0c;当然是用商业版啦。国外的工作流引擎没有考虑中国的实际情况&#xff0c;很多像回退、委派、撤销等等功能都没有&#xff0c;所以最省事的还是…

若依前后端分离框架去掉首页 登录后跳转至动态路由的第一个路由

若依前后端分离框架去掉首页 登录后跳转至动态路由的第一个路由若依框架VUE前端界面&#xff0c;登录后默认跳转至动态路由第一路由&#xff08;第一个子菜单&#xff09;一、登录后跳转第一路由界面二、设置路由的首页路径&#xff0c;方便后续的获取三、点击若依的logo跳转的…

字符串函数(4)--strtok函数和strerror函数

1.strtok函数 — 分割字符串函数 2.strerror函数 — 错误报告函数 1.strstok函数的用法 char* strtok(char* str, const char* delimiters);直接看函数的声明&#xff1a; 参数1&#xff1a;要切割的地址&#xff0c;参数2&#xff1a;切割时的标记物 注意&#xff1a;strt…

单链表的python实现

首先说下线性表&#xff0c;线性表是一种最基本&#xff0c;最简单的数据结构&#xff0c;通俗点讲就是一维的存储数据的结构。 线性表分为顺序表和链接表&#xff1a; 顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据元素&#xff0c;称为线性表的顺序存储结构或…

Nginx安装配置及vue项目部署【Centos7】

Background 网上好多都是源码安装&#xff0c;各种编译环境安装配置&#xff0c;感觉太麻烦了&#xff0c;这里直接下载一个rpm包就行了&#xff0c;离线安装也方便。 1、nginx rpm包下载 选择你要使用的版本下载。 nginx官方下载地址&#xff1a;http://nginx.org/packages/ce…