chore: W1 项目骨架 — 基线 v1.0 架构落盘(Godot 4.7.2 / gl_compatibility)
架构基线:docs/architecture/2026-10-19-F-architecture.md(v1.0) 范围:WRATH OF THE DEAD《怨返》单人挂机 · GDScript · 1280×720 · 12 班底数据驱动 - 骨架:project.godot(4.7 + GL Compatibility)、架构 §2.1 完整目录树(含占位说明)、 .gitignore/.gitattributes(LF 纪律)、README.md、CLAUDE.md、export_presets.cfg 占位、 pipeline/README.md(3ds Max 侧契约) - 数据管线段 1:data/sheets/generators.csv(GDD §3.1 十二班底逐值抄录) + data/schema/generators.schema.json(v0)+ src/tools/sheet_importer.gd (import_all/import_sheet/validate + ImportReport + .tres stub + 行号/列名/原因失败策略) + src/tools/import_main.gd(CI CLI 入口)+ data/build/generators.json(字节级确定性产物) - 探针:P1(SCREEN_TEXTURE/CanvasLayer 排序)与 P3(NoiseTexture2D seamless)场景代码与 截图/统计工具;实测手册与结论模板在工作区 docs/engineering/(随仓库外文档树) - CI:数据门激活(import_all + schema validate + build 漂移门);单测/sim/导出 W3+ 注释占位; 4.7.2 headless CLI 行为标注待本机验证 待用户侧:P1/P3 实测回填结论;P6 字体许可 / P7 GPU 实测;look-dev 游魂初版(Max 侧)
This commit is contained in:
commit
856326a766
42 files changed
+1814
No files matched your search
@@ -0,0 +1,14 @@
|
||||
# 探针 P1 —— SCREEN_TEXTURE / CanvasLayer 排序语义
|
||||
|
||||
验证 Godot 4.7 后处理三问(架构 §11 P1 / §5.2 ADR-2):
|
||||
① 背景色是否含入 SCREEN_TEXTURE 采样;② CanvasLayer 排序(L0 世界 < L1 后处理 < L2 UI);③ UI 层是否被后处理污染。
|
||||
|
||||
**完整实测手册(必读,约 30 分钟)**:
|
||||
`docs/engineering/2026-10-19-f-w1-probe-p1-manual.md`(本仓库外的工作区文档树)
|
||||
|
||||
**跑法**:编辑器打开 `tests/probe_p1_screen_texture/probe_p1.tscn` → F6 运行当前场景。
|
||||
键位:`1` 直通 / `2` 反色 / `3` 红染 / `4` 纯绿 / `V` 显隐后处理层 / `S` 截图到 `user://` / `Esc` 退出。
|
||||
控制台会打印引擎版本 / rendering_method / 显卡适配器——回填结论时连同截图一起归档。
|
||||
|
||||
**结论回填**:`docs/engineering/probes/P1-result.md`
|
||||
**不过的回退**:SubViewport + BackBufferCopy(架构预算 +2-4h)。
|
||||
@@ -0,0 +1,183 @@
|
||||
extends Node
|
||||
|
||||
# ============================================================================
|
||||
# 探针 P1 —— Godot 4.7 hint_screen_texture / SCREEN_TEXTURE 语义
|
||||
# 架构依据:§11 P1 / §5.2(ADR-2 单趟 fused 后处理的 CanvasLayer 拓扑)
|
||||
# 实测手册:docs/engineering/2026-10-19-f-w1-probe-p1-manual.md
|
||||
# 结论回填:docs/engineering/probes/P1-result.md
|
||||
#
|
||||
# 三问:
|
||||
# ① 背景/世界色是否含入 SCREEN_TEXTURE 采样(后处理 L1 能否看见 L0)
|
||||
# ② CanvasLayer 排序语义(L1 后处理在 L0 世界之上、L2 UI 之下)
|
||||
# ③ UI 层是否被后处理污染(UI 保持 crisp、不被 shader 调制)
|
||||
#
|
||||
# 场景在 _ready() 中代码化搭建(不手写 .tscn 降低出错面)。
|
||||
# 键位:1 直通 | 2 反色 | 3 红染 | 4 纯绿 | V 显/隐后处理层 | S 截图 user:// | Esc 退出
|
||||
# ============================================================================
|
||||
|
||||
enum PostMode { PASSTHROUGH, INVERT, RED_TINT, SOLID_GREEN }
|
||||
|
||||
var _post: ColorRect
|
||||
var _post_visible := true
|
||||
var _mode: int = PostMode.PASSTHROUGH
|
||||
var _mat: ShaderMaterial
|
||||
var _hud: Label
|
||||
var _shot_n := 0
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_build_world()
|
||||
_build_post()
|
||||
_build_ui()
|
||||
_print_environment()
|
||||
|
||||
|
||||
func _build_world() -> void:
|
||||
var world := CanvasLayer.new()
|
||||
world.name = "L0_World"
|
||||
world.layer = 0
|
||||
add_child(world)
|
||||
|
||||
var bg := ColorRect.new()
|
||||
bg.name = "Background"
|
||||
bg.color = Color("#23384F") # 已知底色:后处理里能看见它 = 世界含入采样
|
||||
bg.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
world.add_child(bg)
|
||||
|
||||
var marker := ColorRect.new()
|
||||
marker.name = "WorldMarker"
|
||||
marker.color = Color("#D08A2E")
|
||||
marker.position = Vector2(400, 240)
|
||||
marker.size = Vector2(480, 240)
|
||||
world.add_child(marker)
|
||||
|
||||
var world_label := Label.new()
|
||||
world_label.name = "WorldLabel"
|
||||
world_label.text = "L0 World: bg #23384F + marker #D08A2E"
|
||||
world_label.position = Vector2(24, 180)
|
||||
world_label.add_theme_color_override("font_color", Color.WHITE)
|
||||
world.add_child(world_label)
|
||||
|
||||
|
||||
func _build_post() -> void:
|
||||
var post_layer := CanvasLayer.new()
|
||||
post_layer.name = "L1_PostProcess"
|
||||
post_layer.layer = 1
|
||||
add_child(post_layer)
|
||||
|
||||
var sh := load("res://tests/probe_p1_screen_texture/probe_p1.gdshader") as Shader
|
||||
_mat = ShaderMaterial.new()
|
||||
_mat.shader = sh
|
||||
_mat.set_shader_parameter("mode", PostMode.PASSTHROUGH)
|
||||
|
||||
_post = ColorRect.new()
|
||||
_post.name = "PostProcessRect"
|
||||
_post.material = _mat
|
||||
_post.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
_post.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
post_layer.add_child(_post)
|
||||
|
||||
|
||||
func _build_ui() -> void:
|
||||
var ui_layer := CanvasLayer.new()
|
||||
ui_layer.name = "L2_UI"
|
||||
ui_layer.layer = 2
|
||||
add_child(ui_layer)
|
||||
|
||||
var root := Control.new()
|
||||
root.name = "UIRoot"
|
||||
root.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
ui_layer.add_child(root)
|
||||
|
||||
# UI 样本:四色板 + 一块纯白。被后处理污染 = 颜色变了/出现着色/纸纹
|
||||
var chip_colors := [
|
||||
Color("#1A1614"), Color("#EDE6D8"), Color("#B03A2E"),
|
||||
Color("#3A5A6B"), Color("#FFFFFF"),
|
||||
]
|
||||
var chip_names := ["墨 #1A1614", "骨白 #EDE6D8", "朱砂 #B03A2E", "靛 #3A5A6B", "纯白 #FFFFFF"]
|
||||
for i in chip_colors.size():
|
||||
var chip := ColorRect.new()
|
||||
chip.name = "Chip%d" % i
|
||||
chip.color = chip_colors[i]
|
||||
chip.size = Vector2(200, 40)
|
||||
chip.position = Vector2(960, 48 + i * 56)
|
||||
root.add_child(chip)
|
||||
var lbl := Label.new()
|
||||
lbl.name = "ChipLabel%d" % i
|
||||
lbl.text = chip_names[i]
|
||||
lbl.position = Vector2(1010, 54 + i * 56)
|
||||
if chip_colors[i].get_luminance() > 0.5:
|
||||
lbl.add_theme_color_override("font_color", Color.BLACK)
|
||||
else:
|
||||
lbl.add_theme_color_override("font_color", Color.WHITE)
|
||||
root.add_child(lbl)
|
||||
|
||||
_hud = Label.new()
|
||||
_hud.name = "HUDHelp"
|
||||
_hud.text = _help_text()
|
||||
_hud.position = Vector2(24, 648)
|
||||
_hud.add_theme_color_override("font_color", Color.WHITE)
|
||||
root.add_child(_hud)
|
||||
|
||||
|
||||
func _help_text() -> String:
|
||||
var mode_names := ["PASS直通", "INVERT反色", "RED红染", "GREEN纯绿"]
|
||||
var mode_name := mode_names[_mode] if _mode >= 0 and _mode < mode_names.size() else "?"
|
||||
return "探针 P1 | 1 直通 2 反色 3 红染 4 纯绿 | V 显/隐后处理层(当前:%s)| S 截图到 user:// | Esc 退出 | 当前 mode=%s" % [
|
||||
"显示" if _post_visible else "隐藏", mode_name]
|
||||
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
var key_event := event as InputEventKey
|
||||
if key_event != null and key_event.pressed and not key_event.echo:
|
||||
match key_event.keycode:
|
||||
KEY_1:
|
||||
_set_mode(PostMode.PASSTHROUGH)
|
||||
KEY_2:
|
||||
_set_mode(PostMode.INVERT)
|
||||
KEY_3:
|
||||
_set_mode(PostMode.RED_TINT)
|
||||
KEY_4:
|
||||
_set_mode(PostMode.SOLID_GREEN)
|
||||
KEY_V:
|
||||
_post_visible = not _post_visible
|
||||
_post.visible = _post_visible
|
||||
_hud.text = _help_text()
|
||||
KEY_S:
|
||||
_screenshot()
|
||||
KEY_ESCAPE:
|
||||
get_tree().quit()
|
||||
|
||||
|
||||
func _set_mode(m: int) -> void:
|
||||
_mode = m
|
||||
_mat.set_shader_parameter("mode", m)
|
||||
_hud.text = _help_text()
|
||||
var mode_names := ["PASS直通", "INVERT反色", "RED红染", "GREEN纯绿"]
|
||||
print("P1 mode → %d(%s)" % [m, mode_names[m] if m >= 0 and m < mode_names.size() else "?"])
|
||||
|
||||
|
||||
func _screenshot() -> void:
|
||||
var tex := get_viewport().get_texture()
|
||||
if tex == null:
|
||||
push_warning("P1: viewport texture 为空,回退:请用系统截图(Win+Shift+S)")
|
||||
return
|
||||
var img := tex.get_image()
|
||||
if img == null:
|
||||
push_warning("P1: get_image() 失败,回退:请用系统截图(Win+Shift+S)")
|
||||
return
|
||||
var path := "user://p1_mode_%d_%02d.png" % [_mode, _shot_n]
|
||||
_shot_n += 1
|
||||
var err := img.save_png(path)
|
||||
print("P1 screenshot → ", path, " err=", err)
|
||||
|
||||
|
||||
func _print_environment() -> void:
|
||||
var v := Engine.get_version_info()
|
||||
print("=== P1 probe 环境(截图请连同此段一起归档)===")
|
||||
print("godot: %d.%d.%d %s" % [int(v.major), int(v.minor), int(v.patch), str(v.status)])
|
||||
print("rendering_method: ", ProjectSettings.get_setting("rendering/renderer/rendering_method"))
|
||||
print("adapter: ", RenderingServer.get_video_adapter_name())
|
||||
print("viewport: ", get_viewport().get_visible_rect().size)
|
||||
print("stretch: ", ProjectSettings.get_setting("display/window/stretch/mode"), " / ", ProjectSettings.get_setting("display/window/stretch/aspect"))
|
||||
print("=== 键位:1 直通 | 2 反色 | 3 红染 | 4 纯绿 | V 显隐后处理 | S 截图 | Esc 退出 ===")
|
||||
@@ -0,0 +1,26 @@
|
||||
shader_type canvas_item;
|
||||
|
||||
// ============================================================================
|
||||
// 探针 P1 shader —— SCREEN_TEXTURE 语义(架构 §11 P1 / §5.2 ADR-2)
|
||||
// 由 probe_p1.gd 以 ShaderMaterial 挂到 L1 全屏 ColorRect 上。
|
||||
// mode(uniform int):
|
||||
// 0 直通 —— 验证"背景/世界是否含入 SCREEN_TEXTURE 采样"
|
||||
// 1 反色 —— 放大世界内容差异,便于肉眼确认采样到了 L0
|
||||
// 2 红色染色 —— L1 全屏染色:验证 L2 UI 是否被后处理污染(UI 应保持原色 crisp)
|
||||
// 3 纯绿 —— 顺序验证:整屏变绿 = CanvasLayer 排序 L0<L1<L2 符合预期
|
||||
// ============================================================================
|
||||
|
||||
uniform int mode = 0;
|
||||
|
||||
void fragment() {
|
||||
vec4 screen = texture(SCREEN_TEXTURE, SCREEN_UV);
|
||||
if (mode == 0) {
|
||||
COLOR = screen;
|
||||
} else if (mode == 1) {
|
||||
COLOR = vec4(1.0 - screen.rgb, screen.a);
|
||||
} else if (mode == 2) {
|
||||
COLOR = vec4(screen.r, 0.0, 0.0, 1.0);
|
||||
} else {
|
||||
COLOR = vec4(0.0, 1.0, 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
[gd_scene load_steps=2 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://tests/probe_p1_screen_texture/probe_p1.gd" id="1"]
|
||||
|
||||
[node type="Node" name="ProbeP1ScreenTexture"]
|
||||
script = ExtResource("1")
|
||||
@@ -0,0 +1,16 @@
|
||||
# 探针 P3 —— NoiseTexture2D / FastNoiseLite 平铺语义
|
||||
|
||||
验证 `seamless = true` 是否真正可平铺(架构 §11 P3;纸纹 pass 的 tileable 前提,管线报告 §6.3)。
|
||||
屏上为 `seamless = true/false` 两个 2×2 平铺网格(红线 = tile 边界);按 `S` 生成边界差图 PNG(`user://p3_diff_*.png`)并打印 wrap/grad 比统计。
|
||||
|
||||
**完整实测手册(必读,约 30 分钟)**:
|
||||
`docs/engineering/2026-10-19-f-w1-probe-p3-manual.md`(本仓库外的工作区文档树)
|
||||
|
||||
**跑法**:编辑器打开 `tests/probe_p3_noise_tiling/probe_p3.tscn` → F6 运行当前场景。
|
||||
键位:`S` 生成检查图 + 打印统计 / `Esc` 退出。
|
||||
|
||||
**结论回填**:`docs/engineering/probes/P3-result.md`
|
||||
**不过的回退**:脚本预烘焙无缝纹理(用 Image 环绕混合生成 256² 纸纹源,不进 NoiseTexture2D)。
|
||||
|
||||
**知识缺口标注**:`FastNoiseLite.TYPE_SIMPLEX` / `FRACTAL_FBM` / `NoiseTexture2D.seamless` / `seamless_blend_ratio`
|
||||
为 4.x 稳定名;若 4.7.2 打开报错,按实际属性名修正并记录到 `docs/engineering/`。
|
||||
@@ -0,0 +1,167 @@
|
||||
extends Node2D
|
||||
|
||||
# ============================================================================
|
||||
# 探针 P3 —— NoiseTexture2D / FastNoiseLite 平铺语义(架构 §11 P3)
|
||||
# 依据:管线报告 §6.3;作用于 §5.2 纸纹 pass(双尺度 noise 有序抖动的 tileable 前提)
|
||||
# 实测手册:docs/engineering/2026-10-19-f-w1-probe-p3-manual.md
|
||||
# 结论回填:docs/engineering/probes/P3-result.md
|
||||
#
|
||||
# 验证:seamless = true 是否真正可平铺
|
||||
# - 屏上:左右两个 2×2 tile 网格(红线 = tile 边界 @256px)肉直视读接缝
|
||||
# - 按 S:生成边界差图 PNG(user://p3_diff_*.png)+ 控制台统计
|
||||
# * wrap_* = |左边缘-右边缘| / |上边缘-下边缘|(平铺接缝强度)
|
||||
# * grad_mean = 相邻像素平均差(自然梯度基线)
|
||||
# * seamless 若有效:wrap ≈ grad(同数量级);若无效:wrap >> grad
|
||||
#
|
||||
# 知识缺口:FastNoiseLite/NoiseTexture2D 属性名(seamless / seamless_blend_ratio /
|
||||
# TYPE_SIMPLEX / FRACTAL_FBM)为 4.x 稳定名;4.7.2 若报错按实际属性名修正并记录。
|
||||
# ============================================================================
|
||||
|
||||
const NOISE_SIZE := 256 # 每 tile 256×256;面板 512×512 = 2×2 平铺
|
||||
const PANEL_SIZE := 512
|
||||
|
||||
var _textures: Array = []
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_textures = [_make_texture(true), _make_texture(false)]
|
||||
var positions := [Vector2(96, 160), Vector2(672, 160)]
|
||||
var titles := ["seamless = true", "seamless = false"]
|
||||
for i in _textures.size():
|
||||
var tr := TextureRect.new()
|
||||
tr.name = "Panel%d" % i
|
||||
tr.texture = _textures[i]
|
||||
tr.position = positions[i]
|
||||
tr.size = Vector2(PANEL_SIZE, PANEL_SIZE)
|
||||
tr.stretch_mode = TextureRect.STRETCH_TILE
|
||||
tr.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
add_child(tr)
|
||||
var overlay := SeamOverlay.new()
|
||||
overlay.position = positions[i]
|
||||
add_child(overlay)
|
||||
var t := Label.new()
|
||||
t.name = "PanelTitle%d" % i
|
||||
t.text = "%s(红线 = tile 边界;面板内 2×2 平铺)" % titles[i]
|
||||
t.position = Vector2(int(positions[i].x), 128)
|
||||
t.add_theme_color_override("font_color", Color.WHITE)
|
||||
add_child(t)
|
||||
var hud := Label.new()
|
||||
hud.name = "HUDHelp"
|
||||
hud.text = "探针 P3 | 对比两侧红线处接缝(错位/亮度跳变=异常)| S 生成检查图到 user:// 并打印统计 | Esc 退出"
|
||||
hud.position = Vector2(96, 648)
|
||||
hud.add_theme_color_override("font_color", Color.WHITE)
|
||||
add_child(hud)
|
||||
_print_environment()
|
||||
|
||||
|
||||
func _make_texture(seamless: bool) -> NoiseTexture2D:
|
||||
var fnl := FastNoiseLite.new()
|
||||
fnl.seed = 20261019
|
||||
fnl.noise_type = FastNoiseLite.TYPE_SIMPLEX
|
||||
fnl.frequency = 0.02
|
||||
fnl.fractal_type = FastNoiseLite.FRACTAL_FBM
|
||||
fnl.fractal_octaves = 3
|
||||
fnl.fractal_lacunarity = 2.0
|
||||
fnl.fractal_gain = 0.5
|
||||
var nt := NoiseTexture2D.new()
|
||||
nt.width = NOISE_SIZE
|
||||
nt.height = NOISE_SIZE
|
||||
nt.noise = fnl
|
||||
nt.seamless = seamless
|
||||
nt.seamless_blend_ratio = 0.25
|
||||
nt.generate_mipmaps = false
|
||||
return nt
|
||||
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
var key_event := event as InputEventKey
|
||||
if key_event != null and key_event.pressed and not key_event.echo:
|
||||
match key_event.keycode:
|
||||
KEY_S:
|
||||
_generate_check_images()
|
||||
KEY_ESCAPE:
|
||||
get_tree().quit()
|
||||
|
||||
|
||||
func _generate_check_images() -> void:
|
||||
var names := ["seamless", "periodic"]
|
||||
print("=== P3 检查图与统计 ===")
|
||||
for i in _textures.size():
|
||||
var nt: NoiseTexture2D = _textures[i]
|
||||
var img := nt.get_image()
|
||||
if img == null:
|
||||
push_warning("P3: NoiseTexture2D.get_image() 返回 null(%s)。回退:系统截图(Win+Shift+S)+ 肉眼判读。" % names[i])
|
||||
continue
|
||||
var w := img.get_width()
|
||||
var h := img.get_height()
|
||||
# 边界差图(×8 放大):wrap 接缝越亮 = 平铺越不连续
|
||||
var strip_v := Image.create(w, h, false, Image.FORMAT_RGBA8)
|
||||
var strip_h := Image.create(w, h, false, Image.FORMAT_RGBA8)
|
||||
for y in h:
|
||||
var dv := _amp(absf(img.get_pixel(0, y).r - img.get_pixel(w - 1, y).r))
|
||||
for x in w:
|
||||
strip_v.set_pixel(x, y, Color(dv, dv, dv, 1.0))
|
||||
for x in w:
|
||||
var dh := _amp(absf(img.get_pixel(x, 0).r - img.get_pixel(x, h - 1).r))
|
||||
for y in h:
|
||||
strip_h.set_pixel(x, y, Color(dh, dh, dh, 1.0))
|
||||
strip_v.save_png("user://p3_diff_v_%s.png" % names[i])
|
||||
strip_h.save_png("user://p3_diff_h_%s.png" % names[i])
|
||||
var stats := _edge_stats(img)
|
||||
print("%s: wrap_v mean=%.5f max=%.5f | wrap_h mean=%.5f max=%.5f | grad_mean=%.5f → wrap/grad v=%.2fx h=%.2fx" % [
|
||||
names[i], stats.wrap_v_mean, stats.wrap_v_max, stats.wrap_h_mean, stats.wrap_h_max, stats.grad_mean,
|
||||
stats.wrap_v_mean / maxf(stats.grad_mean, 1e-9), stats.wrap_h_mean / maxf(stats.grad_mean, 1e-9)])
|
||||
print("PNG 位置:%APPDATA%/Godot/app_userdata/<项目名>/p3_diff_*.png")
|
||||
print("判读:seamless 行 wrap/grad ≈ 1-3x = 可用;periodic 行 wrap/grad ≫ 1 = 对照组生效(说明指标有效)")
|
||||
|
||||
|
||||
func _amp(d: float) -> float:
|
||||
return clampf(d * 8.0, 0.0, 1.0)
|
||||
|
||||
|
||||
func _edge_stats(img: Image) -> Dictionary:
|
||||
var w := img.get_width()
|
||||
var h := img.get_height()
|
||||
var wrap_v := 0.0
|
||||
var wrap_v_max := 0.0
|
||||
for y in h:
|
||||
var d := absf(img.get_pixel(0, y).r - img.get_pixel(w - 1, y).r)
|
||||
wrap_v += d
|
||||
wrap_v_max = maxf(wrap_v_max, d)
|
||||
var wrap_h := 0.0
|
||||
var wrap_h_max := 0.0
|
||||
for x in w:
|
||||
var d := absf(img.get_pixel(x, 0).r - img.get_pixel(x, h - 1).r)
|
||||
wrap_h += d
|
||||
wrap_h_max = maxf(wrap_h_max, d)
|
||||
var grad := 0.0
|
||||
for y in h:
|
||||
for x in w - 1:
|
||||
grad += absf(img.get_pixel(x, y).r - img.get_pixel(x + 1, y).r)
|
||||
return {
|
||||
"wrap_v_mean": wrap_v / h,
|
||||
"wrap_v_max": wrap_v_max,
|
||||
"wrap_h_mean": wrap_h / w,
|
||||
"wrap_h_max": wrap_h_max,
|
||||
"grad_mean": grad / float((w - 1) * h),
|
||||
}
|
||||
|
||||
|
||||
func _print_environment() -> void:
|
||||
var v := Engine.get_version_info()
|
||||
print("=== P3 probe 环境 ===")
|
||||
print("godot: %d.%d.%d %s" % [int(v.major), int(v.minor), int(v.patch), str(v.status)])
|
||||
print("rendering_method: ", ProjectSettings.get_setting("rendering/renderer/rendering_method"))
|
||||
print("adapter: ", RenderingServer.get_video_adapter_name())
|
||||
print("noise: FastNoiseLite simplex fbm oct3 f0.02 | tile 256×256 | blend_ratio 0.25")
|
||||
|
||||
|
||||
class SeamOverlay extends Node2D:
|
||||
const TILE := 256
|
||||
const PANEL := 512
|
||||
|
||||
func _draw() -> void:
|
||||
var c := Color(1.0, 0.2, 0.2, 0.6)
|
||||
draw_line(Vector2(TILE, 0), Vector2(TILE, PANEL), c, 1.0)
|
||||
draw_line(Vector2(0, TILE), Vector2(PANEL, TILE), c, 1.0)
|
||||
draw_rect(Rect2(Vector2.ZERO, Vector2(PANEL, PANEL)), c, false, 1.0)
|
||||
@@ -0,0 +1,6 @@
|
||||
[gd_scene load_steps=2 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://tests/probe_p3_noise_tiling/probe_p3.gd" id="1"]
|
||||
|
||||
[node type="Node2D" name="ProbeP3NoiseTiling"]
|
||||
script = ExtResource("1")
|
||||
@@ -0,0 +1 @@
|
||||
# tests/sim_reports —— 模拟器 14 门报告 report-<date>.json(git 跟踪,月度对账证据)。W4 首轮(架构 §9.3/§10.3)。
|
||||
@@ -0,0 +1 @@
|
||||
# tests/unit —— GUT 单测(core 全覆盖:公式/迁移/格式化)。W3 激活;GUT addon 待合入(CI W3 占位)。
|
||||
Reference in new issue
Block a user