我最近开始使用 openGL 进行编程。我已经完成了创建基本原语的代码,并在 webGL 中使用了着色器。我已经广泛地搜索了这个主题,但对我来说仍然不是很清楚。基本上,这就是我想知道的。有没有什么可以在 GLSL 中完成而不能在普通 openGL 中完成的事情,或者 GLSL 只是更有效地做事?
2 回答
简短的版本是:OpenGL 是一种用于渲染图形的 API,而 GLSL(代表 GL 着色语言)是一种让程序员能够修改管线着色器的语言。换句话说,GLSL 是整个 OpenGL 框架的一个(小)部分。
要了解 GLSL 适合大局的位置,请考虑一个非常简化的图形管道。
指定的顶点---(顶点着色器)--->变换的顶点---(原始组装)--->基元---(光栅化)--->片段---(片段着色器)--->输出像素
着色器(在这里,只是顶点和片段着色器)是可编程的。你可以用它们做各种各样的事情。您可以只交换红色和绿色通道,或者您可以实施凹凸贴图以使您的表面看起来更加详细。编写这些着色器是图形编程的重要组成部分。这是一个包含一些不错示例的链接,可以帮助您了解使用自定义着色器可以完成什么:http: //docs.unity3d.com/Documentation/Components/SL-SurfaceShaderExamples.html。
在不久的将来,对它们进行编程的唯一方法是使用 GPU 汇编器。在 OpenGL 的情况下,该语言被称为 ARB 汇编程序。由于这个困难,OpenGL 的人给了我们 GLSL。GLSL 是一种高级语言,可以在图形硬件上编译和运行。综上所述,可编程着色器是 OpenGL 框架(或任何现代图形 API)不可或缺的一部分,而 GLSL 使它们的编程变得更加容易。
正如 Mattsills 回答的那样,GL Shader Language 或 GLSL 是 OpenGL 的一部分,它支持在 OpenGL 中创建称为着色器的算法。着色器在 GPU 上运行。
着色器决定诸如表面部分颜色等因素,以及表面共享信息(如反射光)的方式。顶点着色器、几何着色器、曲面细分着色器和像素着色器是可以用 GLSL 编写的着色器类型。
Q1:
有什么可以在 GLSL 中完成而不能在普通 OpenGL 中完成的事情吗?
A:
您可能可以只使用没有 GLSL 部分的 OpenGL,但如果您想要自己的表面属性,您可能需要一个着色器,使其相当简单和高性能,用 GLSL 之类的东西创建。这里有些例子:
Q2:
还是 GLSL 只是更有效地做事?
A:
像素着色器特别是非常并行的,为 2D 网格的每个单元独立计算值,同时还包含重要的警告,例如无法非常高效地处理类似条件的“if”语句,因此这是使用不同类型的着色器的情况在 OpenGL 的其余部分描述和处理的表面上有优势。
问题 3:
我怀疑您想知道是否可以选择仅使用 GLSL,而我只能根据我对一种着色器 Pixel Shaders 的了解来回答这个问题。该答案的其余部分涵盖了“仅”使用 GLSL 作为可能的选项:
A:
虽然 GLSL 是 OpenGL 的一部分,但您可以使用 OpenGL 的其余部分来设置环境并编写您的程序几乎完全作为像素着色器,其中像素着色器的每个元素为整个屏幕的一个像素着色。
例如:
(请注意,WebGL 倾向于占用 CPU 到使整个系统停滞的地步,而 Windows 8.1 允许这样做,Chrome 似乎比 Firefox 更擅长查看这些链接。)
不,这不是真实水的视频剪辑:
https://www.shadertoy.com/view/Ms2SD1
提供给这只蜗牛的唯一外部资源是一些易于生成的纹理:
https://www.shadertoy.com/view/ld3Gz2
使用嘈杂的分形点云进行渲染:
https://www.shadertoy.com/view/Xtc3RS
https://www.shadertoy.com/view/MsdGzl
一个完美的球体:1 个多边形,1 个曲面,没有边或顶点:
https://www.shadertoy.com/view/ldS3DW
类似在赛道上模拟汽车的粒子系统,使用第二个窄但长的像素着色器作为汽车位置的数据表:
https://www.shadertoy.com/view/Md3Szj
随机值相当简单:
fract(sin(p)*10000.)
我发现该语言在某些方面难以使用,并且以这种方式将 GLSL 用于游戏或模拟等大型项目可能会或可能不会特别实用,但是正如这些演示所示,计算机游戏不必看起来像电脑游戏,这种方法应该是一种选择,可能与生成的内容和/或外部数据一起使用。
据我了解,在 OpenGL 中执行合理的像素着色器:
- 必须加载到一小段内存中。
- 不支持:
- “if”语句之类的条件。
- 递归或while循环之类的流控制。
- 仅限于一小部分有效指令和数据类型。
- 包括“sin”、mod、向量乘法、浮点数和半精度浮点数。
- 缺少对象或 lambda 等高级功能。
- 并有效地同时并行计算所有值。
所有这一切的结果是代码看起来更像是封闭形式的方程行,并且缺乏算法或更高级别的结构,使用模块化算法来处理类似于条件的东西。