如何在XCode中编写OpenGL ES片段着色器?

3
我试图制作自己的着色器,以用作SKSpriteNode的SKShader,但我不知道正确的方法。我只想一种编写具有自动完成功能的着色器代码的方法,并在不必等待巨大程序编译的情况下查看着色器,但这似乎比我想象的更困难。
我已经安装了GLFW3和其他一些奇怪的东西,因为大多数教程建议使用OpenGL这样的东西,但它似乎更适用于整个OpenGL,而不仅仅是一种特定类型的着色器。
简而言之:是否有人知道一种快速简便的方法来编写着色器,并将其用作SpriteKit中的SKShaders?

你真正需要着色器是为了什么?着色器并不难,但当人们寻求“快速”和“简单”时,往往表明他们没有深思熟虑。设置着色器很容易,但根据你所做的事情和范围,调试/正确获取着色器可能更加困难。 - Mobile Ben
我所说的快速和简便是指它具有自动完成功能,因此您不必每5秒钟就犯错,并且快速意味着您不必编译整个程序才能使其工作。然而似乎这是不可能的。 - MysteryPancake
4个回答

5

让我们从你的精灵开始

let spaceship = SKSpriteNode(imageNamed: "Spaceship")

enter image description here

SKShader对象

您需要将其连接到一个SKShader对象

spaceship.shader = SKShader(fileNamed: "MyShader.fsh")

着色器代码

接下来,您可以创建MyShader.fsh文件,并在其中编写片段着色器的逻辑。

在以下示例中,我将每个像素的蓝色分量设置为0

void main() {
    vec4 color = texture2D(u_texture, v_tex_coord);
    color.b = 0.0;
    gl_FragColor = color;
}

enter image description here


我知道如何将着色器应用于精灵,我的问题是我应该如何编写着色器文件(以及是否有可能在等待整个编译过程完成之前查看它)。有没有办法为其获取自动完成? - MysteryPancake
1
@MysteryPancake:不需要,只需在Xcode中创建一个空文件,将其命名为.fsh扩展名并编写OpenGL着色语言代码即可。 - Luca Angeletti
我想我会等待看看是否有更好的方法。我不喜欢在盲目尝试中工作,试图弄清楚为什么每次更改某些内容时着色器都会崩溃。 - MysteryPancake

2
使用Xcode中的SpriteKit场景编辑器。当您在检查器中将着色器源文件与节点关联时,场景视图立即为您提供该着色器的实时预览效果。
然后,您可以使用Xcode的助手编辑器窗格来查看和编辑与当前选择的场景节点相关联的着色器源代码 - 包括着色器中任何动画(来自u_time输入)的实时预览。

Xcode shader editing

这段话的意思是:这样做可以获得语法高亮,但无法自动完成。Xcode的自动完成引擎似乎仅限于其主编译器工具链 - 让它支持着色器通常是一个好事情,可以通过报告错误来实现。编辑着色器源代码应该会更新实时预览,但似乎至少有一些Xcode版本需要在检查器中重新选择自定义着色器才能使更改生效。(这也可能值得报告错误...)
上面示例中的着色器代码(由Shadertoy通过Endless Wave blog提供):
void main(void) {

    vec2 uv = v_tex_coord;

    uv.y += (cos((uv.y + (u_time * 0.04)) * 45.0) * 0.0019) +
    (cos((uv.y + (u_time * 0.5)) * 10.0) * 0.002);

    uv.x += (sin((uv.y + (u_time * 0.07)) * 15.0) * 0.0029) +
    (sin((uv.y + (u_time * 0.5)) * 15.0) * 0.002);

    gl_FragColor = texture2D(u_texture, uv);
}

我知道我不应该说谢谢……但还是非常感谢,我真的很绝望!同样,感谢每个人花时间编写示例,向我展示SpriteKit的工作方式——即使我已经知道,我相信它将来会帮助某些人。 - MysteryPancake
好的...最后一个问题。我怎样才能刷新预览,以便查看我对着色器所做的任何更改?我找到的唯一方法是将节点的着色器更改为空,然后再将其更改回我的着色器,但是否有其他更快的方法? - MysteryPancake

1

一份非常简单的工作中的SpriteKit着色器可以在我关于此主题的博客文章中找到。您应该从现有示例开始工作,而不是从头开始。其中包括了一些有用的着色器信息链接。


我并不是在寻找一个例子,因为我已经用一个工作的着色器完成了一个项目。我一直想问的问题是如何快速编写着色器-快速意味着使用自动完成(如果可能的话),并且(也许)具有实时预览...除了最后两个回复之外,似乎没有办法做到这一点。哦,好吧。 - MysteryPancake
不,这几乎是不可能的。着色器是你可能编写的最复杂的代码之一。你需要理解每个浮点运算的每个细节,没有什么能让它更快。 - MoDJ

1

如果你真的在寻找自动完成功能,我不认为你可以在Xcode中实现,但是还有其他选择。例如,在Atom中:

https://atom.io/packages/autocomplete-glsl

还有其他的问题需要解决。尽管自动完成会有所帮助,但有很多其他方式可能会导致编译问题。就像通过Xcode编写ObjC/Swift代码一样,你可能已经正确地自动完成了代码。但它仍然可能出错。更好的方法是花费精力找到一个优化的路径来解决错误并测试你的着色器。

如果你正在尝试使用着色器,你可以设置一个简单的应用程序来进行测试,或者在游戏中设置一些隔离模式来进行测试(这就是我所做的)。

请记住,你不会一直编写着色器。在构建游戏的过程中,这些通常很少出现(假设你正在制作游戏,否则这个说法可能没有任何价值)。


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