Add animation controller system, material assets and skeleton visualization
- .animctrl state machine asset (params/transitions/blend trees, 1D+2D directional blending) with Unity Animator-style editor panel: state list, transitions, params, directional pad preview driving live CrossFade on the selected entity - Split animation evaluation out of SceneRenderer into AnimationSystem/AnimationEvaluator; skin palettes with rest-pose fallback and blend-weight epsilon filtering - MaterialAsset (.material) with reload-safe preview tile pool (DropMaterial clears dirty refs before instance destruction) - EditorGizmoPass skeleton wires + viewport joint overlay; camera projection rework (baked Vulkan Y-flip, ortho support) - Editor/game build split via HELLOVULKAN_EDITOR option
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
#version 450
|
||||
|
||||
// Editor gizmo 图标片元:按 aux.x(形状 id,与 SceneRenderer 收集常量
|
||||
// 一一对应)在 uv ∈ [-1,1] 上做程序化 SDF 造型,预乘 alpha 输出
|
||||
//(pass 侧混合 ONE, ONE_MINUS_SRC_ALPHA)。
|
||||
// 0 方向光(太阳盘 + 8 向光芒)
|
||||
// 1 点光(亮核 + 柔和光晕)
|
||||
// 2 相机(机身挖孔 + 镜头环 + 取景器凸块)
|
||||
// 3 天空盒(等距立方线框)
|
||||
// 4 天空光(环 + 内核点)
|
||||
|
||||
layout(location = 0) in vec4 inColor;
|
||||
layout(location = 1) in vec4 inAux;
|
||||
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
// 方框 SDF
|
||||
float sdBox(vec2 p, vec2 b) {
|
||||
vec2 d = abs(p) - b;
|
||||
return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);
|
||||
}
|
||||
|
||||
// 线段 SDF
|
||||
float sdSegment(vec2 p, vec2 a, vec2 b) {
|
||||
vec2 pa = p - a, ba = b - a;
|
||||
float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
|
||||
return length(pa - ba * h);
|
||||
}
|
||||
|
||||
// 等边六边形 SDF(circumradius r,iq 惯用式)
|
||||
float sdHexagon(vec2 p, float r) {
|
||||
const vec3 k = vec3(-0.866025404, 0.5, 0.577350269);
|
||||
p = abs(p);
|
||||
p -= 2.0 * min(dot(k.xy, p), 0.0) * k.xy;
|
||||
p -= vec2(clamp(p.x, -k.z * r, k.z * r), r);
|
||||
return length(p) * sign(p.y);
|
||||
}
|
||||
|
||||
float ShapeSDF(vec2 p, int id) {
|
||||
if (id == 0) { // 方向光:太阳盘 + 8 向光芒
|
||||
float r = length(p);
|
||||
float disc = r - 0.38;
|
||||
float a = atan(p.y, p.x);
|
||||
float s45 = 0.78539816; // 45° 扇区
|
||||
float fa = abs(mod(a + s45 * 0.5, s45) - s45 * 0.5);
|
||||
float ray = max(r * sin(fa), abs(r - 0.58) - 0.20);
|
||||
return min(disc, ray);
|
||||
}
|
||||
if (id == 1) return length(p) - 0.22; // 点光亮核(光晕在 main)
|
||||
if (id == 2) { // 相机
|
||||
float body = sdBox(p - vec2(0.05, 0.0), vec2(0.50, 0.36));
|
||||
float hole = max(body, -(length(p - vec2(0.05, 0.0)) - 0.20));
|
||||
float ring = abs(length(p - vec2(0.05, 0.0)) - 0.28) - 0.035;
|
||||
float vf = sdBox(p - vec2(0.30, 0.44), vec2(0.14, 0.10));
|
||||
return min(min(hole, ring), vf);
|
||||
}
|
||||
if (id == 3) { // 天空盒:等距立方线框
|
||||
float hex = abs(sdHexagon(p, 0.72)) - 0.045;
|
||||
float e1 = sdSegment(p, vec2(0.0), vec2(0.0, -0.72)) - 0.045;
|
||||
float e2 = sdSegment(p, vec2(0.0), vec2(-0.6235, 0.36)) - 0.045;
|
||||
float e3 = sdSegment(p, vec2(0.0), vec2(0.6235, 0.36)) - 0.045;
|
||||
return min(hex, min(e1, min(e2, e3)));
|
||||
}
|
||||
// 天空光(id == 4):环 + 内核点
|
||||
return min(abs(length(p) - 0.52) - 0.09, length(p) - 0.14);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 uv = inAux.yz;
|
||||
int id = int(inAux.x + 0.5);
|
||||
// uv 空间的像素级边缘宽度(quad 上 uv 随屏幕像素线性变化)
|
||||
float aa = fwidth(uv.x) * 1.5 + 1e-4;
|
||||
|
||||
float alpha = smoothstep(aa, -aa, ShapeSDF(uv, id));
|
||||
|
||||
if (id == 1) { // 点光:核心外叠加径向光晕
|
||||
float r = length(uv);
|
||||
float halo = (1.0 - smoothstep(0.25, 1.0, r)) * 0.35;
|
||||
alpha = max(alpha, halo);
|
||||
}
|
||||
|
||||
// 预乘 alpha:ONE / ONE_MINUS_SRC_ALPHA 混合下的正确形式
|
||||
outColor = vec4(inColor.rgb * alpha, alpha);
|
||||
}
|
||||
Reference in New Issue
Block a user