前言

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的修饰符有LYVertexInputIndexVerticesLYVertexInputIndexMatrix,与业务层的枚举变量一致;
在计算顶点坐标的时候,增加了projectionMatrixmodelViewMatrix的处理;

片元shader的texture的修饰符是LYFragmentInputIndexTexture
尝试把从图片读取颜色的代码屏蔽,使用上面的代码,可以得到顶点颜色的显示结果;

总结

Metal的三维变换与OpenGL ES一样,重点是如何初始化矩阵,并且把矩阵传递给顶点shader;同时Metal的Shader有语法检测,使用枚举变量能在编译阶段就定位到问题。

这里可以下载demo代码。

转载于:https://juejin.im/post/5b40bebe6fb9a04f844aaa49

Metal入门教程(二)三维变换相关推荐

  1. python elasticsearch 入门教程(二) ---全文搜索

    python elasticsearch 入门教程(二) ---全文搜索 截止目前的搜索相对都很简单:单个姓名,通过年龄过滤.现在尝试下稍微高级点儿的全文搜索--一项 传统数据库确实很难搞定的任务. ...

  2. R语言七天入门教程二:认识变量与运算符

    R语言七天入门教程二:认识变量与运算符 一.什么是变量 1.变量 顾名思义,我们可以将变量理解为"可以改变的量",是计算机语言中能储存计算结果或能表示值的抽象概念.这里的值可以是数 ...

  3. (转)tensorflow入门教程(二十六)人脸识别(上)

    https://blog.csdn.net/rookie_wei/article/details/81676177 1.概述 查看全文 http://www.taodudu.cc/news/show- ...

  4. Android WebRTC 入门教程(二) -- 模拟p2p本地视频传输

    Android WebRTC 入门教程(一) – 使用相机 Android WebRTC 入门教程(二) – 模拟p2p本地视频传输 源码工程: https://github.com/LillteZh ...

  5. LittleVGL (LVGL)干货入门教程二之LVGL的输入设备(indev)API对接。

    LittleVGL (LVGL)干货入门教程二之LVGL的输入设备(indev)API对接 前言: 阅读前,请确保你拥有以下条件: 你已经完成"显示API"的移植. 你已经实现了一 ...

  6. c语言类似于 n的标识符,C语言快速入门教程(二)

    C语言快速入门教程(二) C语言的基本语法 本节学习路线图: 引言: C语言,顾名思义就是一门语言,可以类比一下英语; 你要说出一个英语的句子需要: 单词 + 语法! 将单词按照一定的语法拼凑起来就成 ...

  7. 微信小程序云开发 初学者入门教程二

    微信小程序云开发 初学者入门教程二-前端操作数据库模块 如何操作数据库,作为一名前端,如果对数据的知识不够熟悉也没关系,从现在开始好好学习就行,数据库的操作内容差不多涉及增删改查四大模块,花一些业余的 ...

  8. python爬虫入门教程(二):开始一个简单的爬虫

    2019/10/28更新 使用Python3,而不再是Python2 转载请注明出处:https://blog.csdn.net/aaronjny/article/details/77945329 爬 ...

  9. quarkus 入门教程(二) -项目开发模式热更新及项目断点调试方法

    quarkus 入门教程(二) -项目断点调试方法 1.项目热更新 quarkus:dev runs 方式启动,项目会以开发者模式启动,当修改了java文件或者resource文件后,项目会在后台编译 ...

最新文章

  1. VRPM包安装失败解决方案:had non-zero exit status
  2. Win7和Win10安装VC6.0注意事项
  3. python计算直角三角形顶点坐标
  4. elasticsearch 二、elasticsearch-head安装
  5. 深度学习笔记(25) 池化层
  6. L1-039 古风排版 (20 分)—团体程序设计天梯赛
  7. scipy.optimize.curve_fit
  8. 大工《电机与拖动实验》实验报告离线作业
  9. Arcgis专题制图流程
  10. JS实现类似打字的特效,JS实现打字效果
  11. BladeX框架源码分析--00、包结构
  12. 数据分析神经网络模型图,神经网络模型数据处理
  13. ceph BALANCER
  14. 智能家居雷达模块应用,毫米波雷达传感器,雷达感应技术应用
  15. Win10 易升更新 安装wls2 部署docker
  16. 量化投资学习——股票价格估值模型
  17. 第三次实验报告MapReduce
  18. Usb 声卡 linux,树莓派:使用usb声卡播放音乐
  19. HTML/CSS 知识点解析
  20. 第一章笔记MySQL数据库的安装目录详解

热门文章

  1. EF – 8.多对多关联
  2. java位运算(转)
  3. 隐藏文字的另一种方法
  4. Think in Java之斐波那契数列
  5. silverlight动态创建WCF服务
  6. 1562区别 洛达1552_洛达1562A与洛达1536u与杰里有哪些区别呢?
  7. 如何升级成鸿蒙,如何将自己的华为手机升级成鸿蒙系统
  8. python rpc webservice_关于RPC、HTTP、WebService的区别
  9. lnmp环境搭建完全手册(四)——lnmp搭建(源码安装)
  10. HiveQL中如何排查数据倾斜问题