图像处理

MetalPetal使用自定义Metal文件的注意事项

2021-04-15  本文已影响0人  One苹果OneDay

关于iOS的图像处理目前主流的有OpenGL ES和Metal,这里介绍一下Metal的第三方库,这个库简化了非常多的原生初始化方法,可以非常简便的实现各种滤镜效果,MetalPetal的自带滤镜使用很简单这里不展开讨论,作为一个初学者,简单记录一下学习MetalPetal库时遇到的的问题,重点是自定义Metal文件下如何使用MetalPetal
设置三个属性
//计算管线
@property(nonatomic,strong) MTIComputePipelineKernel *customComputeKernel;
//渲染管线
@property(nonatomic,strong) MTIRenderPipelineKernel *customRenderKernel;
//图像
@property (nonatomic, strong) MTIImage *inputImage;
首先是初始化一个MTIImage
UIImage *img = [UIImage imageNamed:@"gakiki"];
self.inputImage = [[MTIImage alloc] initWithCGImage:img.CGImage options:nil isOpaque:YES];
初始化计算管线和渲染管线
-(void)setupPipeline
{
//计算管线

NSURL *defaultUrl = [[NSBundle mainBundle] URLForResource:@"default" withExtension:@"metallib"];
MTIFunctionDescriptor *customKernelDes = [[MTIFunctionDescriptor alloc] initWithName:@"normalTestKernel" libraryURL:defaultUrl];


//初始化计算管线
self.customComputeKernel = [[MTIComputePipelineKernel alloc] initWithComputeFunctionDescriptor:customKernelDes];
//渲染管线
//顶点描述
MTIFunctionDescriptor *VertexFunctionDescriptor = [[MTIFunctionDescriptor alloc] initWithName:@"normalvertexShader" libraryURL:defaultUrl];
//片元描述
MTIFunctionDescriptor *fragmentFunctionDescriptor = [[MTIFunctionDescriptor alloc] initWithName:@"normalfragmentShader" libraryURL:defaultUrl];
//初始化渲染管线
self.customRenderKernel = [[MTIRenderPipelineKernel alloc] initWithVertexFunctionDescriptor:VertexFunctionDescriptor fragmentFunctionDescriptor:fragmentFunctionDescriptor];

}
这里有第一个要注意的点,如果是自定义的.metal文件MTIFunctionDescriptor的描述必须要用libraryURL的方式去初始化,因为MetalPetal默认的library是自带的那些文件方法,如果不用libraryURL这个方式是读取不到你自己的方法的,剩下的就是根据方法名去初始化MTIFunctionDescriptor,记得MTIRenderPipelineKernel要顶点和片元两个描述,别漏了就行
渲染管线和计算管线已经初始化好了,接下来就是应用了,首先看一下计算管线的使用

MTIVertices *geometry = [[MTIVertices alloc] initWithVertices:(MTIVertex []){ { .position = {1, -1, 0.0, 1.0} , .textureCoordinate = { 1.f, 1.f } }, { .position = {-1, -1, 0.0, 1.0 } , .textureCoordinate = { 0.f, 1.f } }, { .position = {-1, 1, 0.0, 1.0} , .textureCoordinate = { 0.f, 0.f } }, { .position = {1, -1, 0.0, 1.0} , .textureCoordinate = { 1.f, 1.f } },{ .position = {-1, 1, 0.0, 1.0} , .textureCoordinate = { 0.f, 0.f } },{ .position = {1, 1, 0.0, 1.0} , .textureCoordinate = { 1.f, 0.f } } } count:6 primitiveType:MTLPrimitiveTypeTriangleStrip];
//
// //定点数据和纹理数据都传递给GPU

MTIRenderCommand *command = [[MTIRenderCommand alloc] initWithKernel:_customRenderKernel geometry:geometry images:@[outImage] parameters:@{}];
MTIRenderPassOutputDescriptor *outputDescriptor = [[MTIRenderPassOutputDescriptor alloc] initWithDimensions:MTITextureDimensionsMake2DFromCGSize(_outputImage.size) pixelFormat:_renderView.colorPixelFormat];
self.renderView.image = [MTIRenderCommand imagesByPerformingRenderCommands:@[command]
outputDescriptors:@[outputDescriptor]].firstObject;

这里geometry是顶点数据跟Metal原生的格式一样的

这里只是最基本的自定义metal的实现,如果想做更多的自定义功能,比如多重纹理什么的,还是要对metal原生框架有过深入了解,作为初学者,我会不断记录遇到的问题,以便日后随时查看

上一篇 下一篇

猜你喜欢

热点阅读