swift 金属线带:如何画粗线?

uqzxnwby  于 2023-03-28  发布在  Swift
关注(0)|答案(1)|浏览(95)

我正在使用Xcode14.2开发一个iOS应用,而我的部署目标是iOS16.2,我有一个X、Y、Z值的列表,我想使用lineStrip用Metal绘制这些值,这样就可以了,不过这条线对我的目的来说太细了。我读过关于如何加粗这条线的各种策略,我我决定尝试绘制同一条线多次迭代,每次使用少量的噪声,以给予线看起来更粗。
我每次通过渲染循环生成3个随机浮点数,并将它们发送到我的顶点着色器,问题是,结果线似乎比随机更周期性,更多的迭代似乎并没有给予更粗的线的外观。
如何使用此策略绘制较粗的线条?
第一节第一节第一节第一节第一次
绘制多个迭代:

// Draw many iterations
for iteration in 1...1024 {
    scene.track?.draw(encoder: commandEncoder,
                      modelMatrix: accumulatedRotationMatrix,
                      projectionMatrix: projectionMatrix * viewMatrix,
                      secondsInEpoch: Float(self.epochTime))
}

随机浮动:

var jitter = 1.0 / Float(self.screenSizeX) - 1 / Float(self.screenSizeY)
var jitterX = Float.random(in: -jitter...jitter)
var jitterY = Float.random(in: -jitter...jitter)
var jitterZ = Float.random(in: -jitter...jitter)

顶点均匀:

struct VertexUniforms {
    
    var viewProjectionMatrix: float4x4
    var modelMatrix: float4x4
    var normalMatrix: float3x3
    var jitterX: Float
    var jitterY: Float
    var jitterZ: Float
    var iteration: Float
}

绘制基本体调用:

encoder.drawPrimitives(type: .lineStrip , vertexStart: 0, vertexCount: vertices.count / 3)

顶点着色器:

// Calculate the jitter for X/Y/Z
//float subFactor = 0.0099;
float subFactor = 0.0105;
float smallFactorX = (subFactor * uniforms.jitterX);
float smallFactorY = (subFactor * uniforms.jitterY);
float smallFactorZ = (subFactor * uniforms.jitterZ);
if (vertexId % 2 == 0) {
    vertexOut.position.x += (vertexOut.position.x * smallFactorX);
    vertexOut.position.y += (vertexOut.position.y * smallFactorY);
    vertexOut.position.z += (vertexOut.position.z * smallFactorZ);
} else {
    vertexOut.position.x -= (vertexOut.position.x * smallFactorX);
    vertexOut.position.y -= (vertexOut.position.y * smallFactorY);
    vertexOut.position.z -= (vertexOut.position.z * smallFactorZ);
}

return vertexOut;
41zrol4v

41zrol4v1#

要生成较粗的线,您可以:

  • 绘制多条相邻的线,要足够靠近,以免出现间隙。
  • 使用triangleStrip而不是lineStrip

你需要记住,金属线是一个像素厚。因此,对于每一个额外的像素线厚度,你将需要一个新的,直接相邻的线。而不是依赖于随机性,我会简单地增加/减少一个像素的线,在每次迭代,在一种垂直于线的方向。我也会使迭代的数量视屏幕大小而定。
你可以将迭代次数设置为屏幕宽度或高度(取决于线条是垂直还是水平)除以所需的线条厚度。你也可以将像素大小(屏幕大小的1倍)传递给顶点着色器,在那里你将通过像素大小乘以所讨论的线条的迭代次数来偏移线条。
或者,您可以放弃绘制lineStrip的想法,而是绘制triangleStrip。这种解决方案可能比以略微不同的偏移量绘制大量线条更有效。
为了实现这个,你需要复制这条线上的每个顶点(额外的一条线,而不是无数条线),并在垂直于线本身的方向上将其偏移所需的厚度。然后你需要调用drawPrimitives(),使用type: .triangleStrip而不是type: .lineStrip。新的顶点将与旧的顶点交错,而不是在它们之后。

相关问题