победа над водопадами, шейдеры m2

This commit is contained in:
2026-07-07 10:45:43 +04:00
parent 8738c2495d
commit 44614a79e4
38 changed files with 4820 additions and 192 deletions
+100 -12
View File
@@ -21,6 +21,10 @@ static var _baked_texture_material_cache: Dictionary = {}
static var _alpha_texture_cache: Dictionary = {}
static var _layered_material_cache: Dictionary = {}
static func _ensure_wow_shader_globals() -> void:
pass
## Build a Node3D with 256 terrain chunk meshes.
## `extracted_dir` must be an absolute path to the extracted/ folder so BLPs can be loaded.
static func build(data: Dictionary, extracted_dir: String = "") -> Node3D:
@@ -1253,6 +1257,7 @@ static func _get_control_splat_shader() -> Shader:
if _control_splat_shader:
return _control_splat_shader
_ensure_wow_shader_globals()
_control_splat_shader = Shader.new()
_control_splat_shader.code = """
shader_type spatial;
@@ -1269,10 +1274,34 @@ uniform float ambient = 0.62;
uniform float diffuse = 0.38;
uniform float hemi = 0.12;
global uniform vec4 wow_ambient_color;
global uniform vec4 wow_light_color;
global uniform vec3 wow_light_dir;
global uniform vec4 wow_fog_color;
global uniform vec2 wow_fog_range;
global uniform float wow_fog_density;
varying vec3 world_pos;
varying vec3 world_normal;
varying vec3 view_pos;
void vertex() {
world_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
world_normal = normalize(MODEL_NORMAL_MATRIX * NORMAL);
view_pos = (MODELVIEW_MATRIX * vec4(VERTEX, 1.0)).xyz;
}
vec3 sample_layer(float layer, vec2 continuous_chunk_uv) {
return texture(terrain_tex, vec3(continuous_chunk_uv * uv_scale, layer), mip_bias).rgb;
}
vec3 apply_wow_fog(vec3 color) {
float dist = length(view_pos);
float range_fog = smoothstep(wow_fog_range.x, wow_fog_range.y, dist);
float fog_amount = range_fog * clamp(wow_fog_density, 0.0, 0.55);
return mix(color, wow_fog_color.rgb, fog_amount);
}
void fragment() {
vec2 tile_uv = clamp(UV, vec2(0.0), vec2(0.999999));
vec2 chunk_uv = tile_uv * 16.0;
@@ -1300,15 +1329,18 @@ void fragment() {
sample_layer(layers.z, chunk_uv) * w2 +
sample_layer(layers.w, chunk_uv) * w3;
vec3 n = normalize(NORMAL);
vec3 n = normalize(world_normal);
if (!FRONT_FACING) {
n = -n;
}
vec3 l = normalize(light_dir);
vec3 l = normalize(wow_light_dir);
float ndl = max(dot(n, l), 0.0);
float hemi_term = clamp(n.y * 0.5 + 0.5, 0.0, 1.0);
float light = ambient + diffuse * ndl + hemi * hemi_term;
ALBEDO = albedo * light;
vec3 ambient_tint = mix(vec3(0.74), max(wow_ambient_color.rgb, vec3(0.08)), 0.22);
vec3 light_tint = mix(vec3(1.0), wow_light_color.rgb, 0.12);
vec3 light = ambient_tint * ambient + light_tint * diffuse * ndl + vec3(hemi * hemi_term);
light = clamp(light, vec3(0.48), vec3(1.08));
ALBEDO = apply_wow_fog(albedo * light);
}
"""
return _control_splat_shader
@@ -1465,6 +1497,7 @@ static func _get_terrain_shader() -> Shader:
if _terrain_shader:
return _terrain_shader
_ensure_wow_shader_globals()
_terrain_shader = Shader.new()
_terrain_shader.code = """
shader_type spatial;
@@ -1487,6 +1520,30 @@ uniform float ambient = 0.62;
uniform float diffuse = 0.38;
uniform float hemi = 0.12;
global uniform vec4 wow_ambient_color;
global uniform vec4 wow_light_color;
global uniform vec3 wow_light_dir;
global uniform vec4 wow_fog_color;
global uniform vec2 wow_fog_range;
global uniform float wow_fog_density;
varying vec3 world_pos;
varying vec3 world_normal;
varying vec3 view_pos;
void vertex() {
world_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
world_normal = normalize(MODEL_NORMAL_MATRIX * NORMAL);
view_pos = (MODELVIEW_MATRIX * vec4(VERTEX, 1.0)).xyz;
}
vec3 apply_wow_fog(vec3 color) {
float dist = length(view_pos);
float range_fog = smoothstep(wow_fog_range.x, wow_fog_range.y, dist);
float fog_amount = range_fog * clamp(wow_fog_density, 0.0, 0.55);
return mix(color, wow_fog_color.rgb, fog_amount);
}
void fragment() {
vec2 tiled_uv = UV * uv_scale;
@@ -1516,15 +1573,18 @@ void fragment() {
if (layer_count > 2) { albedo += c2 * w2; }
if (layer_count > 3) { albedo += c3 * w3; }
vec3 n = normalize(NORMAL);
vec3 n = normalize(world_normal);
if (!FRONT_FACING) {
n = -n;
}
vec3 l = normalize(light_dir);
vec3 l = normalize(wow_light_dir);
float ndl = max(dot(n, l), 0.0);
float hemi_term = clamp(n.y * 0.5 + 0.5, 0.0, 1.0);
float light = ambient + diffuse * ndl + hemi * hemi_term;
ALBEDO = albedo.rgb * light;
vec3 ambient_tint = mix(vec3(0.74), max(wow_ambient_color.rgb, vec3(0.08)), 0.22);
vec3 light_tint = mix(vec3(1.0), wow_light_color.rgb, 0.12);
vec3 light = ambient_tint * ambient + light_tint * diffuse * ndl + vec3(hemi * hemi_term);
light = clamp(light, vec3(0.48), vec3(1.08));
ALBEDO = apply_wow_fog(albedo.rgb * light);
}
"""
return _terrain_shader
@@ -1534,6 +1594,7 @@ static func _get_single_texture_shader() -> Shader:
if _single_texture_shader:
return _single_texture_shader
_ensure_wow_shader_globals()
_single_texture_shader = Shader.new()
_single_texture_shader.code = """
shader_type spatial;
@@ -1548,6 +1609,23 @@ uniform float ambient = 0.62;
uniform float diffuse = 0.38;
uniform float hemi = 0.12;
global uniform vec4 wow_ambient_color;
global uniform vec4 wow_light_color;
global uniform vec3 wow_light_dir;
global uniform vec4 wow_fog_color;
global uniform vec2 wow_fog_range;
global uniform float wow_fog_density;
varying vec3 world_pos;
varying vec3 world_normal;
varying vec3 view_pos;
void vertex() {
world_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
world_normal = normalize(MODEL_NORMAL_MATRIX * NORMAL);
view_pos = (MODELVIEW_MATRIX * vec4(VERTEX, 1.0)).xyz;
}
vec3 sample_sharp(sampler2D tex, vec2 uv) {
vec3 center = texture(tex, uv, mip_bias).rgb;
if (sharpen_strength <= 0.001) {
@@ -1564,16 +1642,26 @@ vec3 sample_sharp(sampler2D tex, vec2 uv) {
return clamp(center * (1.0 + 4.0 * sharpen_strength) - side * sharpen_strength, vec3(0.0), vec3(1.0));
}
vec3 apply_wow_fog(vec3 color) {
float dist = length(view_pos);
float range_fog = smoothstep(wow_fog_range.x, wow_fog_range.y, dist);
float fog_amount = range_fog * clamp(wow_fog_density, 0.0, 0.55);
return mix(color, wow_fog_color.rgb, fog_amount);
}
void fragment() {
vec3 n = normalize(NORMAL);
vec3 n = normalize(world_normal);
if (!FRONT_FACING) {
n = -n;
}
vec3 l = normalize(light_dir);
vec3 l = normalize(wow_light_dir);
float ndl = max(dot(n, l), 0.0);
float hemi_term = clamp(n.y * 0.5 + 0.5, 0.0, 1.0);
float light = ambient + diffuse * ndl + hemi * hemi_term;
ALBEDO = sample_sharp(tex0, UV * uv_scale) * light;
vec3 ambient_tint = mix(vec3(0.74), max(wow_ambient_color.rgb, vec3(0.08)), 0.22);
vec3 light_tint = mix(vec3(1.0), wow_light_color.rgb, 0.12);
vec3 light = ambient_tint * ambient + light_tint * diffuse * ndl + vec3(hemi * hemi_term);
light = clamp(light, vec3(0.48), vec3(1.08));
ALBEDO = apply_wow_fog(sample_sharp(tex0, UV * uv_scale) * light);
}
"""
return _single_texture_shader