Files
HelloVulkan/shaders/debug/gizmo_billboard.frag
T
atdunbg f73e52926f Reorganize directory layout: editor panels/, grouped shaders, drop stale header
- App/editor: move 7 panels into panels/ (Editor core stays at root)
- shaders/: group into pbr/ post/ debug/ env/ (runtime load paths updated)
- Delete outdated duplicate Engine/src/Renderer/VulkanAssetUploader.h
2026-10-07 09:52:17 +08:00

85 lines
3.1 KiB
GLSL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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);
}