Metal lineStrip:如何画出更粗的线条?

问题描述 投票:0回答:1

我正在使用 Xcode 14.2 开发一个 iOS 应用程序,我的部署目标是 iOS 16.2。我有一个 X、Y 和 Z 值列表,我想使用 lineStrip 用 Metal 绘制这些值。这行得通。但是,绘制的线对于我的目的来说太细了。我已经阅读了有关如何加粗线条的各种策略,并且我决定尝试多次迭代地绘制同一条线,每次都使用少量噪音来呈现更粗的线条。

我每次通过渲染循环生成 3 个随机浮点数,并使用 uniform 将它们发送到我的顶点着色器。问题是生成的线似乎比随机线更具周期性,而且更多的迭代似乎并没有给出更粗线的外观。

如何使用此策略绘制更粗的线条?

绘制多次迭代:

// 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;
ios swift metal metalkit
1个回答
0
投票

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

  • 画多条相邻的线,足够近,不会有间隙。
  • 使用
    triangleStrip
    而不是
    lineStrip
    .

你需要记住,金属线是一个像素厚。因此,对于线条粗细的每一个额外像素,您都需要一条新的、紧邻的线条。我不依赖于随机性,而是在每次迭代时简单地向直线添加/减去一个像素,以一种垂直于直线方向的方式。我还会根据屏幕尺寸设置迭代次数。

您可以将迭代次数设置为屏幕宽度或高度(取决于线条是垂直还是水平)除以所需的线条粗细。您还可以将像素大小(屏幕大小的 1)传递给顶点着色器,在那里您可以将线偏移像素大小乘以相关线的迭代次数。

或者,你可以放弃画一个

lineStrip
的想法,而是画一个
triangleStrip
。这个解决方案可能比以稍微不同的偏移量多次绘制线更有效。

要实现这一点,您将复制线中的每个顶点(1 条额外的线而不是无数条线),并在垂直于线本身的方向上将其偏移所需的厚度。然后你会用

drawPrimitives()
而不是
type: .triangleStrip
来调用
type: .lineStrip
。新顶点将与旧顶点交错,而不是紧随其后。

© www.soinside.com 2019 - 2024. All rights reserved.