Android OpenGL ES 学习(二) -- 图形渲染管线和GLSL

article/2025/10/25 1:08:55

OpenGL 学习教程
Android OpenGL ES 学习(一) – 基本概念
Android OpenGL ES 学习(二) – 图形渲染管线和GLSL
Android OpenGL ES 学习(三) – 绘制平面图形
Android OpenGL ES 学习(四) – 正交投屏
Android OpenGL ES 学习(五) – 渐变色
Android OpenGL ES 学习(六) – 使用 VBO、VAO 和 EBO/IBO 优化程序
Android OpenGL ES 学习(七) – 纹理
代码工程地址: https://github.com/LillteZheng/OpenGLDemo.git

上一章,我们学习了 OpenGL 的基本知识,这一章,一起学习OpenGL的渲染模式和渲染语言GLSL。
很多人跟我一样,学习 OpenGL 的时候,最痛苦的就是,着色器是怎么传递给 OpenGL 的?为啥要这样写,虽然照着 demo 写了,但是不知道为啥这样写。
因此,理解 OpenGL 的渲染管线,是非常重要的事情,因此,这一章,可以重点看,也需要你自行搜索资料一起看,毕竟我只是基于我的理解。

一. 图形渲染管线

在 OpenGL 中,任何食物都是在 3D 空间中的,而屏幕和窗口却是 2D 像素数组,而 3D 坐标转为 2D 的处理过程,则由 GL 的图形渲染管线(Graphics Pipeline ) 负责,实际上指的是一堆原始图形数据经过各种处理,最终出现在屏幕的过程。图形渲染管道有两个主要部分:

  1. 把 3D 坐标转换成 2D 坐标
  2. 把 2D 坐标转变成实际的有颜色的像素。

从 3D 坐标到转成 2D 有色的 2D 数据,管线会划分几个阶段,每个阶段都会把前一段的输出作为输入,这些阶段都是一些特定的函数,他们能在 GPU 上各自运行,从而快速处理你的数据,这些特定函数也叫着色器。

1.1. 渲染流程

刚才说道,从数据再到屏幕的有色像素,是由一个个着色器程序完成的,而 GL 中,有些是系统配置好的,而有些则可以由开发者去配置,从而实现高度配置化。如下图,蓝色部分是可以自己配置的:
在这里插入图片描述
从这里看出,OpenGL 需要使用顶点着色器,先绘制好轮廓,再通过图元装配,将顶点转换成图元,然后通过光栅化,将图片这种矢量图形,转成为栅格化数据,最后,使用片段着色器,将光栅化的数据,每一个像素进行运算,并绘制上对应的颜色,然后再展示到屏幕中。而我们可以配置的是:

  • 顶点着色器
  • 几何着色器 (可选,后面再学习这个)
  • 片段着色器
    现在是不是解惑了,为啥一般只需要写顶点着色器和片段着色器了。
    所以我们开发的重点,需要重点关注,顶点着色器,片段着色器,将数据传递到着色器上这三个重点就可以了。

1.2. 基本概念

  • 顶点:一个顶点(Vertex)是一个3D坐标的数据的集合,它包含坐标,颜色等数据;其中坐标在 GL 是3个分量的,但是为什么有 vec4 4个分量呢?是因为它为了进行缩放,平移等图形变换,这里等学习图形变换再细讲。
  • 顶点着色器:对顶点数据进行一系列操作的程序。
  • 图元片段: OpenGL ES 只有三种图元,点、线,三角形,它会把顶点数据数据计算成一个个图元,在这个阶段会进行裁减,透视分割和其他变换操作。
  • 几何着色器:几何着色器把图元形式的一系列顶点的集合作为输入,它可以通过产生新顶点构造出新的(或是其它的)图元来生成其他形状,比如点,线,三角形。
  • 光栅化:把图元映射为最终屏幕上相应的像素,生成供片段着色器(Fragment Shader)使用的片段(Fragment)
    • 片段着色器:主要目的是计算一个像素的最终颜色。
  • 测试和混合:检测片段的对应的深度(和模板(Stencil))值(后面会讲),用它们来判断这个像素是其它物体的前面还是后面,决定是否应该丢弃。

二. 坐标

与 Android 左边西不同,GL 的其实位置是在屏幕的中心,以(0,0)为中心店,x 坐标从做到有,y 从下到上,在 [-1,1] 之前取值,再映射到屏幕,而超出 [-1,1] 之外的,不会在屏幕上显示。如下图:

在这里插入图片描述

四. GLSL 语言

GLSL (OpenGL Shading Language)是着色器程序的编程语言,该程序会在 GPU 上执行,使得渲染管线具有可编程性。这里,你可以先简单浏览,等在编写 GLSL 的语言的时候,再来看一下。

4.1 GLSL 特有语法

GLSL 与 C 语言而非常相似,有基本的类型、函数、结构体,但没有指针;当然也有自己的一些特殊类型。

4.1.1 基本类型

在计算机图形中,向量和矩阵是变换的基础,这两种数据类型也是 GLSL 的核心,它的基本类型如下:

  • 浮点向量:vec2 ,vec3 ,vec4
  • 整数向量:ivec2 ,ivec3 ,ivec4
  • 无符号整型向量:uvec2 ,uvec3 ,uvec4
  • boolean向量:bvec2 ,bvec3 ,bvec4
  • 浮点矩阵:mat2,mat3,mat4,mat2x3…
  • 二维纹理句柄:sampler2D

4.1.2 修饰符

2.0 版本

  • const:(只读) 常量变量
  • attribute:只能用于顶点着色器,用于经常更改的信息
  • uniform: (始终如一的)用于不经常更改的信息,可用于顶点和片元着色器
  • varying:(易变的)用于修饰从顶点着色器向片元着色器传递变量。
    更多的解释,可以参考:https://zhuanlan.zhihu.com/p/52807564

3.0版本
在3.0版本,去掉了 attribute 和 varying,使用 in 和 out 和表示输入和输出。为了更好的关管理着色器的顶点数据,会使用 location 这一元数据指定输入变量,比如 layout(location = 0) 表示当前变量index为0的顶点数据,后面使用也是根据 index 。
例如:

4.2 内置变量

OpenGL 中,有几个内置变量,最常见的是在顶点着色器和片段着色器中

  • 顶点着色器(Vectex Shader):gl_position(位置) 和 gl_pointSize (大小)
  • 片段着色器(Fragment Shader):gl_FragColor (颜色值) < 3.0之后删除 >

更多3.0 和 2.0 的区别,参考 https://blog.csdn.net/afei__/article/details/88859449

4.3 函数和内置函数

GLSL 的函数使用,与 C 语言基本一直,在定义函数之前先申明类型。不同之处,在于 GLSL 在函数参数上提供了特殊的限定符(修饰符),这个跟 aidl 有点像,如:

  • in:默认模式,相当于传入参数只是 in 实参的一份拷贝,修改的值不会影响 in 参数本身,相当于java的 get
  • out:相当于 wirte-only,可写不可读,相当于 java 的set方法
  • inpuot:可读可写模式,直接改到实参,可以理解有 get 和set 方法。

GLSL 提供内置函数还是挺方便的,常见的有:

  • abs:绝对值
  • floor:向下取整
  • ceil:向上取整
  • mod:取模
  • min:最小
  • max:最大
  • clamp:中间值
  • dot:计算两个向量的点积
  • pow:计算标量的幂次

4.4 GLSL 编写工具

在 Android studio 中,下载 GLSL 的插件,就可以编写后,再拷贝到着色器代码了,有代码提示真的很不错:
在这里插入图片描述

OpenGL 的渲染框架

接下来,看看 GLSL 是如何把 着色器的值传递给 OpenGL 的渲染管线的,如下图:
在这里插入图片描述
从上面可以看到,管线可以分为 client 和 server:

Client:
这里是我们赋予着色器参数的动态值,以及调用的 OpenGL api ,这里指我们的程序代码。

Server:
Server 是整个渲染的核心,它运行再 GPU,Client 和 Server 只能通过 Attributes ,Uniforms 等类型通信。然后再通过着色器 Shader 将数据绘制渲染出来。

参考:
https://mp.weixin.qq.com/s?__biz=MzU5NjkxMjE5Mg==&mid=2247483771&idx=1&sn=9b122a361188aa4cc0d75549be0ee4a4&chksm=fe5a3054c92db942d350306739c2c775c95d107b8f2a213d6ddc9cbc5c042c702dc1d36c3581&scene=21#wechat_redirect
https://www.jianshu.com/p/48c52f862f42
https://www.jianshu.com/p/a818684333f2
https://zhuanlan.zhihu.com/p/52807564


http://chatgpt.dhexx.cn/article/dIp2voQf.shtml

相关文章

Android开发的经典入门教材和学习路线

---------------------------------------------------------------------------------------------------------------------- Android开发书籍推荐&#xff1a;从入门到精通系列学习路线书籍介绍 (https://www.diycode.cc/wiki/androidbook) 很多时候我们都会不断收到新手…

2022 Android 进阶学习RoadMap

看到一篇文章中提到“最近几年国内的初级Android程序员已经很多了&#xff0c;但是中高级的Android技术人才仍然稀缺“;这的确不假&#xff0c;今年已经是2022年了&#xff0c;距离Android巅峰时期那会已经过去七八年了&#xff0c;现在想找一个适合的中高级Android工程师的确不…

Android入门基础教程

第1章 Android Studio运行第一个程序 1.1 Android Studio下载&#xff1a; 1.1.1 Android开发者官网&#xff1a; https://developer.android.google.cn ​ 1.1.2 下载Android Studio开发者工具&#xff1a; 进入Android开发者官网&#xff1b;找到Android Studio工具下载页…

学习Android逆向

工具 抓包&#xff1a;httpcanary高级版-Android文档类资源-CSDN下载安卓手机抓包工具httpcanary高级版.apk更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/XJ74110/85031291 反编译&#xff1a;AndroidKiller_v1.3.1-Android文档类资源-CSDN下…

Android 学习路线

Java基础 Java Object类方法 HashMap原理&#xff0c;Hash冲突&#xff0c;并发集合&#xff0c;线程安全集合及实现原理 HashMap 和 HashTable 区别 HashCode 作用&#xff0c;如何重载hashCode方法 ArrayList与LinkList区别与联系 GC机制 Java反射机制&#xff0c;Java…

【Android -- 学习】学习资料汇总

文章目录 一、前言二、书籍1. Java 书籍2. 算法与数据结构3. 操作系统4. 网络5. Android 书籍6. 软件工程7. 敏捷开发8. 其它 三、学习网站1. 大学资源网2. 北京大学公开课3. 大学自学网4. 偶书5. 哔哩哔哩6. 简单教程7. Stack Overflow8. YouTube9. 牛客网10. CSDN 四、博客五…

Android八大模块进阶学习笔记(性能优化、百大框架、高级UI、Flutter、Kotlin...)

今年来&#xff0c;Android开发行业的就业形势愈加严峻&#xff0c;无论刚刚入门Android学习没有头绪的、还是开发多年想要突破薪资范畴的&#xff0c;都需要跳出编码和业务的局限&#xff0c;学会选型、扩展&#xff0c; 提升编程思维&#xff0c;建立良好的职业规划&#xff…

Android学习笔记(一):Android基础

1 Android发展和历史 Android是由Android公司创造的手机操作系统&#xff0c;公司创始人是Andy Rubin&#xff0c;后来被Google收购&#xff0c;Google于2007年11月发布了Android 1.0手机操作系统&#xff0c;在2009年发布了Android 1.5&#xff0c;此后Android发展迅速。目前…

dspic c语言教程,轻松学PIC之数码管篇 PIC单片机学习系列教程

轻松学PIC之数码管篇 PIC单片机学习系列教程 大家好&#xff0c;通过前一期的学习&#xff0c;我们已经对ICD2仿真烧写器和增强型PIC实验板的使用方法及学习方式有所了解与熟悉&#xff0c;学会了如何用单片机来控制发光管、继电器、蜂鸣器、按键等资源&#xff0c;体会到了学习…

PIC单片机之I/O控制

I/O控制对于单片机而言是最基础最核心的东西&#xff0c;其实单片机除了AD DA 转换之外的事情。其他大部分的事情I/O口都能做的到。I/O控制简单却能千变万化。 单片机在大部分应用中做的事情&#xff0c;莫过于 输入高低电平 &#xff0c;输出高低电平。就是通过这简单的控制电…

PIC单片机入门_中断系统详解

1.中断的基本概念 当单片机正在执行程序时&#xff0c;出现了某些特殊状况&#xff0c;例如定时时间到、有键盘信号输入等&#xff0c;此时CPU须要暂时停止当前的程序&#xff0c;而转去执行处理这些事件的程序&#xff0c;待执行完这些特定的程序之后&#xff0c;再返回到原先…

PIC单片机学习笔记

视频内容来自哔哩哔哩-【单片机】PIC单片机F877A视频教程&#xff08;郭天祥&#xff09; 1、简介 本视频使用的单片机是PIC16F877A &#xff08;公司用的的dsPIC33FJ128GP306&#xff09; dsPIC33——16位单片机 中档产品仅有35条汇编语言——意外之喜 哈佛总线结构、RI…

PIC单片机学习—USART串口

PIC单片机学习—USART串口 最近做了几个项目都用到了PIC单片机&#xff0c;在这几个项目之前我只用到了51单片机和STM32来做控制类的项目&#xff0c;用PIC单片机的时候发现使用的时候和51单片机还是有所区别&#xff0c;有许多小坑需要注意&#xff0c;所以决定写几篇针对新手…

PIC单片机应用开发实践教程(四): MPLAB X IDE Debug

源码基于 PIC16F15355开发板&#xff0c;想了解详情&#xff0c;请点 PIC16F15355开发板 当程序写好后&#xff0c;我们就可以使用在线调试功能&#xff0c;验证代码的正确性。 1、打开工程 File - Open Project &#xff0c;打开我们要调试的工程 2、打开工程属性&#xf…

PIC单片机

PIC芯片所用编译器是MPLAB X IDE&#xff0c;刚开始接触PIC单片机&#xff0c;也是一脸茫然&#xff0c;然后查阅资料逐渐了解、运用编译器&#xff0c;这里我就不说编译器怎么使用了&#xff0c;下面我将以PIC12LF1822芯片为例&#xff0c;简单来说说我见解&#xff0c;分别说…

PIC单片机应用开发实践教程(六): 代码配置器(MCC)

源码基于 PIC16F15355开发板&#xff0c;想了解详情&#xff0c;请点 PIC16F15355开发板 1、简介 MPLAB 代码配置器&#xff08;MPLAB Code Configurator&#xff0c;MCC&#xff09;通过图形用户界面&#xff08;Graphical User Interface&#xff0c;GUI&#xff09;生成驱…

【PIC】单片机基本概述

1. 公司 PIC 单片机是 Microchip&#xff08;微芯&#xff09; 公司的产品&#xff0c;始于1989年。 2. 精简指令集技术 传统的单片机采用复杂指令集&#xff08;Complex Instruction Set Computer, CISC&#xff09;结构&#xff0c;通常有50~110条。而 PIC 采用精简指令集&…

PIC单片机应用开发实践教程(二): 新建工程

源码基于 PIC16F15355开发板&#xff0c;想了解详情&#xff0c;请点 PIC16F15355开发板 1 打开MPLAB X IDE File---New Project Microchip Embedded --- Standalone Project 选择所用MCU对应型号 点击 Finish 后&#xff0c;工程就建好了 2 添加main.c文件 3 添加main.h文件 …

PIC单片机的入门认识(以PIC12为学习目标)

1.学习PIC12针脚定义 针脚1及针脚8可接电源5V和地线。针脚2.3可外接晶振。 针脚4为复位脚&#xff0c;当单片机正常运行时接高电平&#xff0c;若有一个低电平输入&#xff0c;单片机便复位。 针脚5则为单片机的I/O脚&#xff0c;可控制它为输入或输出&#xff0c;输入0&…

PIC单片机应用开发实践教程(七):PIC16F153xx——时钟使用

源码基于 PIC16F15355开发板&#xff0c;想了解详情&#xff0c;请点 PIC16F15355开发板 PIC16F15355 内部晶振框图如下&#xff0c;从框图中我们知道MCU时钟来源有3个&#xff1a;外部时钟&#xff0c;内部时钟&#xff0c;Timer1 内部时钟源&#xff08;INTERNAL CLOCK SOUR…