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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Metal入门教程(二)三维变换

發布時間:2025/3/15 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Metal入门教程(二)三维变换 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

Metal入門教程(一)圖片繪制

上一篇的教程介紹了如何繪制一張圖片,這次的目標是把圖片顯示到3D物體上,并進行三維變換。

Metal系列教程的代碼地址;
OpenGL ES系列教程在這里;

你的star和fork是我的源動力,你的意見能讓我走得更遠。

正文

核心思路

在圖片繪制的基礎上,給頂點數據增加z坐標,并使用頂點的索引緩存;為了實現三維變換,給頂點shader增加投影矩陣和模型變換矩陣。

效果展示


具體細節

1、新建MTKView、設置渲染管道、設置紋理數據

同Metal入門教程(一)圖片繪制;

2、設置頂點數據
- (void)setupVertex {static const LYVertex quadVertices[] ={ // 頂點坐標 頂點顏色 紋理坐標{{-0.5f, 0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, 0.5f}, {0.0f, 1.0f}},//左上{{0.5f, 0.5f, 0.0f, 1.0f}, {0.0f, 0.5f, 0.0f}, {1.0f, 1.0f}},//右上{{-0.5f, -0.5f, 0.0f, 1.0f}, {0.5f, 0.0f, 1.0f}, {0.0f, 0.0f}},//左下{{0.5f, -0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, 0.5f}, {1.0f, 0.0f}},//右下{{0.0f, 0.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 1.0f}, {0.5f, 0.5f}},//頂點};self.vertices = [self.mtkView.device newBufferWithBytes:quadVerticeslength:sizeof(quadVertices)options:MTLResourceStorageModeShared];static int indices[] ={ // 索引0, 3, 2,0, 1, 3,0, 2, 4,0, 4, 1,2, 3, 4,1, 4, 3,};self.indexs = [self.mtkView.device newBufferWithBytes:indiceslength:sizeof(indices)options:MTLResourceStorageModeShared];self.indexCount = sizeof(indices) / sizeof(int); } 復制代碼

LYVertex由頂點坐標、頂點顏色、紋理坐標組成;
索引緩存的創建和頂點緩存的創建一樣,本質都是存放數據的緩存;

3、設置投影變換和模型變換矩陣
- (void)setupMatrixWithEncoder:(id<MTLRenderCommandEncoder>)renderEncoder {CGSize size = self.view.bounds.size;float aspect = fabs(size.width / size.height);GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(90.0), aspect, 0.1f, 10.f);GLKMatrix4 modelViewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0.0f, 0.0f, -2.0f);static float x = 0.0, y = 0.0, z = M_PI;if (self.rotationX.on) {x += self.slider.value;}if (self.rotationY.on) {y += self.slider.value;}if (self.rotationZ.on) {z += self.slider.value;}modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, x, 1, 0, 0);modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, y, 0, 1, 0);modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, z, 0, 0, 1);LYMatrix matrix = {[self getMetalMatrixFromGLKMatrix:projectionMatrix], [self getMetalMatrixFromGLKMatrix:modelViewMatrix]};[renderEncoder setVertexBytes:&matrixlength:sizeof(matrix)atIndex:LYVertexInputIndexMatrix]; } 復制代碼

projectionMatrix 是投影變換矩陣,modelViewMatrix是模型變換矩陣,為了方便理解,把繞x、y、z軸旋轉用三次GLKMatrix4Rotate實現。
沒有找到Metal和MetalKit快捷創建矩陣的方法,于是用了GLKit的方法進行創建,再通過getMetalMatrixFromGLKMatrix:方法進行轉換,方法如下:

/**找了很多文檔,都沒有發現metalKit或者simd相關的接口可以快捷創建矩陣的,于是只能從GLKit里面借力@param matrix GLKit的矩陣@return metal用的矩陣*/ - (matrix_float4x4)getMetalMatrixFromGLKMatrix:(GLKMatrix4)matrix {matrix_float4x4 ret = (matrix_float4x4){simd_make_float4(matrix.m00, matrix.m01, matrix.m02, matrix.m03),simd_make_float4(matrix.m10, matrix.m11, matrix.m12, matrix.m13),simd_make_float4(matrix.m20, matrix.m21, matrix.m22, matrix.m23),simd_make_float4(matrix.m30, matrix.m31, matrix.m32, matrix.m33),};return ret; } 復制代碼
4、具體渲染過程
id<MTLRenderCommandEncoder> renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];[renderEncoder setViewport:(MTLViewport){0.0, 0.0, self.viewportSize.x, self.viewportSize.y, -1.0, 1.0 }];[renderEncoder setRenderPipelineState:self.pipelineState];[self setupMatrixWithEncoder:renderEncoder];[renderEncoder setVertexBuffer:self.verticesoffset:0atIndex:LYVertexInputIndexVertices];[renderEncoder setFrontFacingWinding:MTLWindingCounterClockwise];[renderEncoder setCullMode:MTLCullModeBack]; 復制代碼

頂點數據設置的index參數使用了枚舉變量LYVertexInputIndexVertices,這樣可以保證和shader里面的索引對齊;
在設置完頂點數據后,還增加CullMode(剔除模式),MTLWindingCounterClockwise表示對順時針順序的三角形進行剔除。

5、Shader處理
vertex RasterizerData // 頂點 vertexShader(uint vertexID [[ vertex_id ]],constant LYVertex *vertexArray [[ buffer(LYVertexInputIndexVertices) ]],constant LYMatrix *matrix [[ buffer(LYVertexInputIndexMatrix) ]]) {RasterizerData out;out.clipSpacePosition = matrix->projectionMatrix * matrix->modelViewMatrix * vertexArray[vertexID].position;out.textureCoordinate = vertexArray[vertexID].textureCoordinate;out.pixelColor = vertexArray[vertexID].color;return out; }fragment float4 // 片元 samplingShader(RasterizerData input [[stage_in]],texture2d<half> textureColor [[ texture(LYFragmentInputIndexTexture) ]]) {constexpr sampler textureSampler (mag_filter::linear,min_filter::linear);// half4 colorTex = textureColor.sample(textureSampler, input.textureCoordinate);half4 colorTex = half4(input.pixelColor.x, input.pixelColor.y, input.pixelColor.z, 1);return float4(colorTex); } 復制代碼

頂點shader的buffer的修飾符有LYVertexInputIndexVertices和LYVertexInputIndexMatrix,與業務層的枚舉變量一致;
在計算頂點坐標的時候,增加了projectionMatrix 和 modelViewMatrix的處理;

片元shader的texture的修飾符是LYFragmentInputIndexTexture;
嘗試把從圖片讀取顏色的代碼屏蔽,使用上面的代碼,可以得到頂點顏色的顯示結果;

總結

Metal的三維變換與OpenGL ES一樣,重點是如何初始化矩陣,并且把矩陣傳遞給頂點shader;同時Metal的Shader有語法檢測,使用枚舉變量能在編譯階段就定位到問題。

這里可以下載demo代碼。


轉載于:https://juejin.im/post/5b40bebe6fb9a04f844aaa49

總結

以上是生活随笔為你收集整理的Metal入门教程(二)三维变换的全部內容,希望文章能夠幫你解決所遇到的問題。

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