Metal_入門02_帶你走流程

Metal 系列教程
Metal_入門01_為什么要學(xué)習(xí)它
Metal_入門02_帶你走流程

  • 有話要說

要學(xué)好Metal 它的工作原理,是比較重要的,搞清楚每個類都在干什么事情,就很不錯了,今天只是帶大家跑起來一個工程,熟悉一下相關(guān)流程,可能不會用太多的知識點(diǎn),順便說一句,學(xué)過OpenGL 的同學(xué)可能理解起來更加容易,但是沒有學(xué)過OpenGL 的同學(xué)也不要灰心,畢竟兩者沒有任何關(guān)系,我們從簡單做起!后面會不斷更新相關(guān)技術(shù)!

  • 步驟

1.創(chuàng)建工程

讓學(xué)習(xí)成為一種習(xí)慣

就和創(chuàng)建一般的應(yīng)用工程一樣,我選擇的是Swift 語言,為啥用它,個人比較懶,Swift語法寫起來比較簡單。

2.導(dǎo)入框架

讓學(xué)習(xí)成為一種習(xí)慣

注意

為了簡單,我們借助系統(tǒng)提供給我的Metalkit來簡化操作,后面我會教大家只使用Metal 去實現(xiàn)這個過程,由于是入門就不要那么復(fù)雜了。

3.創(chuàng)建Metal專用視圖

let mtkView = MTKView(frame: self.view.bounds)
self.view.addSubview(mtkView)

提示:

這個視圖有個屬性就是MTLDevice 必須要指定的,默認(rèn)是沒有賦值的

4.獲取GPU設(shè)備,檢查手機(jī)是否支持

  guard  let device = MTLCreateSystemDefaultDevice() else{
       print("不支持Metal,可以在這里使用OpenGL ES 代替Metal")
       return
 }

提示:

在上一章我們知道,device 代表的就是GPU ,可以創(chuàng)建新的命令隊列,可以分配內(nèi)存,可以創(chuàng)建紋理和查詢設(shè)備信息

5.創(chuàng)建命令線程

let commandQueue = device.makeCommandQueue()

提示:

1.上一章講到過命令線程,主要提供了方法創(chuàng)建命令緩沖對象,MTLCommandBuffer協(xié)議為命令緩沖對象定義了一些方法,提供方法去創(chuàng)建命令編碼器,入隊命令緩沖區(qū)執(zhí)行,檢查狀態(tài)
2.本實例,我們只用線程隊列創(chuàng)建一個命令緩沖對象

6.創(chuàng)建代表繪圖函數(shù)的資源對象

let defaultLibrary = device.newDefaultLibrary()
let fragmentProgram = defaultLibrary?.makeFunction(name: "passThroughFragment")!
let vertexProgram = defaultLibrary?.makeFunction(name: "passThroughVertex")!

提示:

資源對象的作用就是加載Metal 支持的著色器程序,生成MTLFunction 對象,我們在渲染管線描述對象需要使用生成的函數(shù)對象
passThroughFragment 和 passThroughVertex 是處理頂點(diǎn)和片段著色器的函數(shù)名

讓學(xué)習(xí)成為一種習(xí)慣

7.創(chuàng)建渲染管線描述對象

let pipelineStateDescriptor = MTLRenderPipelineDescriptor()
pipelineStateDescriptor.vertexFunction = vertexProgram// 指定頂點(diǎn)處理程序
pipelineStateDescriptor.fragmentFunction = fragmentProgram// 指定片段程序
pipelineStateDescriptor.colorAttachments[0].pixelFormat = mtkView.colorPixelFormat// 指定顏色格式
pipelineStateDescriptor.sampleCount = mtkView.sampleCount// 設(shè)置采樣數(shù)量

提示:

這個對象的作用,主要是描述渲染管線狀態(tài)的配置信息,如指定片段著色器函數(shù),設(shè)置渲染像素格式等
頂點(diǎn)著色器和片段著色器程序方法必須指定,顏色格式也必須設(shè)置

8.創(chuàng)建管線狀態(tài)對象

 do {
        try pipelineState = device.makeRenderPipelineState(descriptor: pipelineStateDescriptor)
    } catch let error {
        print("Failed to create pipeline state, error \(error)")
    }

提示:

這個對象創(chuàng)建很簡單,就是根據(jù)管線描述對象生成需要的管線狀態(tài)對象

渲染管線流程圖

8.創(chuàng)建緩沖區(qū)(頂點(diǎn)和顏色)

 let vertexLength = vertexData.count * MemoryLayout<Float>.size
 let vertexBuffer = device.makeBuffer(bytes: vertexData, length: vertexLength, options: [])
 let colorLength = vertexColorData.count * MemoryLayout<Float>.size
 let colorBuffer = device.makeBuffer(bytes: vertexColorData, length: colorLength, options: [])

提示:

MTLBuffer 是我們緩存數(shù)據(jù)的緩沖區(qū)對象

10.創(chuàng)建命令緩沖區(qū)

let commandBuffer = commandQueue.makeCommandBuffer()

提示:

這個對象相對比較重要,它攜帶了GPU 渲染圖像的所有數(shù)據(jù)
11.創(chuàng)建命令編碼器

/// 獲取視圖當(dāng)前的渲染描述和繪制對象
 let renderPassDescriptor = mtkView.currentRenderPassDescriptor
 let currentDrawable = mtkView.currentDrawable // 獲取當(dāng)前幀的繪制對象
 /// 創(chuàng)建渲染編碼器
 let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor!)
renderEncoder.setRenderPipelineState(pipleState!)// 指定渲染管線對象
 renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, at: 0)// 設(shè)置頂點(diǎn)緩沖區(qū)
renderEncoder.setVertexBuffer(colorBuffer, offset:0 , at: 1)// 設(shè)置顏色緩沖區(qū)
renderEncoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: 6, instanceCount: 1)// 設(shè)置繪制方式
renderEncoder.endEncoding()/// 結(jié)束掉這個編碼對象
commandBuffer.present(currentDrawable!) /// 讓繪制對象綁定到當(dāng)前繪制幀

12.提交

commandBuffer.commit()

提示:

執(zhí)行這一步,GPU 會記錄命令緩沖區(qū)對象,準(zhǔn)備渲染

  • 附上頂點(diǎn)和顏色數(shù)組
let vertexData:[Float] =
[
    -1.0, -1.0, 0.0, 1.0,
    -1.0,  1.0, 0.0, 1.0,
    1.0, -1.0, 0.0, 1.0,
    
    1.0, 1.0, 0.0, 1.0,
    0.0,  1.0, 0.0, 1.0,
    1.0,  0.0, 0.0, 1.0,
]

let vertexColorData:[Float] =
[
    1.0, 0.0, 0.0, 1.0,
    0.0, 1.0, 0.0, 1.0,
    0.0, 0.0, 1.0, 1.0,
    
    0.0, 0.0, 1.0, 1.0,
    0.0, 1.0, 0.0, 1.0,
    1.0, 0.0, 0.0, 1.0,
]

這個時候你運(yùn)行一下程序就能看到下面的畫面

讓學(xué)習(xí)成為一種習(xí)慣

我制作了一張流程圖幫助大家理解

不斷的克服困難的任務(wù)才有成就感

代碼地址 - 想要不斷學(xué)習(xí)的同學(xué)可以標(biāo)記一下,后續(xù)的代碼都會放在這里

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容