当前位置: 首页 > news >正文

learnopengl——三角形

原文网址:https://learnopengl.com/Getting-started/Hello-Triangle

在OpenGL中,所有的东西都是3D空间中。但是屏幕和窗口是2D数组的像素。所以OpenGL的大部分工作是关于把3D坐标转换为2D像素。将3D坐标转换为2D像素的过程是由OpenGL的图形管线控制的。图形管线可以被分为两个部分:第一部分是把3D坐标转换为2D坐标,第二部分是把2D坐标转换为颜色像素。本节我们将会简要的讨论图形管线,以及如何使用它来创建好看的像素。

图形管线的输入时一系列3D坐标,然后把他们转换到有颜色的2D像素,最终显示在屏幕上。图形管线可以被分为几个步骤,每个步骤都需要前一步的输出作为输入。所有的步骤都是高度特殊化的,他们可以并行执行。因为他们并行的特性,目前图形显卡由几千个小的处理内核,加速了处理数据的能力,处理数据的小程序是工作在GPU上的,这些小程序叫做shader。

有些shader可以由开发者配置,你可以写自己的shader,替换掉默认的shader。这个允许我们细粒度的控制管线的特定的部分,由于他们是工作在GPU上的,所以他们节省了大量的CPU时间。shader可以使用GLSL——OpenGL Shading Language编写,下一节我们可以更加详细的介绍。

下面我们抽象出管线的几个步骤,注意蓝色的部分是我们可以加入shader的部分:
在这里插入图片描述

你可以看到,图形管线包含大量的部分,每个部分负责处理对应的数据。

定点数据定义好之后,我们把他输入到管线的第一个步——顶点着色器。这个操作是在GPU上开辟内存,然后储存顶点数据,顶点着色器负责处理这些顶点数据。

我们使用VBO——vertex buffer object来管理这个内存,VBO对象可以储存GPU中的大量的顶点数据。使用这些缓冲对象的优势是,我们可以一次发送一大批的数据给图形显卡,而不需要每次发送一个顶点数据。由CPU发送数据给图形显卡是很慢的,所以我们一次发送尽量发送多的数据。一旦数据在图形显卡的内存中了,顶点着色器就可以快速的处理这些数据了。

本节是第一次出现顶点缓冲对象的概念。像OpenGL中其他的对象一样,它也需要一个唯一的ID来标识。所以我们需要调用glGenBuffers来生成这个唯一的ID:

unsigned int VBO;
glGenBuffers(1, &VBO);  

OpenGL由多种类型的缓冲对象,顶点缓冲对象的类型为GL_ARRAY_BUFFER。OpenGL允许我们一次绑定几个缓冲只要他们的类型不同。我们可以绑定新创建的顶点缓冲对象到GL_ARRAY_BUFFER ,使用函数glBindBuffer:

glBindBuffer(GL_ARRAY_BUFFER, VBO);  

这样绑定之后,我们的VBO对象就绑定到了GL_ARRAY_BUFFER目标了。然后我们可以调用glBufferData函数来拷贝数据到缓冲:

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

glBufferData把用户指定的额数据拷贝到当前绑定的的缓冲。第一个参数是缓冲的类型,当前缓冲对象是绑定到GL_ARRAY_BUFFER目标的。第二个参数指定了数据的大小,按字节计算。第三个参数是真正的数据。第四个参数指定了我们如何去控制管线的中的数据。他有三个形式:
1、GL_STATIC_DRAW:标记管线中的数据不会改变。
2、GL_DYNAMIC_DRAW:标记管线中的数据可以被改变。
3、GL_STREAM_DRAW:标记在每次绘制的时候,数据会被改变。

三角形的位置数据不会改变,每次渲染调用都保持不变,所以他的类型为:GL_STATIC_DRAW。
如果缓冲中的数据会被改变,那么要使用GL_DYNAMIC_DRAW 或者 GL_STREAM_DRAW。

顶点着色器
顶点着色器是每个人根据喜好能够可编程的着色器。当前的OpenGL要求是,如果想要做些渲染的事情,至少创建一个顶点着色器、一个片段着色器。所以为了画第一个三角形,需要简单的引入两个简单的着色器。后面的章节,我们将会更详细的讨论着色器。

第一件事是,使用GLSL着色语言写一个顶点着色器,然后是编译着色器,所以我们可以在自己的程序中使用它们。下面的是使用GLSL语言编写的简单的顶点着色器:

#version 330 core
layout (location = 0) in vec3 aPos;

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

你可以看到,GLSL看起来像C。每个shader开始都要是版本号的声明。由于OpenGL3.3和更高版本的GLSL匹配OpenGL(GLSL版本420对应的是OpenGL版本4.2)。

接着我们声明了所有的输入属性,使用关键字in。我们声明了一个顶点位置作为输入属性。GLSL有一个向量数据类型,它包含1到4个浮点数,这个后缀代表了几个浮点数。由于每个顶点有一个3D坐标,我们创建vec3作为输入,它的名字是aPos。我们同样设置其输入变量的位置是0,通过语法(layout=0)表示。你后面会看到我们为什么需要这个位置。

为了设置顶点着色器的输出,我们需要指定位置数据到预定义的gl_Position变量,这个是在场景背后的vec4变量。在main函数的结束,无论我们把gl_Position设置为多少,它都会是顶点着色器的输出。由于我们的书是一个3维的向量,我们需要把它转换为4维的向量。我们可以把三维向量的第四维设置为1.0f,变为四维向量,后面会介绍我们为什么会这样做。

当前的顶点着色器是一个简单的着色器,因为我们不做任何特殊的处理,只是简单的把输入的数据作为着色器的输出。在真实的应用中,输入数据通常是不在规格化的设备坐标中,所谓我们首先要做的是,转换输入数据到OpenGL可视区域。

编译shader

片段着色器
片段着色器是我们创建用来渲染三角形的第二个也是最后一个shader。片段着色器是关于计算颜色的。为了保持其简单性,我们只是将输出的颜色设置为orange-ish颜色。

#version 330 core
out vec4 FragColor;

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

片段着色器只需要一个输出变量,他是四维的向量。定义了最终的颜色,是由我们自己计算的。我们可以用out关键字来声明输出变量,这里我们的输出变量名为FragColor。接着我们指定vec4作为输出,alpha值为1.0,表示非透明。

顶点数组对象
一个顶点数组对象(称之为VAO),可以像顶点缓冲对象一样绑定,接下来的顶点属性的调用,都会被储存在VAO中。这个优点是,当我们在配置顶点属性指针的时候,你只需要在想要绘制物体的时候调用一次即可,我们只需要绑定到指定的VAO。这个在不同的顶点数据和属性之间做切换,唯一做的是绑定到不同的VAO,所有的状态都存储在VAO中。

一个顶点数组存储的方式如下:
1、调用glEnableVertexAttribArray 或者 glDisableVertexAttribArray
2、顶点属性配置通过glVertexAttribPointer
3、顶点缓冲对象和顶点属性相关,通过调用函数glVertexAttribPointer
在这里插入图片描述

创建要给VAO对象,和创建VBO类似:

unsigned int VAO;
glGenVertexArrays(1, &VAO);  

相关文章:

  • songho——OpenGL的帧缓冲
  • while 循环 及 and or not
  • songho——OpenGL的顶点缓冲对象
  • OGL(教程35)——延迟渲染1——代码结构梳理
  • 安装MySQL_安装Navicat_启动数据库服务
  • android studio查看android手机日志
  • Python02(Linux命令)
  • luaforwindws安装与调用方式
  • vs添加链接文件
  • httpclient
  • 继成ScriptableObject的静态类对象竟然没有销毁
  • 国内镜像站
  • unity地形
  • Excel催化剂开源第5波-任务窗格在OFFICE2013中新建文档不能同步显示问题解决
  • shader 顶点属性——颜色
  • [译]Python中的类属性与实例属性的区别
  • 【挥舞JS】JS实现继承,封装一个extends方法
  • 2017 前端面试准备 - 收藏集 - 掘金
  • canvas 高仿 Apple Watch 表盘
  • CentOS学习笔记 - 12. Nginx搭建Centos7.5远程repo
  • C学习-枚举(九)
  • Docker容器管理
  • dva中组件的懒加载
  • es6
  • Idea+maven+scala构建包并在spark on yarn 运行
  • JavaScript 基本功--面试宝典
  • Java-详解HashMap
  • Netty+SpringBoot+FastDFS+Html5实现聊天App(六)
  • Ruby 2.x 源代码分析:扩展 概述
  • Vue官网教程学习过程中值得记录的一些事情
  • Vue小说阅读器(仿追书神器)
  • 从tcpdump抓包看TCP/IP协议
  • 机器学习学习笔记一
  • 基于Android乐音识别(2)
  • 前端之Sass/Scss实战笔记
  • 使用 QuickBI 搭建酷炫可视化分析
  • 一天一个设计模式之JS实现——适配器模式
  • ​linux启动进程的方式
  • ​软考-高级-系统架构设计师教程(清华第2版)【第9章 软件可靠性基础知识(P320~344)-思维导图】​
  • #HarmonyOS:软件安装window和mac预览Hello World
  • #Java第九次作业--输入输出流和文件操作
  • (175)FPGA门控时钟技术
  • (3)(3.5) 遥测无线电区域条例
  • (pytorch进阶之路)CLIP模型 实现图像多模态检索任务
  • (附源码)php投票系统 毕业设计 121500
  • (附源码)springboot太原学院贫困生申请管理系统 毕业设计 101517
  • (七)Knockout 创建自定义绑定
  • (求助)用傲游上csdn博客时标签栏和网址栏一直显示袁萌 的头像
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • (太强大了) - Linux 性能监控、测试、优化工具
  • (原创)boost.property_tree解析xml的帮助类以及中文解析问题的解决
  • (转)ORM
  • (转)创业的注意事项
  • .gitignore
  • .net core Swagger 过滤部分Api