OpenGL 学习之渲染基础

一、OpenGL与着色器

在OpenGL3.0之前,OpenGL包含一个固定功能的管线,它可以在不使用着色器的情况下处理几何和像素数据。在3.1版本之后,固定管线从核心模式中去掉了。因此现在需要使用着色器来完成。

二、基础图形管线

OpenGL 中的图元只不过是顶点的集合以预定的方式结合在一起的。
例如:一个点就是一个图元。

2.1 OpenGL渲染管线流程解析

渲染流程解析流程

OpenGL在处理任何图形渲染,都是依据它. 基于OpenGL 封装的框架都是也都是遵循这个图的规则.

客户端(client)、服务端(server)

  • 管线分为上下两个部分,上部分是客户端,下部分是服务端。

  • 客户端是存储在CPU存储器中的,并且在应用程序中执行,或者在系统内存的驱动程序中执行。驱动程序会将渲染命令和数组结合起来,发送给服务端执行(在一台计算机上,服务器实际指的是图形加速卡上的硬件和内存)

  • 服务端和客户机在功能上也是异步执行他们独立的软件和硬件块。我们是希望2个端都尽量的不停的工作。客户端在不断把数据块和命令块组合在一起输送到缓冲区,然后缓冲区就发送到服务器执行。

  • 如果服务器停止工作等待客户机,或者客户机停止工作等待服务器做好接收更多的命令准备,我们把这种情况称为管线停滞

着色器

上图的Vertex Shader(顶点着色器)和Fragment Shader(片段着色器)

  1. 着色器是使用GLSL语言编写的。看起来和C语言很相似。着色器必须源代码中编译和链接在一起。最终准备就绪的着色器程序。

  2. 顶点着色器(Vertex Shader)-> 处理从客户机输入的数据、应用变换、进行其他的类型数学运算来计算光照效果、位移、颜色值等等。(为了渲染工三个顶点的三角形,顶点着色器意味着将执行三次,也就是每个顶点执行一次),在目前硬件上有多个执行单元同时运行,也就意味着所有的顶点可以同时进行处理。

  3. 上图的图元装配(Primitive Assembly)说明的是:3个顶点已经组合在一起,而三角形赢逐个片段的进行光栅化。每个片段通过执行片元着色器进行填充。片元着色器会输出我们将在屏幕上看到的最终颜色值。

我们必须在之前为着色器提供数据,否则将无法实现。
有三种向OpenGL着色器传递渲染数据的方法供我们选择

  1. 属性(Attributes)
  2. uniform值
  3. 纹理(TextureData)

三、属性、uniform、纹理、输出

3.1 属性(Attributes)

属性:就是对每个顶点都要做改变的数据元素。实际上,顶点位置本身就是一个属性。属性值可以是float、int、bool数据

  • 属性总是以思维向量的形式进行内部存储的,即使我们不会使用所有的4个分量。一个顶点可能存储(x,y,z),将占有4个分量的3个。

  • 实际上如果是在平面情况下,只要xy平面上就能绘制,那么z分量就会自动设置为0.

  • 属性可以是:纹理坐标、颜色值、光照计算表面法线

  • 属性会从本地客户机内存中复制存储砸在图形硬件中的一个缓冲区上。这些属性只提供给顶点着色器使用。对于片段着色器意义不大。

3.2 Uniform值

属性是一种对整个批次属性都取统一值得单一值。它是不变的。通过uniform变量就紧接着发送一个图元批次命令,Uniform变量实践上可以无数次限制的使用,设置一个应用于整个表面的单个颜色值,还可以设置一个时间值,在每次渲染某种类型的顶点动画时修改它。

  • 注意:这里的uniform变量每个批次改变一次,而不是每个顶点改变一次。
  • uniform变量最常见的应用是在顶点渲染中设置变换矩阵。
  • 与属性相同的:可以是float、int、Bool
  • 与属性不同点:顶点着色器和片元着色器都可以直接使用uniform变量。uniform变量还可以是标量类型、矢量类型、uniform矩阵。

3.2 纹理(Texture)

传递给着色器的第三种数据类型:纹理数据(Texture Data)

  • 在顶点着色器、片段着色器都可以对纹理数据进行采样和筛选。
  • 典型的应用场景:片段着色器对一个纹理值进行采样,然后在一个三角形表面应用渲染纹理数据。
  • 纹理数据,不仅仅表现在图形,很多图形文件格式都是以无符合字节(每个颜色通道8位)形式对颜色分量进行存储的。

四、坐标系

4.1 正投影

这就是一个正投影的 ,在所在3个轴(X,Y,Z)中,它们的范围都是从-100到+100。这个视景体将包括所有的 何图形。

如果你指定了视景体外的几何图形,就会被裁减掉!(它将沿着视景体的边界进行剪切)

在正投影中,所有在这个空间范围内的所有东西都将被呈现在屏幕上。而不存在照相机或视点坐标系的概念。

4.2 透视投影

透视投影

透视投影会进行透视除法对距离观察者很远的对象进行缩短和收缩。在投影到屏幕之后,视景体背面与视景体正面的宽度测量标准不同。

上图所示:平截头体(frustum)的几何体,它的观察方向是从金字塔的尖端到宽阔端。观察者的视点与金字塔的尖端拉开一定距离。

GLFrustum类通过setPerspective 方法为我们构建一个平截头体。

CLFrustum::SetPerspective(float fFov,float fAspect,float fNear,float fFar);

参数:
fFov:垂直方向上的视场角度
fAspect:窗口的宽度与高度的纵横比 ( 纵横比 = 宽(w)/ (h) )
fNear:近裁剪面距离
fFar:远裁剪面距离

存储着色器

5.1 使用背景

在OpenGL 核心框架中,并没有提供任何内建渲染管线,在提交一个几何图形进行渲染之前,必须实现一个着色器。

5.2 存储着色器的使用

1.1 GLShaderManger的初始化

// GLShaderManger
GLShaderManger shaderManger;
shaderManger.initializeStockShaders()

1.2 GLShaderManger

标识符 描述
GLT_ATTRIBUTE_VERTEX 3分量(x,y,z)顶点位置
GLT_ATTRIBUTE_COLOR 4分量(r,g,b,a)顶点位置
GLT_ATTRIBUTE_NORMAL 3分量(x,y,z)表面法线
GLT_ATTRIBUTE_TEXTURE0 第一对2分量坐标(s,t)纹理坐标
GLT_ATTRIBUTE_TEXTURE1 第一对2分量坐标(s,t)纹理坐标

存储着色器位每个变量都使用一致的内部变量命名规则和相同的属性槽。以上就是存储着色器的属性列表。

1.3 GLShaderManger的uniform值

一般情况,要对几何图形进行渲染,我们需要给对象递交属性矩阵,首先要绑定我们想要使用的着色器程序上,并提供程序的uniform值。但是GLShanderManager 类可以暂时为我们完成工作。

1)useStockShader 函数会选择一个存储着色器并提供这个着色器的uniform值。

GLShaderManager::UserStockShader(GLEnum shader...);

5.3 单元(Indentity着色器)

GLShaderManager::UserStockShader(GLT_ATTRIBUTE_VERTEX, GLfloat vColor[4]);

参数1:GLT_ATTRIBUTE_VERTEX(顶点分量)
参数2:vColor[4],你需要的颜色

单元着色器:只是简单的使用默认笛卡尔坐标系(坐标范围(-1.0,1.0))。所有的片段都应用于同一种颜色,几何图形位实心和未渲染的。

5.4 平面着色器

GLShaderManager::UserStockShader(GLT_SHADER_FLAT, GLfloat mvp[16], GLFloat cColor[4]);

参数1:平面着色器
参数2:允许变化的4*4矩阵
参数3:颜色

5.5 上色着色器

GLShaderManager::UserStockShader(GLT_SHADER_SHADED, GLfloat mvp[16]);

参数1:平面着色器
参数2:允许变化的4*4矩阵
颜色颜色值将被平滑的插入顶点之间(平滑着色器)

5.6 默认光源着色器

GLShaderManager::UserStockShader(GLT_SHADER_DEFAULT_LIGHT, GLfloat mvMatrix[16], GLfloat Matrix[16], GLfloat vColor[4]);

参数1:默认光源
参数2:模型视图矩阵
参数3:投影矩阵
参数4:颜色值

点光源着色器和默认光源着色器很相似,区别在于:光源位置是特定的。同样需要设置存储着色器的GLT_ATTRIBUTE_VERTEX(顶点分量)和GLT_ATTRIBUTE_NORMAL(表面法线)

5.7

点光源着色器 GLShaderManager::UserStockShader(GLT_SHADER_DEFAULT_LIGHT_DIEF,GLfloat mvMatrix[16], GLfloat pMatrix[16],GLfloat vLightPos[3],GLfloat vColor[4]);

参数1:点光源着色器
参数2:模型视图矩阵
参数3:投影矩阵
参数4:视点坐标光源位置
参数5:颜色值

点光源着色器和默认光源着色器很相似,区别在于: 光源位置是特定的。同样需要设置存储着色器的 GLT_ATTRIBUTE_VERTEX(顶点分量) 和 GLT_ATTRIBUTE_NORMAL(表面法线)

5.8 纹理替换矩阵

GLShaderManager::UserStockShader(GLT_SHADER_TEXTURE_REPLACE,GLfloat mvMatrix[16],GLint nTextureUnit);

着色器通过给定的模型视图投影矩阵,使用绑定到 nTextureUnit (纹理单元) 指定纹理里单元的纹理对几何图形进行变化。

片段颜色 :是直接从纹理样本中直接获取的。

需要设置存储着色器的GLT_ATTRIBUTE_VERTEX(顶点分量) 和 GLT_ATTRIBUTE_NORMAL(表面法线)

5.9 纹理调整着色器

讲一个基本色乘以一个取自纹理单元 nTextureUnit 的纹理。 需要设置存储着色器的 GLT_ATTRIBUTE_VERTEX(顶点分量) 和 GLT_ATTRIBUTE_TEXTURE0(纹理坐标)

GLShaderManager::UserStockShader(GLT_SHADER_TEXTURE_MODULATE,GLfloat mvMatrix[16],GLfloat vColor[4],GLint nTextureUnit);

5.10 纹理光源着色器

将一个纹理通过漫反射照明计算机进行调整(相乘)。光线在视觉空间中的位置是给定的。需要设置存储着色器的 GLT_ATTRIBUTE_VERTEX(顶点分量) 和GLT_ATTRIBUTE_TEXTURE0(纹理坐标)、GLT_ATTRIBUTE_NORMAL(表面法线)

GLShaderManager::UserStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIEF,GLfloat mvMatrix[16],GLfloat pMatrix[16],GLfloat vLightPos[3],GLfloat vBaseColor[4],GLint nTextureUnit);

参数1:纹 光源着色器
参数2:投影矩阵
参数3:视觉空间中的光源位置
参数4: 几何图形的基本
参数5:将要使用的纹理单元

五、图元

OpenGL 基本7种基本图元

图元 描述
GL_POINTS 每个顶点在屏幕上都是单独点
GL_LINES 每一对顶点定义⼀个线段
GL_LINE_STRIP ⼀个从第一个顶点依次经过每⼀个后续顶点⽽绘制的线条
GL_LINE_LOOP 和GL_LINE_STRIP相同,但是最后⼀个顶点和第⼀个顶点连接起来了.
GL_TRIANGLES 每3个顶点定义⼀个新的三角形
GL_TRIANGLE_STRIP 共⽤⼀个条带(strip)上的顶点的一组三角形
GL_TRIANGLE_FAN 以一个圆点为中心呈扇形排列,共⽤相邻顶点的⼀组三角形
OpenGL基本图元
  • OpenGL 点/线
  • OpenGL 三角形 默认逆时针环绕为正三角,顺时针环绕为逆三角
  • OpenGL 三角形环绕方式
  • OpenGL 三角形带
  • OpenGL 三角形扇
  • OpenGL 工具类 GLBatch
  • OpenGL 图形绘制的3种填充方式 1、线框填充 2、颜色填充 3、纹理填充
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • 学习目标: OpenGL 渲染结构 如何使用7种OpenGL基础图元 如何使用储存着色器 如何使用Uniform属...
    velue阅读 1,802评论 0 0
  • OpenGL基础渲染 一、OpenGL 与 着色器 在OpenGL 3.0之前,OpenGL包含一个固定功能的管线...
    wjl7004阅读 386评论 0 2
  • 目录 OpenGL渲染架构 投影方式设置 固定管线解析 OpenGL基本图元解析 图元绘制 GLBatch Ope...
    Tobesky阅读 375评论 1 0
  • 一、基础图形管线 渲染管线(rendering pipeline),它是一系列数据处理过程,并且将应用程序的数据转...
    凡几多阅读 3,233评论 6 18
  • 渲染管线 苹果提供了两种OpenGL ES的可视化模型,一种是客户端—服务端的架构模型,另一种就是管线的模型。 客...
    sellse阅读 12,019评论 1 10