序言
好,你决定试一下Shader啦?也许你听说过Shader可以实现很多酷炫的特效,并且运行神速。也许你还听说过Shader挺难学的。没错,这些说的都对。
Shader可以用来实现各式各样的特效(实际上现代渲染引擎绘制的每一样东西都会用到Shader)。
对于不熟悉Shader的朋友来说,写Shader是相当难的。Godot尝试着通过暴露一些有用的内置属性以及处理一些底层的初始化工作来降低写Shader的难度。然而,GLSL(OpenGL Shading Language:Godot使用的着色器语言)仍然是不易懂而且约束很大的,尤其是对于那些习惯于GDScript的人。
为啥会这样?
Shader是运行在GPU(Graphics Processing Units)上的特殊的程序。绝大多数电脑都会有GPU,要么集成在CPU上要么独立的(例如显卡)。GPU尤其适于渲染,因为它们被优化用于并行执行成千上万的指令。
Shader的输出结果就是绘制在视区的传统彩色像素。但是一些Shader允许特殊的输出(比如:Vulkan)。Shader运行在着色器管线的内部。标准处理流程是顶点着色器->片元着色器 型着色器管线。顶点着色器决定顶点的去向,而片元着色器决定每个独立像素接收的颜色。
试想一下,如果你想把一个纹理图片的所有像素都更新为一个指定颜色,在CPU中你将这样写:
for x in range(width):
for y in range(height):
set_color(x, y, some_color)
而在Shader中你只能在循环体(loop)中访问,因此你将这样写:
// 此函数会逐像素调用
void fragment() {
COLOR = some_color;
}
你无法控制这个函数如何被调用,所以设计Shader和设计CPU程序有很大的不同。
在着色器管线中,你无法访问上次执行的结果,你也无法访问当前正在绘制的像素以外的像素,并且你也无法修改当前正在绘制的像素以外的像素。因为像素间是互不依赖的,所以这样的机制允许GPU可以并行的处理不同的像素Shader。这种损失了灵活性的设计专门针对GPU来设计,它能够让Shader的运行快得难以置信。
网友评论