【问题标题】:Stroke Width with a SceneKit line primitive type具有 SceneKit 线图元类型的笔画宽度
【发布时间】:2014-12-29 13:59:05
【问题描述】:

我正在尝试使用场景工具包复制这个立方体图像形状(经original creator 许可)。

到目前为止,我已经有了线条和顶点的绘图代码。我不能使用图片,因为背景必须是透明的。

我现在要解决的具体问题是如何编辑SCNGeometryPrimitiveType.Line 元素的笔画宽度。

我创建线条的基本方式是这样的:

private func squareVertices(length: Float) -> [SCNVector3] {
    let m = length/Float(2)

    let topLeft =       SCNVector3Make(-m-q,  m+q, m+q)
    let topRight =      SCNVector3Make( m+q,  m+q, m+q)
    let bottomLeft =    SCNVector3Make(-m-q, -m-q, m+q)
    let bottomRight =   SCNVector3Make( m+q, -m-q, m+q)

    return [topLeft, topRight, bottomLeft, bottomRight]
}

private func cubeFace() -> SCNGeometry {

    let vertices : [SCNVector3] = squareVertices(l)
    let geoSrc = SCNGeometrySource(vertices: UnsafePointer<SCNVector3>(vertices), count: vertices.count)

    // index buffer
    let idx1 : [Int32] = [0, 3]
    let data1 = NSData(bytes: idx1, length: (sizeof(Int32) * idx1.count))
    let geoElements1 = SCNGeometryElement(data: data1, primitiveType: SCNGeometryPrimitiveType.Line, primitiveCount: idx1.count, bytesPerIndex: sizeof(Int32))

    let idx2 : [Int32] = [1, 2]
    let data2 = NSData(bytes: idx2, length: (sizeof(Int32) * idx2.count))
    let geoElements2 = SCNGeometryElement(data: data2, primitiveType: SCNGeometryPrimitiveType.Line, primitiveCount: idx2.count, bytesPerIndex: sizeof(Int32))

    let geo = SCNGeometry(sources: [geoSrc], elements: [geoElements1, geoElements2])

    return geo
}

    private func setupFaceNodes() {
    // sides
    for i in 0..<4 {
        let face = SCNNode(geometry: cubeFace())
        face.rotation = SCNVector4Make(0, 1, 0, Float(i) * Float(M_PI_2))
        rootNode.addChildNode(face)
    }
    // top/bottom
    for i in [1, 3] {
        let face = SCNNode(geometry: cubeFace())
        face.rotation = SCNVector4Make(1, 0, 0, Float(i) * Float(M_PI_2))
        rootNode.addChildNode(face)
    }
}

我有一些看起来像这样的东西,整体形状正确:

但我不知道如何增加使用 SceneKit 绘制的线条的宽度。我怎样才能做到这一点?

对于那些感兴趣的人,here 是一个示例项目。

【问题讨论】:

    标签: ios swift drawing scenekit scnnode


    【解决方案1】:

    SceneKit 不为此提供控件。但是,SceneKit 使用 OpenGL ES 进行绘制。

    当您在GL_LINES 模式下使用 GL 绘图时,glLineWidth 调用会更改线宽。 (注意:参数是实际像素,而不是 UI 布局点,因此如果您不希望 Retina 显示屏上出现超细细线,则需要比您想象的更大的宽度。)

    那么,您在 SceneKit 应用程序中的哪个位置调用它?你有几个选择。在像您这样的简单场景中,您只渲染一件事,您可以在场景渲染之前设置它。为您的视图设置delegate,然后实现renderer:willRenderSceneAtTime: 并在那里调用glLineWidth

    但是,OpenGL 线渲染非常有限——如果您想要更多地自定义渲染,您将需要一种不同的方法。哪种方法最有效取决于您的具体目标,因此这里有一些想法供您研究:

    • 用窄三角形条制作“线条”
    • 从原始 SCN 几何形状(如盒子和圆柱体)制作它们
    • 保持简单的立方体几何形状,但使用片段着色器(或着色器修改器 sn-p)仅在每个多边形的边缘附近绘制

    【讨论】:

    • “保持简单的立方体几何形状,但使用片段着色器(或着色器修改器 sn-p)仅在每个多边形的边缘附近绘制”您将如何使用片段着色器来做到这一点?用着色器绘制线框的问题不是更难解决吗? Wireframe shader
    • 它可以更复杂,但也允许更大的灵活性——例如模糊/发光的边缘。并且根据您的需要,您不需要将另一个属性(SceneKit 中的几何源)传递到重心坐标的管道中——如果您想突出显示四边形的边缘,请忘记它实际上是两个三角形,只需查看特克斯库兹。 (假设您的 texcoords 设置为跟随四边形。)
    • 我尝试了这种方法,在委托方法中添加 glLineWidth 调用,它适用于模拟器,但对设备没有影响。你们见过同样的行为吗?奇怪的是,如果我直接使用 GLES 而不是 SceneKit,我可以让 glLineWidth 在设备上使用相当粗的线条。
    • @eddy:SceneKit 甚至在您的设备上使用 GL 渲染器吗? glLineWidth 对 Metal 没有任何作用(也没有 Metal 等价物)。
    • glLineWidth 也因设备而异。我在 iOS 上从来没有遇到过任何运气,所以我放弃了它。
    【解决方案2】:

    您可以使用glLineWidth 设置线宽。
    确保在您的项目中包含 OpenGLES。

    这是你的立方体在线宽设置为 8 时的样子。

    【讨论】:

      猜你喜欢
      • 2021-07-23
      • 1970-01-01
      • 1970-01-01
      • 2014-04-13
      • 1970-01-01
      • 2015-05-30
      • 2013-03-08
      • 2013-04-01
      • 1970-01-01
      相关资源
      最近更新 更多