看见反常 · 动一处 · 抓证据
症状出现后,代码该从哪一段查?
只读 · 与实验共用计算模型
这页解决什么
空间错误、精度损失、重绘和提交成本各有一个入口。按症状选择章节,不必从头硬读。
先找数据在哪一步被解释错
改公式前,找到坐标空间发生变化的边界。
// Graphics Debugger Suite — executable teaching model
type Space = "tangent" | "object" | "world" | "view";
const normal = normalize(TBN * decodeNormalMap(rgb));
const correctedNormal = normalize(inverseTranspose(model) * vec4(normal, 0.0)).xyz;
const stage = { vertex, varying, fragment };
shaderError = !normalDecode || (worldScale !== 1.0 && !inverseTranspose);
法线贴图要先解码,再换参照物
Tangent → World 是矩阵变换,不是改个名字。
type Space = "tangent" | "object" | "world" | "view";
const normal = normalize(TBN * decodeNormalMap(rgb));
const correctedNormal = normalize(inverseTranspose(model) * vec4(normal, 0.0)).xyz;
const stage = { vertex, varying, fragment };
shaderError = !normalDecode || (worldScale !== 1.0 && !inverseTranspose);
深度能分多细,取决于使用范围
Near/Far 比值和世界尺度会先解释症状。
const depthRatio = log(far / near) / log(1000000.0);
const precisionError = precision === "f16" ? depthRatio * (worldScale / 24.0) : depthRatio * 0.04;
const depth01 = clamp(depth, 0.0, 1.0); // projection-encoded depth, not world metres
const reversedZ = 1.0 - depth01; // visual mapping: near high, far low; real setup also needs reversed projection + GREATER + float depthPrepass 省片元,也会增加提交与带宽
要对比省下的工作和新增的深度成本。
const overdraw = layers * (depthPrepass ? 0.62 : 1.0);
const effectiveDrawCalls = instancing ? ceil(drawCalls * 0.38) : drawCalls;
const cpuMs = 0.18 + effectiveDrawCalls * 0.035 + (depthPrepass ? 0.42 : 0.0);
const gpuMs = resolutionScale * resolutionScale * (0.45 + overdraw * 0.31);
const bandwidthMb = resolutionScale * resolutionScale * (8.0 + variants * 1.7) * (1.0 - atlasCoverage * 0.35);证据必须带着当时的参数
别人用同一组参数,才可能复现你的结论。
reportId = `${scene}-${debugMode}-${hash(config)}`;
risk = max(shaderError, precisionError, cpuMs > targetMs, gpuMs > targetMs);