生活随笔
收集整理的這篇文章主要介紹了
Metal之渲染绘制三角形
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
準備工作
Metal渲染的構(gòu)建流程, 請參考:Metal之簡單渲染動態(tài)切換屏幕顏色 Metal三角形的渲染顯示與渲染構(gòu)建流程大體一致, 本文主要介紹以下方面的修改和實現(xiàn): ① metal渲染文件 ② 創(chuàng)建C 與 OC 的橋接函數(shù) ③ initWithMetalKitView方法中需要加載metal文件 ④ drawInMTKView方法中加載三角形數(shù)據(jù) Metal三角形的渲染顯示是基于世界坐標系下。
渲染流程
一、metal渲染文件
command + N --> Metal File 創(chuàng)建metal著色器文件, 新建metal文件:YDWShaders.metal
定義頂點著色器輸入和片元著色器輸入,相當于OpenGL ES中的varying修飾的變量,即橋接變量;
typedef struct { float4 clipSpacePosition
[ [ position
] ] ; float4 color
; } RasterizerData
;
定義頂點著色器函數(shù)和片元著色器函數(shù): ① 處理頂點數(shù)據(jù): 執(zhí)行坐標系轉(zhuǎn)換,將生成的頂點剪輯空間寫入到返回值中; 將頂點顏色值傳遞給返回值; ② 初始化輸出剪輯空間位置: 索引到我們的數(shù)組位置以獲得當前頂點, 我們的位置是在像素維度中指定的, 每個頂點著色器的輸出位置在剪輯空間中(也稱為歸一化設(shè)備坐標空間,NDC),剪輯空間中的(-1,-1)表示視口的左下角,而(1,1)表示視口的右上角, 計算和寫入 XY值到我們的剪輯空間的位置.為了從像素空間中的位置轉(zhuǎn)換到剪輯空間的位置,我們將像素坐標除以視口的大小的一半; ③ 把輸入的顏色直接賦值給輸出顏色, 這個值將于構(gòu)成三角形的頂點的其他顏色值插值, 從而為片段著色器中的每個片段生成顏色值;
vertex RasterizerData
vertexShader ( uint vertexID
[ [ vertex_id
] ] , constant CJLVertex
* vertices
[ [ buffer ( CJLVertexInputIndexVertices
) ] ] , constant vector_uint2
* viewportSizePointer
[ [ buffer ( CJLVertexInputIndexViewportSize
) ] ] ) { RasterizerData out
; out
. clipSpacePosition
= vertices
[ vertexID
] . position
; out
. color
= vertices
[ vertexID
] . color
; return out
;
}
fragment float4
fragmentShader ( RasterizerData
in [ [ stage_in
] ] ) { return in . color
;
}
二、創(chuàng)建C與OC的橋接文件
該頭文件的目的是為了c代碼與OC代碼可以共享與 shader 和 C 代碼 為了確保Metal Shader緩存區(qū)索引能夠匹配 Metal API Buffer 設(shè)置的集合調(diào)用
定義緩存區(qū)索引值,表示向metal著色器傳遞數(shù)據(jù)的入口枚舉值,相當于OpenGL ES中GLSL語言定義的頂點坐標入口position
typedef enum YDWVertexInputIndex
{ YDWVertexInputIndexVertices
= 0 , YDWVertexInputIndexViewportSize
= 1 ,
} YDWVertexInputIndex
;
定義圖形數(shù)據(jù)的結(jié)構(gòu)體,包含頂點和顏色值,類似于OpenGL ES中的頂點數(shù)據(jù)的結(jié)構(gòu)體
typedef struct { vector_float4 position
; vector_float4 color
;
} YDWVertex
;
三、initWithMetalKitView方法中需要加載metal文件
獲取GPU設(shè)備device 加載.metal著色器文件 配置用于創(chuàng)建管道狀態(tài)的管道描述符 同步創(chuàng)建并返回渲染管線狀態(tài)對象 創(chuàng)建命令隊列
- ( nonnull instancetype
) initWithMetalKitView
: ( nonnull MTKView
* ) mtkView
{ self = [ super init
] ; if ( self ) { NSError
* error
= NULL ; _device
= mtkView
. device
; id
< MTLLibrary
> defaultLibrary
= [ _device newDefaultLibrary
] ; id
< MTLFunction
> vertexFunction
= [ defaultLibrary newFunctionWithName
: @"vertexShader" ] ; id
< MTLFunction
> fragmentFunction
= [ defaultLibrary newFunctionWithName
: @"fragmentShader" ] ; MTLRenderPipelineDescriptor
* pipelineStateDescriptor
= [ [ MTLRenderPipelineDescriptor alloc
] init
] ; pipelineStateDescriptor
. label
= @"Simple Pipeline" ; pipelineStateDescriptor
. vertexFunction
= vertexFunction
; pipelineStateDescriptor
. fragmentFunction
= fragmentFunction
; pipelineStateDescriptor
. colorAttachments
[ 0 ] . pixelFormat
= mtkView
. colorPixelFormat
; _pipelineState
= [ _device newRenderPipelineStateWithDescriptor
: pipelineStateDescriptor error
: & error
] ; if ( ! _pipelineState
) { NSLog ( @"Failed to created pipeline state, error %@" , error
) ; return nil
; } _commandQueue
= [ _device newCommandQueue
] ; } return self ;
}
四、drawInMTKView方法中加載三角形數(shù)據(jù)
頂點數(shù)據(jù)/顏色數(shù)據(jù)
static const YDWVertex triangleVertices
[ ] = { { { 0.5 , - 0.25 , 0.0 , 1.0 } , { 1 , 0 , 0 , 1 } } , { { - 0.5 , - 0.25 , 0.0 , 1.0 } , { 0 , 1 , 0 , 1 } } , { { - 0.0f , 0.25 , 0.0 , 1.0 } , { 0 , 0 , 1 , 1 } } , } ;
為當前渲染的每個渲染傳遞創(chuàng)建一個新的命令緩沖區(qū)
id
< MTLCommandBuffer
> commandBuffer
= [ _commandQueue commandBuffer
] ; commandBuffer
. label
= @"MyCommand" ;
MTLRenderPassDescriptor
* renderPassDescriptor
= view
. currentRenderPassDescriptor
;
id
< MTLRenderCommandEncoder
> renderEncoder
= [ commandBuffer renderCommandEncoderWithDescriptor
: renderPassDescriptor
] ; renderEncoder
. label
= @"MyRenderEncoder" ;
設(shè)置我們繪制的可繪制區(qū)域: 視口指定Metal渲染內(nèi)容的drawable區(qū)域。 視口是具有x和y偏移,寬度和高度以及近和遠平面的3D區(qū)域。 為管道分配自定義視口需要通過調(diào)用setViewport:方法將MTLViewport結(jié)構(gòu)編碼為渲染命令編碼器。 如果未指定視口,Metal會設(shè)置一個默認視口,其大小與用于創(chuàng)建渲染命令編碼器的drawable相同。
MTLViewport viewPort
= { 0.0 , 0.0 , _viewportSize
. x
, _viewportSize
. y
, - 1.0 , 1.0 } ; [ renderEncoder setViewport
: viewPort
] ;
[ renderEncoder setRenderPipelineState
: _pipelineState
] ;
從應(yīng)用程序OC代碼中發(fā)送數(shù)據(jù)給 Metal 頂點著色器函數(shù) 頂點數(shù)據(jù)+顏色數(shù)據(jù): 指向要傳遞給著色器的內(nèi)存的指針, 想要傳遞的數(shù)據(jù)的內(nèi)存大小; 一個整數(shù)索引,它對應(yīng)于我們的“vertexShader”函數(shù)中的緩沖區(qū)屬性限定符的索引。
[ renderEncoder setVertexBytes
: triangleVerticeslength
: sizeof ( triangleVertices
) atIndex
: YDWVertexInputIndexVertices
] ;
[ renderEncoder setVertexBytes
: & _viewportSizelength
: sizeof ( _viewportSize
) atIndex
: YDWVertexInputIndexViewportSize
] ;
[ renderEncoder drawPrimitives
: MTLPrimitiveTypeTrianglevertexStart
: 0 vertexCount
: 3 ] ;
結(jié)束編碼: 表示已該編碼器生成的命令都已完成, 且從NTLCommandBuffer中分離
[ renderEncoder endEncoding
] ;
一旦框架緩沖區(qū)完成,使用當前可繪制的進度表
[ commandBuffer presentDrawable
: view
. currentDrawable
] ;
[ commandBuffer commit
] ;
效果展示
完整示例
Metal之基于世界坐標系下渲染繪制三角形
總結(jié)
以上是生活随笔 為你收集整理的Metal之渲染绘制三角形 的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔 推薦給好友。