学习ios Metal(3)—宽度可调的线条的绘制

metal的基础知识入门,首推Metal By Example系列:http://metalbyexample.com/。博主的相关文章,主要给出工程实际遇到的典型问题及其解决方案。
学习ios Metal(3)—宽度可调的线条的绘制
文章图片

本节源码:https://github.com/sjy234sjy234/Learn-Metal/tree/master/MetalLine。
根据苹果官方的说法,metal是一个底层的图形API,因此它与opengles不同,没有提供任何上层封装的常用功能的实现。其中绘制有宽度的线条,在opengles是内置支持的,但是metal内置并不支持。如上一节所说,MTLPrimitiveType中包含MTLPrimitiveTypeLine类型,但是调用drawPrimitives进行线条绘制时,只能得到固定宽度为1pixel的线条,不能进行宽度调整:https://github.com/sjy234sjy234/Learn-Metal/tree/master/MetalLinePrimitive。下面给出一种利用矩形模拟有宽度的线条的方法进行宽度可调的线条的绘制。
首先介绍一下原理,会涉及到一点点的几何数学。假设在二维平面上,需要绘制宽度为W的线段P1P2,其中P1(x1, y1)、P2(x2, y2)坐标已知,宽度W已知。如图所示,只需要绘制两个实心的三角形PaPbPc和PaPcPd即可。
学习ios Metal(3)—宽度可调的线条的绘制
文章图片

代码中实现计算Pa, Pb, Pc, Pd这4个点时,采用了向量的方式:

float thickness=0 float4 position1=vertices[lineIndex1].position; float4 position2=vertices[lineIndex2].position; .02; float4 v = position2 - position1; float2 p0 = float2(position1.x,position1.y); float2 v0 = float2(v.x,v.y); float2 v1 = thickness * normalize(v0) * float2x2(float2(0,-1),float2(1,0)); float2 pa = p0 + v1; float2 pb = p0 - v1; float2 pc = p0 - v1 + v0; float2 pd = p0 + v1 + v0;

参见博主给出的源码,每一条线段可以看成一个绘制的实例,每个绘制实例由2个三角形构成,下面是对于每个实例,根据vertex_main中传入的vid(0~5)来确定具体要传递给fragment_main的是Pa, Pb, Pc, Pd中的哪一个点。即每条宽线段是由2个三角形、4个点和6个index(vid)来解释的,需要对实例的绘制有所理解。
Vertex outVertex; switch(vid) { case 0: outVertex.position = float4(pa.x,pa.y,position1.z,position1.w); break; case 1: outVertex.position = float4(pb.x,pb.y,position1.z,position1.w); break; case 2: outVertex.position = float4(pc.x,pc.y,position2.z,position2.w); break; case 3: outVertex.position = float4(pa.x,pa.y,position1.z,position1.w); break; case 4: outVertex.position = float4(pc.x,pc.y,position2.z,position2.w); break; case 5: outVertex.position = float4(pd.x,pd.y,position2.z,position2.w); break; }outVertex.color={1.0,0.0,0.0,1.0}; return outVertex;

【学习ios Metal(3)—宽度可调的线条的绘制】PS:关于实例绘制的基础请参考:http://metalbyexample.com/的第11章。demo中给出的是直接在ndc坐标系中绘制的直线,具体到绘制三维模型的线框图的实现时,既要考虑遮挡关系,又要考虑正反面,博主会在后续给出三维模型的线框图的渲染实现。

    推荐阅读