已关闭。此问题需要更多的focused。当前不接受答案。
**想要改进此问题吗?**更新问题,使其仅关注editing this post的一个问题。
去年关闭了。
去年,机构群体审查了是否重新讨论此问题,并将其关闭:
原始关闭原因未解决
Improve this question
当我试图通过www.learnopengl.com上的openGL wiki和教程时,我的直觉永远无法理解整个概念是如何工作的。有人能用更抽象的方式来解释一下它是如何工作的吗?什么是顶点着色器和片段着色器,我们用它们做什么?
3条答案
按热度按时间5t7ly7z51#
OpenGL wiki给出了一个很好的定义:
着色器是一个用户定义的程序,设计用于在图形处理器的某个阶段上运行。
"历史课"
过去,显卡是执行一组固定算法的非可编程芯片:
所有这些都使用一个固定的参数化算法,通常类似于Phong reflection model。图片来自Wiki:
这样的架构被称为“固定功能流水线”,因为它们只能实现一个算法。
但这对于想要创建许多不同的复杂视觉效果的程序员来说限制太大了。
因此,随着半导体制造技术的进步,GPU设计师能够在每平方毫米上压缩更多的晶体管,供应商开始允许渲染管道的一些部分被编程为编程语言,如类似C的GLSL。
然后,这些语言被转换为semi-undocumented instruction sets,运行在内置于这些较新GPU的小型“CPU”上。
一开始,那些着色器语言were not even Turing complete!
术语 * 通用GPU(GPGPU)* 指的是现代GPU增强的可编程性,新的语言被创造出来以比OpenGL更好地适应它,特别是OpenCL和CUDA。关于哪种算法更适合GPU而不是CPU计算,请参阅此答案的简短讨论:术语“受CPU限制”和“受I/O限制”是什么意思?
现代着色器管线概述
在OpenGL 4模型中,只有下图中的蓝色阶段是可编程的:
Image source。
着色器从前一流水线阶段获取输入(例如顶点位置、颜色和光栅化像素),并自定义下一阶段的输出。
最重要的两个方面是:
以下相关示例更清楚地说明了什么是投影:如何在OpenGL中使用glOrtho()?
碎片是从先前计算的三角形投影离散化的,参见:
相关问题:What are Vertex and Pixel shaders?
由此我们看到,“着色器”这个名字对当前的架构来说并不是很具描述性。这个名字当然起源于“阴影”,它是由我们现在所说的“片段着色器”处理的。但是GLSL中的“着色器”现在也像顶点着色器一样管理顶点位置,更不用说OpenGL 4. 3
GL_COMPUTE_SHADER
了,它允许与渲染完全无关的任意计算,与OpenCL非常相似。TODO OpenGL是否可以单独使用OpenCL高效地实现,即,使所有阶段都可编程?当然,必须在性能/灵活性之间进行权衡。
第一批带有着色器的GPU甚至使用不同的专用硬件来进行顶点和片段着色,因为它们的工作负载完全不同。然而,当前的架构使用单一类型硬件(基本上是小型CPU)的多个通道来处理所有着色器类型,这节省了一些硬件重复。这种设计被称为Unified Shader Model:
x1c4d 1x指令集
改编自this image、SVG source。
以下来自Asianometry https://youtu.be/GuV-HyslPxk?t=350的精彩总结还澄清了一些管线实际上是由CPU本身处理的,而不是早期技术中的GPU,主要由NVIDIA领导:
同一视频还继续提到他们2001年推出的GeForce 3 series是第一款引入某种程度着色器可编程性的产品。
源代码示例
要真正了解着色器及其功能,您必须查看许多示例并学习API。例如,https://github.com/JoeyDeVries/LearnOpenGL是一个很好的源代码。
在现代的OpenGL 4中,即使是hello world三角形程序也使用超级简单的着色器,而不是像
glBegin
和glColor
这样的旧的被弃用的即时API。请考虑以下三角形hello world示例,该示例在单个程序中同时包含着色器版本与即时版本:https://stackoverflow.com/a/36166310/895245
main.c
改编自Learn OpenGL、my GitHub upstream。
编译并在Ubuntu 20.04上运行:
两者的结果相同:
指令集
由此我们可以看出:
vertexShaderSource
和fragmentShaderSource
)的C样式字符串并且还将其输出
ourColor
中的一个定义为颜色阵列,然后该颜色阵列变为片段着色器的输入:然后,C程序将包含顶点位置和颜色的数组从CPU提供给GPU
然而,在直接非着色器示例中,我们看到进行了显式给予位置和颜色的魔术API调用:
因此,我们理解,这代表了一个更加受限的模型,因为位置和颜色不再是存储器中的任意用户定义数组,然后由任意用户提供的程序处理,而是仅仅输入到Phong类模型。
在这两种情况下,渲染输出通常直接进入视频,而不通过CPU传回,尽管可以读取到CPU,例如,如果您想要将其保存到文件:如何使用GLUT/OpenGL渲染文件?
出色的3D图形着色器应用程序
非平凡着色器的一个经典酷应用是动态阴影,即一个对象投射到另一个对象上的阴影,与仅取决于三角形法线和光源之间Angular 的阴影相反,Phong模型中已经涵盖了这一点:
Image source中的一个。
超酷的非3D片段着色器应用程序
https://www.shadertoy.com/是一个“片段着色器的Twitter”,它包含了大量视觉上令人印象深刻的着色器,可以作为一个“零设置”的方式来玩片段着色器Shadertoy运行在WebGL上,这是一个浏览器的OpenGL接口,所以当你点击一个shadertoy时,它会在你的浏览器中渲染着色器代码,和大多数“片段着色器图形应用程序”一样,他们只是有一个固定的简单顶点着色器,在屏幕上画两个三角形,就在摄像头的前面:WebGL/GLSL - How does a ShaderToy work?,因此使用者只会编写片段着色器。
下面是我亲手挑选的一些更科学的例子:
指令集
指令集
ckocjqey2#
着色器基本上是根据几个光线方程为你要渲染的对象给予正确的颜色。所以如果你有一个球体,一个光源和一个摄像机,那么摄像机应该会看到一些阴影,一些发光的部分等等,即使球体只有一种颜色。着色器执行光线方程计算来给你这些效果。
顶点着色器将虚拟空间(3D模型)中每个顶点的3D位置转换为该顶点在屏幕上显示的2D坐标。
基本上,片段着色器通过执行灯光计算来为每个像素着色。
zqry0prt3#
GPU例程以一种简短而简单的方式提供了钩子/回调函数,以便绘制面部纹理。这些钩子就是着色器。