![36a8d78f4022b4e4c8c4d27238c40677.png](https://img-blog.csdnimg.cn/img_convert/36a8d78f4022b4e4c8c4d27238c40677.png)
【Metal2研发笔录】完整版CSDN专栏: https:// blog.csdn.net/cordova/c ategory_9467887.html
[toc]
一、关键词
上:
- 图像处理、后处理
- Metal Performance Shader
- Compute Shader
- 灰度变换
- bit plane slice
- 直方图,累加直方图
- 直方图均衡化
下:
- 图像算数操作
- 图像二阶偏导数、梯度
- 图像卷积与图像相关
- 高斯模糊
- 空域和时域
- 空域滤波(均值滤波、加权均值滤波、中值滤波)
- 拉普拉斯算子
- 图像去噪
二、Metal引擎下实现图像处理
Demo: https:// github.com/jiangxh1992/ XHMetalImageProcessing
Xcode新建一个Game工程,选择Metal作为引擎技术框架,会得到一个简单的绘制Cude的示例基础工程。这里对基础工程进行改装实现游戏RT后处理和图像处理的流程。
Demo中第一次提交版本实现了简单的后处理流程,先将图形绘制到我们的自定义RT上,然后对RT进行后处理,最后将RT画到一个和屏幕一样的Quad上并提交给view的 backbuffer绘制到屏幕上;
第二次提交对工程进行了简化,只用来做纯图像的处理,直接使用kenel函数对加载进来的MTLTexture进行图像处理,然后将结果画到Quad上提交给backbuffer显示到屏幕上。
Demo中定义了两个MTLTexture,sourceTexture用来加载要处理的图像,destTexture用来保存对sourceTexture图像处理后的结果,并作为RT渲染到屏幕上。
我们使用MTKTextureLoader加载本地图片到sourceTexture,用于后面的处理,图像选用了经典的lena人像:
MTKTextureLoader* textureLoader = [[MTKTextureLoader alloc] initWithDevice:_device];
NSDictionary *textureLoaderOptions =
@{
MTKTextureLoaderOptionTextureUsage : @(MTLTextureUsageShaderRead),
MTKTextureLoaderOptionTextureStorageMode : @(MTLStorageModePrivate)
};
sourceTexture = [textureLoader newTextureWithName:@"lena"
scaleFactor:1.0
bundle:nil
options:textureLoaderOptions
error:&error];
![6e83f1a4d1050affdf27458e201ffda1.png](https://img-blog.csdnimg.cn/img_convert/6e83f1a4d1050affdf27458e201ffda1.png)
绘制阶段设置一个tile shader,设置每个tile上多线程数目的规格,setTileTexture传入sourceTexture和destTexture,在kernel函数中对图像进行处理:
// 图像处理
[myRenderEncoder pushDebugGroup:@"ImageProcess"];
[myRenderEncoder setRenderPipelineState:_postprocessPipeline];
[myRenderEncoder setTileTexture:sourceTexture atIndex:0];
[myRenderEncoder setTileTexture:destTexture atIndex:1];
[myRenderEncoder dispatchThreadsPerTile:MTLSizeMake(32, 32, 1)];
[myRenderEncoder popDebugGroup];
kernel void postProcessing(texture2d<float, access::read> source[[texture(0)]],
texture2d<float, access::write> dest[[texture(1)]],
uint2 gid [[thread_position_in_grid]]
)
{
float4 source_color = source.read(gid);
float4 result_color = source_color; // 直接拷贝图像,不做处理
dest.write(result_color, gid);
}