这一节我们学一下用着色器(shader)描边效果。来看看最终效果:
一、进行shader初始设置
首先我们进入NPC场景,选择Sprite2D节点,在检查器中中岛CanvasItem属性,并在Material->Material后方选择下拉按钮选择新建ShaderMaterial
然后选中新建的材质球,在Shader属性选择新建着色器,在弹出框内进行如下设置:
然后创建保存。
二、编写代码
这样我们就可以在着色器内进行编码了。我们先来学习一下Shader的基本知识。在 Godot 游戏引擎中,片段着色器(Fragment Shader)是一种运行在图形处理单元(GPU)上的程序,用于计算并确定屏幕上每个像素的颜色。片段着色器是图形渲染过程中的关键部分,它们使得开发者能够创造出丰富和动态的视觉效果。
片段着色器的基本概念:
- 像素颜色计算:
- 片段着色器的主要任务是计算每个像素的颜色。这可以通过直接指定颜色值或使用纹理映射来实现。
- 并行处理:
- 片段着色器在 GPU 上并行运行,这意味着它们同时对所有像素进行处理。这种并行处理方式使得着色器非常适合执行复杂的数学运算,以实现高效的图形渲染。
- 输入和输出:
- 片段着色器接收一系列输入,如纹理坐标(UV)、顶点颜色、时间变量等,并输出最终的颜色值。
片段着色器的结构:
一个基本的片段着色器通常包含以下部分:
- 声明着色器类型:
shader_type canvas_item; // 对于 2D 渲染 // 或者 shader_type spatial; // 对于 3D 渲染
- 片段函数:
void fragment() { // 片段着色器的代码 COLOR = vec4(1.0, 0.0, 0.0, 1.0); // 设置像素颜色为红色 }
- 使用 UV 坐标:
void fragment() { COLOR = vec4(UV.x, UV.y, 0.0, 1.0); // 使用 UV 坐标设置颜色 }
- 使用纹理:
void fragment() { COLOR = texture(TEXTURE, UV); // 从纹理中获取颜色 }
片段着色器的应用:
- 颜色效果:可以创建颜色渐变、色调映射、颜色校正等效果。
- 纹理处理:可以实现纹理混合、模糊、锐化等效果。
- 光照和阴影:模拟不同的光照模型和阴影效果。
- 后处理效果:如模糊、边缘检测、颜色过滤等。
在 Godot 中使用片段着色器:
- 创建材质:在 Godot 中,首先需要创建一个
ShaderMaterial
。 - 编写着色器代码:在材质编辑器中,可以编写和修改着色器代码。
- 应用到对象:将材质应用到场景中的对象上,着色器效果就会应用到该对象。
片段着色器是 Godot 提供的一个强大工具,可以极大地扩展游戏的视觉表现力。开发者可以通过不断学习和实践,创造出各种独特的视觉效果。
三、编写代码
我们先录入如下代码,然后我在解释一下原理和重点知识:
shader_type canvas_item;
uniform float outline_width=1.0;
uniform vec4 outline_color:source_color =vec4(0,0,0,1);
void fragment() {
vec2 uv =UV;
vec2 uv_up = uv+vec2(0,TEXTURE_PIXEL_SIZE.y)*outline_width;
vec2 uv_down = uv + vec2(0,-TEXTURE_PIXEL_SIZE.y)*outline_width;
vec2 uv_left = uv + vec2(TEXTURE_PIXEL_SIZE.x,0)*outline_width;
vec2 uv_right = uv + vec2(-TEXTURE_PIXEL_SIZE.x,0)*outline_width;
vec4 color_up = texture(TEXTURE,uv_up);
vec4 color_down = texture(TEXTURE,uv_up);
vec4 color_left = texture(TEXTURE,uv_left);
vec4 color_right = texture(TEXTURE,uv_right);
vec4 outline = color_down+color_up+color_left+color_right;
outline.rgb = outline_color.rgb;
vec4 original_color = texture(TEXTURE,UV);
COLOR = mix(outline,original_color,original_color.a);
}
看一下前后对比效果:
未添加描边效果如下:
添加描边效果如下:
而且描边的宽度和颜色均可以通过参数来控制。
原理
我们想要实现描边效果,只需每个点位上下左右向外扩展一个点位,这样在与原图像叠加到一起,让后把扩展的点变成描边颜色即可。
重点知识学习
- shader_type::是用来定义一个着色器(Shader)的类型的关键字,Godot 支持多种类型的着色器,每种类型的着色器都有其特定的用途和上下文环境。
- canvas_item:着色器类型用于处理 2D 渲染,它通常用于控制 CanvasItem 类型的节点,比如 Sprite、TextureRect 或自定义的 2D 节点。当你在 Godot 中使用这种类型的着色器时,你可以自定义这些节点的渲染行为,比如颜色混合、纹理处理、光照效果等。
- uniform:该关键字用于声明全局变量,这些变量在着色器的所有执行实例中保持一致。换句话说,
uniform
变量是那些你在渲染过程中想要从 CPU 传递到 GPU 的值,并且这些值对于同一绘制调用的所有片段都是相同的。 - TEXTURE_PIXEL_SIZE:是一个内置变量,用于在着色器中获取纹理的像素大小。这个变量通常用于片段着色器中,以确定纹理中每个像素的物理大小。在 Godot 的片段着色器中,
TEXTURE_PIXEL_SIZE
的值通常表示为二维向量,其中包含了纹理的宽度和高度上的像素大小。例如,如果纹理的分辨率是 320x240,那么TEXTURE_PIXEL_SIZE
应该是(1/320, 1/240)
,这意味着在每个维度上,一个单元代表一个像素。 texture()
函数用于在着色器中从指定的纹理中采样颜色值。- mix() 函数用于在两个值之间进行线性插值,常用于混合颜色或向量。一句话描述其用途是:函数有三个参数,第一个参数表示起始颜色,第二参数表示结束颜色;第三个参数(通常是一个介于 0.0 和 1.0 之间的系数)在两个值之间进行平滑过渡,如果为0,表示第一种颜色;1表示第二种颜色;0到1之间表示过度颜色。