---
name: godot-shader-fundamentals
description: Godot 4 Shader 基础语法与数学，包含类型系统、Uniform变量、内置函数及实用技巧。
---

# Godot Shader 基础

## 1. Shader 概述

Shader 是一种运行在 GPU 上的特殊程序，负责决定如何处理网格模型的数据（如顶点位置、颜色、法线等）以及如何将它们绘制到屏幕上。Godot 引擎的 Shader 语言基于 GLSL，进行了简化和扩展。

### 为什么使用 Shader

- **高性能**：GPU 并行处理，适合处理大量像素
- **程序化生成**：可以动态生成纹理、颜色、效果
- **视觉效果**：实现光照、阴影、材质等复杂效果
- **实时反馈**：支持时间相关的动态效果

## 2. Shader 类型

Godot 4 支持 5 种 Shader 类型：

### spatial（3D 着色器）

用于 3D 场景中的物体渲染，如网格、地形等。

```gdscript
shader_type spatial;

void vertex() {
    // 顶点着色器：处理每个顶点
}

void fragment() {
    // 片段着色器：处理每个像素
}

void light() {
    // 光照着色器：处理光照计算
}
```

### canvas_item（2D 着色器）

用于 2D 场景中的渲染，如 Sprite2D、Control 组件、ColorRect 等。

```gdscript
shader_type canvas_item;

void vertex() {
    // 顶点着色器
}

void fragment() {
    // 片段着色器
    COLOR = vec4(1.0, 0.0, 0.0, 1.0); // 输出红色
}
```

### particles（粒子着色器）

```gdscript
shader_type particles;

void start() {
    // 粒子产生时调用
}

void process() {
    // 粒子每帧更新时调用
}

void fragment() {
    // 粒子片段着色器
}
```

## 3. 数据类型

### 基础类型

| 类型 | 描述 |
|------|------|
| `void` | 空类型 |
| `bool` | 布尔类型 |
| `int` | 有符号整型 |
| `float` | 浮点数 |
| `bvec2/3/4` | 2/3/4 维布尔向量 |
| `ivec2/3/4` | 2/3/4 维整型向量 |
| `vec2/3/4` | 2/3/4 维浮点向量 |

### 矩阵类型

| 类型 | 描述 |
|------|------|
| `mat2` | 2x2 矩阵 |
| `mat3` | 3x3 矩阵 |
| `mat4` | 4x4 矩阵 |

### 纹理类型

| 类型 | 描述 |
|------|------|
| `sampler2D` | 2D 纹理采样器 |
| `samplerCube` | 立方体纹理采样器 |
| `sampler3D` | 3D 纹理采样器 |

## 4. Uniform 变量

Uniform 变量用于从 CPU 端向 GPU 端传递数据。

```gdscript
shader_type canvas_item;

uniform float my_float = 1.0;
uniform vec4 my_color;
uniform sampler2D my_texture;
```

### Hint 提示

| Hint | 描述 |
|------|------|
| `hint_range(min, max)` | 范围提示 |
| `source_color` | 颜色提示 |
| `hint_albedo` | 纹理提示（默认白色） |
| `hint_normal` | 法线纹理提示 |

```gdscript
uniform vec4 hurt_color : source_color;
uniform float hurt_intensity : hint_range(0.0, 1.0) = 0.0;
uniform float progress : hint_range(0.0, 1.0, 0.1) = 0.5;
```

## 5. 内置全局变量

### 数学常量

| 变量 | 描述 | 值 |
|------|------|-----|
| `PI` | 圆周率 | 3.14159265359 |
| `TAU` | 2倍圆周率 | 6.28318530718 |
| `E` | 自然常数 e | 2.71828182846 |

### 时间相关

| 变量 | 描述 |
|------|------|
| `TIME` | 从游戏开始经过的时间（秒） |
| `FRAME` | 当前帧编号 |

### UV 坐标

| 变量 | 描述 |
|------|------|
| `UV` | 当前像素的 UV 坐标（0.0 ~ 1.0） |

## 6. 基础数学函数

### 绝对值与取整

```glsl
float abs(float x)
float floor(float x)
float ceil(float x)
float round(float x)
float fract(float x)
```

### 极值与限制

```glsl
float min(float x, float y)
float max(float x, float y)
float clamp(float x, min_val, max_val)
float step(float edge, float x)
```

### 插值函数

```glsl
float mix(float x, float y, float alpha)
float smoothstep(float edge0, float edge1, float x)
```

## 7. 三角函数

```glsl
sin(x), cos(x), tan(x)
asin(x), acos(x), atan(x)
```

## 8. 向量运算

### 点乘与叉乘

```glsl
float dot(vec2 x, vec2 y)
vec3 cross(vec3 x, vec3 y)
```

### 长度与归一化

```glsl
float length(vec2 v)
vec2 normalize(vec2 v)
float distance(vec2 a, vec2 b)
```

### 反射与折射

```glsl
vec2 reflect(vec2 I, vec2 N)
vec3 refract(vec3 I, vec3 N, float eta)
```

## 9. UV 操作模式

### 缩放

```gdscript
shader_type canvas_item;

uniform vec2 scale = vec2(2.0, 2.0);
uniform vec2 pivot = vec2(0.5, 0.5);

void vertex() {
    UV -= pivot;
    UV /= scale;
    UV += pivot;
}
```

### 旋转

```gdscript
shader_type canvas_item;
render_mode unshaded;

uniform float angular_speed = 1.0;
uniform vec2 pivot = vec2(0.5, 0.5);

void vertex() {
    UV -= pivot;
    float rot = TIME * angular_speed;
    UV *= mat2(
        vec2(sin(rot), -cos(rot)),
        vec2(cos(rot), sin(rot))
    );
    UV += pivot;
}
```

### 偏移/滚动

```gdscript
shader_type canvas_item;

uniform vec2 scroll_speed = vec2(1, 0.0);

void fragment() {
    vec2 offset_uv = UV + cos(TIME) * scroll_speed;
    COLOR = texture(TEXTURE, offset_uv);
}
```

## 10. 颜色操作

### 灰度处理

```gdscript
shader_type canvas_item;

void fragment() {
    vec4 color = texture(TEXTURE, UV);
    float gray = dot(color.rgb, vec3(0.299, 0.587, 0.114));
    COLOR = vec4(vec3(gray), color.a);
}
```

### 颜色调整

```gdscript
shader_type canvas_item;

uniform float brightness = 0.0;
uniform float contrast = 1.0;
uniform float saturation = 1.0;

void fragment() {
    vec4 color = texture(TEXTURE, UV);
    color.rgb += brightness;
    color.rgb = (color.rgb - 0.5) * contrast + 0.5;
    float gray = dot(color.rgb, vec3(0.299, 0.587, 0.114));
    color.rgb = mix(vec3(gray), color.rgb, saturation);
    COLOR = color;
}
```

## 11. 噪声函数

### 随机数

```glsl
float random(float x) {
    return fract(sin(x) * 43758.5453);
}

float noise(vec2 st) {
    vec2 i = floor(st);
    vec2 f = fract(st);
    float a = random(i);
    float b = random(i + vec2(1.0, 0.0));
    float c = random(i + vec2(0.0, 1.0));
    float d = random(i + vec2(1.0, 1.0));
    vec2 u = f * f * (3.0 - 2.0 * f);
    return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y;
}
```

### FBM (分形布朗运动)

```glsl
float fbm(vec2 st) {
    float value = 0.0;
    float amplitude = 0.5;
    float frequency = 1.0;

    for (int i = 0; i < 6; i++) {
        value += amplitude * noise(st * frequency);
        frequency *= 2.0;
        amplitude *= 0.5;
    }
    return value;
}
```

## 12. 实用技巧

### 创建圆形

```glsl
shader_type canvas_item;

void fragment() {
    vec2 center = vec2(0.5, 0.5);
    float radius = 0.4;
    float dist = length(UV - center);
    float circle = step(radius, dist);
    COLOR = vec4(vec3(circle), 1.0);
}
```

### 波浪效果

```glsl
void fragment() {
    float wave = sin(UV.y * 10.0 + TIME * 2.0) * 0.1 + 0.5;
    COLOR = vec4(vec3(wave), 1.0);
}
```

### 条纹动画

```glsl
void fragment() {
    float stripe = sin(UV.y * 20.0 + TIME * 5.0);
    stripe = stripe * 0.5 + 0.5;
    COLOR = vec4(vec3(stripe), 1.0);
}
```

## 13. 性能优化

### 减少纹理采样

```gdscript
// 错误：多次采样
void fragment() {
    float r = texture(TEXTURE, UV).r;
    float g = texture(TEXTURE, UV + vec2(0.1, 0.0)).g;
}

// 正确：单次采样
void fragment() {
    vec4 tex = texture(TEXTURE, UV);
    float r = tex.r;
    float g = tex.g;
}
```

### 避免分支

```gdscript
// 避免
if (condition) {
    color = a;
} else {
    color = b;
}

// 推荐：使用 step 或 mix
color = mix(a, b, step(threshold, value));
```
