M2.5: ShaderMaterial + texture resolution + fog; multi-skeleton verified
- m2_material: Metin2-style ShaderMaterial. blend_mix shader (opaque /
alpha-blend / alpha-test-cutout via `mode` uniform) + blend_add shader
(additive glow). modulate(tex, COORD) * COLOR, diffuse_lambert.
- Metin2Model: material_mode prop ("metin2" ShaderMaterial | "standard");
_resolve_texture does filename-convention + case-insensitive dir scan of
*.dds (face/hair keyword slots, stem match, fallback); set_surface_texture
override; guess_blend heuristic (hair->cutout, cape->alpha, effect->add).
Texture cache. Fixed opaque path to NOT alpha-discard (was hiding bodies).
- harness: AABB-based camera framing, engine depth fog (MTGODOT_FOG=1),
MTGODOT_ANIM_T fixed-pose capture (needs explicit anim reload first),
MTGODOT_AUTOSHOT batch screenshot.
Verified: warrior 5/5 surfaces textured under the shader (t=9 dance pose,
lit, fogged). assassin 17/17 textured via dir scan. shaman_lord (gr2 v7)
renders. Screenshots test/golden/m25-*.png, m2c-t*.png.
Gap (M2.5 gate not closed): libgr2 POD API exposes no material/texture-name/
blend data, so multi-slot -> texture/blend mapping is heuristic only. Needs
a libgr2 material API (gr2_material.cpp walking the type tree) — same gap as
xrender-poc M1 T5. Documented in docs/GODOT-POC-PLAN.md §M2.5 T2.5.6.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WaHYEY9rwLWt21PULiYjeJ
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
#include "m2_material.h"
|
||||
|
||||
#include <godot_cpp/classes/shader.hpp>
|
||||
#include <godot_cpp/classes/shader_material.hpp>
|
||||
#include <godot_cpp/classes/texture2d.hpp>
|
||||
#include <godot_cpp/variant/color.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
namespace mtgodot {
|
||||
namespace {
|
||||
|
||||
// blend_mix shader: covers opaque (mode 0, alpha-scissor) and alpha (mode 1).
|
||||
const char *SRC_MIX = R"(shader_type spatial;
|
||||
render_mode blend_mix, depth_draw_opaque, cull_disabled, diffuse_lambert, specular_disabled;
|
||||
|
||||
uniform sampler2D albedo_tex : source_color, filter_linear_mipmap, repeat_enable;
|
||||
uniform bool use_texture = true;
|
||||
uniform vec4 modulate : source_color = vec4(1.0);
|
||||
uniform float alpha_scissor : hint_range(0.0, 1.0) = 0.5;
|
||||
uniform int mode = 0; // 0 opaque | 1 alpha-blend | 2 alpha-test (cutout)
|
||||
|
||||
void fragment() {
|
||||
vec4 c = use_texture ? texture(albedo_tex, UV) : vec4(1.0);
|
||||
c *= modulate * COLOR;
|
||||
if (mode == 2 && c.a < alpha_scissor) {
|
||||
discard;
|
||||
}
|
||||
ALBEDO = c.rgb;
|
||||
ALPHA = (mode == 1) ? c.a : 1.0;
|
||||
}
|
||||
)";
|
||||
|
||||
// blend_add shader: additive glow (effects, enchant overlays).
|
||||
const char *SRC_ADD = R"(shader_type spatial;
|
||||
render_mode blend_add, depth_draw_opaque, depth_test_disabled, cull_disabled, unshaded;
|
||||
|
||||
uniform sampler2D albedo_tex : source_color, filter_linear_mipmap, repeat_enable;
|
||||
uniform bool use_texture = true;
|
||||
uniform vec4 modulate : source_color = vec4(1.0);
|
||||
|
||||
void fragment() {
|
||||
vec4 c = use_texture ? texture(albedo_tex, UV) : vec4(1.0);
|
||||
c *= modulate * COLOR;
|
||||
ALBEDO = c.rgb * c.a;
|
||||
ALPHA = 1.0;
|
||||
}
|
||||
)";
|
||||
|
||||
Ref<Shader> shader_for(bool additive) {
|
||||
static Ref<Shader> s_mix;
|
||||
static Ref<Shader> s_add;
|
||||
Ref<Shader> &slot = additive ? s_add : s_mix;
|
||||
if (slot.is_null()) {
|
||||
slot.instantiate();
|
||||
slot->set_code(additive ? SRC_ADD : SRC_MIX);
|
||||
}
|
||||
return slot;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Ref<ShaderMaterial> make_material(const MaterialDesc &d) {
|
||||
Ref<ShaderMaterial> m;
|
||||
m.instantiate();
|
||||
|
||||
const bool additive = (d.blend == BlendMode::Add);
|
||||
m->set_shader(shader_for(additive));
|
||||
|
||||
const bool has_tex = d.albedo.is_valid();
|
||||
m->set_shader_parameter("use_texture", has_tex);
|
||||
if (has_tex) {
|
||||
m->set_shader_parameter("albedo_tex", d.albedo);
|
||||
}
|
||||
m->set_shader_parameter("modulate", has_tex ? Color(1, 1, 1, 1) : Color(0.8, 0.8, 0.82, 1));
|
||||
|
||||
if (!additive) {
|
||||
m->set_shader_parameter("alpha_scissor", d.alpha_scissor);
|
||||
int mode = 0;
|
||||
if (d.blend == BlendMode::Alpha) {
|
||||
mode = 1;
|
||||
} else if (d.blend == BlendMode::AlphaTest) {
|
||||
mode = 2;
|
||||
}
|
||||
m->set_shader_parameter("mode", mode);
|
||||
}
|
||||
if (d.blend == BlendMode::Alpha) {
|
||||
m->set_render_priority(1);
|
||||
} else if (additive) {
|
||||
m->set_render_priority(2);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
} // namespace mtgodot
|
||||
Reference in New Issue
Block a user