音视频- iOS使用metal渲染图像(一)

news2024/11/27 16:30:48

概要   

        本文主要总结一下Metal的基本使用,用来渲染拍照的到的图像,其中涉及到的有UIKit中的MTKView,Metal中负责渲染的几个类,使用MSL(Metal  Shading Language)编写着色器,最终将图片渲染出来。这一篇先简介一下Metal的工作流程。

Metal对图像的处理流程

       图像的最小单位可以认为是像素,一幅图片由若干像素组成,每个像素在图片中都有一个位置,也就是该像素的坐标。二维下也就是(x,y),三维下也就是(x,y,x)。所以Metal对图像处理,其实就是对每个像素的处理。

        Metal的处理流程简化可以表示成以下这张图,从最左侧的Vertices是提供的初始的顶点数据,经过Vertex function处理

        和OpenGL中类似,Metal中的Vertex stage可以理解为OpenGL中的顶点处理阶段,主要来进行坐标转换,Vertex function就是此阶段实现的方法,同样,fragment stage对应到片段处理阶段,主要计算点的颜色值Fragment function就是此阶段实现的方法。所以Vertex fucntion和fragment function也就对应上了OpenGL中的顶点着色器和片段着色器。只不过编写的语言使用的是Metal的MSL,不再是glsl。

        在顶点处理阶段,有几个坐标需要先明确一下,首先是在使用UIKit布局的时候,通常是以左上角为(0,0),而右下角是(1,1);同时,在使用纹理的时候,对应的纹理也有一个自己的坐标系,在Metal中叫做标准纹理坐标,如下图: 

左上角为(0,0),右下角为(1,1);Metal最终进行绘制的时候,使用的另一种坐标系,就是标准化设备坐标,和上面的就不太一样,如下图:

 在只有2D情况下,中心点是(0,0),左下角是(-1,-1),右上角是(1,1),在3D情况下,z就是表示距离屏幕的距离。结合上面的标准化纹理坐标,如果要将纹理布满整个Metal的绘制范围,那么就需要将四个角的坐标对应上,也就是:

纹理坐标:(0,0)         设备坐标:(-1,1)

纹理坐标:(1,0)         设备坐标:(1,1)

纹理坐标:(0,1)         设备坐标:(-1,-1)

纹理坐标:(1,1)         设备坐标:(1,-1)

这样,就能将纹理中布满整个渲染空间范围,而这个,也就是vertex function主要要做的事情,我举的这个例子是最简单的,实际情况中肯定会很复杂,而且vertex function计算出来的坐标,有时候超过-1~1的这个区间,而这个时候,中间的光栅化器(Rasterization)就发挥作用了。

        光栅化器要做的就是,将vertex function得到的所有坐标以标准化设备坐标为边界进行选取,超出标准化设备坐标的点,一律去掉,并且将范围内的点转换成屏幕上对应的像素。将这些有效像素传递到下一个阶段。

        fragment function接下来登场了,这里面就是将光栅化器筛选出来的有效像素进行上色,当然,具体怎么上色,这个就需要根据实际情况来看,这也就是我们实现自己上色逻辑的重要部分。

        关于vertex function和fragment function的例子,放到下一章实践的时候再看。从纹理坐标到设备坐标,这个主要是针对图像的渲染。试想一个场景,我在一个MTKView上点击了一个点,或者用手指画了一条线,如何使用Metal来绘制呢?我也是突然想到的,以后实现之后再看吧。上面的部分是Metal渲染的概念部分,下面看下Metal中具体实现这个过程,涉及到的一些东西。

 Metal实现绘制的组件

 MTLDevice    

        Metal使用GPU来进行绘制,这个MTLDevice就代表了给当前绘制分配的设备,官方文档中说到这个就相当于一个GPU。这个device主要提供了一些方法,主要有三个方面

  1. 查询设备状态
  2. 创建设备相关的绘制资源,比如缓冲区,纹理等等
  3. 执行渲染的命令

下面是一些代码例子,这几个后面都会介绍:

let defaultLibrary = self.renderDevice.makeDefaultLibrary()

let pipelineState = try! self.renderDevice.makeRenderPipelineState(descriptor: pipelineStateDesc)

let vertices = self.renderDevice.makeBuffer(bytes: vertexArr!,
                                                    length: MemoryLayout<AVImageVertex>.size * 6,
                                                    options: .storageModeShared)

MTLCommandQueue、MTLCommandBuffer、MTLCommandEncoder

        这三个放到了一起,因为它们配合起来完成实际的绘制过程。首先commandQueue是由上面的device创建,从名字能看出来,是一个队列,那么这个队列里面是什么呢?就是commandBuffer。若干commandBuffer的顺序由这个commandQueue来组织,然后依次执行。

        然后是commandBuffer,是个啥呢?它的主要作用是创建commandEncoder,以及在commandEncoder工作完成之后,将所有渲染命令提交,进入commandQueue中。

        那么commandEncoder是干什么的呢?它的主要就是决定了绘制的具体操作,包括需要的顶点资源,绘制的方式(点、线、三角形)等等,具体的绘制都由它管。commandBuffer支持三种commandEncoder。官方文档中特别提到一点,在一个commandBuffer中,某一个时刻只能有一个commandEncoder处于激活状态,这一点我暂时还没有什么体会,后面使用中再慢慢了解吧。我的例子里面只使用了负责图形绘制的MTLRenderCommandEncoder,对其他感兴趣的可以自行去了解。

        然后用一张官方的大图来看下这个绘制的结构:

这个图还是比较清晰的,我会面会根据代码来一步一步地对应上去。 图中有些地方没有介绍到,后面涉及到的我会特别提到

MTKView

        这个是将Metal的工作和UI框架相联系的一个东西,一方面继承自UIView,参与UIKit中的工作,一方面实现了Metal的协议,参与Metal绘制的逻辑工作,还是挺重要的,其实用起来比较方便。使用这个类需要实现一个协议:MTKViewDelegate,必须实现其中的两个方法

  1. func mtkView(MTKView, drawableSizeWillChange: CGSize),这个方法主要是在布局发生改变,需要重新调整View大小的时候,会被调用,传入的drawableSizeWillChange就是新的尺寸;
  2. func draw(in: MTKView) 这个方法中通常就是具体的绘制操作,也就是前面提到的使用commandQueue、commandBuffer以及commandEncoder的地方。

结束

        以上主要从Metal绘制流程,绘制的功能组件以及UIKit中的MTKView这三个方面简介使用Metal的几个主要部分,接下来,后来的会从我自己的使用过程,来具体看看Metal绘制的流程。

如果有不对的地方,欢迎大家指正,相互学习,共同进步吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/92052.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python 绘制极坐标图(玫瑰花图优化)

风速的玫瑰花图可见 Matlab 绘制风速、风向统计玫瑰花图 在今天的这边博文,选用Python工具,绘制玫瑰花图,并对图进行优化。 example 1 【不规则宽度】N = 20 theta = np.linspace(0.0,2*np.pi,N,endpoint=False)

Jmeter(十五):jmeter场景的运行方式(GUI运行和命令行运行)命令行相关参数

jmeter场景的运行方式(GUI运行和命令行运行) 运行方式&#xff1a; GUI运行&#xff1a;通过图形界面方式运行&#xff0c;该运行方式的可视化界面及监听器动态展示 结果都比较消耗负载机资源&#xff0c;建议大并发时不用&#xff0c;一般进行脚本调试&#xff1b; 命令行运…

【PTA-训练day17】L2-029 特立独行的幸福 + L1-071 前世档案

L2-029 特立独行的幸福 - 递归/模拟 判断素数 PTA | 程序设计类实验辅助教学平台 思路&#xff1a; 第一层循环是边界循环 for(int il;i<r;i)枚举每一个i 第二层循环是判断这个i是不是幸福数st数组 判定 i 这个数在迭代过程中是否出现循环 如果出现循环及时跳出比如&…

【TypeScript系列】【一篇就够】TypeScript知识点总结(二)

12 面向对象简介 简而言之&#xff0c;面向对象就是程序之中所有的操作都需要通过对象来完成。 举例来说&#xff0c; 操作浏览器要使用windows对象&#xff1b;操作网页要使用document对象&#xff1b;操作控制台要使用console对象。一切操作都要通过对象&#xff0c;也就是…

nacos--扩展--03--系统参数

nacos–扩展–03–系统参数 1、Nacos Server 配置参数位置&#xff1a;{nacos.home}/conf/application.properties里注意&#xff1a;如果参数名后标注了(-D)的&#xff0c;则表示是 JVM 的参数&#xff0c;需要在{nacos.home}/bin/startup.sh里进行相应的设置。 案例&#xf…

测试用例等级怎么划分?别再傻傻的一脸懵逼

我们都知道测试工程师最基本的能力便是编写测试用例&#xff0c;可是看似简单的用例&#xff0c;后面其实蕴含这个很多人忽略的细节&#xff0c;今天就来说测试里面所蕴含的很多细节。 很多时候不只是测试和测试用例息息相关&#xff0c;开发&#xff0c;产品也有的时候对于测试…

C/C++程序的断点调试 - CodeBlocks

本文以CodeBlocks为例&#xff0c;简述C/C程序断点调试的基本方法和过程。其它的IDE环境&#xff0c;大同小异。 本文引用自作者编写的下述图书; 本文允许以个人学习、教学等目的引用、讲授或转载&#xff0c;但需要注明原作者"海洋饼干叔 叔"&#xff1b;本文不允许…

单链表翻转-链表篇

leetcode206单链表的翻转 题目&#xff1a; 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1] 示例 2&#xff1a; 输入&#xff1a;head [1,2] 输出…

如何指定标签在页面中显示的位置

如何指定标签在页面中显示的位置 在HTML页面设计中常常需要调整标签&#xff08;元素&#xff09;的位置&#xff0c;那么&#xff0c;如何指定标签在页面中显示的位置呢&#xff1f; 使用标签的align属性指定标签在页面中显示的位置&#xff0c;如align"left|right|cen…

02加锁源码分析-ReentrantReadWriteLock原理-AQS-并发编程(Java)

文章目录3.1 加锁3.1.1 读锁加锁3.1.1.1 tryAcquireShared()3.1.1.2 readerShouldBlock()3.1.1.3 fullTryAcquireShared()3.1.1.4 doAcquireShared()3.1.2 写锁加锁3.1.2.1 tryAcquire()3.1.2.2 acquireQueued()3.2 加锁示意图3.2.1 先写锁在读锁3.2.2 先读锁在写锁后记3.1 加锁…

全网惟一面向软件测试人员的Python基础教程-Python数据类型中有那些故事呢?

全网惟一面向软件测试人员的Python基础教程 起点&#xff1a;《python软件测试实战宝典》介绍 第一章 为什么软件测试人员要学习Python 第二章 学Python之前要搞懂的道理 第三章 你知道Python代码是怎样运行的吗&#xff1f; 第四章 Python数据类型中有那些故事呢&#xff1f;…

PHP+Laravel框架RabbitMQ简单使用

RabbitMQ安装教程请转到&#xff1a;RabbitMQ安装教程&#xff08;超详细&#xff09; 1、创建生产者 在app/Http/Controllers里创建一个php控制器文件&#xff0c; namespace App\Http\Controllers;use App\Http\Controllers\Controller; //引入amqp扩展 use PhpAmqpLib\Co…

铁路轨道交通智慧管理系统

摘 要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;各行各业相继进入信息管理时代&…

sklearn基础篇(九)-- 主成分分析(PCA)

1 引言 降维是对数据高维度特征的一种预处理方法。降维是将高维度的数据保留下最重要的一些特征&#xff0c;去除噪声和不重要的特征&#xff0c;从而实现提升数据处理速度的目的。在实际的生产和应用中&#xff0c;降维在一定的信息损失范围内&#xff0c;可以为我们节省大量的…

机器学习项目中Xgboost深入理解(二)梯度及GB的理解

Xgboost 与 GBDT同源&#xff0c;那么所谓的梯度是什么意思呢&#xff1f;G、B又代表什么。 1. 梯度Gradient 梯度是一个向量&#xff08;矢量&#xff09;&#xff0c;表示梯度是方向导数在某一点的最大值。理解为某函数&#xff08;可以指损失函数&#xff09;在某点处的方…

Fluent后处理的色谱设置

PART 1 概述 对物理场的空间分布进行可视化展示&#xff0c;在科研、工程等领域是必不可少的环节。 将物理量不同数值赋予不同色彩&#xff0c;是一种很常见的物理场可视化方法。通过色彩的变化&#xff0c;即可识别物理量的分布规律。 物理量数值和颜色之间的对应关系称为色…

Linux常用指令

目录 1.1关于目录操作的指令 1.2文件操作的指令 1.3创建/删除目录操作 1.4目录/文件的移动/复制/改名 1.5 vim对文件进行编辑 1.1关于目录操作的指令 ls 列出当前目录下都有啥 ls 具体路径或 /注意中间含有一个空格&#xff0c;列出跟目录下或指定路径的内容 ls -l / 以列表的…

mysql日志篇

mysql日志篇1、Undo-log 撤销日志 Undo即撤销的意思&#xff0c;大家通常也习惯称它为回滚日志。如果大家有仔细研究过 MySQL 的日志&#xff0c;应该会发现 Undo-log 并不存在单独的日志文件&#xff0c;也就是磁盘中并不会存在 xx-undo.log 这类的文件&#xff0c;那 Undo-lo…

12个python超强学习网站

一、python学习网站 1 CSDN 地址&#xff1a; CSDN学院 特点&#xff1a;从免费视频到入门项目&#xff0c;从入门到进阶&#xff0c;学习视频应有尽有&#xff0c;还有Python学习社区&#xff0c;良好的学习和沟通氛围&#xff01; 2 Python123 地址&#xff1a;python123…

ReentrantLock源码分析

ReentrantLock源码分析 源码思想加锁&#xff1a; (1)使用构造方法设置该锁为公平锁FairSync或非公平锁NonfairSync;(本处选定非公平锁) (2)调用lock方法进行获取锁,第一次(getState() 0)在NonfairSync中使用CAS(compareAndSwapInt)直接获取(此处默认未获取成功),第一次获取失…