OpenGL ES 2.0渲染管线

2024-09-08 08:18
文章标签 es 渲染 opengl 2.0 管线

本文主要是介绍OpenGL ES 2.0渲染管线,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

http://codingnow.cn/opengles/1504.html

Opengl es 2.0实现了可编程的图形管线,比起1.x的固定管线要复杂和灵活很多,由两部分规范组成:Opengl es 2.0 API规范和Opengl es着色语言规范。下图是Opengl es 2.0渲染管线,阴影部分是opengl es 2.0的可编程阶段。

 

1. 顶点着色器(VertexShader)
顶点着色器对顶点实现了一种通用的可编程方法。
顶点着色器的输入数据由下面组成:
Attributes:使用顶点数组封装每个顶点的数据,一般用于每个顶点都各不相同的变量,如顶点位置、颜色等。
Uniforms:顶点着色器使用的常量数据,不能被着色器修改,一般用于对同一组顶点组成的单个3D物体中所有顶点都相同的变量,如当前光源的位置。
Samplers:这个是可选的,一种特殊的uniforms,表示顶点着色器使用的纹理。
Shader program:顶点着色器的源码或可执行文件,描述了将对顶点执行的操作。
顶点着色器的输出数据是varying变量,在图元光栅化阶段,这些varying值为每个生成的片元进行计算,并将结果作为片元着色器的输入数据。从分配给每个顶点的原始varying值来为每个片元生成一个varying值的机制叫做插值。
顶点着色器数据的输入和输出可以参考下图:
顶点着色器可用于传统的基于顶点的操作,例如:基于矩阵变换位置,进行光照计算来生成每个顶点的颜色,生成或者变换纹理坐标。
另外因为顶点着色器是由应用程序指定的,所以你可以用来进行任意自定义的顶点变换。

下面是一个用opengl es着色器语言编写的顶点着色器源码,这个顶点着色器使用一个position和跟它相关联的color数据作为输入数据,通过一个4×4矩阵变换位置,然后输出变换后的位置和颜色数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1.  // uniforms used by the vertex shader
2. uniform mat4 u_mvpMatrix;  // matrix to convert P from model
3.  // space to normalized device space.
4.
5.  // attributes input to the vertex shader
6. attribute vec4 a_position;  // position value
7. attribute vec4 a_color;  // input vertex color
8.
9.  // varying variables – input to the fragment shader
10. varying vec4 v_color;  // output vertex color
11.
12.  void
13. main()
14. {
15. v_color = a_color;
16. gl_Position = u_mvpMatrix * a_position;
17. }

第2行代码定义了一个uniform变量u_mvpMatrix,mat4表示4×4浮点数矩阵,该变量存储了组合模型视图和投影矩阵。6和7行代码定义了顶点着色器的输入数据:Attributes,vec4表示包含了4个浮点数的向量,a_position是顶点位置属性,a_color是顶点颜色属性。第10行代码定义了varying类型的变量v_color,varying是用于从顶点着色器传递到片元着色器的变量,v_color是顶点着色器的输出数据,存储了每个顶点的颜色。12-17行的main函数是顶点着色器和片元着色器的入口,第15行读取了顶点着色器输入属性中a_color的值,并把它赋值给输出数据v_color,第16行的gl_Position 是内置的varying变量,不需要声明,顶点着色器必须把变换后的位置赋值给它。

2.图元装配(Primitive Assembly)
顶点着色器之后,渲染流水线的下一个阶段是图元装配,图元是一个能用opengl es绘图命令绘制的几何体,绘图命令指定了一组顶点属性,描述了图元的几何形状和图元类型。顶点着色器使用这些顶点属性计算顶点的位置、颜色以及纹理坐标,这样才能传到片元着色器。在图元装配阶段,这些着色器处理过的顶点被组装到一个个独立的几何图元中,例如三角形、线、点精灵。对于每个图元,必须确定它是否位于视椎体内(3维空间显示在屏幕上的可见区域),如果图元部分在视椎体中,需要进行裁剪,如果图元全部在视椎体外,则直接丢弃图元。裁剪之后,顶点位置转换成了屏幕坐标。背面剔除操作也会执行,它根据图元是正面还是背面,如果是背面则丢弃该图元。经过裁剪和背面剔除操作后,就进入渲染流水线的下一个阶段:光栅化。

3. 光栅化(Rasterization)
光栅化阶段把图元转换成片元集合,之后会提交给片元着色器处理,这些片元集合表示可以被绘制到屏幕的像素。如下图所示:

 

4. 片元着色器(FragmentShader)
片元着色器对片元实现了一种通用的可编程方法,它对光栅化阶段产生的每个片元进行操作,需要的输入数据如下:
Varying variables:顶点着色器输出的varying变量经过光栅化插值计算后产生的作用于每个片元的值。
Uniforms:片元着色器使用的常量数据
Samplers:一种特殊的uniforms,表示片元着色器使用的纹理。
Shader program:片元着色器的源码或可执行文件,描述了将对片元执行的操作。
片元着色器也可以丢弃片元或者为片元生成一个颜色值,保存到内置变量gl_FragColor。光栅化阶段产生的颜色、深度、模板和屏幕坐标(Xw, Yw)成为流水线中pre-fragment阶段( FragmentShader之后)的输入。如下图:

下面是一个简单的片元着色器源码,可以跟上面的顶点着色器源码结合绘制一个高洛德着色的三角形。

1
2
3
4
5
6
7
8
9
10
1. precision mediump  float ;
2.
3. varying vec4 v_color;  // input vertex color from vertex shader
4.
5.
6.  void
7. main( void )
8. {
9. gl_FragColor = v_color;
10.}

第1行代码设置默认的精度修饰符,有highp、mediump、lowp,这个后面再详细解释。第3行代码定义了片元着色器的输入数据,顶点着色器必须赋值给片元着色器一组一样的varying变量。注意:gl_FragColor是片元着色器唯一的输出,第9行代码把输入数据v_color赋值给gl_FragColor。

5. 逐个片元操作阶段(Per-Fragment Operations)
片元着色器之后就是逐个片元操作阶段,包括一系列的测试阶段。一个光栅化阶段产生的具有屏幕坐标(Xw, Yw)的片元,只能修改framebuffer(帧缓冲)中位置在(Xw, Yw)的像素。下图是Opengl es 2.0逐片元操作的过程:

Pixel ownership test:像素所有权测试决定framebuffer中某一个(Xw, Yw)位置的像素是否属于当前Opengl ES的context,比如:如果一个Opengl ES帧缓冲窗口被其他窗口遮住了,窗口系统将决定被遮住的像素不属于当前Opengl ES的context,因此也就不会被显示。
Scissor test:裁剪测试决定位置为(Xw, Yw)的片元是否位于裁剪矩形内,如果不在,则被丢弃。
Stencil and depth tests:模板和深度测试传入片元的模板和深度值,决定是否丢弃片元。
Blending:将新产生的片元颜色值和framebuffer中某个(Xw, Yw)位置存储的颜色值进行混合。
Dithering:抖动可以用来最大限度的减少使用有限精度存储颜色值到framebuffer的工件。
逐片元操作之后,片元要么被丢弃,要么一个片元的颜色,深度或者模板值被写入到framebuffer的(Xw, Yw)位置,不过是否真的会写入还得依赖于write masks启用与否。write masks能更好的控制颜色、深度和模板值写入到合适的缓冲区。例如:颜色缓冲区中的write mask可以被设置成没有红色值写入到颜色缓冲区。另外,Opengl ES 2.0提供从framebuffer中获取像素的接口,不过需要记住的是像素只能从颜色缓冲区读回,深度和模板值不能读回。

注意:Opengl ES 2.0 的Per-Fragment Operations已经不再支持Alpha test 和 LogicOp了,这两个步骤在 OpenGL 2.0 和 OpenGL ES 1.x中是存在的。Alpha test 阶段不再需要的原因是片元着色器可以丢弃片元,所以可以在片元着色器中执行Alpha test。 LogicOp因为很少使用,所以不再支持了。

这篇关于OpenGL ES 2.0渲染管线的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1147599

相关文章

ElasticSearch的DSL查询⑤(ES数据聚合、DSL语法数据聚合、RestClient数据聚合)

目录 一、数据聚合 1.1 DSL实现聚合 1.1.1 Bucket聚合  1.1.2 带条件聚合 1.1.3 Metric聚合 1.1.4 总结 2.1 RestClient实现聚合 2.1.1 Bucket聚合 2.1.2 带条件聚合 2.2.3 Metric聚合 一、数据聚合 聚合(aggregations)可以让我们极其方便的实现对数据的统计、分析、运算。例如:

OPENGL顶点数组, glDrawArrays,glDrawElements

顶点数组, glDrawArrays,glDrawElements  前两天接触OpenGL ES的时候发现里面没有了熟悉的glBegin(), glEnd(),glVertex3f()函数,取而代之的是glDrawArrays()。有问题问google,终于找到答案:因为OpenGL ES是针对嵌入式设备这些对性能要求比较高的平台,因此把很多影响性能的函数都去掉了,上述的几个函数都被移除了。接

OpenGL ES学习总结:基础知识简介

什么是OpenGL ES? OpenGL ES (为OpenGL for Embedded System的缩写) 为适用于嵌入式系统的一个免费二维和三维图形库。 为桌面版本OpenGL 的一个子集。 OpenGL ES管道(Pipeline) OpenGL ES 1.x 的工序是固定的,称为Fix-Function Pipeline,可以想象一个带有很多控制开关的机器,尽管加工

OpenGL雾(fog)

使用fog步骤: 1. enable. glEnable(GL_FOG); // 使用雾气 2. 设置雾气颜色。glFogfv(GL_FOG_COLOR, fogColor); 3. 设置雾气的模式. glFogi(GL_FOG_MODE, GL_EXP); // 还可以选择GL_EXP2或GL_LINEAR 4. 设置雾的密度. glFogf(GL_FOG_DENSITY, 0

opengl纹理操作

我们在前一课中,学习了简单的像素操作,这意味着我们可以使用各种各样的BMP文件来丰富程序的显示效果,于是我们的OpenGL图形程序也不再像以前总是只显示几个多边形那样单调了。——但是这还不够。虽然我们可以将像素数据按照矩形进行缩小和放大,但是还不足以满足我们的要求。例如要将一幅世界地图绘制到一个球体表面,只使用glPixelZoom这样的函数来进行缩放显然是不够的。OpenGL纹理映射功能支持将

【Unity小技巧】URP管线遮挡高亮效果

前言 在URP渲染管线环境下实现物体遮挡高亮显示效果,效果如下: Unity URP遮挡高亮 实现步骤 创建层级,为需要显示高亮效果的物体添加层级,比如Player 创建一个材质球,也就是高亮效果显示的材质球找到Universal Renderer Data Assets 4.在Assets上添加两个Render Objects组件 第一个做如下三处设置 指定遮挡层级指

QT项目实战之音乐播放器2.0版本

该版本相较于1.0版本最主要的不同在于连接数据库实现类似于歌曲收藏和取消收藏的功能。 详细情况看我的这篇文章http://t.csdnimg.cn/WS5s8。 效果展示 VSMyMusicShow2.0 define.h UseMySQL.h   musicInfo.h   VSMyMusicPlayer.h

MemSQL Start[c]UP 2.0 - Round 1A(构造)

题目链接:http://codeforces.com/problemset/problem/452/A 解题思路: 打个表暴力查找匹配。 完整代码: #include <algorithm>#include <iostream>#include <cstring>#include <complex>#include <cstdio>#include <strin

OpenGL/GLUT实践:流体模拟——数值解法求解Navier-Stokes方程模拟二维流体(电子科技大学信软图形与动画Ⅱ实验)

源码见GitHub:A-UESTCer-s-Code 文章目录 1 实现效果2 实现过程2.1 流体模拟实现2.1.1 网格结构2.1.2 数据结构2.1.3 程序结构1) 更新速度场2) 更新密度值 2.1.4 实现效果 2.2 颜色设置2.2.1 颜色绘制2.2.2 颜色交互2.2.3 实现效果 2.3 障碍设置2.3.1 障碍定义2.3.2 障碍边界条件判定2.3.3 障碍实现2.3.

OpenGL——着色器画一个点

一、 绘制 在窗口中间画一个像素点: #include <GL/glew.h>#include <GLFW/glfw3.h>#include <iostream>using namespace std;#define numVAOs 1GLuint renderingProgram;GLuint vao[numVAOs];GLuintcreateShaderProgram (){c