архитектура и цели для агентов
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
class_name M2Builder
|
||||
|
||||
const WOW_M2_MATERIAL := preload("res://addons/mpq_extractor/loaders/wow_m2_material.gd")
|
||||
const MATERIAL_FORMAT_VERSION := 1
|
||||
const MATERIAL_FORMAT_VERSION := 2
|
||||
|
||||
static var _texture_cache: Dictionary = {}
|
||||
|
||||
@@ -164,6 +164,14 @@ static func _build_material(
|
||||
combiner["stage1_uv_scroll"] = _resolve_texture_scroll(batch, 1, tex_transform_combos, tex_transforms)
|
||||
combiner["stage2_uv_scroll"] = _resolve_texture_scroll(batch, 2, tex_transform_combos, tex_transforms)
|
||||
combiner["stage3_uv_scroll"] = _resolve_texture_scroll(batch, 3, tex_transform_combos, tex_transforms)
|
||||
combiner["stage0_uv_rotation"] = _resolve_texture_rotation(batch, 0, tex_transform_combos, tex_transforms)
|
||||
combiner["stage1_uv_rotation"] = _resolve_texture_rotation(batch, 1, tex_transform_combos, tex_transforms)
|
||||
combiner["stage2_uv_rotation"] = _resolve_texture_rotation(batch, 2, tex_transform_combos, tex_transforms)
|
||||
combiner["stage3_uv_rotation"] = _resolve_texture_rotation(batch, 3, tex_transform_combos, tex_transforms)
|
||||
combiner["stage0_uv_rotation_speed"] = _resolve_texture_rotation_speed(batch, 0, tex_transform_combos, tex_transforms)
|
||||
combiner["stage1_uv_rotation_speed"] = _resolve_texture_rotation_speed(batch, 1, tex_transform_combos, tex_transforms)
|
||||
combiner["stage2_uv_rotation_speed"] = _resolve_texture_rotation_speed(batch, 2, tex_transform_combos, tex_transforms)
|
||||
combiner["stage3_uv_rotation_speed"] = _resolve_texture_rotation_speed(batch, 3, tex_transform_combos, tex_transforms)
|
||||
combiner["vertex_shader_id"] = _m2_vertex_shader_id(texture_count, int(batch.get("shader_id", 0)))
|
||||
combiner["pixel_shader_id"] = _m2_pixel_shader_id(texture_count, int(batch.get("shader_id", 0)))
|
||||
combiner["priority_plane"] = int(batch.get("priority_plane", 0))
|
||||
@@ -460,6 +468,38 @@ static func _resolve_texture_scroll(
|
||||
return transform.get("translation_speed", Vector2.ZERO)
|
||||
|
||||
|
||||
static func _resolve_texture_rotation(
|
||||
batch: Dictionary,
|
||||
stage: int,
|
||||
tex_transform_combos: PackedInt32Array,
|
||||
tex_transforms: Array) -> Vector4:
|
||||
|
||||
var combo_index := int(batch.get("texture_transform_combo_index", -1)) + stage
|
||||
if combo_index < 0 or combo_index >= tex_transform_combos.size():
|
||||
return Vector4(1.0, 0.0, 0.0, 1.0)
|
||||
var transform_index := int(tex_transform_combos[combo_index])
|
||||
if transform_index < 0 or transform_index >= tex_transforms.size():
|
||||
return Vector4(1.0, 0.0, 0.0, 1.0)
|
||||
var transform: Dictionary = tex_transforms[transform_index] if tex_transforms[transform_index] is Dictionary else {}
|
||||
return transform.get("rotation", Vector4(1.0, 0.0, 0.0, 1.0))
|
||||
|
||||
|
||||
static func _resolve_texture_rotation_speed(
|
||||
batch: Dictionary,
|
||||
stage: int,
|
||||
tex_transform_combos: PackedInt32Array,
|
||||
tex_transforms: Array) -> float:
|
||||
|
||||
var combo_index := int(batch.get("texture_transform_combo_index", -1)) + stage
|
||||
if combo_index < 0 or combo_index >= tex_transform_combos.size():
|
||||
return 0.0
|
||||
var transform_index := int(tex_transform_combos[combo_index])
|
||||
if transform_index < 0 or transform_index >= tex_transforms.size():
|
||||
return 0.0
|
||||
var transform: Dictionary = tex_transforms[transform_index] if tex_transforms[transform_index] is Dictionary else {}
|
||||
return float(transform.get("rotation_speed", 0.0))
|
||||
|
||||
|
||||
static func _default_texture_path(model_path: String, texture_type: int) -> String:
|
||||
var normalized := model_path.replace("\\", "/")
|
||||
var rel_model := _relative_extracted_model_path(normalized)
|
||||
|
||||
@@ -84,6 +84,14 @@ static func build(
|
||||
mat.set_shader_parameter("stage1_uv_scroll", combiner.get("stage1_uv_scroll", Vector2.ZERO))
|
||||
mat.set_shader_parameter("stage2_uv_scroll", combiner.get("stage2_uv_scroll", Vector2.ZERO))
|
||||
mat.set_shader_parameter("stage3_uv_scroll", combiner.get("stage3_uv_scroll", Vector2.ZERO))
|
||||
mat.set_shader_parameter("stage0_uv_rotation", combiner.get("stage0_uv_rotation", Vector4(1.0, 0.0, 0.0, 1.0)))
|
||||
mat.set_shader_parameter("stage1_uv_rotation", combiner.get("stage1_uv_rotation", Vector4(1.0, 0.0, 0.0, 1.0)))
|
||||
mat.set_shader_parameter("stage2_uv_rotation", combiner.get("stage2_uv_rotation", Vector4(1.0, 0.0, 0.0, 1.0)))
|
||||
mat.set_shader_parameter("stage3_uv_rotation", combiner.get("stage3_uv_rotation", Vector4(1.0, 0.0, 0.0, 1.0)))
|
||||
mat.set_shader_parameter("stage0_uv_rotation_speed", float(combiner.get("stage0_uv_rotation_speed", 0.0)))
|
||||
mat.set_shader_parameter("stage1_uv_rotation_speed", float(combiner.get("stage1_uv_rotation_speed", 0.0)))
|
||||
mat.set_shader_parameter("stage2_uv_rotation_speed", float(combiner.get("stage2_uv_rotation_speed", 0.0)))
|
||||
mat.set_shader_parameter("stage3_uv_rotation_speed", float(combiner.get("stage3_uv_rotation_speed", 0.0)))
|
||||
mat.set_shader_parameter("effect_alpha_scale", combiner.get("effect_alpha_scale", 1.0))
|
||||
mat.set_shader_parameter("effect_alpha_power", combiner.get("effect_alpha_power", 1.0))
|
||||
mat.set_shader_parameter("uv_edge_fade_strength", combiner.get("uv_edge_fade_strength", 0.0))
|
||||
@@ -227,6 +235,14 @@ uniform vec2 stage0_uv_scroll = vec2(0.0);
|
||||
uniform vec2 stage1_uv_scroll = vec2(0.0);
|
||||
uniform vec2 stage2_uv_scroll = vec2(0.0);
|
||||
uniform vec2 stage3_uv_scroll = vec2(0.0);
|
||||
uniform vec4 stage0_uv_rotation = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
uniform vec4 stage1_uv_rotation = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
uniform vec4 stage2_uv_rotation = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
uniform vec4 stage3_uv_rotation = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
uniform float stage0_uv_rotation_speed = 0.0;
|
||||
uniform float stage1_uv_rotation_speed = 0.0;
|
||||
uniform float stage2_uv_rotation_speed = 0.0;
|
||||
uniform float stage3_uv_rotation_speed = 0.0;
|
||||
uniform float effect_alpha_scale = 1.0;
|
||||
uniform float effect_alpha_power = 1.0;
|
||||
uniform float uv_edge_fade_strength = 0.0;
|
||||
@@ -315,8 +331,27 @@ vec3 apply_wow_fog(vec3 color) {
|
||||
return mix(color, wow_fog_color.rgb, fog_amount);
|
||||
}
|
||||
|
||||
vec2 transform_uv(vec2 uv, vec4 uv_transform, vec2 uv_scroll) {
|
||||
return uv * uv_transform.xy + uv_transform.zw + uv_scroll * TIME;
|
||||
vec2 rotate_uv(vec2 uv, vec4 rotation) {
|
||||
return vec2(
|
||||
rotation.x * uv.x + rotation.y * uv.y,
|
||||
rotation.z * uv.x + rotation.w * uv.y
|
||||
);
|
||||
}
|
||||
|
||||
vec2 rotate_uv_angle(vec2 uv, float angle) {
|
||||
float c = cos(angle);
|
||||
float s = sin(angle);
|
||||
return vec2(c * uv.x - s * uv.y, s * uv.x + c * uv.y);
|
||||
}
|
||||
|
||||
vec2 transform_uv(vec2 uv, vec4 uv_transform, vec2 uv_scroll, vec4 uv_rotation, float uv_rotation_speed) {
|
||||
vec2 centered = uv - vec2(0.5);
|
||||
centered = rotate_uv(centered, uv_rotation);
|
||||
if (abs(uv_rotation_speed) > 0.000001) {
|
||||
centered = rotate_uv_angle(centered, uv_rotation_speed * TIME);
|
||||
}
|
||||
centered *= uv_transform.xy;
|
||||
return centered + vec2(0.5) + uv_transform.zw + uv_scroll * TIME;
|
||||
}
|
||||
|
||||
vec2 env_uv(vec3 normal) {
|
||||
@@ -325,10 +360,10 @@ vec2 env_uv(vec3 normal) {
|
||||
}
|
||||
|
||||
vec2 stage_uv(int stage, vec3 normal) {
|
||||
vec2 t1 = transform_uv(uv_interp, stage0_uv_transform, stage0_uv_scroll);
|
||||
vec2 t2 = transform_uv(uv2_interp, stage1_uv_transform, stage1_uv_scroll);
|
||||
vec2 t3 = transform_uv(uv2_interp, stage2_uv_transform, stage2_uv_scroll);
|
||||
vec2 t4 = transform_uv(uv2_interp, stage3_uv_transform, stage3_uv_scroll);
|
||||
vec2 t1 = transform_uv(uv_interp, stage0_uv_transform, stage0_uv_scroll, stage0_uv_rotation, stage0_uv_rotation_speed);
|
||||
vec2 t2 = transform_uv(uv2_interp, stage1_uv_transform, stage1_uv_scroll, stage1_uv_rotation, stage1_uv_rotation_speed);
|
||||
vec2 t3 = transform_uv(uv2_interp, stage2_uv_transform, stage2_uv_scroll, stage2_uv_rotation, stage2_uv_rotation_speed);
|
||||
vec2 t4 = transform_uv(uv2_interp, stage3_uv_transform, stage3_uv_scroll, stage3_uv_rotation, stage3_uv_rotation_speed);
|
||||
vec2 env = env_uv(normal);
|
||||
|
||||
if (vertex_shader_id == 1) {
|
||||
@@ -383,12 +418,12 @@ vec2 stage_uv(int stage, vec3 normal) {
|
||||
if (stage0_env) {
|
||||
return env;
|
||||
}
|
||||
return transform_uv(stage0_uv2 ? uv2_interp : uv_interp, stage0_uv_transform, stage0_uv_scroll);
|
||||
return transform_uv(stage0_uv2 ? uv2_interp : uv_interp, stage0_uv_transform, stage0_uv_scroll, stage0_uv_rotation, stage0_uv_rotation_speed);
|
||||
}
|
||||
if (stage1_env) {
|
||||
return env;
|
||||
}
|
||||
return transform_uv(stage1_uv2 ? uv2_interp : uv_interp, stage1_uv_transform, stage1_uv_scroll);
|
||||
return transform_uv(stage1_uv2 ? uv2_interp : uv_interp, stage1_uv_transform, stage1_uv_scroll, stage1_uv_rotation, stage1_uv_rotation_speed);
|
||||
}
|
||||
|
||||
void resolve_m2_pixel(vec4 tex1, vec4 tex2, vec4 tex3, vec4 tex4, out vec3 diffuse, out vec3 specular, out float discard_alpha, out float can_discard) {
|
||||
|
||||
@@ -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));"
|
||||
|
||||
Reference in New Issue
Block a user