金属线条:如何绘制更粗的线条?

3
我正在使用Xcode 14.2开发iOS应用程序,我的部署目标是iOS 16.2。我有一组X、Y和Z值,想要使用Metal的lineStrip绘制。这个方法可行。但是,绘制出来的线条对于我的目的来说太细了。我已经阅读了关于如何加粗线条的各种策略,并决定尝试多次绘制相同的线条,每次都加入少量噪音,以呈现出更粗的线条外观。
我在渲染循环中每次生成3个随机浮点数,并将它们作为uniform发送到我的顶点着色器。问题是,结果线条似乎比随机更周期性,而且更多的迭代并没有使线条看起来更粗。
如何使用这种策略绘制更粗的线条?

enter image description here enter image description here

绘制多个迭代:

// 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)

顶点 Uniform:

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;
1个回答

3

要生成更粗的线条,您可以选择以下两种方法:

  • 绘制多个相邻的线条,距离足够接近以避免出现间隙。
  • 使用triangleStrip而不是lineStrip

需要记住的是,Metal线条的厚度为一个像素。因此,对于每增加一个像素的线条厚度,您都需要一个新的、紧贴的线条。我建议不要依赖随机性,而是在每次迭代中简单地添加/减去一像素的线条,以与线条方向垂直的方式进行。我还会使迭代次数取决于屏幕大小。

您可以将迭代次数设置为屏幕宽度或高度(取决于线条是垂直还是水平),除以所需线条的厚度。您还可以将像素大小(屏幕大小的倒数)传递到顶点着色器中,在那里您将通过像素大小乘以所讨论的线条的迭代次数来偏移线条。

或者,您可以放弃绘制lineStrip的想法,改为绘制triangleStrip。这种解决方案可能比在略微不同的偏移量下多次绘制线条要高效得多。

为了实现这个,你需要复制线上的每个顶点(而不是无数条线),并将其沿着垂直于线本身的方向偏移所需的厚度。然后,你需要使用type: .triangleStrip而不是type: .lineStrip调用drawPrimitives()。新的顶点将与旧的顶点交错而不是在它们之后出现。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接