使用空的着色器程序绘制是不是有效?

Posted

技术标签:

【中文标题】使用空的着色器程序绘制是不是有效?【英文标题】:Is it valid to draw with an empty shader program?使用空的着色器程序绘制是否有效? 【发布时间】:2013-03-17 14:30:17 【问题描述】:

在我的游戏中有一个处理着色器、帧缓冲区和绘图的渲染模块。现在我想分别封装这三个任务的逻辑。这个想法是我将渲染模块分成三个模块。我这样做是为了降低代码复杂性并轻松实现实时着色器重新加载,但对我的问题并不重要。

绘图模块将使用glCreateProgram() 创建空着色器对象,并将它们与源文件的路径一起全局存储。着色器模块将检查它们并通过加载源文件、编译和链接来创建实际的着色器。

但在这个概念中,可能会出现渲染模块已经想要绘制但着色器模块没有创建实际着色器的情况。所以我的问题是,使用空着色器程序绘制是否有效?发生这种情况时屏幕会变黑对我来说是完全可以接受的。创建着色器应该很快就准备好了,所以延迟可能不明显。

使用空的着色器程序绘制是否有效?否则我该如何实现其他地方加载着色器的想法?

【问题讨论】:

这如何“降低代码复杂度”?你有 3 个相互依赖的系统,它们以某种方式独立运行。如果您想实现实时着色器重新加载......那么只需将引用粘贴到程序旁边的着色器来源即可。这似乎是构建渲染系统的一种非常复杂的方式。 【参考方案1】:

你如何定义“有效”和“空”?

如果程序对象的最后一个链接不成功(或者如果它没有最后一个链接),那么在它上面调用glUseProgram 是一个GL_INVALID_OPERATION 错误。这也意味着glUseProgram会失败,所以当前程序不会改变。所以所有glUniform calls 都将引用该程序而不是新程序;如果该程序为零,您将收到更多GL_INVALID_OPERATION 错误。

如果没有当前程序(即程序为0),则尝试渲染将产生未定义的行为。

未定义的行为对您的需求“有效”吗?如果您不打算向用户显示该帧(通过不调用交换缓冲区),那么您渲染的内容将无关紧要。 OpenGL 错误队列中的所有这些错误对您“有效”吗?

【讨论】:

我试着回答你的问题。空我的意思是glCreateProgram 返回的id,它没有附加着色器。有效是指行为由 OpenGL 定义并且没有错误。我希望 OpenGL 会跳过渲染。无论是否给定有效的着色器,我都会每帧交换缓冲区。 @sharethis:您对“空”的定义无关紧要。程序不需要附加着色器就可以使用;它们必须被链接才能有用。是的,您需要将着色器附加到链接,但重要的一步是 链接。确实,一旦将着色器链接到程序中,就应该将它们分离。 感谢您的澄清。如果相关着色器尚未链接,我将需要让渲染模块跳过绘制调用。或者也许我应该尝试不同的方法。顺便说一句,我仍然对最小可链接程序的组成感兴趣。你知道吗?【参考方案2】:

文档中的两个相关行:

glAttachShader

可以对着色器对象执行的所有操作都是有效的,无论着色器对象是否附加到程序对象。在将源代码加载到着色器对象之前或编译着色器对象之前,允许将着色器对象附加到程序对象。

glUseProgram

如果program 为零,则当前渲染状态指的是无效的程序对象,并且着色器执行的结果未定义。但是,这不是错误。 如果程序不包含 GL_FRAGMENT_SHADER 类型的着色器对象,则会在顶点上安装可执行文件,可能还会安装几何处理器,但片段着色器执行的结果将是未定义的。

所以似乎可以这样做,但您可能不会在所有机器上得到相同的结果。

【讨论】:

我可以glUseProgram 一个带有未编译的附加着色器的程序吗?结果会怎样? 嗯,它说这是允许的,glUseProgram 的描述还指出,程序只有在链接后才会实际加载到硬件中。我很确定什么都不会发生,您将获得与使用空程序对象相同的渲染。

以上是关于使用空的着色器程序绘制是不是有效?的主要内容,如果未能解决你的问题,请参考以下文章

如何避免使用着色器在 OpenGL 中消失线?

在片段着色器中绘制别名像素完美线?

OpenGL着色器程序在使用时导致屏幕变黑

学习WebGL:着色器绘制一个点

风场可视化:绘制轨迹

试图制作一个绘制像素的着色器