初始天空盒
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
# 2026-09-21
|
||||
|
||||
## 程序化卡通天空(world/sky/)
|
||||
|
||||
新增 `res://world/sky/cartoon_sky.gdshader` + `cartoon_sky.tres`(Sky 资源,内含调好的 ShaderMaterial),
|
||||
并让 `world/main.tscn` 的 WorldEnvironment 改用它;同时把 `Sun` 的 light_color 调成暖白
|
||||
(1.0, 0.97, 0.90),项目设置开了 `rendering/anti_aliasing/quality/use_debanding`。
|
||||
|
||||
渲染顺序:渐变天空 → 地面半球 → 星空 → 太阳 → 云 → 地平线雾霭。
|
||||
全部由噪声现场生成,无贴图。参数按 Gradient / Sun / Stars / Clouds / Haze 分组暴露在 Inspector。
|
||||
|
||||
### Godot shader 踩坑(重要,下次直接避开)
|
||||
|
||||
1. **`mat2(a,b,c,d)` 不合法**。Godot 着色器语言只接受列向量构造:`mat2(vec2, vec2)`。
|
||||
同理 mat3 要用三个 vec3。报错形式是
|
||||
`Invalid arguments for the built-in function: "mat2(float,float,float,float)"`。
|
||||
2. **天空着色器的编译错误不在 `logs_read(source="editor")` 里**,除非触发一次编译。
|
||||
可靠的取错方式:改完 → `filesystem_manage(op="scan")` → `project_run` →
|
||||
`logs_read(source="editor", include_details=true)`。game 日志只给一行
|
||||
`version_get_shader: Parameter "version" is null`,没用。
|
||||
3. **`smoothstep(edge0, edge1, x)` 不要写 edge0 > edge1**,改成 `1.0 - smoothstep(...)`。
|
||||
4. 变量重名(同一函数内二次声明)会报 `Redefinition of 'x'`,直接让整个 shader 编译失败。
|
||||
5. shader 编译失败时天空渲染成**纯黑**,不是品红 —— 别以为是资源没挂上。
|
||||
6. **编辑器里的 Shader 面板会缓存旧的编译报错**。外部改完 .gdshader + scan 之后,
|
||||
面板可能仍显示上一次失败的 `mat2(float,float,float,float)` 之类信息,
|
||||
而 Debugger → Errors 已经是空的。判定方法:看 `logs_read(source="editor")` 是否为空,
|
||||
再 `project_run` 一次看天空是否正常。**不要照着这条过期报错去改代码。**
|
||||
注意:如果 Shader 标签页里留着一份旧的未保存副本,从面板里保存会把我改好的文件覆盖回去。
|
||||
|
||||
### 云的形态(花了最多时间)
|
||||
|
||||
- **别用「水平云平面」投影 `uv = dir.xz / dir.y`**:低仰角处透视压缩成 10:1,
|
||||
云被拉成细条;若再对 dir.y 做硬 clamp,被钉死的距离会让噪声只随方位角变化,
|
||||
直接拉出**竖条拖影**。
|
||||
- **也别用方位角等距投影**(`uv = normalize(dir.xz) * acos(dir.y)`):天顶是极点,
|
||||
云会全部朝圆心收拢,抬头就看得见。
|
||||
- **正解是球极投影 `uv = dir.xz / (1.0 + dir.y)`**:保角 → 形状不拉伸;
|
||||
天顶只是圆盘圆心而非收缩极点;方位角天然无缝;角尺寸从地平线到天顶只放大 2 倍,
|
||||
接近真实透视。这个投影配 2D Perlin 出图最好。
|
||||
- **噪声用 Perlin 梯度噪声,不要 value noise**:value noise 在格点处梯度为零,
|
||||
阈值化后会切出一块块多边形的棱角("晶体"感)。
|
||||
- **三维 Perlin 在这台机器上不行**:sin 系哈希(`fract(sin(dot(p,k))*43758)`)在大坐标
|
||||
(fbm 第 3~4 个倍频时 dot 可达 1e4)下掉精度,高频倍频退化成纯噪声 → 云变成细丝。
|
||||
Hoskins 的 fract 系哈希精度安全,但出图仍偏块状。最终放弃 3D,回到 2D Perlin。
|
||||
- **阈值要压在 fbm 分布均值之上**。阈值贴着均值时等值线本身就很纠结,
|
||||
云会变成一张"蛛网";抬到 +0.5σ 以上才是干净的团块。
|
||||
|
||||
### 当前调好的参数
|
||||
|
||||
coverage 0.33 / scale 5.0 / edge 0.16 / warp 0.30 / horizon_fade 0.18 / speed 0.01,
|
||||
云影色 (0.45,0.62,0.88),边缘辉光 (1,0.93,0.76)。
|
||||
|
||||
## Sun 阴影(当天稍后)
|
||||
|
||||
`/Main/Sun` 开了 `shadow_enabled = true`;同时把 `directional_shadow_max_distance`
|
||||
从默认 100 收到 40(场景只有 40×40,收窄后阴影贴图分辨率集中到实际范围,边缘干净很多),
|
||||
并开 `directional_shadow_blend_splits` 消除 split 之间的接缝。
|
||||
|
||||
### 又一个 Godot MCP 坑
|
||||
|
||||
`node_set_property` 写 **bool** 属性会失败:`true` 和 `1` 都被序列化成 String,
|
||||
报 `WRONG_TYPE: Cannot write String to a bool property`。
|
||||
**bool 属性只能直接改 .tscn,再 `scene_open(force_reload=true)`。**
|
||||
(Color / Vector3 用 dict 传是正常的,`light_color` 就是这么改的。)
|
||||
|
||||
## 待办 / 可选后续
|
||||
|
||||
- 地面还是灰白色 (0.55,0.58,0.62),被天空的蓝色环境光染成了淡紫。
|
||||
换成草绿之类的固有色会协调很多 —— 这是目前画面里最突兀的一处。
|
||||
- `star_amount` 默认 0,太阳落到地平线以下会自动淡入星空,还没实测过夜景。
|
||||
+1
-1
@@ -31,7 +31,7 @@ spring_length = 4.0
|
||||
|
||||
[node name="Camera" type="Camera3D" parent="CameraRig/SpringArm" unique_id=52294557]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 4)
|
||||
fov = 70.0
|
||||
fov = 82.2
|
||||
|
||||
[node name="Body" type="Node3D" parent="." unique_id=394283421]
|
||||
|
||||
|
||||
+7
-10
@@ -1,6 +1,7 @@
|
||||
[gd_scene format=3 uid="uid://bp8l1uwgshc86"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://bekuuw153mv03" path="res://player/player.tscn" id="1_gjxf3"]
|
||||
[ext_resource type="Sky" path="res://world/sky/cartoon_sky.tres" id="2_cartoon"]
|
||||
|
||||
[sub_resource type="BoxShape3D" id="BoxShape3D_hyim0"]
|
||||
size = Vector3(40, 0.5, 40)
|
||||
@@ -14,19 +15,11 @@ subdivide_depth = 8
|
||||
albedo_color = Color(0.5529412, 0.5803922, 0.61960787, 1)
|
||||
roughness = 0.9
|
||||
|
||||
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_cmo1i"]
|
||||
sky_top_color = Color(0.38, 0.45, 0.55, 1)
|
||||
sky_horizon_color = Color(0.65, 0.67, 0.7, 1)
|
||||
ground_bottom_color = Color(0.2, 0.17, 0.13, 1)
|
||||
ground_horizon_color = Color(0.65, 0.67, 0.7, 1)
|
||||
|
||||
[sub_resource type="Sky" id="Sky_i1eo7"]
|
||||
sky_material = SubResource("ProceduralSkyMaterial_cmo1i")
|
||||
|
||||
[sub_resource type="Environment" id="Environment_gu74f"]
|
||||
background_mode = 2
|
||||
sky = SubResource("Sky_i1eo7")
|
||||
sky = ExtResource("2_cartoon")
|
||||
ambient_light_source = 3
|
||||
reflected_light_source = 2
|
||||
|
||||
[node name="Main" type="Node3D" unique_id=58155864]
|
||||
|
||||
@@ -42,6 +35,10 @@ surface_material_override/0 = SubResource("StandardMaterial3D_spvjk")
|
||||
|
||||
[node name="Sun" type="DirectionalLight3D" parent="." unique_id=910400852]
|
||||
transform = Transform3D(0.8660248, 0.3830344, -0.32138094, 0, 0.6427605, 0.76606715, 0.5000011, -0.66343313, 0.5566465, 0, 0, 0)
|
||||
light_color = Color(1, 0.97, 0.9, 1)
|
||||
shadow_enabled = true
|
||||
directional_shadow_blend_splits = true
|
||||
directional_shadow_max_distance = 40.0
|
||||
|
||||
[node name="Player" parent="." unique_id=869687860 instance=ExtResource("1_gjxf3")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.3, 0)
|
||||
|
||||
@@ -0,0 +1,249 @@
|
||||
shader_type sky;
|
||||
|
||||
/* ===========================================================================
|
||||
Cartoon Sky · 纯程序化,零贴图
|
||||
---------------------------------------------------------------------------
|
||||
渲染顺序: 渐变天空 → 地面半球 → 星星 → 太阳 → 云层 → 地平线雾霭
|
||||
|
||||
所有参数都暴露在 Inspector 里(按分组排列),可以实时调、不用重新编译。
|
||||
云与星星全部由 hash / value-noise / fbm 现场生成。
|
||||
=========================================================================== */
|
||||
|
||||
// ----------------------------------------------------------- 渐变天空 -----
|
||||
group_uniforms Gradient;
|
||||
uniform vec3 zenith_color : source_color = vec3(0.118, 0.357, 0.851); // 天顶
|
||||
uniform vec3 mid_color : source_color = vec3(0.353, 0.651, 0.941); // 中段
|
||||
uniform vec3 horizon_color : source_color = vec3(0.851, 0.933, 1.000); // 地平线
|
||||
uniform vec3 ground_color : source_color = vec3(0.290, 0.329, 0.384); // 地面半球
|
||||
uniform float gradient_bias : hint_range(0.10, 6.00) = 0.85; // 渐变挤压
|
||||
uniform float band_count : hint_range(0.00, 20.00) = 0.00; // 0=平滑,>0=色阶数
|
||||
uniform float band_sharpness : hint_range(0.00, 1.00) = 0.90; // 色阶硬度
|
||||
|
||||
// ---------------------------------------------------------------- 太阳 -----
|
||||
group_uniforms Sun;
|
||||
uniform float follow_scene_light : hint_range(0.0, 1.0) = 1.0; // 跟随场景平行光
|
||||
uniform vec3 sun_direction = vec3(0.35, 0.55, 0.35); // 不跟随时手动指定
|
||||
uniform vec3 sun_core_color : source_color = vec3(1.000, 0.976, 0.878);
|
||||
uniform vec3 sun_halo_color : source_color = vec3(1.000, 0.827, 0.478);
|
||||
uniform float sun_disk_size : hint_range(0.0, 0.40) = 0.035; // 弧度
|
||||
uniform float sun_disk_softness : hint_range(0.0, 1.0) = 0.20;
|
||||
uniform float sun_halo_size : hint_range(0.0, 2.00) = 0.55;
|
||||
uniform float sun_halo_strength : hint_range(0.0, 4.00) = 0.65;
|
||||
uniform float sun_bloom_strength : hint_range(0.0, 4.00) = 0.35;
|
||||
uniform float sun_intensity : hint_range(0.0, 8.00) = 1.70;
|
||||
|
||||
// ---------------------------------------------------------------- 星空 -----
|
||||
group_uniforms Stars;
|
||||
uniform float star_amount : hint_range(0.0, 1.0) = 0.0; // 太阳落山后自动淡入
|
||||
uniform float star_density : hint_range(10.0, 160.0) = 60.0;
|
||||
uniform float star_size : hint_range(0.005, 0.30) = 0.050;
|
||||
uniform float star_twinkle : hint_range(0.0, 1.0) = 0.65;
|
||||
uniform vec3 star_color : source_color = vec3(0.85, 0.90, 1.00);
|
||||
|
||||
// ---------------------------------------------------------------- 云层 -----
|
||||
group_uniforms Clouds;
|
||||
uniform vec4 cloud_color : source_color = vec4(1.000, 1.000, 1.000, 1.0); // 受光面
|
||||
uniform vec4 cloud_shadow_color : source_color = vec4(0.624, 0.761, 0.910, 1.0); // 背光面
|
||||
uniform vec4 cloud_rim_color : source_color = vec4(1.000, 0.914, 0.722, 1.0); // 边缘辉光
|
||||
uniform float cloud_coverage : hint_range(0.0, 1.0) = 0.46; // 云量
|
||||
uniform float cloud_scale : hint_range(0.50, 12.0) = 4.0; // 云团大小(越大云越小越多)
|
||||
uniform float cloud_horizon_fade : hint_range(0.0, 0.60) = 0.18; // 地平线淡出高度(sin 仰角)
|
||||
uniform float cloud_edge : hint_range(0.005, 0.60) = 0.10; // 轮廓软硬
|
||||
uniform float cloud_warp : hint_range(0.0, 3.0) = 0.55; // 揉皱程度(蓬松感)
|
||||
uniform float cloud_speed : hint_range(0.0, 1.0) = 0.010; // 飘动速度
|
||||
uniform vec2 cloud_direction = vec2(1.0, 0.25); // 风向
|
||||
uniform float cloud_shading : hint_range(0.0, 1.0) = 0.55; // 明暗对比
|
||||
uniform float cloud_rim : hint_range(0.0, 2.0) = 0.40; // 描边辉光强度
|
||||
uniform float cloud_opacity : hint_range(0.0, 1.0) = 1.0;
|
||||
|
||||
// ------------------------------------------------------------ 地平线雾霭 ---
|
||||
group_uniforms Haze;
|
||||
uniform vec3 haze_color : source_color = vec3(0.851, 0.929, 1.000);
|
||||
uniform float haze_strength : hint_range(0.0, 1.0) = 0.55;
|
||||
uniform float haze_height : hint_range(0.0, 0.60) = 0.14;
|
||||
|
||||
// ===========================================================================
|
||||
// 噪声工具
|
||||
// ===========================================================================
|
||||
|
||||
float hash21(vec2 p) {
|
||||
p = fract(p * vec2(123.34, 456.21));
|
||||
p += dot(p, p + 45.32);
|
||||
return fract(p.x * p.y);
|
||||
}
|
||||
|
||||
// 伪随机梯度方向(每个分量 -1..1)。用 fract 混合而不是 sin,
|
||||
// 大坐标下也不会掉精度。
|
||||
vec2 hash22(vec2 p) {
|
||||
vec3 p3 = fract(vec3(p.x, p.y, p.x) * vec3(0.1031, 0.1030, 0.0973));
|
||||
p3 += dot(p3, vec3(p3.y, p3.z, p3.x) + 33.33);
|
||||
return fract(vec2((p3.x + p3.y) * p3.z, (p3.x + p3.z) * p3.y)) * 2.0 - 1.0;
|
||||
}
|
||||
|
||||
// 梯度噪声(Perlin)。相比 value noise,它在格点处不会出现「梯度为零」的平台,
|
||||
// 等值线是有机的团块 —— 阈值化之后不会切出一块块多边形的棱角。
|
||||
float gradient_noise(vec2 p) {
|
||||
vec2 i = floor(p);
|
||||
vec2 f = fract(p);
|
||||
// 五次插值:二阶导连续
|
||||
vec2 u = f * f * f * (f * (f * 6.0 - 15.0) + 10.0);
|
||||
float a = dot(hash22(i), f);
|
||||
float b = dot(hash22(i + vec2(1.0, 0.0)), f - vec2(1.0, 0.0));
|
||||
float c = dot(hash22(i + vec2(0.0, 1.0)), f - vec2(0.0, 1.0));
|
||||
float d = dot(hash22(i + vec2(1.0, 1.0)), f - vec2(1.0, 1.0));
|
||||
return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);
|
||||
}
|
||||
|
||||
// 5 个倍频的分形噪声:每个倍频先旋转再平移,避免出现轴向条纹
|
||||
float fbm(vec2 p) {
|
||||
float sum = 0.0;
|
||||
float amp = 0.5;
|
||||
float norm = 0.0;
|
||||
mat2 rot = mat2(vec2(0.80, 0.60), vec2(-0.60, 0.80));
|
||||
for (int i = 0; i < 5; i++) {
|
||||
sum += amp * gradient_noise(p);
|
||||
norm += amp;
|
||||
p = rot * p * 2.03 + 11.31;
|
||||
amp *= 0.5;
|
||||
}
|
||||
return sum / norm;
|
||||
}
|
||||
|
||||
// 卡通色阶:把 0..1 压成 n 段硬边色块(n<0.5 时原样返回 = 平滑)
|
||||
float posterize(float t, float n, float sharp) {
|
||||
if (n < 0.5) {
|
||||
return t;
|
||||
}
|
||||
float s = t * n;
|
||||
float base = floor(s);
|
||||
float fr = s - base;
|
||||
float e = mix(0.5, 0.015, clamp(sharp, 0.0, 1.0));
|
||||
return (base + smoothstep(0.5 - e, 0.5 + e, fr)) / n;
|
||||
}
|
||||
|
||||
// 云密度场:先做一次廉价的 domain warp 把噪声揉皱,云朵才会蓬松。
|
||||
// 返回未归一化的原始 fbm —— 调用方需要它来算方向性明暗。
|
||||
float cloud_field(vec2 p, float warp_amt) {
|
||||
if (warp_amt > 0.001) {
|
||||
vec2 w = vec2(gradient_noise(p * 0.5 + vec2(13.7, 5.1)),
|
||||
gradient_noise(p * 0.5 + vec2(2.3, 21.9)));
|
||||
p += w * warp_amt;
|
||||
}
|
||||
return fbm(p);
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// 主函数
|
||||
// ===========================================================================
|
||||
|
||||
void sky() {
|
||||
vec3 dir = normalize(EYEDIR);
|
||||
|
||||
// ---------------------------------------------------------- 渐变天空 --
|
||||
float up = clamp(dir.y, 0.0, 1.0);
|
||||
float t = pow(up, 1.0 / max(gradient_bias, 0.05));
|
||||
t = posterize(t, band_count, band_sharpness);
|
||||
|
||||
vec3 col = mix(horizon_color, mid_color, smoothstep(0.02, 0.30, t));
|
||||
col = mix(col, zenith_color, smoothstep(0.30, 0.80, t));
|
||||
|
||||
// 地平线以下:压向地面色
|
||||
float below = 1.0 - smoothstep(-0.05, 0.005, dir.y);
|
||||
col = mix(col, ground_color, below * 0.9);
|
||||
|
||||
// --------------------------------------------------------------- 太阳 --
|
||||
vec3 sun_dir = normalize(sun_direction);
|
||||
if (LIGHT0_ENABLED && follow_scene_light > 0.5) {
|
||||
sun_dir = normalize(LIGHT0_DIRECTION);
|
||||
}
|
||||
float sun_dot = clamp(dot(dir, sun_dir), -1.0, 1.0);
|
||||
// 小角度近似,比 acos 数值稳定得多
|
||||
float ang = sqrt(max(2.0 * (1.0 - sun_dot), 0.0));
|
||||
|
||||
// 太阳低于地平线时自动入夜
|
||||
float night = 1.0 - smoothstep(-0.10, 0.08, sun_dir.y);
|
||||
|
||||
// --------------------------------------------------------------- 星空 --
|
||||
if (star_amount > 0.001 && night > 0.001 && dir.y > -0.02) {
|
||||
vec2 suv = vec2(atan(dir.x, dir.z), dir.y);
|
||||
vec2 gv = suv * star_density;
|
||||
vec2 id = floor(gv);
|
||||
vec2 f = fract(gv) - 0.5;
|
||||
float rnd = hash21(id);
|
||||
// 稀疏化:只有一小部分格子长星星
|
||||
float keep = step(0.93, rnd);
|
||||
vec2 offset = (vec2(hash21(id + 3.7), hash21(id + 9.1)) - 0.5) * 0.7;
|
||||
float d = length(f - offset);
|
||||
float twinkle = mix(1.0, 0.30 + 0.70 * sin(TIME * (1.5 + rnd * 4.0) + rnd * 40.0), star_twinkle);
|
||||
float star = (1.0 - smoothstep(0.0, max(star_size, 0.0001), d)) * keep * twinkle;
|
||||
col += star_color * star * star_amount * night * smoothstep(-0.02, 0.10, dir.y);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------- 太阳 --
|
||||
// 硬边圆盘
|
||||
float disk_in = max(sun_disk_size * (1.0 - sun_disk_softness * 0.85), 0.0001);
|
||||
float disk = 1.0 - smoothstep(disk_in, max(sun_disk_size, disk_in + 0.0001), ang);
|
||||
// 光晕
|
||||
float halo = pow(1.0 - smoothstep(sun_disk_size, sun_disk_size + max(sun_halo_size, 0.0001), ang), 2.0);
|
||||
// 大范围泛光
|
||||
float bloom = pow(max(sun_dot, 0.0), 12.0);
|
||||
|
||||
vec3 sun_col = sun_core_color * (disk * sun_intensity)
|
||||
+ sun_halo_color * (halo * sun_halo_strength * sun_intensity)
|
||||
+ sun_halo_color * (bloom * sun_bloom_strength);
|
||||
col += sun_col * (1.0 - below);
|
||||
|
||||
// --------------------------------------------------------------- 云层 --
|
||||
// 球极投影:把上半球保角地映到一张圆盘上(天顶落在圆心,地平线落在半径 1)。
|
||||
// 保角 = 云朵形状不被拉伸;天顶只是圆盘的圆心,不会像方位角等距投影那样
|
||||
// 把云朝一个点收拢。云的角尺寸从地平线到天顶平滑放大 2 倍,接近真实透视。
|
||||
vec2 uv = (dir.xz / (1.0 + dir.y)) * cloud_scale;
|
||||
|
||||
vec2 wind = cloud_direction;
|
||||
if (length(wind) < 0.0001) {
|
||||
wind = vec2(1.0, 0.0);
|
||||
}
|
||||
uv += normalize(wind) * (TIME * cloud_speed * 3.0);
|
||||
|
||||
// 形状采样 + 朝太阳方位偏移一次的采样 → 得到方向性明暗
|
||||
vec2 sun_az = sun_dir.xz;
|
||||
if (length(sun_az) < 0.0001) {
|
||||
sun_az = vec2(1.0, 0.0);
|
||||
}
|
||||
sun_az = normalize(sun_az);
|
||||
vec2 light_off = sun_az * (cloud_shading * 0.8);
|
||||
|
||||
float raw = cloud_field(uv, cloud_warp);
|
||||
float raw_lit = cloud_field(uv + light_off, cloud_warp);
|
||||
|
||||
// 原始 fbm 落在 -0.4..0.4 附近,拉开对比后映射到 0..1 再交给阈值
|
||||
float dens = clamp(raw * 1.3 + 0.5, 0.0, 1.0);
|
||||
|
||||
// 云量控制阈值:coverage 越大,阈值越低,云越多
|
||||
float thresh = mix(0.80, 0.10, cloud_coverage);
|
||||
float mask = smoothstep(thresh, thresh + cloud_edge, dens);
|
||||
|
||||
// 受光判定:朝太阳方向采样到的密度更低 → 当前点处在迎光侧。
|
||||
// 再按厚度压暗云芯,最后压成 3 段,得到赛璐璐风格的两面明暗。
|
||||
float lit = clamp((raw - raw_lit) * cloud_shading * 20.0 + 0.5, 0.0, 1.0);
|
||||
float thickness = smoothstep(thresh, thresh + 0.5, dens);
|
||||
lit = clamp(lit - thickness * 0.32, 0.0, 1.0);
|
||||
lit = posterize(lit, 3.0, 0.9);
|
||||
|
||||
vec3 cloud_col = mix(cloud_shadow_color.rgb, cloud_color.rgb, lit);
|
||||
|
||||
// 边缘辉光:靠近轮廓、且朝太阳那一侧
|
||||
float interior = smoothstep(thresh, thresh + cloud_edge * 2.0, dens);
|
||||
float rim = mask * (1.0 - interior) * smoothstep(0.45, 0.95, lit) * cloud_rim;
|
||||
cloud_col += cloud_rim_color.rgb * rim;
|
||||
|
||||
// 越贴近地平线越淡
|
||||
float cloud_a = mask * cloud_opacity * smoothstep(0.0, max(cloud_horizon_fade, 0.001), dir.y);
|
||||
col = mix(col, cloud_col, cloud_a);
|
||||
|
||||
// ----------------------------------------------------------- 地平线雾 --
|
||||
float haze = pow(1.0 - smoothstep(0.0, max(haze_height, 0.001), abs(dir.y)), 2.0);
|
||||
col = mix(col, haze_color, haze * haze_strength * (1.0 - cloud_a * 0.7));
|
||||
|
||||
COLOR = col;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://de7313djio1xm
|
||||
@@ -0,0 +1,9 @@
|
||||
[gd_resource type="Sky" format=3 uid="uid://bi632suyifms5"]
|
||||
|
||||
[ext_resource type="Shader" uid="uid://de7313djio1xm" path="res://world/sky/cartoon_sky.gdshader" id="1_cartoon"]
|
||||
|
||||
[sub_resource type="ShaderMaterial" id="ShaderMaterial_cartoon"]
|
||||
shader = ExtResource("1_cartoon")
|
||||
|
||||
[resource]
|
||||
sky_material = SubResource("ShaderMaterial_cartoon")
|
||||
Reference in New Issue
Block a user