[MetalKit]Using MetalKit part 10使用MetalKit10

本系列文章是对 http://metalkit.org 上面MetalKit内容的全面翻译和学习.

MetalKit系统文章目录


今天我们关注Metal function中没用过的类型,kernel function内核函数compute shader计算着色器.你将经常听到它们两个的混合词变形词.内核是用于计算任务,也就是在GPU上进行大规模并行计算.例如:图像处理,科学模拟,等等.关于内核有一些重要特点:没有渲染管线,函数总是返回void,并且名字总是以kernel关键字开头,就像我们以前用过的前面带有vertexvertex关键字的函数一样.

让我们从第8部分Part 8的playground处继续.首先,删除MathUtils.swift因为我们已经不需要了.然后,在MetalView.swift中删除createBuffers()函数及其在初始化中的调用,还有两个缓冲器.将MTLRenderPipelineState声明替换为MTLComputePipelineState声明.下一步,来到registerShaders()函数.下面是新旧两个版本的不同:

chapter10_1.png

注意,我们不在使用descriptor了,而是在内核函数中直接创建MTLComputePipelineState.下一步,我们看看drawRect()函数的不同:

chapter10_2.png

注意,currentRenderPassDescriptor也不用了.命令编码器则用computeCommandEncoder()函数来创建.显然,我们也不再需要设置顶点缓冲器和绘制基本体了.作为替代,使用用一个设置了纹理的内核函数,创建线程组并指派它们干活.我们用MTLSize来设置线程组的维数,及每次计算调用中要执行的线程组的数量.

最后,我们到Shaders.metal文件中,用下面代码替换所有内容:

#include <metal_stdlib>

using namespace metal;

kernel void compute(texture2d<float, access::write> output [[texture(0)]],
                    uint2 gid [[thread_position_in_grid]])
{
    output.write(float4(0, 0.5, 0.5, 1), gid);
}

我们只简单地给纹理中的每个像素/位置设置了相同的颜色.现在如果你到playground的主页面,并显示Assistant editor中的Timeline,你应该能看到类似的视图:

chapter10_3.png

如果你看到了上面的输出,就说明准备好继续下去了.从当前开始,我们将不再关注主代码(MetalView.swift)了,因为我们所有的工作都将在内核着色器中完成.

好了,让我们先从简单的开始.用下面的代码替换内核函数中的代码:

int width = output.get_width();
int height = output.get_height();
float red = float(gid.x) / float(width);
float green = float(gid.y) / float(height);
output.write(float4(red, green, 0, 1), gid);

你可能已经猜到了,我们拿到纹理的widthheight,然后根据像素在纹理中的位置来计算redgreen的值,然后将新颜色写入回纹理中.你将看到类似这样的东西:

chapter10_4.png

接着,让我们在屏幕中间画一个黑色的圆.用下面几行代码替换最后一行:

float2 uv = float2(gid) / float2(width, height);
uv = uv * 2.0 - 1.0;
bool inside = length(uv) < 0.5;
output.write(inside ? float4(0) : float4(red, green, 0, 1), gid); 

你会看到类似这样的东西:

chapter10_5.png

我们到底是怎么做到的呢?其实,这是在着色中很常用的技术,叫做distance function.我们使用length函数来确定像素是否在屏幕中心也就是我们圆的中心的0.5倍之内.注意,我们归一化了uv向量来匹配窗口坐标范围[-1,1].最后,我们判断像素如果在内部就是黑色,否则就像原来一样,给它一个渐变色.

让我们抽出这个圆内部/外部计算到一个距离函数中:

float dist(float2 point, float2 center, float radius)
{
    return length(point - center) - radius;
} 

然后,用下面几行替换我们定义内部的那行:

float distToCircle = dist(uv, float2(0), 0.5);
bool inside = distToCircle < 0;

看不到任何改变,但我们现在有了一个可以轻易重用的函数.下一步,让我们看看如何根据到圆的距离改变背景颜色,而不是仅根据像素的绝对位置.我们通过计算像素到圆的距离来改变透明通道的值.用下面这行替换最后一行:

output.write(inside ? float4(0) : float4(1, 0.7, 0, 1) * (1 - distToCircle), gid);

你应该看到类似这样的东西:

chapter10_6.png

很漂亮,对吧?现在我们让它变成了日食,让我们将它变得更真实一些.我们需要另一个圆(太阳),并且我们想要让初始的圆向左一点,向下一点,这样它们就都能看到了.用下面几行替换我们定义内部的那行:

float distToCircle2 = dist(uv, float2(-0.1, 0.1), 0.5);
bool inside = distToCircle2 < 0;

你会看到类似下面的东西:

chapter10_7.png

我们现在只是学会了着色技术的皮毛.在下一章节我们将学习更复杂和动态的计算任务.特别感谢Chris Wood的建议.

源代码source code 已发布在Github上.
下次见!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,042评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,996评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,674评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,340评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,404评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,749评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,902评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,662评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,110评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,451评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,577评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,258评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,848评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,726评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,952评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,271评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,452评论 2 348

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,735评论 25 707
  • 纹理(Textures) 我们已经了解到,我们可以为每个顶点使用颜色来增加图形的细节,从而创建出有趣的图像。但是通...
    IceMJ阅读 5,626评论 2 13
  • 1、 前几天参加一个付费社群,由于清空了缓存导致没收听到录音,就在群里随口问了一下,谁整理了录音和资料能否方便给我...
    普罗米阅读 1,030评论 23 18
  • 喜欢就是饿了看见面包 第一次觉得它这么美 想抓紧它握住它 如一根泉中稻草 她那么美眼睛如湖水 就像牛奶咖啡 惬意恬...
    我开始写影评了阅读 137评论 0 2
  • 随着教育信息化的不断推进,多媒体教室已经成为高校的重要组成部分,其管理的质量和效率直接影响到高校的教学。多媒体教室...
    岁月静好丶_e9ed阅读 361评论 0 2