如何在 SKShapeNode 中绘制渐变?

Posted

技术标签:

【中文标题】如何在 SKShapeNode 中绘制渐变?【英文标题】:How to draw gradient in SKShapeNode? 【发布时间】:2021-12-22 20:00:35 【问题描述】:

我正在尝试在 SKShapeNode 对象中绘制渐变。

我使用 alpha 分量绘制了一个带有颜色的三角形,它工作正常。我想添加渐变,使三角形的一个边缘慢慢消失到背景中。我想要实现的是模拟角色的视线范围。

我找到了一个关于这个挑战的答案:How to apply a gradient to SKShapeNode created from a path,但答案在 XCode 13.1 中不起作用。 原因是无法编译添加SKTexture的建议解决方案:

var testTexture = SKTexture(size: CGSize(width: 200, height: 1), color1: CIColor(red: 1.0, green: 0.0, blue: 1.0, alpha: 1.0), color2: CIColor(red: 1.0, green: 0.0, blue: 1.0, alpha: 0.0), direction: GradientDirection.Left)

它会导致错误“在范围内找不到'GradientDirection'...”。而且我找不到任何其他添加渐变的方法。

我找到了另一个答案,它说这是不可能的,但它是从 2013 年开始的,所以可能发生了一些变化 (How to create a Gradient in Spritekit?)。

我也尝试了这个解决方案:https://augmentedcode.io/2017/11/12/drawing-gradients-in-spritekit/,但它不会产生任何效果并降低应用程序的性能。

【问题讨论】:

【参考方案1】:

来自互联网的一些来源将我定向到 OpenGL 着色语言:https://www.khronos.org/opengl/wiki/Core_Language_(GLSL)。

这里是部分解决方案:

let sight = SKShapeNode()
let gradientShader = SKShader(source: "void main() " +
                                          "float distanceFromCenter = distance(v_tex_coord, vec2(0.5,0.5));" +
                                          "gl_FragColor = vec4(0.6, 0.3, 0.0, distanceFromCenter*6.0);" +
                                          "")
sight.fillColor = .clear
sight.fillShader = gradientShader

以下是有用的链接:Drawing a circle with a shader in SpriteKit、https://thebookofshaders.com/02/、Add shader for SKShapeNode、https://developer.apple.com/documentation/spritekit/skshapenode/controlling_shape_drawing_with_shaders。

上述解决方案已经完成了一半,但又过了几个小时,我设法实现了我想要的。

let pos = n.sprite.position
let frame = n.sight.frame
let x = (pos.x - frame.minX) / frame.width
let y = (pos.y - frame.minY) / frame.height
let gradientShader = SKShader(source: "void main() " +
                                          "float distanceFromCenter = distance(v_tex_coord, npcLocation);" +
                                          "float alpha = 0.8 - distanceFromCenter;" +
                                          "if (alpha < 0)  alpha = 0.0;" +
                                          "gl_FragColor = vec4(0.0, 0.0, 0.0, alpha);" +
                                          "")
  gradientShader.uniforms = [SKUniform(name: "npcLocation", vectorFloat2: vector_float2(Float(x), Float(y)))]
  n.sight.fillColor = .clear
  n.sight.fillShader = gradientShader

【讨论】:

您可能希望使用一个属性将有关玩家位置的信息传递给着色器。 developer.apple.com/documentation/spritekit/skattribute 感谢您的建议。事实上,确实:D

以上是关于如何在 SKShapeNode 中绘制渐变?的主要内容,如果未能解决你的问题,请参考以下文章

SpriteKit:如何在没有 SKShapeNode 的情况下绘制自定义形状?

如何在 PHP 中绘制渐变矩形? [关闭]

如何在 UIView 上绘制渐变封面

如何在 Android 的画布上绘制平滑/抖动渐变

如何在Sprite-kit中画一条线

Plotly:如何在 Plotly 中绘制具有渐变颜色的矩形?