GLKit的GLKBaseEffect和自定义着色器

12

我一直在研究这个问题,但似乎无法完全理解它以便解决它,所以我想把它放到这里,让聪明的人们给出一些想法。

基本上,我已经在一个iPhone项目上工作了一段时间,我有幸能够使用所有最新的框架并针对5.1进行目标设置。因此,我一直在使用GLKit和GLKBaseEffect,它们一直都很好用。我之所以开始使用GLKBaseEffect而不是编写自己的着色器,是因为我不熟悉glsl语言。然而,要求变得更加精确,基本效果似乎已经不再适用。

由于我已经在使用基本效果进行所有转换,因此我希望如果可能的话保持我的基本效果不变,但在其上增加类似于glsl的着色器。

我的旧方法看起来像这样(这是在循环渲染所有对象时进行的操作,其中对象包含诸如变换、网格和其他一些与此问题不太相关的东西,例如纹理、材料等)

ObjectBase *obj = [ResourceManager.shared getObjectNamed:name inScene:sceneName];
GLKMatrix4 modelview = effect.transform.modelviewMatrix;
effect.transform.modelviewMatrix = GLKMatrix4Multiply(effect.transform.modelviewMatrix, obj.transform);

[effect prepareToDraw];
[obj render];

effect.transform.modelviewMatrix = modelView;

在这里,我们获取一个要呈现和变换(即平移、旋转和缩放)的对象,然后渲染它,其中渲染本身会获取对象的网格,绑定缓冲区并将其渲染。

到目前为止还不错。

然而,我想在[obj render];调用期间,让对象也执行一些像glUseProgram(someProgram);这样的操作,从而添加更多专门的着色器代码。

我想你可以说我正在尝试为我的顶点着色器使用基本效果,并希望为我的片段着色器使用“正常”的着色器。至少我认为我想这样做。

我已经尝试了一些东西。

我尝试创建只有片段着色器并在上面运行glUseProgram,但是当设置和编译它时,它说我需要一个顶点着色器和一个片段着色器。我还尝试创建一个空的顶点着色器,但是结果不太好,我不知道发生了什么,但我猜它会覆盖基本效果。

最终,我倾向于接受这个事实,即最好丢弃基本效果并完全编写自己的着色器。我只是觉得这样做需要很多工作,所以我想看看我能节省多少工作。

我确实理解我的着色器理解是给我带来最大问题的部分,所以请耐心等待。

2个回答

18

我想为对此感兴趣的人提供我的结论。

我的做法实际上是彻底放弃了GLBaseEffect,并实现了自己的着色器代码。

我的最大问题是我真的不理解它是“全有或全无”的,可以这么说。

请注意,我可能是错的,因此对我错误的任何更正将不胜感激,我真的不想欺骗任何阅读此内容的人。

在我的努力中发现了一些关键点:

  • GLKBaseEffect旨在模仿OpenGLES早期版本中看到的固定功能流水线。因此,它包装了常见的着色器代码,因此您不必太在意。您将拥有基本功能,但不太可扩展。
  • 如果编写自己的着色器代码,则仍然可以使用GLKit的美妙功能,例如纹理加载程序、数学库等等。因此,如果要进行更复杂或可定制化的操作(凸起映射、卡通渲染等),完全值得重写所需的样板代码以正确呈现。我首先使用GLKBaseEffect来定位场景,因为它非常舒适且易于使用。但是当我想要做更多的事情(切线空间法线映射)时,我有点卡住了,因为我无法添加到由GLKBaseEffect处理的着色器程序中。
  • 着色器并不像我一直以为的那么可怕!我只是不知道它实际上意味着什么,我很惊讶我读了这么多关于它们的内容,但还没有真正理解,基本上着色器是替代固定功能流水线的程序。就是这样简单。

我想我已经抱怨够了,只是想跟进并添加我迄今收集到的一些片段。


嗨,qrikko,我可以给您发送一封电子邮件,关于一个潜在的项目吗?感谢您详细的回答! - Crashalot
当然,没问题。我总是尽力在SO上提供详尽的帮助,因为它对于很多人来说都是如此重要的资源。 :) - qrikko
啊,我以为它是公开的,抱歉。qrikko@gmail.com - qrikko

11
正如你发现的那样,你不能仅使用片段着色器而不使用顶点着色器。这是因为两者有不同的任务。顶点着色器处理每个顶点的方面:计算顶点数据、纹理(uv)等,最后绘制面(三角形)。片段着色器处理屏幕上(或视口中)每个像素将绘制什么。当你只提供一个片段着色器时,你并没有告诉OpenGL你的顶点数据是什么,而是只告诉它在像素上做些什么。而且这些像素什么也没有/胡言乱语(我不确定哪种),因为你的顶点着色器什么也没做。

当使用GLKEffect时,调用[yourEffect prepareToDraw]方法会处理着色器等。

如果您只想使用现成的着色器对,为什么不使用XCode OpenGL游戏模板中提供的那个?运行它时,它有两个立方体,一个使用GLKit渲染,另一个是普通方式。虽然我认为这对大多数效果来说可能不够。如果您想了解更多关于着色器的知识,可以查看NeHe GLSL入门article。它介绍了GLSL以及如何在代码中编写和使用着色器。您可能还想查看Diney Bomfim's All About Shaders文章和这个page

在大多数情况下,使用GLKit非常方便,因为它可以避免编写大量无用的、重复的代码。例如,当您可以使用GLKTextureLoader时,您就不必遍历许多具有不同颜色编码和每像素位数(每个格式)的图像格式。


我似乎完全忘记了实际上感谢你提供的链接,它们真正拓宽了我的理解。我很高兴我问了,即使在问的时候,我感觉自己并不知道我实际上要问什么...所以很好地解决了这个问题;) 谢谢。 - qrikko
非常感谢。我很沮丧,因为我的着色器编译和链接了,但没有输出任何内容。删除prepareToDraw的调用就解决了问题。生活真美好! - VaporwareWolf

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