在深入了解着色器中的颜色处理之前,让我们先建立对颜色在计算机图形学中的基本认知
在 Makepad 着色器中,我们使用 vec4
(RGBA向量) 来表示颜色:
0.0
到 1.0
0.0
到 1.0
0.0
到 1.0
0.0
(完全透明)到 1.0
(完全不透明)1// 基础纯色着色器
2fn pixel(self) -> vec4 {
3 // 格式: vec4(红, 绿, 蓝, 透明度)
4 return vec4(1.0, 0.0, 0.0, 1.0); // 纯红色
5}
线性渐变是在两种颜色之间创建平滑过渡的技术。以下是一个水平渐变的实现:
1fn pixel(self) -> vec4 {
2 // self.pos.x 给出从0.0到1.0的水平位置
3 let mix_factor = self.pos.x;
4
5 let color1 = vec4(1.0, 0.0, 0.0, 1.0); // 红色
6 let color2 = vec4(0.0, 0.0, 1.0, 1.0); // 蓝色
7
8 // 在两种颜色之间线性插值
9 return mix(color1, color2, mix_factor);
10}
视觉表现如下:
1红色 [================>] 蓝色
2 <- 混合因子 ->
对于对角线渐变,我们可以这样实现:
1fn pixel(self) -> vec4 {
2 // 组合x和y坐标实现对角线方向
3 let mix_factor = (self.pos.x + self.pos.y) * 0.5;
4
5 let color1 = vec4(1.0, 0.0, 0.0, 1.0); // 红色
6 let color2 = vec4(0.0, 0.0, 1.0, 1.0); // 蓝色
7
8 return mix(color1, color2, mix_factor);
9}
径向渐变创建从中心点向外扩散的圆形颜色过渡:
1fn pixel(self) -> vec4 {
2 // 计算到中心点的距离
3 let center = vec2(0.5, 0.5);
4 let dist = length(self.pos - center);
5
6 // 将距离转换为混合因子
7 let mix_factor = clamp(dist * 2.0, 0.0, 1.0);
8
9 let inner_color = vec4(1.0, 1.0, 1.0, 1.0); // 中心白色
10 let outer_color = vec4(0.0, 0.0, 0.0, 1.0); // 边缘黑色
11
12 return mix(inner_color, outer_color, mix_factor);
13}
纹理映射是将 2D 图像应用到几何图形表面的技术。
1DrawTexture = {{DrawTexture}} {
2 texture tex: texture2d // 声明纹理uniform
3
4 fn pixel(self) -> vec4 {
5 // 在当前位置采样纹理
6 return sample2d(self.tex, self.pos);
7 }
8}
UV坐标用于将纹理像素映射到几何体:
1(0,0) +-----------+ (1,0)
2 | |
3 | 纹理 |
4 | |
5(0,1) +-----------+ (1,1)
1fn vertex(self) -> vec4 {
2 // 转换UV坐标
3 self.uv = self.geom_pos * self.tex_scale + self.tex_offset;
4
5 // 常规顶点变换
6 let clip_pos = self.geom_pos * self.rect_size + self.rect_pos;
7 return self.camera_projection * vec4(clip_pos, 0.0, 1.0);
8}
9
10fn pixel(self) -> vec4 {
11 // 使用变换后的UV采样
12 return sample2d(self.tex, self.uv);
13}
下面是一个简单的高斯模糊实现:
1fn blur(self) -> vec4 {
2 let blur_radius = 2.0; // 模糊半径
3 let mut color = vec4(0.0);
4 let mut total_weight = 0.0;
5
6 // 在当前像素周围的5x5网格中采样
7 for i in -2..3 {
8 for j in -2..3 {
9 let offset = vec2(float(i), float(j)) * blur_radius;
10 // 计算高斯权重
11 let weight = exp(-(offset.x * offset.x + offset.y * offset.y));
12
13 color += sample2d(self.tex, self.pos + offset) * weight;
14 total_weight += weight;
15 }
16 }
17
18 return color / total_weight; // 归一化结果
19}
1fn glow(self) -> vec4 {
2 let base_color = sample2d(self.tex, self.pos); // 原始颜色
3 let blur_color = self.blur(); // 模糊后的颜色
4
5 // 将模糊版本叠加以创建发光效果
6 return base_color + blur_color * self.glow_strength;
7}
1// 使用Makepad内置的GaussShadow来实现阴影效果
2fn draw_shadow(self) -> vec4 {
3 let shadow_color = vec4(0.0, 0.0, 0.0, 0.5);
4 let shadow_offset = vec2(5.0, 5.0);
5
6 // 计算阴影区域
7 let shadow = GaussShadow::box_shadow(
8 self.rect_pos + shadow_offset,
9 self.rect_size,
10 self.pos,
11 10.0 // 阴影模糊半径
12 );
13
14 return shadow_color * shadow;
15}