архитектура и цели для агентов

This commit is contained in:
2026-07-10 10:28:37 +04:00
parent f561e52aa9
commit 93bfe114c0
46 changed files with 2826 additions and 55 deletions
@@ -4,7 +4,7 @@ class_name WowWMOMaterial
const WMOBLEND_OPAQUE := 0
const WMOBLEND_ALPHA_KEY := 1
const WMOBLEND_ALPHA := 2
const SHADER_VERSION := 3
const SHADER_VERSION := 10
static var _shader_cache: Dictionary = {}
@@ -31,7 +31,9 @@ static func build(
texture3: Texture2D = null,
texture3_path: String = "") -> ShaderMaterial:
var mode := _blend_shader_mode(blend_mode)
var is_window_material := _is_window_texture(texture_path)
var is_glass_blend_material := is_window_material and blend_mode == WMOBLEND_ALPHA
var mode := _blend_shader_mode(blend_mode, is_glass_blend_material)
var effective_diffuse := diffuse_color
if maxf(maxf(effective_diffuse.r, effective_diffuse.g), effective_diffuse.b) <= 0.001:
effective_diffuse = Color.WHITE
@@ -40,7 +42,7 @@ static func build(
var mat := ShaderMaterial.new()
mat.resource_name = texture_path.get_file().get_basename()
var pixel_shader := _wmo_pixel_shader_id(shader_id)
mat.shader = _get_shader(mode, texture2 != null, texture3 != null)
mat.shader = _get_shader(mode, texture2 != null, texture3 != null, is_window_material)
mat.render_priority = 0 if blend_mode <= WMOBLEND_ALPHA_KEY else 1
mat.set_shader_parameter("albedo_tex", texture)
mat.set_shader_parameter("detail_tex", texture2)
@@ -53,11 +55,13 @@ static func build(
mat.set_shader_parameter("alpha_output_strength", _alpha_output_strength(blend_mode, pixel_shader))
mat.set_shader_parameter("vertex_color_strength", 0.72)
mat.set_shader_parameter("ambient_floor", 0.22)
mat.set_shader_parameter("unlit_material", 1.0 if (material_flags & 0x01) != 0 else 0.0)
mat.set_shader_parameter("diffuse_color", effective_diffuse)
mat.set_shader_parameter("emissive_color", emissive_color)
mat.set_shader_parameter("material_emissive_strength", _material_emissive_strength(material_flags, emissive_color, texture_path))
mat.set_shader_parameter("secondary_color", _effective_secondary_color(secondary_color))
mat.set_shader_parameter("detail_strength", 1.0 if texture2 != null else 0.0)
mat.set_shader_parameter("window_material", 1.0 if is_glass_blend_material else 0.0)
mat.set_meta("texture0_path", texture_path)
mat.set_meta("texture1_path", texture2_path)
mat.set_meta("texture2_path", texture3_path)
@@ -65,6 +69,8 @@ static func build(
mat.set_meta("wow_shader", shader_id)
mat.set_meta("wow_wmo_pixel_shader", pixel_shader)
mat.set_meta("wow_blend_mode", blend_mode)
mat.set_meta("wow_wmo_window_material", is_window_material)
mat.set_meta("wow_wmo_glass_blend_material", is_glass_blend_material)
return mat
@@ -127,7 +133,7 @@ static func _shader_alpha_is_opacity(pixel_shader: int) -> bool:
static func _alpha_ref(blend_mode: int, pixel_shader: int) -> float:
if blend_mode > WMOBLEND_OPAQUE:
if blend_mode == WMOBLEND_ALPHA_KEY:
return 0.501960814
return 0.0
@@ -151,13 +157,24 @@ static func _material_emissive_strength(material_flags: int, color: Color, textu
var strength := 0.12
if (material_flags & 0x10) != 0:
strength = 0.26
var lower_path := texture_path.to_lower()
if lower_path.contains("window") or lower_path.contains("_wnd_") or lower_path.contains("wnd_"):
if _is_window_texture(texture_path):
strength = minf(strength, 0.18)
return strength
static func _blend_shader_mode(blend_mode: int) -> String:
static func _is_window_texture(texture_path: String) -> bool:
var lower_path := texture_path.to_lower().replace("\\", "/")
var file_name := lower_path.get_file()
return lower_path.contains("/windows/") \
or lower_path.contains("/glass/") \
or file_name.contains("window") \
or file_name.contains("glass") \
or file_name.contains("_wnd_")
static func _blend_shader_mode(blend_mode: int, is_glass_blend_material: bool) -> String:
if is_glass_blend_material:
return "glass"
match blend_mode:
WMOBLEND_ALPHA_KEY:
return "cutout"
@@ -167,29 +184,31 @@ static func _blend_shader_mode(blend_mode: int) -> String:
return "opaque"
static func _get_shader(mode: String, has_detail: bool, has_extra: bool) -> Shader:
var key := "v=%d|%s|detail=%s|extra=%s" % [SHADER_VERSION, mode, str(has_detail), str(has_extra)]
static func _get_shader(mode: String, has_detail: bool, has_extra: bool, stable_albedo_sampler: bool = false) -> Shader:
var key := "v=%d|%s|detail=%s|extra=%s|stable_albedo=%s" % [SHADER_VERSION, mode, str(has_detail), str(has_extra), str(stable_albedo_sampler)]
if _shader_cache.has(key):
return _shader_cache[key]
var shader := Shader.new()
shader.code = _shader_code(mode, has_detail, has_extra)
shader.code = _shader_code(mode, has_detail, has_extra, stable_albedo_sampler)
_shader_cache[key] = shader
return shader
static func _shader_code(mode: String, has_detail: bool, has_extra: bool) -> String:
var render_modes: Array[String] = ["blend_mix", "cull_disabled", "unshaded"]
static func _shader_code(mode: String, has_detail: bool, has_extra: bool, stable_albedo_sampler: bool = false) -> String:
var render_modes: Array[String] = ["blend_mix", "unshaded"]
render_modes.append("cull_back" if mode == "glass" or stable_albedo_sampler else "cull_disabled")
if mode == "opaque" or mode == "cutout":
render_modes.append("depth_draw_opaque")
else:
render_modes.append("depth_prepass_alpha")
render_modes.append("depth_draw_never")
var albedo_sampler_hint := "filter_linear, repeat_disable" if stable_albedo_sampler else "filter_linear_mipmap_anisotropic, repeat_enable"
return """
shader_type spatial;
render_mode %s;
uniform sampler2D albedo_tex : source_color, filter_linear_mipmap_anisotropic, repeat_enable;
uniform sampler2D albedo_tex : source_color, %s;
uniform sampler2D detail_tex : source_color, filter_linear_mipmap_anisotropic, repeat_enable;
uniform sampler2D extra_tex : source_color, filter_linear_mipmap_anisotropic, repeat_enable;
uniform bool use_texture = false;
@@ -200,11 +219,13 @@ uniform float alpha_ref = 0.0;
uniform float alpha_output_strength = 0.0;
uniform float vertex_color_strength = 0.88;
uniform float ambient_floor = 0.20;
uniform float unlit_material = 0.0;
uniform vec4 diffuse_color : source_color = vec4(1.0);
uniform vec4 emissive_color : source_color = vec4(0.0);
uniform float material_emissive_strength = 0.0;
uniform vec4 secondary_color : source_color = vec4(1.0);
uniform float detail_strength = 0.0;
uniform float window_material = 0.0;
global uniform vec4 wow_ambient_color;
global uniform vec4 wow_light_color;
@@ -217,11 +238,13 @@ global uniform float wow_sun_elevation;
varying vec3 world_normal;
varying vec3 world_pos;
varying vec3 view_pos;
varying vec3 view_normal;
void vertex() {
world_normal = normalize(MODEL_NORMAL_MATRIX * NORMAL);
world_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
view_pos = (MODELVIEW_MATRIX * vec4(VERTEX, 1.0)).xyz;
view_normal = normalize((MODELVIEW_MATRIX * vec4(NORMAL, 0.0)).xyz);
}
vec3 apply_wow_fog(vec3 color) {
@@ -318,6 +341,9 @@ void fragment() {
vec3 zone_light = mix(vec3(1.0), wow_light_color.rgb, 0.10);
float day_strength = mix(0.48, 0.92, clamp(wow_sun_elevation, 0.0, 1.0));
vec3 lit = baked_lit * (zone_ambient * 0.86 + zone_light * ndl * 0.24 * day_strength);
if (unlit_material > 0.5) {
lit = vec3(1.0);
}
lit = clamp(lit, vec3(0.46), vec3(1.05));
vec3 material_color = untextured_material_color(diffuse_color.rgb);
if (use_texture) {
@@ -327,10 +353,30 @@ void fragment() {
vec3 material_emissive = mat_diffuse * emissive_color.rgb * emissive_color.a * material_emissive_strength * emissive_mask;
vec3 emissive = shader_emissive * 0.35 + material_emissive;
vec3 color = clamp(material_color * lit + emissive, vec3(0.0), vec3(1.0));
float window_facing = 1.0;
if (window_material > 0.5) {
vec3 vn = normalize(view_normal);
if (!FRONT_FACING) {
vn = -vn;
}
window_facing = abs(dot(vn, normalize(-view_pos)));
float edge_reflect = pow(1.0 - window_facing, 3.0);
vec3 glass_tint = mix(color, vec3(0.58, 0.70, 0.82), 0.24);
color = clamp(mix(color, glass_tint + vec3(edge_reflect) * 0.12, 0.36), vec3(0.0), vec3(1.0));
}
ALBEDO = apply_wow_fog(color);
%s
}
""" % [
", ".join(render_modes),
"" if mode == "opaque" or mode == "cutout" else "\tALPHA = mix(diffuse_color.a, tex1.a * diffuse_color.a, clamp(alpha_output_strength, 0.0, 1.0));",
albedo_sampler_hint,
_alpha_output_code(mode),
]
static func _alpha_output_code(mode: String) -> String:
if mode == "opaque" or mode == "cutout":
return ""
if mode == "glass":
return "\tALPHA = clamp(mix(0.40, 0.95, window_facing) * max(diffuse_color.a, 0.45), 0.35, 0.95);"
return "\tALPHA = mix(diffuse_color.a, tex1.a * diffuse_color.a, clamp(alpha_output_strength, 0.0, 1.0));"