571 lines
21 KiB
GDScript
571 lines
21 KiB
GDScript
extends RefCounted
|
|
class_name WowM2Material
|
|
|
|
const M2BLEND_OPAQUE := 0
|
|
const M2BLEND_ALPHA_KEY := 1
|
|
const M2BLEND_ALPHA := 2
|
|
const M2BLEND_NO_ALPHA_ADD := 3
|
|
const M2BLEND_ADD := 4
|
|
const M2BLEND_MOD := 5
|
|
const M2BLEND_MOD_2X := 6
|
|
|
|
static var _shader_cache: Dictionary = {}
|
|
|
|
|
|
static func clear_cache() -> void:
|
|
_shader_cache.clear()
|
|
|
|
|
|
static func _ensure_wow_shader_globals() -> void:
|
|
pass
|
|
|
|
|
|
static func build(
|
|
texture: Texture2D,
|
|
texture2: Texture2D,
|
|
texture3: Texture2D,
|
|
texture4: Texture2D,
|
|
material_flags: int,
|
|
blend_mode: int,
|
|
texture_flags: int,
|
|
texture2_flags: int,
|
|
texture3_flags: int,
|
|
texture4_flags: int,
|
|
resource_name: String = "",
|
|
combiner: Dictionary = {}) -> ShaderMaterial:
|
|
|
|
var two_sided := (material_flags & 0x04) != 0
|
|
var unlit := (material_flags & 0x01) != 0 or blend_mode >= M2BLEND_MOD
|
|
var depth_test := (material_flags & 0x08) == 0
|
|
var depth_write := (material_flags & 0x10) == 0
|
|
var repeat_enabled := (
|
|
(texture_flags & 0x03) != 0
|
|
or (texture2_flags & 0x03) != 0
|
|
or (texture3_flags & 0x03) != 0
|
|
or (texture4_flags & 0x03) != 0
|
|
)
|
|
var mode := _blend_shader_mode(blend_mode)
|
|
|
|
_ensure_wow_shader_globals()
|
|
var mat := ShaderMaterial.new()
|
|
mat.resource_name = resource_name
|
|
mat.shader = _get_shader(mode, two_sided, depth_test, depth_write, repeat_enabled, texture2 != null, texture3 != null, texture4 != null)
|
|
mat.render_priority = clampi(_render_priority(blend_mode) + int(combiner.get("priority_plane", 0)), -128, 127)
|
|
mat.set_shader_parameter("albedo_tex", texture)
|
|
mat.set_shader_parameter("stage2_tex", texture2)
|
|
mat.set_shader_parameter("stage3_tex", texture3)
|
|
mat.set_shader_parameter("stage4_tex", texture4)
|
|
mat.set_shader_parameter("use_texture", texture != null)
|
|
mat.set_shader_parameter("use_stage2", texture2 != null)
|
|
mat.set_shader_parameter("use_stage3", texture3 != null)
|
|
mat.set_shader_parameter("use_stage4", texture4 != null)
|
|
mat.set_shader_parameter("alpha_ref", _alpha_ref(blend_mode))
|
|
mat.set_shader_parameter("unlit_strength", 1.0 if unlit else 0.0)
|
|
mat.set_shader_parameter("mesh_color", combiner.get("mesh_color", Color.WHITE))
|
|
mat.set_shader_parameter("tex_sample_alpha", combiner.get("tex_sample_alpha", Vector3.ONE))
|
|
mat.set_shader_parameter("ambient_color", Color(0.45, 0.45, 0.42, 1.0))
|
|
mat.set_shader_parameter("light_color", Color(0.82, 0.78, 0.68, 1.0))
|
|
mat.set_shader_parameter("light_dir", Vector3(-0.45, -0.75, -0.35).normalized())
|
|
mat.set_shader_parameter("diffuse_strength", 0.72)
|
|
mat.set_shader_parameter("modulate_2x", 1.0 if blend_mode == M2BLEND_MOD_2X else 0.0)
|
|
mat.set_shader_parameter("vertex_shader_id", int(combiner.get("vertex_shader_id", 0)))
|
|
mat.set_shader_parameter("pixel_shader_id", int(combiner.get("pixel_shader_id", 0)))
|
|
mat.set_shader_parameter("stage0_op", int(combiner.get("op0", 0 if blend_mode == 0 else 1)))
|
|
mat.set_shader_parameter("stage1_op", int(combiner.get("op1", 1)))
|
|
mat.set_shader_parameter("stage0_env", bool(combiner.get("env0", false)))
|
|
mat.set_shader_parameter("stage1_env", bool(combiner.get("env1", false)))
|
|
mat.set_shader_parameter("stage0_uv2", bool(combiner.get("use_uv2_0", false)))
|
|
mat.set_shader_parameter("stage1_uv2", bool(combiner.get("use_uv2_1", false)))
|
|
mat.set_shader_parameter("stage0_uv_transform", combiner.get("stage0_uv_transform", Vector4(1.0, 1.0, 0.0, 0.0)))
|
|
mat.set_shader_parameter("stage1_uv_transform", combiner.get("stage1_uv_transform", Vector4(1.0, 1.0, 0.0, 0.0)))
|
|
mat.set_shader_parameter("stage2_uv_transform", combiner.get("stage2_uv_transform", Vector4(1.0, 1.0, 0.0, 0.0)))
|
|
mat.set_shader_parameter("stage3_uv_transform", combiner.get("stage3_uv_transform", Vector4(1.0, 1.0, 0.0, 0.0)))
|
|
mat.set_shader_parameter("stage0_uv_scroll", combiner.get("stage0_uv_scroll", Vector2.ZERO))
|
|
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("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))
|
|
mat.set_shader_parameter("billboard_enabled", bool(combiner.get("billboard_enabled", false)))
|
|
mat.set_meta("wow_flags", material_flags)
|
|
mat.set_meta("wow_blend_mode", blend_mode)
|
|
mat.set_meta("wow_priority_plane", int(combiner.get("priority_plane", 0)))
|
|
mat.set_meta("wow_texture_flags", texture_flags)
|
|
mat.set_meta("wow_texture2_flags", texture2_flags)
|
|
mat.set_meta("wow_texture3_flags", texture3_flags)
|
|
mat.set_meta("wow_texture4_flags", texture4_flags)
|
|
mat.set_meta("wow_m2_billboard_enabled", bool(combiner.get("billboard_enabled", false)))
|
|
return mat
|
|
|
|
|
|
static func _blend_shader_mode(blend_mode: int) -> String:
|
|
match blend_mode:
|
|
M2BLEND_ALPHA_KEY:
|
|
return "cutout"
|
|
M2BLEND_ALPHA:
|
|
return "alpha"
|
|
M2BLEND_NO_ALPHA_ADD, M2BLEND_ADD:
|
|
return "add"
|
|
M2BLEND_MOD, M2BLEND_MOD_2X:
|
|
return "mul"
|
|
_:
|
|
return "opaque"
|
|
|
|
|
|
static func _render_priority(blend_mode: int) -> int:
|
|
if blend_mode <= M2BLEND_ALPHA_KEY:
|
|
return 0
|
|
if blend_mode >= M2BLEND_MOD:
|
|
return 2
|
|
return 1
|
|
|
|
|
|
static func _alpha_ref(blend_mode: int) -> float:
|
|
if blend_mode == M2BLEND_ALPHA_KEY:
|
|
return 0.87843138
|
|
if blend_mode == M2BLEND_OPAQUE:
|
|
return 0.0
|
|
return 0.0039215689
|
|
|
|
|
|
static func _get_shader(
|
|
mode: String,
|
|
two_sided: bool,
|
|
depth_test: bool,
|
|
depth_write: bool,
|
|
repeat_enabled: bool,
|
|
has_stage2: bool,
|
|
has_stage3: bool,
|
|
has_stage4: bool) -> Shader:
|
|
|
|
var key := "%s|sided=%s|dt=%s|dw=%s|repeat=%s" % [
|
|
mode,
|
|
str(two_sided),
|
|
str(depth_test),
|
|
str(depth_write),
|
|
str(repeat_enabled),
|
|
]
|
|
key += "|stage2=%s" % str(has_stage2)
|
|
key += "|stage3=%s|stage4=%s" % [str(has_stage3), str(has_stage4)]
|
|
if _shader_cache.has(key):
|
|
return _shader_cache[key]
|
|
|
|
var shader := Shader.new()
|
|
shader.code = _shader_code(mode, two_sided, depth_test, depth_write, repeat_enabled, has_stage2, has_stage3, has_stage4)
|
|
_shader_cache[key] = shader
|
|
return shader
|
|
|
|
|
|
static func _shader_code(
|
|
mode: String,
|
|
two_sided: bool,
|
|
depth_test: bool,
|
|
depth_write: bool,
|
|
repeat_enabled: bool,
|
|
has_stage2: bool,
|
|
has_stage3: bool,
|
|
has_stage4: bool) -> String:
|
|
|
|
var render_modes: Array[String] = []
|
|
match mode:
|
|
"alpha":
|
|
render_modes.append("blend_mix")
|
|
"add":
|
|
render_modes.append("blend_add")
|
|
"mul":
|
|
render_modes.append("blend_mul")
|
|
_:
|
|
render_modes.append("blend_mix")
|
|
|
|
render_modes.append("cull_disabled" if two_sided else "cull_back")
|
|
if not depth_test:
|
|
render_modes.append("depth_test_disabled")
|
|
if not depth_write:
|
|
render_modes.append("depth_draw_never")
|
|
elif mode == "opaque" or mode == "cutout":
|
|
render_modes.append("depth_draw_opaque")
|
|
else:
|
|
render_modes.append("depth_draw_never")
|
|
render_modes.append("unshaded")
|
|
|
|
var repeat_hint := "repeat_enable" if repeat_enabled else "repeat_disable"
|
|
return """
|
|
shader_type spatial;
|
|
render_mode %s;
|
|
|
|
uniform sampler2D albedo_tex : source_color, filter_linear_mipmap_anisotropic, %s;
|
|
uniform sampler2D stage2_tex : source_color, filter_linear_mipmap_anisotropic, %s;
|
|
uniform sampler2D stage3_tex : source_color, filter_linear_mipmap_anisotropic, %s;
|
|
uniform sampler2D stage4_tex : source_color, filter_linear_mipmap_anisotropic, %s;
|
|
uniform bool use_texture = false;
|
|
uniform bool use_stage2 = false;
|
|
uniform bool use_stage3 = false;
|
|
uniform bool use_stage4 = false;
|
|
uniform float alpha_ref = 0.0;
|
|
uniform float unlit_strength = 0.0;
|
|
uniform vec4 mesh_color : source_color = vec4(1.0);
|
|
uniform vec3 tex_sample_alpha = vec3(1.0);
|
|
uniform vec4 ambient_color : source_color = vec4(0.45, 0.45, 0.42, 1.0);
|
|
uniform vec4 light_color : source_color = vec4(0.82, 0.78, 0.68, 1.0);
|
|
uniform vec3 light_dir = vec3(-0.45, -0.75, -0.35);
|
|
uniform float diffuse_strength = 0.72;
|
|
uniform float modulate_2x = 0.0;
|
|
uniform int vertex_shader_id = 0;
|
|
uniform int pixel_shader_id = 0;
|
|
uniform int stage0_op = 0;
|
|
uniform int stage1_op = 1;
|
|
uniform bool stage0_env = false;
|
|
uniform bool stage1_env = false;
|
|
uniform bool stage0_uv2 = false;
|
|
uniform bool stage1_uv2 = false;
|
|
uniform vec4 stage0_uv_transform = vec4(1.0, 1.0, 0.0, 0.0);
|
|
uniform vec4 stage1_uv_transform = vec4(1.0, 1.0, 0.0, 0.0);
|
|
uniform vec4 stage2_uv_transform = vec4(1.0, 1.0, 0.0, 0.0);
|
|
uniform vec4 stage3_uv_transform = vec4(1.0, 1.0, 0.0, 0.0);
|
|
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 float effect_alpha_scale = 1.0;
|
|
uniform float effect_alpha_power = 1.0;
|
|
uniform float uv_edge_fade_strength = 0.0;
|
|
uniform bool billboard_enabled = false;
|
|
|
|
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;
|
|
global uniform float wow_sun_elevation;
|
|
|
|
varying vec3 world_normal;
|
|
varying vec3 world_pos;
|
|
varying vec3 view_pos;
|
|
varying vec2 uv_interp;
|
|
varying vec2 uv2_interp;
|
|
varying float edge_fade;
|
|
|
|
vec3 safe_normalize(vec3 value, vec3 fallback) {
|
|
float len = length(value);
|
|
if (len <= 0.00001) {
|
|
return normalize(fallback);
|
|
}
|
|
return value / len;
|
|
}
|
|
|
|
vec3 apply_m2_billboard(vec3 vertex, vec3 normal, vec4 custom0, mat4 model_matrix, mat3 model_normal_matrix, mat4 inv_view_matrix, out vec3 billboard_world_normal) {
|
|
billboard_world_normal = safe_normalize(model_normal_matrix * normal, normal);
|
|
if (!billboard_enabled) {
|
|
return vertex;
|
|
}
|
|
|
|
int mode = int(custom0.w + 0.5);
|
|
if (mode <= 0) {
|
|
return vertex;
|
|
}
|
|
|
|
vec3 pivot = custom0.xyz;
|
|
vec3 offset = vertex - pivot;
|
|
vec3 camera_right = safe_normalize(inv_view_matrix[0].xyz, vec3(1.0, 0.0, 0.0));
|
|
vec3 camera_up = safe_normalize(inv_view_matrix[1].xyz, vec3(0.0, 1.0, 0.0));
|
|
vec3 camera_back = safe_normalize(inv_view_matrix[2].xyz, vec3(0.0, 0.0, 1.0));
|
|
vec3 world_x = camera_right;
|
|
vec3 world_y = camera_up;
|
|
vec3 world_z = camera_back;
|
|
|
|
if (mode == 2) {
|
|
world_x = safe_normalize((model_matrix * vec4(1.0, 0.0, 0.0, 0.0)).xyz, camera_right);
|
|
world_y = safe_normalize(camera_up - world_x * dot(camera_up, world_x), (model_matrix * vec4(0.0, 1.0, 0.0, 0.0)).xyz);
|
|
world_z = safe_normalize(cross(world_x, world_y), camera_back);
|
|
} else if (mode == 3) {
|
|
world_z = safe_normalize((model_matrix * vec4(0.0, 0.0, 1.0, 0.0)).xyz, camera_back);
|
|
world_x = safe_normalize(camera_right - world_z * dot(camera_right, world_z), (model_matrix * vec4(1.0, 0.0, 0.0, 0.0)).xyz);
|
|
world_y = safe_normalize(cross(world_z, world_x), camera_up);
|
|
} else if (mode == 4) {
|
|
world_y = safe_normalize((model_matrix * vec4(0.0, 1.0, 0.0, 0.0)).xyz, camera_up);
|
|
world_x = safe_normalize(cross(world_y, camera_back), (model_matrix * vec4(1.0, 0.0, 0.0, 0.0)).xyz);
|
|
world_z = safe_normalize(cross(world_x, world_y), camera_back);
|
|
}
|
|
|
|
vec3 world_pivot = (model_matrix * vec4(pivot, 1.0)).xyz;
|
|
vec3 billboard_world_pos = world_pivot + world_x * offset.x + world_y * offset.y + world_z * offset.z;
|
|
billboard_world_normal = world_z;
|
|
return (inverse(model_matrix) * vec4(billboard_world_pos, 1.0)).xyz;
|
|
}
|
|
|
|
void vertex() {
|
|
vec3 billboard_normal;
|
|
VERTEX = apply_m2_billboard(VERTEX, NORMAL, CUSTOM0, MODEL_MATRIX, MODEL_NORMAL_MATRIX, INV_VIEW_MATRIX, billboard_normal);
|
|
world_normal = billboard_normal;
|
|
world_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
|
|
view_pos = (MODELVIEW_MATRIX * vec4(VERTEX, 1.0)).xyz;
|
|
uv_interp = UV;
|
|
uv2_interp = UV2;
|
|
vec3 view_normal = normalize((MODELVIEW_MATRIX * vec4(NORMAL, 0.0)).xyz);
|
|
float edge_scan = 1.0 - abs(dot(normalize(-view_pos), view_normal));
|
|
edge_fade = (vertex_shader_id == 9 || vertex_shader_id == 12 || vertex_shader_id == 13) ? clamp(edge_scan * 2.5, 0.0, 1.0) : 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);
|
|
}
|
|
|
|
vec2 transform_uv(vec2 uv, vec4 uv_transform, vec2 uv_scroll) {
|
|
return uv * uv_transform.xy + uv_transform.zw + uv_scroll * TIME;
|
|
}
|
|
|
|
vec2 env_uv(vec3 normal) {
|
|
vec3 n = normalize(normal);
|
|
return n.xy * 0.5 + vec2(0.5);
|
|
}
|
|
|
|
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 env = env_uv(normal);
|
|
|
|
if (vertex_shader_id == 1) {
|
|
return env;
|
|
}
|
|
if (vertex_shader_id == 2) {
|
|
return stage == 0 ? t1 : t2;
|
|
}
|
|
if (vertex_shader_id == 3) {
|
|
return stage == 0 ? t1 : env;
|
|
}
|
|
if (vertex_shader_id == 4) {
|
|
return stage == 0 ? env : t1;
|
|
}
|
|
if (vertex_shader_id == 5) {
|
|
return env;
|
|
}
|
|
if (vertex_shader_id == 6) {
|
|
return stage == 1 ? env : t1;
|
|
}
|
|
if (vertex_shader_id == 7 || vertex_shader_id == 8) {
|
|
return t1;
|
|
}
|
|
if (vertex_shader_id == 10) {
|
|
return t2;
|
|
}
|
|
if (vertex_shader_id == 11) {
|
|
return stage == 1 ? env : (stage == 2 ? t2 : t1);
|
|
}
|
|
if (vertex_shader_id == 12) {
|
|
return stage == 0 ? t1 : t2;
|
|
}
|
|
if (vertex_shader_id == 13) {
|
|
return env;
|
|
}
|
|
if (vertex_shader_id == 14) {
|
|
return stage == 1 ? t2 : t1;
|
|
}
|
|
if (vertex_shader_id == 15) {
|
|
return stage == 0 ? t1 : (stage == 1 ? t2 : uv2_interp);
|
|
}
|
|
if (vertex_shader_id == 16) {
|
|
return stage == 0 ? t2 : uv2_interp;
|
|
}
|
|
if (stage == 2) {
|
|
return t3;
|
|
}
|
|
if (stage == 3) {
|
|
return t4;
|
|
}
|
|
if (stage == 0) {
|
|
if (stage0_env) {
|
|
return env;
|
|
}
|
|
return transform_uv(stage0_uv2 ? uv2_interp : uv_interp, stage0_uv_transform, stage0_uv_scroll);
|
|
}
|
|
if (stage1_env) {
|
|
return env;
|
|
}
|
|
return transform_uv(stage1_uv2 ? uv2_interp : uv_interp, stage1_uv_transform, stage1_uv_scroll);
|
|
}
|
|
|
|
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) {
|
|
vec3 mesh_rgb = mesh_color.rgb;
|
|
diffuse = mesh_rgb * tex1.rgb;
|
|
specular = vec3(0.0);
|
|
discard_alpha = tex1.a * mesh_color.a;
|
|
can_discard = 0.0;
|
|
|
|
if (pixel_shader_id == 0) {
|
|
diffuse = mesh_rgb * tex1.rgb;
|
|
} else if (pixel_shader_id == 1) {
|
|
diffuse = mesh_rgb * tex1.rgb;
|
|
discard_alpha = tex1.a * mesh_color.a;
|
|
can_discard = 1.0;
|
|
} else if (pixel_shader_id == 2) {
|
|
diffuse = mesh_rgb * tex1.rgb * tex2.rgb;
|
|
discard_alpha = tex2.a * mesh_color.a;
|
|
can_discard = 1.0;
|
|
} else if (pixel_shader_id == 3) {
|
|
diffuse = mesh_rgb * tex1.rgb * tex2.rgb * 2.0;
|
|
discard_alpha = tex2.a * 2.0 * mesh_color.a;
|
|
can_discard = 1.0;
|
|
} else if (pixel_shader_id == 4) {
|
|
diffuse = mesh_rgb * tex1.rgb * tex2.rgb * 2.0;
|
|
} else if (pixel_shader_id == 5) {
|
|
diffuse = mesh_rgb * tex1.rgb * tex2.rgb;
|
|
} else if (pixel_shader_id == 6) {
|
|
diffuse = mesh_rgb * tex1.rgb * tex2.rgb;
|
|
discard_alpha = tex1.a * tex2.a * mesh_color.a;
|
|
can_discard = 1.0;
|
|
} else if (pixel_shader_id == 7) {
|
|
diffuse = mesh_rgb * tex1.rgb * tex2.rgb * 2.0;
|
|
discard_alpha = tex1.a * tex2.a * 2.0 * mesh_color.a;
|
|
can_discard = 1.0;
|
|
} else if (pixel_shader_id == 8) {
|
|
diffuse = mesh_rgb * tex1.rgb;
|
|
specular = tex2.rgb;
|
|
discard_alpha = (tex1.a + tex2.a) * mesh_color.a;
|
|
can_discard = 1.0;
|
|
} else if (pixel_shader_id == 9) {
|
|
diffuse = mesh_rgb * tex1.rgb * tex2.rgb * 2.0;
|
|
discard_alpha = tex1.a * mesh_color.a;
|
|
can_discard = 1.0;
|
|
} else if (pixel_shader_id == 10) {
|
|
diffuse = mesh_rgb * tex1.rgb;
|
|
specular = tex2.rgb;
|
|
discard_alpha = tex1.a * mesh_color.a;
|
|
can_discard = 1.0;
|
|
} else if (pixel_shader_id == 11) {
|
|
diffuse = mesh_rgb * tex1.rgb * tex2.rgb;
|
|
discard_alpha = tex1.a * mesh_color.a;
|
|
can_discard = 1.0;
|
|
} else if (pixel_shader_id == 12) {
|
|
diffuse = mesh_rgb * mix(tex1.rgb * tex2.rgb * 2.0, tex1.rgb, vec3(tex1.a));
|
|
} else if (pixel_shader_id == 13) {
|
|
diffuse = mesh_rgb * tex1.rgb;
|
|
specular = tex2.rgb * tex2.a;
|
|
} else if (pixel_shader_id == 14) {
|
|
diffuse = mesh_rgb * tex1.rgb;
|
|
specular = tex2.rgb * tex2.a * (1.0 - tex1.a);
|
|
} else if (pixel_shader_id == 15) {
|
|
diffuse = mesh_rgb * mix(tex1.rgb * tex2.rgb * 2.0, tex1.rgb, vec3(tex1.a));
|
|
specular = tex3.rgb * tex3.a * tex_sample_alpha.b;
|
|
} else if (pixel_shader_id == 16) {
|
|
diffuse = mesh_rgb * tex1.rgb;
|
|
specular = tex2.rgb * tex2.a;
|
|
discard_alpha = tex1.a * mesh_color.a;
|
|
can_discard = 1.0;
|
|
} else if (pixel_shader_id == 17) {
|
|
diffuse = mesh_rgb * tex1.rgb;
|
|
specular = tex2.rgb * tex2.a * (1.0 - tex1.a);
|
|
discard_alpha = (tex1.a + tex2.a * dot(tex2.rgb, vec3(0.3, 0.59, 0.11))) * mesh_color.a;
|
|
can_discard = 1.0;
|
|
} else if (pixel_shader_id == 18) {
|
|
diffuse = mesh_rgb * mix(mix(tex1.rgb, tex2.rgb, vec3(tex2.a)), tex1.rgb, vec3(tex1.a));
|
|
} else if (pixel_shader_id == 19) {
|
|
diffuse = mesh_rgb * mix(tex1.rgb * tex2.rgb * 2.0, tex3.rgb, vec3(tex3.a));
|
|
} else if (pixel_shader_id == 21) {
|
|
diffuse = mesh_rgb * tex1.rgb;
|
|
specular = tex2.rgb * (1.0 - tex1.a);
|
|
discard_alpha = (tex1.a + tex2.a) * mesh_color.a;
|
|
can_discard = 1.0;
|
|
} else if (pixel_shader_id == 22) {
|
|
diffuse = mesh_rgb * mix(tex1.rgb * tex2.rgb, tex1.rgb, vec3(tex1.a));
|
|
} else if (pixel_shader_id == 24) {
|
|
diffuse = mesh_rgb * mix(tex1.rgb, tex2.rgb, vec3(tex2.a));
|
|
specular = tex1.rgb * tex1.a * tex_sample_alpha.r;
|
|
} else if (pixel_shader_id == 25) {
|
|
float glow_opacity = clamp(tex3.a * tex_sample_alpha.b, 0.0, 1.0);
|
|
diffuse = mesh_rgb * mix(tex1.rgb * tex2.rgb * 2.0, tex1.rgb, vec3(tex1.a)) * (1.0 - glow_opacity);
|
|
specular = tex3.rgb * glow_opacity;
|
|
} else if (pixel_shader_id == 26) {
|
|
vec4 mixed = mix(mix(tex1, tex2, vec4(clamp(tex_sample_alpha.g, 0.0, 1.0))), tex3, vec4(clamp(tex_sample_alpha.b, 0.0, 1.0)));
|
|
diffuse = mesh_rgb * mixed.rgb;
|
|
discard_alpha = mixed.a * mesh_color.a;
|
|
can_discard = 1.0;
|
|
} else if (pixel_shader_id == 27) {
|
|
diffuse = mesh_rgb * mix(mix(tex1.rgb * tex2.rgb * 2.0, tex3.rgb, vec3(tex3.a)), tex1.rgb, vec3(tex1.a));
|
|
} else if (pixel_shader_id == 28) {
|
|
vec4 mixed = mix(mix(tex1, tex2, vec4(clamp(tex_sample_alpha.g, 0.0, 1.0))), tex3, vec4(clamp(tex_sample_alpha.b, 0.0, 1.0)));
|
|
diffuse = mesh_rgb * mixed.rgb;
|
|
discard_alpha = mixed.a * tex4.a * mesh_color.a;
|
|
can_discard = 1.0;
|
|
} else if (pixel_shader_id == 29) {
|
|
diffuse = mesh_rgb * mix(tex1.rgb, tex2.rgb, vec3(tex2.a));
|
|
} else if (pixel_shader_id == 30) {
|
|
diffuse = mesh_rgb * mix(tex1.rgb * tex2.rgb, tex3.rgb, vec3(tex3.a));
|
|
discard_alpha = tex1.a * mesh_color.a;
|
|
can_discard = 1.0;
|
|
} else if (pixel_shader_id == 31) {
|
|
diffuse = mesh_rgb * tex1.rgb * tex2.rgb;
|
|
discard_alpha = tex1.a * mesh_color.a;
|
|
can_discard = 1.0;
|
|
} else if (pixel_shader_id == 32) {
|
|
diffuse = mesh_rgb * mix(tex1.rgb * tex2.rgb, tex3.rgb, vec3(tex3.a));
|
|
} else if (pixel_shader_id == 35) {
|
|
vec4 combined = tex1 * tex2 * tex3;
|
|
diffuse = mesh_rgb * combined.rgb;
|
|
discard_alpha = combined.a * mesh_color.a;
|
|
can_discard = 1.0;
|
|
} else if (pixel_shader_id == 36) {
|
|
diffuse = mesh_rgb * tex1.rgb * tex2.rgb;
|
|
discard_alpha = tex1.a * tex2.a * mesh_color.a;
|
|
can_discard = 1.0;
|
|
}
|
|
}
|
|
|
|
void fragment() {
|
|
vec4 tex = use_texture ? texture(albedo_tex, stage_uv(0, world_normal)) : vec4(1.0);
|
|
%s
|
|
vec4 stage2 = use_stage2 ? texture(stage2_tex, stage_uv(1, world_normal)) : vec4(1.0);
|
|
vec4 stage3 = use_stage3 ? texture(stage3_tex, stage_uv(2, world_normal)) : vec4(1.0);
|
|
vec4 stage4 = use_stage4 ? texture(stage4_tex, stage_uv(3, world_normal)) : vec4(1.0);
|
|
vec3 mat_diffuse;
|
|
vec3 specular;
|
|
float discard_alpha;
|
|
float can_discard;
|
|
resolve_m2_pixel(tex, stage2, stage3, stage4, mat_diffuse, specular, discard_alpha, can_discard);
|
|
discard_alpha *= edge_fade;
|
|
discard_alpha = pow(clamp(discard_alpha, 0.0, 1.0), max(effect_alpha_power, 0.01)) * effect_alpha_scale;
|
|
if (uv_edge_fade_strength > 0.0) {
|
|
float edge_width = 0.12;
|
|
float edge_mask = smoothstep(0.0, edge_width, uv_interp.x) * smoothstep(0.0, edge_width, 1.0 - uv_interp.x);
|
|
edge_mask *= smoothstep(0.0, edge_width, uv_interp.y) * smoothstep(0.0, edge_width, 1.0 - uv_interp.y);
|
|
discard_alpha *= mix(1.0, edge_mask, clamp(uv_edge_fade_strength, 0.0, 1.0));
|
|
}
|
|
if (alpha_ref > 0.0 && discard_alpha < alpha_ref) {
|
|
discard;
|
|
}
|
|
|
|
vec3 n = normalize(world_normal);
|
|
if (!FRONT_FACING) {
|
|
n = -n;
|
|
}
|
|
float ndl = max(dot(n, normalize(wow_light_dir)), 0.0);
|
|
vec3 zone_ambient = mix(vec3(0.76), max(wow_ambient_color.rgb, vec3(0.08)), 0.18);
|
|
vec3 zone_light = mix(vec3(1.0), wow_light_color.rgb, 0.14);
|
|
float day_strength = mix(0.48, 0.92, clamp(wow_sun_elevation, 0.0, 1.0));
|
|
vec3 lit = zone_ambient * 0.82 + zone_light * ndl * diffuse_strength * 0.72 * day_strength;
|
|
lit = clamp(lit, vec3(0.56), vec3(1.08));
|
|
lit = mix(lit, vec3(1.0), clamp(unlit_strength, 0.0, 1.0));
|
|
vec3 color = mat_diffuse * lit + specular * 0.45;
|
|
color = mix(color, min(color * 2.0, vec3(1.0)), clamp(modulate_2x, 0.0, 1.0));
|
|
color = clamp(color, vec3(0.0), vec3(1.0));
|
|
color = apply_wow_fog(color);
|
|
|
|
ALBEDO = color;
|
|
%s
|
|
}
|
|
""" % [
|
|
", ".join(render_modes),
|
|
repeat_hint,
|
|
repeat_hint,
|
|
repeat_hint,
|
|
repeat_hint,
|
|
"",
|
|
"" if mode == "opaque" or mode == "cutout" else "\tALPHA = clamp(discard_alpha, 0.0, 1.0);",
|
|
]
|