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入门教程(二)三维变换相关推荐
- python elasticsearch 入门教程(二) ---全文搜索
python elasticsearch 入门教程(二) ---全文搜索 截止目前的搜索相对都很简单:单个姓名,通过年龄过滤.现在尝试下稍微高级点儿的全文搜索--一项 传统数据库确实很难搞定的任务. ...
- R语言七天入门教程二:认识变量与运算符
R语言七天入门教程二:认识变量与运算符 一.什么是变量 1.变量 顾名思义,我们可以将变量理解为"可以改变的量",是计算机语言中能储存计算结果或能表示值的抽象概念.这里的值可以是数 ...
- (转)tensorflow入门教程(二十六)人脸识别(上)
https://blog.csdn.net/rookie_wei/article/details/81676177 1.概述 查看全文 http://www.taodudu.cc/news/show- ...
- Android WebRTC 入门教程(二) -- 模拟p2p本地视频传输
Android WebRTC 入门教程(一) – 使用相机 Android WebRTC 入门教程(二) – 模拟p2p本地视频传输 源码工程: https://github.com/LillteZh ...
- LittleVGL (LVGL)干货入门教程二之LVGL的输入设备(indev)API对接。
LittleVGL (LVGL)干货入门教程二之LVGL的输入设备(indev)API对接 前言: 阅读前,请确保你拥有以下条件: 你已经完成"显示API"的移植. 你已经实现了一 ...
- c语言类似于 n的标识符,C语言快速入门教程(二)
C语言快速入门教程(二) C语言的基本语法 本节学习路线图: 引言: C语言,顾名思义就是一门语言,可以类比一下英语; 你要说出一个英语的句子需要: 单词 + 语法! 将单词按照一定的语法拼凑起来就成 ...
- 微信小程序云开发 初学者入门教程二
微信小程序云开发 初学者入门教程二-前端操作数据库模块 如何操作数据库,作为一名前端,如果对数据的知识不够熟悉也没关系,从现在开始好好学习就行,数据库的操作内容差不多涉及增删改查四大模块,花一些业余的 ...
- python爬虫入门教程(二):开始一个简单的爬虫
2019/10/28更新 使用Python3,而不再是Python2 转载请注明出处:https://blog.csdn.net/aaronjny/article/details/77945329 爬 ...
- quarkus 入门教程(二) -项目开发模式热更新及项目断点调试方法
quarkus 入门教程(二) -项目断点调试方法 1.项目热更新 quarkus:dev runs 方式启动,项目会以开发者模式启动,当修改了java文件或者resource文件后,项目会在后台编译 ...
最新文章
- VRPM包安装失败解决方案:had non-zero exit status
- Win7和Win10安装VC6.0注意事项
- python计算直角三角形顶点坐标
- elasticsearch 二、elasticsearch-head安装
- 深度学习笔记(25) 池化层
- L1-039 古风排版 (20 分)—团体程序设计天梯赛
- scipy.optimize.curve_fit
- 大工《电机与拖动实验》实验报告离线作业
- Arcgis专题制图流程
- JS实现类似打字的特效,JS实现打字效果
- BladeX框架源码分析--00、包结构
- 数据分析神经网络模型图,神经网络模型数据处理
- ceph BALANCER
- 智能家居雷达模块应用,毫米波雷达传感器,雷达感应技术应用
- Win10 易升更新 安装wls2 部署docker
- 量化投资学习——股票价格估值模型
- 第三次实验报告MapReduce
- Usb 声卡 linux,树莓派:使用usb声卡播放音乐
- HTML/CSS 知识点解析
- 第一章笔记MySQL数据库的安装目录详解