顶点数据:

顶点数据是一系列顶点的集合。

一个顶点(Vertex)是一个3d坐标的数据的集合。

而顶点数据是用顶点属性(Vertex Attribute)表示的,它可以包含任何我们想用的数据

(但是简单起见,我们还是假定每个顶点只有一个3D位置和一些颜色值组成的。)

图元:

为了让openGL知道我们的坐标和颜色值构成的到底是什么,openGL需要你去指定这些数据所表示的渲染类型。

我们是希望把这些数据渲染成一系列的点?一系列的三角形?还是仅仅是一个长长的线?做出这些提示的叫做图元(Primitive)

任何一个绘制指令的调用都将把图元传递给openGL。这是其中的几个:

GL_POINTS 、GL_TRIANGLES、 GL_LINE_STRIP。

图形渲染管线的第一个部分是顶点着色器(Vertex Shader),它把一个单独的顶点作为输入。

顶点着色器主要的目的是把3D坐标转换为另一种3D坐标,同时顶点着色器允许我们对顶点属性进行一些基本处理。

图元装配(Primitive Assembly)阶段将顶点着色器输出的所有顶点作为输入(如果是GL_POINTS,那么就是一个顶点),

并所有的点装配成指定图元的形状;

图元装配阶段的输出会传递给几何着色器(Geometry Shader)。几何着色器把图元形式的一系列顶点的集合作为输入,

它可以通过产生新顶点构造出新的(或是其他的)图元来生成其他形状。

几何着色器的输出会被传入光栅化阶段(Rasterization Stage),这里它会把图元映射为最终屏幕上相应的像素,

生成供片段着色器(Fragment Shader)使用的片段(Fragment) 。在片段着色器运行之前会执行裁切(Clipping),

裁切会丢弃超出你的视图以外的所有像素,用来提升执行效率。

OpenGL 中的一个片段是OpenGL渲染一个像素所需的所有数据。

片段着色器的主要目的是计算一个像素的最终颜色,这也是所有OpenGL高级效果产生的地方。

通常片段着色器包含3D场景的数据(比如光照、阴影、光的颜色等等),这些数据可以被用来计算最终像素的颜色。

在所有对应颜色值确定以后,最终的对象将会被传到最后一个阶段,我们叫做Alpha测试和混合(Blending)阶段

这个阶段检测片段的对应的深度(和模版(Stencil))值,用它们来判断这个像素是其他物体的前面还是后面,

决定是否应该丢弃。这个阶段也会检查alpha值 并对物体进行混合(Blend)。

然而,对于大多数场合,我们只需要配置定点和片段着色器就行了。几何着色器是可选的,通常使用它默认的着色器就行了。

在现代OpenGL中,我们必须定义至少一个顶点着色器和一个片段着色器(因为GPU中没有默认的顶点/片段着色器)。

渲染一个2D的三角形,我们将它顶点的z坐标设置为0.0,这样子的话三角形每一点的深度(Depth) 都是一样的,从而使它看上去像是2D的。

通常深度可以理解为z坐标,它代表一个像素在空间中和你的距离,如果离你远就可能被别的像素遮挡,你就看不到它了,它会被丢弃,以节省资源。

标准化设备坐标(Normalized Device Coordinates,NDC)

一旦你的顶点坐标已经在顶点着色器中处理过,它们就应该是标准化设备坐标了,

标准化坐标是一个x、y和z值在-1.0到1.0的一小段空间。

标准化设备坐标接着会变换为屏幕空间坐标(Screen-space Coordinates),这是使用你通过glViewport 函数提供的数据,进行视口变换(Viewport Transform)完成的。

所得的屏幕空间坐标又会被变换为片段输入到片段着色器中。

定义这样的顶点数据以后,我们会把它输入发送给图形渲染管线的第一个处理阶段:顶点着色器。

它会在GPU上创建内存用于存储我们的顶点数据,还要配置OpenGL如何解释这些内存,并且指定其如何发送给显卡。

我们通过顶点缓冲对象(Vertex Buffer Objects,VBO)管理这个内存。

顶点缓冲对象是我们在OpenGL中第一个出现的OpenGL对象。

这个缓冲有一个独一无二的ID,所以我们可以使用glGenBuffers 函数和一个缓冲ID生成一个VBO对象:

GLuint VBO;
glGenBuffers(, &VBO);

OpenGL有很多缓冲对象类型,顶点缓冲对象的缓冲类型是GL_ARRAY_BUFFER。OpenGL允许我们同时绑定多个缓冲,

只要它们的是不同的缓冲类型。我们可以使用glBindBuffer 函数把新创建的缓冲绑定到GL_ARRAY_BUFFER目标上:

glBindBuffer(GL_ARRAY_BUFFER,VBO);

从这一刻起,我们使用的任何(在GL_ARRAY_BUFFER目标上的)缓冲调用都会用来配置当前绑定的缓冲(VBO)。

然后我们可以调用glBufferData函数,它会把之前定义的顶点数据复制到缓冲的内存中:

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

glBufferData是一个专门用来把用户定义的数据复制到当前绑定缓冲的函数。

1个参数是目标缓冲的类型;

2个参数是指定传输数据大小(以字节为单位);

3个参数是我们希望发送的实际数据;

4个参数指定了我们希望显卡如何管理给定的数据。它有3种形式:

GL_STATIC_DRAW :数据不会或几乎不会改变。

GL_DYNAMIC_DRAW:数据会被改变很多。

GL_STREAM_DRAW:数据每次绘制时都会改变。

向量(Vector)它简明的表达了任意空间中的位置和方向,并且它有非常有用的数学属性。

在GLSL中一个向量有最多4个分量,每个分量都代表空间中的一个坐标,它们可以通过vec.x、vec.y、vec.z和vec.w来获取。

vec.w分量而是用在所谓透视划分(Perspective Division)上。

在真实的程序里输入数据通常都不是标准化设备坐标,顶点着色器一般会先把它们转换至OpenGL的可视区域内。

顶点着色器(VertexShader)

const GLchar* vertexShaderSource = "#version 330 core \
layout(location = 0) in vec3 position; \
void main() \
{ \
gl_Position = vec4(position.x,position.y,position.z,1.0); \
} \
";

编译着色器

编写之后的顶点着色器源码,为了能让OpenGL使用它,我们必须在运行时动态编译它的源码。

首先创建一个着色器对象,注意还是用ID来引用的。所以我们存储这个顶点着色器为GLuint,

然后用glCreateShader 创建这个着色器:

GLuint vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);

我们把需要创建的着色器类型以参数形式提供给glCreateShader。

由于我们正创建一个顶点着色器,传递的参数是GL_VERTEX_SHADER。

下一步我们把这个顶点着色器源码附加到着色器对象上,然后编译它:

glShaderSource(vertexShader,,&vertexShaderSource,NULL);
glCompileShader(vertexShader);

glShaderSource函数参数:

1个参数要编译的着色器对象;

2个参数指定传递的源码字符串数量,上面这里只有一个;

3个参数是顶点着色器真正的源码;

4个参数我们先设置为NULL。

如果想检测glCompileShader是否成功可以用glGetShaderiv 检查是否编译成功。如果失败可以用glGetShaderInfoLog获取错误信息。

片段着色器(Fragment Shader)

该着色器全是关于计算你的像素最后的颜色输出。

const GLchar* fragmentShaderSource = "#version 330 core    \
out vec4 color; \
void main() \
{ \
color = vec4(1.0f,0.5f,0.2f,1.0f); \
} \
";

在计算机图形中颜色被表示为有4个元素的数组:红色、绿色、蓝色和alpha(透明度)分量,通常缩写为RGBA。

每个分量的强度设置在0.0到1.0之间。

编译片段着色器的过程与顶点着色器类似,只不过我们使用GL_FRAGMENT_SHADER常量作为着色器类型:

GLuint fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader,1,&fragmentShaderSource,null);
glCompileShader(fragmentShader);

两个着色器现在都编译了,剩下的事情是把两个着色器对象链接到一个用来渲染的着色器程序(Shader Program)中。

------------------------------

https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/

openGL一些概念01的更多相关文章

  1. OpenGL 学习笔记 01 环境配置

    以下教程仅适用于Mac下的Xcode编程环境!其他的我也不会搞. 推荐教程:opengl-tutorial  本项目Github网址       OpenGL太可怕了...必需得把学的记下来,不然绝壁 ...

  2. openGL光源概念

    1. 光照模型      环境光——经过多次反射而来的光称为环境光,无法确定其最初的方向,但当特定的光源关闭后,它们将消失. 全局环境光——每个光源都能对场景提供环境光.此外,还有一个环境光,它不来自 ...

  3. 【OpenGL 学习笔记01】HelloWorld演示样例

    <<OpenGL Programming Guide>>这本书是看了忘,忘了又看,赶脚还是把笔记做一做心里比較踏实,哈哈. 我的主题是,好记性不如烂笔头. ========== ...

  4. openGL基本概念

    OpenGL自身是一个巨大的状态机(State Machine):一系列的变量描述OpenGL此刻应当如何运行.OpenGL的状态通常被称为OpenGL上下文(Context).我们通常使用如下途径去 ...

  5. maven的概念-01

    1.maven 简介 maven是Apach软件基金会维护的一款自动化构建工具: 作用是服务于java平台的项目构建和依赖管理:   2.关于项目构建 1)java代码 Java是一门编译型语言,.j ...

  6. openGL一些概念02

    着色器程序 着色器程序对象(Shader Program Object)是多个着色器合并之后并最终链接完成的版本. 如果要使用刚才编译的着色器我们必须把他们链接为一个着色器程序对象,然后在渲染对象的时 ...

  7. Kvm --01 虚拟化基础概念

    目录 1. 虚拟化基础概念 01. 什么是虚拟化? 02. 为什么要用虚拟化? 03. 虚拟化在企业中的应用场景? 04. 虚拟化软件介绍 05. Kvm介绍 2. 安装部署Kvm 3. Kvm虚拟机 ...

  8. [原创]cocos2d-x研习录-第二阶 概念类之精灵类(CCSprite)

    上一节说布景层CCLayer是小容器,那么精灵类CCSprite就是容器添加的内容,它是构成游戏的主要元素.精灵这个名称应该是游戏专用,它表示游戏中玩家操作的主角.敌人.NPC(Non Player ...

  9. OpenGL的glPushMatrix和glPopMatrix矩阵栈顶操作函数详解

    OpenGL中图形绘制后,往往需要一系列的变换来达到用户的目的,而这种变换实现的原理是又通过矩阵进行操作的.opengl中的变换一般包括视图变换.模型变换.投影变换等,在每次变换后,opengl将会呈 ...

随机推荐

  1. shell学习之杂项

    ? 表示任意一个字符. > 重写 >> 追加 &> 将错误信息一并写入 Ctrl+Z 暂停 fg 恢复 jobs 查看所有已暂停任务 bg 丢到后台 env 查看系统环 ...

  2. Delphi_添加_mshtml_tlb

    1. Delphi --> Component --> Install ActiveX Contol ... --> 选择“Microsoft HTML Object Library ...

  3. Oracle中的BLOB和CLOB【转载】

    原文地址:http://jelly.iteye.com/blog/65796 一.区别和定义 LONG: 可变长的字符串数据,最长2G,LONG具有VARCHAR2列的特性,可以存储长文本一个表中最多 ...

  4. js职责链模式

    职责链模式(Chain of Responsiblity),使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系.将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为 ...

  5. javascript删除JSON元素

    首先要搞清JSON的数据格式,我这里所说的JSON都是指javascript中的. JSON数据是由对象和数组数据结构组成,我们只要学会javascript中对对象和数组的删除方法即可对JSON项进行 ...

  6. 一个简单客户端获取IP,国家,城市,省份的代码

    <html><head>  <script src="js/jquery-1.6.2.min.js" type="text/javascri ...

  7. poj1523割顶-点双联通

    题意:求出所有的割顶,而且还有输出该割顶连接了几个点双连通分量 题解:直接tarjan求点双联通分量就好了,可以在加入边的时候记录加入次数,大于1的都是桥,输入输出很恶心,注意格式 #include& ...

  8. uva12563 Jin Ge Jin Qu hao(01背包)

    这是一道不错的题.首先通过分析,贪心法不可取,可以转化为01背包问题.但是这过程中还要注意,本题中的01背包问题要求背包必须装满!这就需要在普通的01背包问题上改动两处,一个是初始化的问题:把dp[0 ...

  9. 程序员如何编写好开发技术文档 如何编写优质的API文档工作

    编写技术文档,是令众多开发者望而生畏的任务之一.它本身是一件费时费力才能做好的工作.可是大多数时候,人们却总是想抄抄捷径,这样做的结果往往非常令人遗憾的,因为优质的技术文档是决定你的项目是否引人关注的 ...

  10. java 网页 保存上传文件

    网页请求提交到另外一个jsp 进行处理 index.jsp <%@ page language="java" import="java.util.*" p ...