为SKShapeNode添加着色器 [英] Add shader for SKShapeNode

查看:62
本文介绍了为SKShapeNode添加着色器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想为SKShapeNode添加投影效果。我找到Emboss着色器here

以下是我的代码:

let node = SKShapeNode(rectOf: CGSize(width: w, height: h),cornerRadius: w / 4.0)
node.position = CGPoint(x: x, y: frame.size.height + h / 2)
node.fillColor = color
node.strokeColor = .clear
node.fillShader = createColorEmboss()
let v = simd_make_float2(Float(w),Float(h))
node.setValue(SKAttributeValue(vectorFloat2: v), forAttribute: "a_size")

func createColorEmboss() -> SKShader {
    let source = "void main() {" +
        "vec4 current_color = SKDefaultShading();" +
        "if (current_color.a > 0.0) {" +
            "vec2 pixel_size = 1.0 / a_size;" +
            "vec4 new_color = current_color;" +
            "new_color += texture2D(u_texture, v_tex_coord + pixel_size) * u_strength;" +
            "new_color -= texture2D(u_texture, v_tex_coord - pixel_size) * u_strength;" +
            "gl_FragColor = vec4(new_color.rgb, 1) * current_color.a * v_color_mix.a;" +
        "} else {" +
            "gl_FragColor = current_color;" +
        "}" +
    "}"
    let shader = SKShader(source: source, uniforms: [SKUniform(name: "u_strength", float: 1)])
    shader.attributes = [SKAttribute(name: "a_size", type: .vectorFloat2)]
    return shader  
  }

但是什么也没发生。有什么想法吗?

推荐答案

纹理(*)SKShapeNodeSKSpriteNode这里有很大区别:

  • 如果SKSpriteNode具有纹理和自定义着色器(shader属性),则着色器将可以通过u_texture统一访问原始纹理,并且可以使用它来渲染节点,即对其应用各种效果,如浮雕、模糊等。
  • SKShapeNode可以fillTexturefillShader,但它们的工作方式不同:
    • fillTexture是转换为灰度的矩形纹理,用于设置形状节点填充区域中fillColor的亮度。
    • fillShader在用于最终渲染之前,只能看到fillTexture作为此矩形图像,无法修改甚至无法查看矩形的哪些区域将可见(填充的一部分),以及最终渲染的外观。
    • 如果没有显式的fillTexture设置,u_texture制服看起来好像是一片无穷无尽的白色:无论您询问什么坐标,它都会返回白色,即使您超出了它的界限。

(*)您也可以只使用一种颜色创建SKSpriteNode;它的行为将是SKShapeNode和带纹理的SKSpriteNode的奇怪混合,对我们的讨论没有帮助,因此我将忽略这种类型。


您可以做的是将SKShapeNode栅格化成一个纹理,并从它创建一个SKSpriteNode。其实很简单:

let node = SKShapeNode(rectOf: CGSize(width: w, height: h),cornerRadius: w / 4.0)
node.fillColor = color
node.strokeColor = .clear

let theTexture = view.texture(from:node)
let spriteNode = SKSpriteNode(texture:theTexture)

spriteNode.position = CGPoint(x: x, y: frame.size.height + h / 2)
spriteNode.shader = createColorEmboss()
let v = simd_make_float2(Float(w),Float(h))
spriteNode.setValue(SKAttributeValue(vectorFloat2: v), forAttribute: "a_size")

如您所见,您甚至不需要将节点添加到场景中;视图会将其呈现为具有清晰背景的纹理。您还可以使用view.texture(from:crop:)指定较大的裁剪,如果投影延伸到原始形状之外,该裁剪可以容纳投影。

但是,我必须警告您,您尝试使用的这个特定着色器可能不是投影…所需的着色器

这篇关于为SKShapeNode添加着色器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆