OpenGLES Android篇零基础系列(三):OpenGL ES的渲染管道及VertexShader与FragmentShader

本文主要是介绍OpenGLES Android篇零基础系列(三):OpenGL ES的渲染管道及VertexShader与FragmentShader,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

在前2篇文章中,我们都说到着色器,且在第二篇中正式说到,这着色器只能用在OpenGL ES2.x等可编程管道里面,而在OpenGL ES1.x是不能用的。但我们一直没有说这是为什么,两者有什么区别。那这篇我们就一起来学习下OpenGL ES中的渲染管道。

正文

管道,英文名叫Pipeline,相信用过FaceBook图片加载库的同学对这个管道并不陌生,因为SimpleImageDrawee里面也是用的管道来对图片进行的一个处理。由于其底层也是C,因此我可以大胆的猜想,FaceBook图片加载库的设计思路可能有参考OpenGL(这当然纯属臆想^_^)。
管道用正确的计算机语言来描述就是:
显卡执行的、从几何体到最终渲染图像的、数据传输处理计算的过程。

即是管道,那就得有先后顺序。整体是从上游流到下游。
在OpenGL ES1.x中,它是固定管道,整体是封闭的,中间的各道工艺按固定的流程顺序走。看下图:
图一

从上图可以看出,这些工艺顺序是固定的。整个过程又可以分成三部分:处理顶点、处理片元、验证片元信息并存入内存
Rasterizer:光栅化处理,当顶点处理完后,会交给rasterizer来进行光栅化处理,结果会把顶点的坐标信息转换成能在屏幕显示的像素信息即片元(fragments)。生成片元后,接下来就是对fragments片元的各种验证,即过滤掉无用的片元,裁剪掉不在视野内的片元,最终把有效片元存储入内存中。

这里对于Rasterizer光栅化,让我们一起来了解学习下:

Rasterizer/Rasterization:光栅化处理

这个词儿Adobe官方翻译成栅格化或者像素化。没错,就是把矢量图形转化成像素点儿的过程。我们屏幕上显示的画面都是由像素组成,而三维物体都是点线面构成的。要让点线面,变成能在屏幕上显示的像素,就需要Rasterize这个过程。就是从矢量的点线面的描述,变成像素的描述。(或:所顶点从世界坐标系转换为屏幕坐标系的片元)
如下图,这是一个放大了1200%的屏幕,前面是告诉计算机我有一个圆形,后面就是计算机把圆形转换成可以显示的像素点。这个过程就是Rasterize。

图二

现在是一个多元化的社会,是一个讲个性化的社会,什么都想着个性化,OpenGL ES也不例外,它为个性化的需求提供了接口。如图一中的蓝色方块部分,就是可以高度定制化的地方,因此也就形成了OpenGL ES2.x等的可编程管道,在OpenGL ES里面有两个专用的词VertexShader(顶点着色器)、FragmentShader(片元着色器),分别对应图一中的Coordinate蓝色块和Texture等蓝色块。

下面就看下OpenGL ES2.0 可渲染管道图:
图三

VertexShader:顶点着色器

顶点着色器,记得在前2篇中,我们有贴出2个着色器的脚本语句,再次贴出如下:

 /*** 顶点着色器的语句*/private final String mVertexShader ="uniform mat4 uMVPMatrix;\n" +"attribute vec4 aPosition;\n" +"attribute vec2 aTextureCoord;\n" +"varying vec2 vTextureCoord;\n" +"void main() {\n" +"  gl_Position = uMVPMatrix * aPosition;\n" +"  vTextureCoord = aTextureCoord;\n" +"}\n";/*** 片元着色器的语句*/private final String mFragmentShader ="precision mediump float;\n" +"varying vec2 vTextureCoord;\n" +"uniform sampler2D sTexture;\n" +"void main() {\n" +"  gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +"}\n";

下面看下vertexShader语句中的关键字:
attribute :使用顶点数组封装每个顶点的数据,一般用于每个顶点都各不相同的变量,如顶点位置、颜色等
uniform : 顶点着色器使用的常量数据,不能被着色器修改,一般用于对同一组顶点组成的单个3D物体中所有顶点都相同的变量,如当前光源的位置。
sampler:这个是可选的,一种特殊的uniform,表示顶点着色器使用的纹理。
mat4: 表示4×4浮点数矩阵,该变量存储了组合模型视图和投影矩阵
vec4:表示包含了4个浮点数的向量
varying是用于从顶点着色器传递到片元着色器或FragmentShader传递到下一步的输出变量
uMVPMatrix * aPosition:通过4*4的变换矩阵变换位置后,输出给gl_Position。gl_Position是顶点着色器内置的输出变量。gl_FragColor:是片元着色器内置的输出变量。

PrimitiveAssembly:图元装配

图元即图形,在OpenGL中有几个基本图元:点,线,三角形,其它的复杂图元都是基于这些基本图元来绘成的。
在图元装配不为阶段,那些经过顶点着色器(VertexShader)处理过的顶点数组或缓冲区的数据(VertexArrays/Buff Objects),被组装到一个个独立的几何图形中(eg:点,线,三角形等)。
对装配好的每一个图元,都必须确保它在世界坐标系(即能显示在屏幕的可见区域)中,而对于不在世界坐标系中的图元,就必须进行裁剪,使其处在世界坐标系中才能流到下一道工序(光栅化处理)。
在这里注意下还有一个剔除操作(Cull),前提是这个功能的开关是打开的:GLES20.glEnable(GLES20.GL_CULL_FACE);,剔除的是图元的背影,阴影,背面等。

FragmentShader:片元着色器

片元着色器主要是对光栅化处理后生成的片元逐个进行处理。接收顶点着色器输出的值,需要传入的数据,以及它经过变换矩阵后输出值存储在哪里可以通过 下图一目了然:
这里写图片描述
gl_FragColor:是片元着色器内置的输出变量。

因为Rasterization光栅化处理后,图元只是在屏幕有了象素,却还没有进行颜色处理,还是看不到东西。
因此FragmentShader可以理解为:告诉电脑如何上色的——如何处理光、阴影、遮挡、环境等等。

Per-Fragment Operations:逐个片元操作阶段

在片元着色器对片元进行综合的处理,并最终为片元生成一个颜色值并存储在gl_FragColor变量后,接下来就是逐个对片元进行一系列的测试。在上面我们说到,在光栅化处理时,它由于是把顶点从世界坐标系转换到屏幕坐标系,因此在光栅处理后,每个片元在屏幕上都有个坐标(Xw,Yw).且存储在了帧缓冲区(FrameBuffer),包括片元着色器也是对(Xw,Yw)这个坐标的片元进行处理。
下图展示了Per-Fragment Operations的过程:
图五

Pixel ownership test:像素所有权测试,它决定FrameBuffer中某一个(Xw, Yw)位置的像素是否属于当前 Opengl ES的context,比如:如果一个Opengl ES帧缓冲窗口被其他窗口遮住了,窗口系统将决定被遮住的像素不属于当前Opengl ES的context,因此也就不会被显示。

Scissor test:裁剪测试决定,判断某一个位置为(Xw, Yw)的片元是否位于裁剪矩形内,如果不在,则被丢弃。
Stencil Test / Depth tests:模板和深度测试,传入片元的模板和深度值,决定是否丢弃片元。
Blending:将FragmentShader新产生的片元颜色值和FrameBuffer中某一个位置为(Xw, Yw)的片元存储的颜色值进行混合。
Dithering:对于可用颜色较少的系统,可以以牺牲分辨率为代价,通过颜色值的抖动来增加可用颜色数量。抖动操作是和硬件相关的,OpenGL允许程序员所做的操作就只有打开或关闭抖动操作。实际上,若机器的分辨率已经相当高,激活抖动操作根本就没有任何意义。要激活或取消抖动,可以用glEnable(GL_DITHER)glDisable(GL_DITHER)函数。默认情况下,抖动是激活的。

参考资料

Android OpenGL ES 开发教程(3):OpenGL ES管道(Pipeline)
如何理解OpenGL中着色器,渲染管线,光栅化等概念?
OpenGL ES 2.0渲染管线

这篇关于OpenGLES Android篇零基础系列(三):OpenGL ES的渲染管道及VertexShader与FragmentShader的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

MySQL中my.ini文件的基础配置和优化配置方式

《MySQL中my.ini文件的基础配置和优化配置方式》文章讨论了数据库异步同步的优化思路,包括三个主要方面:幂等性、时序和延迟,作者还分享了MySQL配置文件的优化经验,并鼓励读者提供支持... 目录mysql my.ini文件的配置和优化配置优化思路MySQL配置文件优化总结MySQL my.ini文件

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

Android WebView的加载超时处理方案

《AndroidWebView的加载超时处理方案》在Android开发中,WebView是一个常用的组件,用于在应用中嵌入网页,然而,当网络状况不佳或页面加载过慢时,用户可能会遇到加载超时的问题,本... 目录引言一、WebView加载超时的原因二、加载超时处理方案1. 使用Handler和Timer进行超

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念