基於金屬的圖像處理框架。
MTIImageMTIImageMTIImageCVPixelBuffer的顏色空間SwiftAppleSiliconMetalPetal是一個基於金屬的圖像處理框架,旨在為靜止圖像和視頻提供實時處理,並易於使用編程界面。
本章涵蓋了金屬斑的關鍵概念,並將幫助您更好地了解其設計,實現,績效含義和最佳實踐。
Metalpetal的設計考慮了以下目標。
易於使用API
提供便利的API並避免常見的陷阱。
表現
有效地使用CPU,GPU和內存。
可擴展性
易於創建自定義過濾器以及插件您的自定義圖像處理單元。
sw
為Swift程序員提供流暢的體驗。
金屬斑的一些核心概念與蘋果核心圖像框架中的核心概念非常相似。
提供了呈現MTIImage s的評估環境。它還存儲許多緩存和狀態信息,因此,盡可能重複上下文更有效。
MTIImage對像是要處理或生成的圖像的表示。它確實直接表示圖像位圖數據,它具有產生圖像或更精確的MTLTexture所需的所有信息。它由兩個部分組成,即如何產生紋理( MTIImagePromise )以及其他信息,例如上下文如何緩存圖像( cachePolicy )以及如何採樣紋理( samplerDescriptor )。
MTIFilter代表圖像處理效果和控制該效果的任何參數。它會產生MTIImage對像作為輸出。要使用過濾器,請創建一個過濾器對象,設置其輸入圖像和參數,然後訪問其輸出圖像。通常,濾波器類擁有靜態內核( MTIKernel ),當您訪問其outputImage屬性時,它會要求帶有輸入圖像和參數的內核生成輸出MTIImage 。
MTIKernel表示圖像處理程序。 MTIKernel負責為過濾器創建相應的渲染或計算管道狀態,並為MTIImage構建MTIImagePromise 。
Metalpetal在引擎蓋下為您提供了很多優化。
它會自動caches函數,內核狀態,採樣器狀態等。
它利用金屬功能,例如可編程混合,無內存的渲染目標,資源堆和金屬性能著色器,以使渲染效率快速有效。在MacOS上,Metalpetal還可以利用Apple Silicon的TBDR架構。
在渲染之前,MetalPetal可以查看您的圖像渲染圖,並找出執行渲染,節省內存,能量和時間所需的中間紋理數量的最小數量。
如果可以連接多個“配方”以消除冗餘渲染通行證,則它還可以重新組織圖像渲染圖。 ( MTIContext.isRenderGraphOptimizationEnabled )
MTIImage對像是不變的,這意味著它們可以在線程之間安全共享。
但是, MTIFilter對像是可變的,因此不能在線程之間安全地共享。
MTIContext包含許多狀態和緩存。有一個用於MTIContext對象的線程安全機制,使得在線程之間共享MTIContext對像是安全的。
完全自定義的頂點和片段功能。
MRT(多個渲染目標)支持。
通常表現更好。 (需要詳細的基準數據)
顏色矩陣
顏色查找
使用顏色查找表來重塑圖像中的顏色。
不透明度
曝露
飽和
亮度
對比
顏色反轉
充滿活力
調整圖像的飽和度,同時保持令人愉悅的膚色。
RGB音調曲線
混合模式
與面具混合
轉換
莊稼
像素化
多層複合材料
國會議員卷積
國會議員高斯模糊
MPS定義
MPS SOBEL
MPS UNSHARP面具
MPS盒子模糊
高通皮平滑
Clahe(對比度限制的自適應直方圖均衡)
鏡頭Blur(Hexagonal散景模糊)
表面模糊
凸起失真
色度鑰匙混合物
彩色半徑
點屏幕
圓角(圓形/連續曲線)
所有核心圖像過濾器
MTIImage您可以從幾乎任何圖像數據來源創建MTIImage對象,包括:
URL s引用要加載的圖像文件CVImageBufferRef或CVPixelBufferRef )CIImage對象MDLTexture對象 let imageFromCGImage = MTIImage ( cgImage : cgImage , isOpaque : true )
let imageFromCIImage = MTIImage ( ciImage : ciImage )
let imageFromCoreVideoPixelBuffer = MTIImage ( cvPixelBuffer : pixelBuffer , alphaType : . alphaIsOne )
let imageFromContentsOfURL = MTIImage ( contentsOf : url )
// unpremultiply alpha if needed
let unpremultipliedAlphaImage = image . unpremultiplyingAlpha ( ) let inputImage = ...
let filter = MTISaturationFilter ( )
filter . saturation = 0
filter . inputImage = inputImage
let outputImage = filter . outputImageMTIImage let options = MTIContextOptions ( )
guard let device = MTLCreateSystemDefaultDevice ( ) , let context = try ? MTIContext ( device : device , options : options ) else {
return
}
let image : MTIImage = ...
do {
try context . render ( image , to : pixelBuffer )
//context.makeCIImage(from: image)
//context.makeCGImage(from: image)
} catch {
print ( error )
}MTIImage let imageView = MTIImageView ( frame : self . view . bounds )
// You can optionally assign a `MTIContext` to the image view. If no context is assigned and `automaticallyCreatesContext` is set to `true` (the default value), a `MTIContext` is created automatically when the image view renders its content.
imageView . context = ...
imageView . image = image如果您想將GPU命令編碼過程移出主線程,則可以使用MTIThreadSafeImageView 。您可以將MTIImage分配給任何線程中的MTIThreadSafeImageView 。
MetalPetal具有用於連接過濾器的類型Swift API。您可以在FilterGraph.makeImage函數中使用=>運算符來連接過濾器並獲取輸出圖像。
這裡有一些例子:
let image = try ? FilterGraph . makeImage { output in
inputImage => saturationFilter => exposureFilter => output
} let image = try ? FilterGraph . makeImage { output in
inputImage => saturationFilter => exposureFilter => contrastFilter => blendFilter . inputPorts . inputImage
exposureFilter => blendFilter . inputPorts . inputBackgroundImage
blendFilter => output
}您可以直接使用=>直接連接一元過濾器( MTIUnaryFilter )。
對於具有多個輸入的過濾器,您需要連接到其一個inputPorts之一。
=>操作員僅在FilterGraph.makeImage方法中起作用。
一個和只有一個過濾器的輸出可以連接到output 。
與AVPlayer合作:
let context = try MTIContext ( device : device )
let asset = AVAsset ( url : videoURL )
let composition = MTIVideoComposition ( asset : asset , context : context , queue : DispatchQueue . main , filter : { request in
return FilterGraph . makeImage { output in
request . anySourceImage! => filterA => filterB => output
} !
}
let playerItem = AVPlayerItem ( asset : asset )
playerItem . videoComposition = composition . makeAVVideoComposition ( )
player . replaceCurrentItem ( with : playerItem )
player . play ( )導出視頻:
以下示例需要Videoio。
import VideoIO
var configuration = AssetExportSession . Configuration ( fileType : . mp4 , videoSettings : . h264 ( videoSize : composition . renderSize ) , audioSettings : . aac ( channels : 2 , sampleRate : 44100 , bitRate : 128 * 1000 ) )
configuration . videoComposition = composition . makeAVVideoComposition ( )
self . exporter = try ! AssetExportSession ( asset : asset , outputURL : outputURL , configuration : configuration )
exporter . export ( progress : { progress in
} , completion : { error in
} )此示例需要Videoio。
import VideoIO
// Setup Image View
let imageView = MTIImageView ( frame : self . view . bounds )
...
// Setup Camera
let camera = Camera ( captureSessionPreset : . hd1920x1080 , configurator : . portraitFrontMirroredVideoOutput )
try camera . enableVideoDataOutput ( on : DispatchQueue . main , delegate : self )
camera . videoDataOutput ? . videoSettings = [ kCVPixelBufferPixelFormatTypeKey as String : kCVPixelFormatType_420YpCbCr8BiPlanarFullRange ]
...
// AVCaptureVideoDataOutputSampleBufferDelegate
let filter = MTIColorInvertFilter ( )
func captureOutput ( _ output : AVCaptureOutput , didOutput sampleBuffer : CMSampleBuffer , from connection : AVCaptureConnection ) {
guard let pixelBuffer = CMSampleBufferGetImageBuffer ( sampleBuffer ) else {
return
}
let inputImage = MTIImage ( cvPixelBuffer : pixelBuffer , alphaType : . alphaIsOne )
filter . inputImage = inputImage
self . imageView . image = filter . outputImage
}請參閱示例項目中的CameraFilterView.swift ,以了解有關預覽和錄製過濾的實時視頻的更多信息。
盡可能重複使用MTIContext 。
上下文是重量級對象,因此,如果您確實創建了一個對象,請儘早進行操作,並在每次需要渲染圖像時重複使用它。
明智地使用MTIImage.cachePolicy 。
當您不想保留圖像的渲染結果時,請使用MTIImageCachePolicyTransient ,例如,當圖像只是過濾器鏈中的中間結果時,因此可以重複使用渲染結果的基本紋理。這是最有效的內存效率選項。但是,當您要求上下文渲染先前渲染的圖像時,它可能會重新渲染該圖像,因為它的基本紋理已被重複使用。
默認情況下,過濾器的輸出圖像具有transient策略。
當您要防止基礎紋理被重複使用時,請使用MTIImageCachePolicyPersistent 。
默認情況下,從外部來源創建的圖像具有persistent策略。
了解MTIFilter.outputImage是計算屬性。
每當您向過濾器詢問其輸出圖像時,該過濾器即使輸入與上一個呼叫相同,該過濾器也可能會給您一個新的輸出圖像對象。因此,請盡可能重複使用輸出圖像。
例如,
// ╭→ filterB
// filterA ─┤
// ╰→ filterC
//
// filterB and filterC use filterA's output as their input.在這種情況下,以下解決方案:
let filterOutputImage = filterA . outputImage
filterB . inputImage = filterOutputImage
filterC . inputImage = filterOutputImage比:
filterB . inputImage = filterA . outputImage
filterC . inputImage = filterA . outputImage如果要在.metal文件中包含MTIShaderLib.h ,則需要將MTIShaderLib.h文件的路徑添加到Metal Compiler - Header Search Paths ( MTL_HEADER_SEARCH_PATHS )設置。
例如,如果您使用Cocoapods,則可以將MTL_HEADER_SEARCH_PATHS設置為${PODS_CONFIGURATION_BUILD_DIR}/MetalPetal/MetalPetal.framework/Headers或${PODS_ROOT}/MetalPetal/Frameworks/MetalPetal/Shaders 。如果使用Swift軟件包管理器,請將MTL_HEADER_SEARCH_PATHS設置為$(HEADER_SEARCH_PATHS)
MetalPetal具有內置機制,可以為您編碼著色器功能參數。您可以將著色器函數參數作為name: value字典到MTIRenderPipelineKernel.apply(toInputImages:parameters:outputDescriptors:) , MTIRenderCommand(kernel:geometry:images:parameters:)等。
例如,金屬函數元素的參數vibranceAdjust可以是:
// Swift
let amount : Float = 1.0
let vibranceVector = float4 ( 1 , 1 , 1 , 1 )
let parameters = [ " amount " : amount ,
" vibranceVector " : MTIVector ( value : vibranceVector ) ,
" avoidsSaturatingSkinTones " : true ,
" grayColorTransform " : MTIVector ( value : float3 ( 0 , 0 , 0 ) ) ] // vibranceAdjust metal function
fragment float4 vibranceAdjust (...,
constant float & amount [[ buffer( 0 ) ]],
constant float4 & vibranceVector [[ buffer( 1 ) ]],
constant bool & avoidsSaturatingSkinTones [[ buffer( 2 ) ]],
constant float3 & grayColorTransform [[ buffer( 3 ) ]])
{
...
}
下面列出了著色器函數參數類型和在參數字典中使用的相應類型。
| 著色器功能參數類型 | 迅速 | Objective-C |
|---|---|---|
| 漂浮 | 漂浮 | 漂浮 |
| int | INT32 | int |
| Uint | Uint32 | Uint |
| 布爾 | 布爾 | 布爾 |
| SIMD(float2,float4,float4x4,int4等) | SIMD(帶有MetalPetal/Swift ) / mtivector | mtivector |
| 結構 | 數據 / mtidatabuffer | NSDATA / MTIDATABUFFER |
| 其他(float *,struct *等)不可變 | 數據 / mtidatabuffer | NSDATA / MTIDATABUFFER |
| 其他(float *,struct *等)可變 | mtidatabuffer | mtidatabuffer |
要構建自定義的一元過濾器,您可以子類MTIUnaryImageRenderingFilter並覆蓋SubclassingHooks類別中的方法。示例: MTIPixellateFilter , MTIVibranceFilter , MTIUnpremultiplyAlphaFilter , MTIPremultiplyAlphaFilter等
// Objective-C
@interface MTIPixellateFilter : MTIUnaryImageRenderingFilter
@property ( nonatomic ) float fractionalWidthOfAPixel;
@end
@implementation MTIPixellateFilter
- ( instancetype ) init {
if (self = [ super init ]) {
_fractionalWidthOfAPixel = 0.05 ;
}
return self;
}
+ (MTIFunctionDescriptor *) fragmentFunctionDescriptor {
return [[MTIFunctionDescriptor alloc ] initWithName: @" pixellateEffect " libraryURL: [bundle URLForResource: @" default " withExtension: @" metallib " ]];
}
- ( NSDictionary <NSString *,id> *) parameters {
return @{ @" fractionalWidthOfAPixel " : @(self. fractionalWidthOfAPixel )};
}
@end //Swift
class MTIPixellateFilter : MTIUnaryImageRenderingFilter {
var fractionalWidthOfAPixel : Float = 0.05
override var parameters : [ String : Any ] {
return [ " fractionalWidthOfAPixel " : fractionalWidthOfAPixel ]
}
override class func fragmentFunctionDescriptor ( ) -> MTIFunctionDescriptor {
return MTIFunctionDescriptor ( name : " pixellateEffect " , libraryURL : MTIDefaultLibraryURLForBundle ( Bundle . main ) )
}
}要構建更複雜的過濾器,您需要做的就是創建一個內核( MTIRenderPipelineKernel / MTIComputePipelineKernel / MTIMPSKernel ),然後將內核應用於輸入圖像。示例: MTIChromaKeyBlendFilter , MTIBlendWithMaskFilter , MTIColorLookupFilter等
@interface MTIChromaKeyBlendFilter : NSObject <MTIFilter>
@property ( nonatomic , strong , nullable ) MTIImage *inputImage;
@property ( nonatomic , strong , nullable ) MTIImage *inputBackgroundImage;
@property ( nonatomic ) float thresholdSensitivity;
@property ( nonatomic ) float smoothing;
@property ( nonatomic ) MTIColor color;
@end
@implementation MTIChromaKeyBlendFilter
@synthesize outputPixelFormat = _outputPixelFormat;
+ (MTIRenderPipelineKernel *) kernel {
static MTIRenderPipelineKernel *kernel;
static dispatch_once_t onceToken;
dispatch_once (&onceToken, ^{
kernel = [[MTIRenderPipelineKernel alloc ] initWithVertexFunctionDescriptor: [[MTIFunctionDescriptor alloc ] initWithName: MTIFilterPassthroughVertexFunctionName] fragmentFunctionDescriptor: [[MTIFunctionDescriptor alloc ] initWithName: @" chromaKeyBlend " ]];
});
return kernel;
}
- ( instancetype ) init {
if (self = [ super init ]) {
_thresholdSensitivity = 0.4 ;
_smoothing = 0.1 ;
_color = MTIColorMake ( 0.0 , 1.0 , 0.0 , 1.0 );
}
return self;
}
- (MTIImage *) outputImage {
if (!self. inputImage || !self. inputBackgroundImage ) {
return nil ;
}
return [ self .class.kernel applyToInputImages: @[ self .inputImage, self .inputBackgroundImage]
parameters: @{ @" color " : [MTIVector vectorWithFloat4: (simd_float4){self. color . red , self. color . green , self. color . blue ,self. color . alpha }],
@" thresholdSensitivity " : @(self. thresholdSensitivity ),
@" smoothing " : @(self. smoothing )}
outputTextureDimensions: MTITextureDimensionsMake2DFromCGSize ( self .inputImage.size)
outputPixelFormat: self .outputPixelFormat];
}
@end您可以使用MTIRenderCommand在一個渲染通道中發出多個拉動呼叫。
// Create a draw call with kernelA, geometryA, and imageA.
let renderCommandA = MTIRenderCommand ( kernel : self . kernelA , geometry : self . geometryA , images : [ imageA ] , parameters : [ : ] )
// Create a draw call with kernelB, geometryB, and imageB.
let renderCommandB = MTIRenderCommand ( kernel : self . kernelB , geometry : self . geometryB , images : [ imageB ] , parameters : [ : ] )
// Create an output descriptor
let outputDescriptor = MTIRenderPassOutputDescriptor ( dimensions : MTITextureDimensions ( width : outputWidth , height : outputHeight , depth : 1 ) , pixelFormat : . bgra8Unorm , loadAction : . clear , storeAction : . store )
// Get the output images, the output image count is equal to the output descriptor count.
let images = MTIRenderCommand . images ( byPerforming : [ renderCommandA , renderCommandB ] , outputDescriptors : [ outputDescriptor ] )您還可以創建多個輸出描述符以在一個渲染通道中輸出多個圖像(MRT,請參閱https://en.wikipedia.org/wiki/multiple_render_targets)。
當MTIVertex無法滿足您的需求時,您可以實現MTIGeometry協議,以將自定義的頂點數據提供給命令編碼器。
使用MTIRenderCommand api發出撥打電話並傳遞自定義MTIGeometry 。
在極少數情況下,您可能需要直接訪問基礎紋理,在一個渲染通道中使用多個MPS內核,進行3D渲染或自己編碼渲染命令。
MTIImagePromise協議可直接訪問基礎紋理和渲染上下文,從而為金屬斑點邁出了一步。
您可以通過實現MTIImagePromise協議來創建新的輸入源或完全自定義的處理單元。您將需要導入一個額外的模塊才能這樣做。
Objective-C
@import MetalPetal.Extension;
迅速
// CocoaPods
import MetalPetal.Extension
// Swift Package Manager
import MetalPetalObjectiveC.Extension
例如,請參見MTIComputePipelineKernel , MTICLAHELUTRecipe或MTIImage的實現。
如果圖像中使用了alpha通道,則有兩種常見的表示:非企業(直/無相關)alpha和parmultiple(相關)alpha。
RGB組件使用無培養的alpha代表像素的顏色,無視其不透明度。
使用超級alpha,RGB組件代表像素的顏色,通過乘法為其不透明度調整。
Metalpetal明確處理α類型。您負責在圖像創建期間提供正確的α類型。
金屬斑中有三種α類型。
MTIAlphaType.nonPremultiplied :圖像中的alpha值未進行體育。
MTIAlphaType.premultiplied :圖像中的alpha值進行了體育鍛煉。
MTIAlphaType.alphaIsOne :圖像中沒有α通道或圖像不透明。
通常, CGImage , CVPixelBuffer和CIImage對象具有alpha頻道。強烈建議使用MTIAlphaType.alphaIsOne ,如果圖像不透明,例如,來自相機提要的CVPixelBuffer或jpg文件中加載的CGImage 。
您可以在MTIImage上調用unpremultiplyingAlpha()或premultiplyingAlpha()以轉換圖像的alpha類型。
出於績效原因,Alpha類型驗證僅發生在調試構建中。
金屬中的大多數過濾器都接受無培養的α和不透明的圖像,並輸出未培養的α圖像。
具有outputAlphaType屬性的過濾器接受所有alpha類型的輸入。您可以使用outputAlphaType指定輸出圖像的alpha類型。
例如, MTIBlendFilter , MTIMultilayerCompositingFilter , MTICoreImageUnaryFilter , MTIRGBColorSpaceConversionFilter
實際上沒有修改顏色的過濾器具有傳遞的Alpha處理規則,這意味著輸出圖像的alpha類型與輸入圖像相同。
例如, MTITransformFilter , MTICropFilter , MTIPixellateFilter , MTIBulgeDistortionFilter
有關Alpha類型和Alpha合成的更多信息,請參閱Bartosz Ciechanowski的這篇驚人的交互式文章。
顏色空間對於圖像處理至關重要。沒有顏色空間,紅色,綠色和藍色組件的數字值沒有意義。
在繼續如何處理金屬處理顏色空間之前,您可能想知道什麼是顏色空間以及它如何影響顏色值的表示。網絡上有許多文章解釋顏色空間,為了開始,該建議是顏色空間 - Bartosz Ciechanowski。
不同的軟件和框架具有不同的處理顏色空間的方式。例如,Photoshop具有默認的SRGB IEC61966-2.1工作色彩空間,而默認情況下,核心圖像使用線性SRGB工作顏色空間。
金屬紋理不會與它們一起存儲任何顏色空間信息。金屬斑點中的大多數顏色空間處理髮生在圖像數據的輸入( MTIImage(...) )和輸出( MTIContext.render... )。
為輸入指定顏色空間意味著金屬斑應該在創建紋理期間將源顏色值轉換為指定的顏色空間。
從URL或CGImage加載時,您可以使用MTICGImageLoadingOptions指定要使用紋理數據的顏色空間。如果加載圖像時未指定任何選項,則使用設備RGB顏色空間( MTICGImageLoadingOptions.default )。 nil空間禁用顏色匹配,這等同於使用輸入圖像的顏色空間來創建MTICGImageLoadingOptions 。如果指定的顏色空間的模型不是RGB,則將設備RGB顏色空間用作後備。
從CIImage加載時,您可以使用MTICIImageRenderingOptions指定您想要的紋理數據所需的顏色空間。如果加載CIImage時未指定任何選項,則使用設備RGB顏色空間( MTICIImageRenderingOptions.default )。 nil空間禁用顏色匹配,顏色值在CIContext的工作顏色空間中加載。
指定輸出的顏色空間時,顏色空間更像是一個標籤,該標籤用於與系統的其餘部分通信,以表示如何表示輸出中的顏色值。沒有進行實際的顏色空間轉換。
您可以使用MTIContext.makeCGImage...或MTIContext.startTaskTo...使用colorSpace參數來指定輸出CGImage的顏色空間。
您可以使用MTICIImageCreationOptions指定輸出CIImage的顏色空間。
金屬斑假設當未指定輸出顏色空間時,輸出顏色值在設備RGB顏色空間中。
CVPixelBuffer的顏色空間MetalPetal使用CVMetalTextureCache和IOSurface將CVPixelBuffer S直接映射到金屬紋理。因此,您無法指定從或渲染到CVPixelBuffer顏色空間。但是,您可以指定是否使用具有SRGB像素格式的紋理進行映射。
在金屬中,如果像素格式名稱具有_sRGB後綴,則在讀取和寫入像素中的顏色值期間應用SRGB伽馬壓縮和解壓縮。這意味著具有_sRGB像素格式的紋理假設其存儲的顏色值是SRGB伽馬校正的,當在著色器中讀取顏色值時,SRGB將執行SRGB到線性RGB轉換。當顏色值寫在著色器中時,將執行線性RGB到SRGB轉換。
您可以使用MTIRGBColorSpaceConversionFilter執行顏色空間轉換。顏色空間轉換功能也可以在MTIShaderLib.h中獲得。
metalpetal::sRGBToLinear (SRGB IEC61966-2.1至線性SRGB)metalpetal::linearToSRGB (線性SRGB到SRGB IEC61966-2.1)metalpetal::linearToITUR709 (線性SRGB至itu-R 709)metalpetal::ITUR709ToLinear (iTu-r 709 to Linear srgb) 您可以使用MTISCNSceneRenderer從SCNScene生成MTIImage s。您可能需要處理場景渲染器的線性RGB顏色空間,請參見第76期,Scenekit的圖像比正常情況要黑。
您可以使用MTISKSceneRenderer從SKScene生成MTIImage s。
您可以從CIImage s創建MTIImage s。
您可以使用MTIContext渲染MTIImage到CIImage 。
您可以直接與MTICoreImageKernel或MTICoreImageUnaryFilter類一起使用CIFilter 。 (僅迅速)
參見MetalPetaljs
使用MetalPetaljs,您可以使用JavaScript創建渲染管道和過濾器,從而可以從“雲”下載過濾器/渲染器。
建議您使用接受MTICGImageLoadingOptions加載CGImage s和來自URL的圖像的API,而不是使用接受MTKTextureLoaderOption的API。
當您使用接受MTKTextureLoaderOption的API時,默認情況下,MetalPetal會使用MTIDefaultTextureLoader加載CGImage S,來自URL的圖像和命名圖像。 MTIDefaultTextureLoader在內部使用MTKTextureLoader ,並為MTKTextureLoader的不一致和錯誤提供了一些解決方法,其性能成本很小。您還可以通過實現MTITextureLoader協議來創建自己的紋理加載程序。然後,在創建MTIContext時,將您的紋理加載程序類分配給MTIContextOptions.textureLoaderClass 。
您可以使用Cocoapods安裝最新版本。
use_frameworks!
pod 'MetalPetal'
# Required if you are using Swift.
pod 'MetalPetal/Swift'
# Recommended if you'd like to run MetalPetal on Apple silicon Macs.
pod 'MetalPetal/AppleSilicon'
Swift為Objective-C API提供特定於Swift的添加和修改,以改善其映射到Swift。強烈建議您使用Swift。
AppleSilicon提供以金屬陰影語言v2.3編譯的默認著色器庫,這是在Apple Silicon Mac上啟用可編程的混合支持所需的。
將軟件包依賴關係添加到您的應用
MetalPetal可以在模擬器上使用Xcode 11+和MacOS 10.15+運行。
MetalPerformanceShaders.framework在模擬器上不可用,因此依靠MetalPerformanceShaders的過濾器,例如MTIMPSGaussianBlurFilter , MTICLAHEFilter ,不起作用。
與實際的Apple GPU相比,模擬器支持更少的功能或不同的實現限制。有關詳細信息,請參見開發在模擬器中運行的金屬應用程序。
如果您快速查看MTIImage ,它將顯示您構建的圖像圖形圖。

為什麼要進行Objective-C?
感謝您考慮為Metalpetal做出貢獻。請閱讀我們的貢獻指南。
金屬塞有緩解許可。執照
/MetalPetalExamples中的文件目錄是在單獨許可下許可的。許可證
文檔是許可的CC-BY-4.0。