日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Metal之渲染绘制三角形

發布時間:2024/5/21 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Metal之渲染绘制三角形 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

準備工作

  • Metal渲染的構建流程, 請參考:Metal之簡單渲染動態切換屏幕顏色
  • Metal三角形的渲染顯示與渲染構建流程大體一致, 本文主要介紹以下方面的修改和實現:
    ① metal渲染文件
    ② 創建C 與 OC 的橋接函數
    ③ initWithMetalKitView方法中需要加載metal文件
    ④ drawInMTKView方法中加載三角形數據
  • Metal三角形的渲染顯示是基于世界坐標系下。

渲染流程

一、metal渲染文件
  • command + N --> Metal File 創建metal著色器文件, 新建metal文件:YDWShaders.metal

  • 定義頂點著色器輸入和片元著色器輸入,相當于OpenGL ES中的varying修飾的變量,即橋接變量;
// 頂點著色器輸出和片段著色器輸入 // 結構體 typedef struct {// 處理空間的頂點信息float4 clipSpacePosition [[position]];// 顏色float4 color;} RasterizerData;
  • 定義頂點著色器函數和片元著色器函數:
    ① 處理頂點數據: 執行坐標系轉換,將生成的頂點剪輯空間寫入到返回值中; 將頂點顏色值傳遞給返回值;
    ② 初始化輸出剪輯空間位置: 索引到我們的數組位置以獲得當前頂點, 我們的位置是在像素維度中指定的, 每個頂點著色器的輸出位置在剪輯空間中(也稱為歸一化設備坐標空間,NDC),剪輯空間中的(-1,-1)表示視口的左下角,而(1,1)表示視口的右上角, 計算和寫入 XY值到我們的剪輯空間的位置.為了從像素空間中的位置轉換到剪輯空間的位置,我們將像素坐標除以視口的大小的一半;
    ③ 把輸入的顏色直接賦值給輸出顏色, 這個值將于構成三角形的頂點的其他顏色值插值, 從而為片段著色器中的每個片段生成顏色值;
//頂點著色器函數 /*vertex:修飾符,表示是頂點著色器RasterizerData:返回值vertexShader:函數名稱,可自定義vertexID:metal自己反饋的idvertices:1)告訴存儲的位置buffer 2)告訴傳遞數據的入口是CJLVertexInputIndexVerticesvertices 和 viewportSizePointer 都是通過CJLRenderer 傳遞進來的*/ vertex RasterizerData vertexShader(uint vertexID [[vertex_id]],constant CJLVertex *vertices [[buffer(CJLVertexInputIndexVertices)]],constant vector_uint2 *viewportSizePointer [[buffer(CJLVertexInputIndexViewportSize)]]) {// 定義outRasterizerData out; // 初始化輸出剪輯空間位置out.clipSpacePosition = vertices[vertexID].position;// 把輸入的顏色直接賦值給輸出顏色. 這個值將于構成三角形的頂點的其他顏色值插值,從而為片段著色器中的每個片段生成顏色值out.color = vertices[vertexID].color;// 完成,將結構體傳遞到管道中下一個階段return out; }/*fragment:修飾符,表示是片元著色器float4:返回值,即顏色值RGBAfragmentShader:函數名稱,可自定義RasterizerData:參數類型(可修改)in:形參變量(可修改)[[stage_in]]:屬性修飾符,表示單個片元輸入(由定點函數輸出)(不可修改),相當于OpenGL ES中的varying*/ fragment float4 fragmentShader(RasterizerData in [[stage_in]]) {// 返回輸入的片元顏色return in.color; }
二、創建C與OC的橋接文件

該頭文件的目的是為了c代碼與OC代碼可以共享與 shader 和 C 代碼 為了確保Metal Shader緩存區索引能夠匹配 Metal API Buffer 設置的集合調用

  • 定義緩存區索引值,表示向metal著色器傳遞數據的入口枚舉值,相當于OpenGL ES中GLSL語言定義的頂點坐標入口position
// 緩存區索引值 共享與shader和C代碼, 為了確保Metal Shader緩存區索引能夠匹配 Metal API Buffer 設置的集合調用 typedef enum YDWVertexInputIndex {// 頂點YDWVertexInputIndexVertices = 0,// 視圖大小YDWVertexInputIndexViewportSize = 1, } YDWVertexInputIndex;
  • 定義圖形數據的結構體,包含頂點和顏色值,類似于OpenGL ES中的頂點數據的結構體
// 結構體: 頂點/顏色值 typedef struct {// 像素空間的位置// 像素中心點(100,100)vector_float4 position;// RGBA顏色vector_float4 color; } YDWVertex;
三、initWithMetalKitView方法中需要加載metal文件
  • 獲取GPU設備device
  • 加載.metal著色器文件
  • 配置用于創建管道狀態的管道描述符
  • 同步創建并返回渲染管線狀態對象
  • 創建命令隊列
// 初始化MTKView- (nonnull instancetype)initWithMetalKitView:(nonnull MTKView *)mtkView {self = [super init];if(self) {NSError *error = NULL;// 獲取GPU 設備_device = mtkView.device;// 在項目中加載所有的(.metal)著色器文件// 從bundle中獲取.metal文件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方法中加載三角形數據
  • 頂點數據/顏色數據
// 頂點數據/顏色數據static const YDWVertex triangleVertices[] = {// 頂點, RGBA 顏色值{ { 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 } },};
  • 為當前渲染的每個渲染傳遞創建一個新的命令緩沖區
// 為當前渲染的每個渲染傳遞創建一個新的命令緩沖區id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];// 指定緩存區名稱commandBuffer.label = @"MyCommand";
  • 創建命令描述符
MTLRenderPassDescriptor *renderPassDescriptor = view.currentRenderPassDescriptor;
  • 創建渲染命令編碼器
// 創建渲染命令編碼器,這樣才可以渲染到somethingid<MTLRenderCommandEncoder> renderEncoder =[commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];// 渲染器名稱renderEncoder.label = @"MyRenderEncoder";
  • 設置我們繪制的可繪制區域:
    視口指定Metal渲染內容的drawable區域。 視口是具有x和y偏移,寬度和高度以及近和遠平面的3D區域。
    為管道分配自定義視口需要通過調用setViewport:方法將MTLViewport結構編碼為渲染命令編碼器。 如果未指定視口,Metal會設置一個默認視口,其大小與用于創建渲染命令編碼器的drawable相同。
MTLViewport viewPort = {0.0,0.0,_viewportSize.x,_viewportSize.y,-1.0,1.0};[renderEncoder setViewport:viewPort];
  • 設置當前渲染管道狀態對象
[renderEncoder setRenderPipelineState:_pipelineState];
  • 從應用程序OC代碼中發送數據給 Metal 頂點著色器函數
    頂點數據+顏色數據: 指向要傳遞給著色器的內存的指針, 想要傳遞的數據的內存大小;
    一個整數索引,它對應于我們的“vertexShader”函數中的緩沖區屬性限定符的索引。
// 指向要傳遞給著色器的內存的指針 // 想要傳遞的數據的內存大小 // 一個整數索引,它對應于“vertexShader”函數中的緩沖區屬性限定符的索引 [renderEncoder setVertexBytes:triangleVerticeslength:sizeof(triangleVertices)atIndex:YDWVertexInputIndexVertices];// 發送到頂點著色函數中,視圖大小// 視圖大小內存空間大小// 對應的索引 [renderEncoder setVertexBytes:&_viewportSizelength:sizeof(_viewportSize)atIndex:YDWVertexInputIndexViewportSize];
  • 畫出三角形的3個頂點:
// @method drawPrimitives:vertexStart:vertexCount:// @brief 在不使用索引列表的情況下,繪制圖元// @param 繪制圖形組裝的基元類型// @param 從哪個位置數據開始繪制,一般為0// @param 每個圖元的頂點個數,繪制的圖型頂點數量/*MTLPrimitiveTypePoint = 0, 點MTLPrimitiveTypeLine = 1, 線段MTLPrimitiveTypeLineStrip = 2, 線環MTLPrimitiveTypeTriangle = 3, 三角形MTLPrimitiveTypeTriangleStrip = 4, 三角型扇*/[renderEncoder drawPrimitives:MTLPrimitiveTypeTrianglevertexStart:0vertexCount:3];
  • 結束編碼: 表示已該編碼器生成的命令都已完成, 且從NTLCommandBuffer中分離
[renderEncoder endEncoding];
  • 一旦框架緩沖區完成,使用當前可繪制的進度表
[commandBuffer presentDrawable:view.currentDrawable];
  • 命令緩沖區提交GPU進行顯示
[commandBuffer commit];

效果展示

完整示例

Metal之基于世界坐標系下渲染繪制三角形

總結

以上是生活随笔為你收集整理的Metal之渲染绘制三角形的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。