File size: 15,286 Bytes
ceea884 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 | """๋
ผ๋ฌธ์ ์ํคํ
์ฒ ๋์ ๋ ์ฅ โ make_panels.py ์ ์ค์ ๋ฐ์ดํฐ ํจ๋์ ํฉ์น๋ค.
fig_viewpoint_model.png : ๋ฉํฐ๋ทฐ ์์ ๋ณํ ๋ชจ๋ธ (๊ตฌ๊ฐ๋ณ 3DGS ํ์ต โ ๋ฆฌ๊ทธ ๋ณํ ๋ ๋)
fig_engine_pipeline.png : Vulkan ์๋ฎฌ๋ ์ด์
์์ง (CPU ์๋ฎฌ๋ ์ด์
๋ฃจํ + GPU ๋ ๋ ๊ทธ๋ํ)
์ฐธ๊ณ ํ ๋์ ํ์: 3DGS (Kerbl 2023) ์ต์ ํ ํ์ดํ๋ผ์ธ, HUGSIM ยท OmniRe ๊ฐ์๋ โ ๋จ๊ณ๋ง๋ค ์ค์ ๋ฐ์ดํฐ ๊ทธ๋ฆผ, ๋ฐ์ดํฐ ํ๋ฆ ํ์ดํ,
gradient ๋๋๋ฆผ ํ์ดํ.
"""
import json
import os
import sys
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt # noqa: E402
from matplotlib.patches import Circle, FancyArrowPatch, FancyBboxPatch, Polygon, Rectangle # noqa: E402
from PIL import Image # noqa: E402
P = Path(sys.argv[1]) # ํจ๋
OUT = Path(sys.argv[2])
EXTRA = Path(sys.argv[3]) # sensors_sim.png, drive_6cam_still.jpg ๊ฐ ์๋ ๊ณณ
ROOT = Path(__file__).resolve().parents[3]
plt.rcParams["font.family"] = ["NanumBarunGothic", "DejaVu Sans"] # ์์ ๊ธฐํธ(ร, แต, ์๋์ฒจ์, โ)๋ DejaVu ๋ก
plt.rcParams["axes.unicode_minus"] = False
NAVY, BLUE, LIGHT, PALE, GRAY, ORANGE, GREEN = "#1F3B70", "#4472C4", "#DCE6F4", "#F4F7FB", "#404040", "#ED7D31", "#5B9B4C"
class Canvas:
def __init__(self, w, h):
self.W, self.H = w, h
self.fig = plt.figure(figsize=(w, h), facecolor="white")
def ax(self, x, y, w, h): # ์์ชฝ ๊ธฐ์ค (y = ์์์ inch)
a = self.fig.add_axes([x / self.W, 1 - (y + h) / self.H, w / self.W, h / self.H])
a.axis("off")
return a
def img(self, path, x, y, w, h, border=NAVY, lw=1.2, title=None, tsize=11, crop=None):
im = Image.open(path).convert("RGB")
if crop:
im = im.crop(crop)
a = self.ax(x, y, w, h)
a.imshow(im, aspect="auto")
a.set_xlim(0, im.width)
a.set_ylim(im.height, 0)
if border:
self.rect(x, y, w, h, fc="none", ec=border, lw=lw, r=0.0)
if title:
self.text(x + w / 2, y - 0.12, title, size=tsize, bold=True, color=NAVY)
return a
def _fig_xy(self, x, y):
return x / self.W, 1 - y / self.H
def rect(self, x, y, w, h, fc=PALE, ec=LIGHT, lw=1.0, r=0.08, ls="-", z=0):
bx = FancyBboxPatch(self._fig_xy(x, y + h), w / self.W, h / self.H,
boxstyle=f"round,pad=0,rounding_size={r / self.W}" if r else "square,pad=0",
transform=self.fig.transFigure, fc=fc, ec=ec, lw=lw, ls=ls, zorder=z)
self.fig.add_artist(bx)
return bx
def text(self, x, y, s, size=11, bold=False, color=GRAY, ha="center", va="center", style="normal", z=8):
self.fig.text(*self._fig_xy(x, y), s, fontsize=size, fontweight="bold" if bold else "normal", color=color,
ha=ha, va=va, fontstyle=style, zorder=z)
def arrow(self, x0, y0, x1, y1, color=BLUE, lw=2.2, ls="-", rad=0.0, head=14):
a = FancyArrowPatch(self._fig_xy(x0, y0), self._fig_xy(x1, y1), transform=self.fig.transFigure,
arrowstyle=f"-|>,head_length={head / 20},head_width={head / 34}", color=color, lw=lw,
ls=ls, connectionstyle=f"arc3,rad={rad}", mutation_scale=10, zorder=5)
self.fig.add_artist(a)
def chip(self, x, y, s, fc=NAVY, color="white", size=10, w=None, h=0.3):
w = w or (0.085 * len(s) * size / 10 + 0.22)
self.rect(x - w / 2, y - h / 2, w, h, fc=fc, ec="none", r=0.12, z=6)
self.text(x, y, s, size=size, bold=True, color=color)
def save(self, path):
self.fig.savefig(path, dpi=220, facecolor="white")
plt.close(self.fig)
def split(path, h_in, cut_in):
"""(a) ยท (b) ๋ ๋ฅผ ๋ฐ๋ก ์ ์ฅ โ ์ฌ๋ผ์ด๋์์ ํฌ๊ฒ ๋ณด์ด๊ฒ."""
im = Image.open(path)
y = int(im.height * cut_in / h_in)
im.crop((0, 0, im.width, y)).save(str(path).replace(".png", "_a.png"))
im.crop((0, y, im.width, im.height)).save(str(path).replace(".png", "_b.png"))
def stack(c, paths, x, y, w, h, dx=0.16, dy=0.16):
"""๊ฒน์น ์ฌ์ง ๋ฌถ์ (๋ฉํฐ๋ทฐ ์
๋ ฅ)."""
for i, p in enumerate(paths):
c.img(p, x + i * dx, y + i * dy, w, h, border="white", lw=1.5)
c.rect(x + i * dx, y + i * dy, w, h, fc="none", ec=NAVY, lw=0.8, r=0)
# ================================================================== ๊ทธ๋ฆผ 1: ๋ฉํฐ๋ทฐ ์์ ๋ณํ ๋ชจ๋ธ
c = Canvas(16, 8.6)
c.text(0.25, 0.3, "(a) ๊ตฌ๊ฐ๋ณ 3DGS ์ฅ๋ฉด ํ์ต โ CUDA ยท gsplat", size=15, bold=True, color=NAVY, ha="left")
c.rect(0.15, 0.5, 15.7, 4.55, fc="#FAFBFD", ec=LIGHT, lw=1.2, r=0.12)
# ์
๋ ฅ
stack(c, [P / "gt_CAM_FRONT_LEFT.jpg", P / "gt_CAM_FRONT_RIGHT.jpg", P / "gt_CAM_FRONT.jpg"], 0.35, 0.95, 2.2, 1.24)
c.text(1.5, 2.65, "๋ฉํฐ๋ทฐ ์ฌ์ง (6์บ , 800ร450)", size=11, bold=True, color=NAVY)
c.img(P / "lidar_init.png", 0.35, 2.95, 2.55, 1.43)
c.text(1.62, 4.55, "์ ์ ๋ผ์ด๋ค ๋์ (์ฝ 400 sweep)", size=11, bold=True, color=NAVY)
c.text(1.62, 4.82, "์ฐจ๋ ยท ์ฌ๋ ๋ฐ์ค ์ ์ ์ ๊ฑฐ", size=9.5, color=GRAY)
c.arrow(2.95, 3.65, 3.45, 2.7, color=GRAY, lw=1.6)
c.chip(3.0, 3.1, "์ด๊ธฐํ", fc=GRAY, size=9)
# 3D ๊ฐ์ฐ์์
c.img(P / "gaussians_3d.png", 3.5, 1.05, 3.0, 1.69, title="3D ๊ฐ์ฐ์์ ์ฅ๋ฉด G")
c.text(5.0, 3.0, "G = { ฮผ, ฮฃ = RSSแตRแต, ฮฑ, SH (3์ฐจ) } ร โค 200๋ง", size=10, color=GRAY)
c.text(5.0, 3.3, "MCMC: ๋ฎ์ ฮฑ ์ฌ๋ฐฐ์น + ์์น ์ก์", size=10, color=GRAY)
c.arrow(6.55, 1.9, 7.25, 1.9)
c.chip(6.9, 1.6, r"w2cยท$\Delta$, K", fc=BLUE, size=8.5, w=0.95)
# ๋ฏธ๋ถ ๋์คํฐ๋ผ์ด์
c.img(P / "splats_tiles.png", 7.3, 1.05, 3.0, 1.69, title="๋ฏธ๋ถ ๋์คํฐ๋ผ์ด์ ")
c.text(8.8, 3.0, "ํฌ์ ฮฃโฒ = J W ฮฃ Wแต Jแต", size=10, color=GRAY)
c.text(8.8, 3.3, "16ร16 ํ์ผ ๊น์ด ์ ๋ ฌ โ ฮฑ ๋ธ๋ ๋ฉ", size=10, color=GRAY)
c.text(8.8, 3.6, "C = ฮฃ cแตข ฮฑแตข ฮ (1 โ ฮฑโฑผ)", size=10, color=GRAY)
c.arrow(10.35, 1.9, 10.85, 1.9)
# ๋ ๋ ์ถ๋ ฅ
c.img(P / "render_front.jpg", 10.9, 0.95, 2.1, 1.18, title="๋ ๋ ร + (1โฮฑ)ยทS(d)")
c.img(P / "render_depth.png", 10.9, 2.45, 2.1, 1.18)
c.text(11.95, 3.83, "๊ธฐ๋ ๊น์ด D", size=10.5, bold=True, color=NAVY)
c.arrow(13.05, 1.55, 13.45, 1.55)
c.arrow(13.05, 3.05, 13.45, 3.05)
# ๊ฐ๋
์ ํธ + ์์ค
c.img(P / "masks.png", 13.5, 0.95, 2.1, 1.18, title="์ค์ ์ฌ์ง ยท ๊ฐ๋ฆผ ๋ง์คํฌ")
c.img(P / "lidar_depth.png", 13.5, 2.45, 2.1, 1.18)
c.text(14.55, 3.83, "๋ผ์ด๋ค ๊น์ด D_lidar", size=10.5, bold=True, color=NAVY)
c.rect(9.0, 4.15, 6.65, 0.62, fc=NAVY, ec="none", r=0.1)
c.text(12.32, 4.46, "L = 0.8ยทL1 + 0.2ยทD-SSIM + 0.1ยทL_depth + 0.05ยท(L_sky + L_surf) + 0.01ยท(แพฑ + sฬ)", size=10.5, bold=True, color="white")
# gradient ๋๋๋ฆผ
c.arrow(9.0, 4.46, 5.0, 3.55, color=ORANGE, lw=2.2, ls="--", rad=-0.08)
c.text(6.7, 4.55, r"$\nabla$L (Adam) โ G ยท $\Delta$ (์นด๋ฉ๋ผ๋ณ SE3) ยท ์ ์ํ ยท ํ๋ ํ๋ธ๋งต", size=10.5, bold=True, color=ORANGE)
c.text(14.55, 4.95, "๋นจ๊ฐ: ์ฐจ๋ยท์ฌ๋ (์์ค ์ ์ธ) ํ๋: ํ๋ (ฮฑ โ 0)", size=9, color=GRAY)
# (b) ์์ ๋ณํ ๋ ๋
y0 = 5.35
c.text(0.25, y0, "(b) ๋ฉํฐ๋ทฐ ์์ ๋ณํ ๋ ๋ โ Vulkan ์คํ์คํฌ๋ฆฐ", size=15, bold=True, color=NAVY, ha="left")
c.rect(0.15, y0 + 0.2, 15.7, 3.15, fc="#FFF9F4", ec="#F6D3B8", lw=1.2, r=0.12)
c.img(P / "rig_transform.png", 0.45, y0 + 0.5, 2.25, 2.46, border=None)
c.text(1.57, y0 + 3.08, "๋ฆฌ๊ทธ ๋ณํ T (6์บ ๊ณตํต)", size=11, bold=True, color=NAVY)
c.text(3.75, y0 + 1.25, "Rโฒ = Rz(yaw)ยทRยทRx(โpitch)ยทRz(roll)", size=10, color=GRAY)
c.text(3.75, y0 + 1.55, "tโฒ = t + shift (cam โ ego)", size=10, color=GRAY)
c.text(3.75, y0 + 1.85, "์์ฐจ ๊ถค์ ยท ์๊ฐ์ ๊ทธ๋๋ก", size=10, color=GRAY)
c.arrow(2.75, y0 + 2.2, 4.6, y0 + 2.2, color=ORANGE)
c.img(P / "segments_bev.png", 4.7, y0 + 0.45, 2.3, 2.3, border=None)
c.text(5.85, y0 + 3.0, "ํ๋ ์๋ง๋ค ๋ด๋น ๊ตฌ๊ฐ ๋ชจ๋ธ", size=11, bold=True, color=NAVY)
c.arrow(7.05, y0 + 1.6, 7.55, y0 + 1.6, color=ORANGE)
lay = [["CAM_FRONT_LEFT", "CAM_FRONT", "CAM_FRONT_RIGHT"], ["CAM_BACK_RIGHT", "CAM_BACK", "CAM_BACK_LEFT"]]
for r, row in enumerate(lay):
for k, cam in enumerate(row):
c.img(P / f"render_{cam}.jpg", 7.6 + k * 1.22, y0 + 0.55 + r * 0.7, 1.18, 0.66, border="white", lw=0.5)
c.text(9.4, y0 + 2.15, "6์บ ๋์ ๋ ๋ (์ ๋ณด์ ์์ = ํ๊ท ์นด๋ฉ๋ผ ์)", size=10.5, bold=True, color=NAVY)
c.arrow(11.3, y0 + 1.25, 11.8, y0 + 1.25, color=ORANGE)
# ๋ณํ 9์ข
(๊ฐ์ ์ฌ ยท ์ ์นด๋ฉ๋ผ)
var = ["left_1m", "left_0.5m", "right_0.5m", "right_1m", "high_0.4m", "low_0.3m", "pitch_down_3", "yaw_left_4", "yaw_right_4"]
meta = json.load(open(ROOT / "outputs/aug/map/scene-0402/left_1m/meta.json"))
fs = [s for s in meta["samples"] if s["cam"] == "CAM_FRONT"]
smp = fs[len(fs) * 3 // 8]
name = os.path.basename(smp["original_filename"])
for i, v in enumerate(var):
r, k = divmod(i, 3)
c.img(ROOT / f"outputs/aug/map/scene-0402/{v}/CAM_FRONT/{name}", 11.9 + k * 1.3, y0 + 0.42 + r * 0.8, 1.26, 0.71, border="white", lw=0.5)
c.text(11.9 + k * 1.3 + 0.63, y0 + 0.42 + r * 0.8 + 0.62, v, size=7.5, bold=True, color="white")
c.text(13.85, y0 + 2.92, "์ ์์ 6์บ ร 9์ข
+ meta.json (์ calibrated_sensor)", size=10.5, bold=True, color=NAVY)
c.save(OUT / "fig_viewpoint_model.png")
split(OUT / "fig_viewpoint_model.png", 8.6, 5.15)
# ================================================================== ๊ทธ๋ฆผ 2: Vulkan ์๋ฎฌ๋ ์ด์
์์ง
c = Canvas(16, 8.45)
c.text(0.25, 0.3, "(a) ์๋ฎฌ๋ ์ด์
๋ฃจํ โ CPU, ๋งค ํ๋ ์ (closed-loop)", size=15, bold=True, color=NAVY, ha="left")
c.rect(0.15, 0.5, 15.7, 3.25, fc="#FAFBFD", ec=LIGHT, lw=1.2, r=0.12)
xs = [0.45, 3.0, 5.55, 8.1, 10.65, 13.2]
yt, bw, bh = 0.95, 2.2, 1.6
titles = ["โ ์ ์ด ์
๋ ฅ", "โก ์์ฐจ ๋์ญํ", "โข ์ถฉ๋ ํ์ ", "โฃ ๊ตฌ๊ฐ ์คํธ๋ฆฌ๋ฐ", "โค ์ผ์ ๋ ์ด์บ์คํธ", "โฅ ๊ธฐ๋ก ยท ๊ด์ธก"]
subs = ["ํค๋ณด๋ ยท ์คํฌ๋ฆฝํธ (50 ms)\nVLA ๊ฐ ๋ค์ด์ฌ ์๋ฆฌ", "ํค๋ค๋งํฑ ์์ ๊ฑฐ ๋ชจ๋ธ\n10 ms ํ์ ์คํ
", "์ฅ์ ๋ฌผ ๊ฒฉ์ 0.2 m ยท ์ฐ์\n์ค์นจ 2์ ยท ํ์ถ ํ์ ",
"๊ฐ๊น์ด ๋ด๋น ๊ถค์ ยท 3 m ํ์คํ
๋ฆฌ์์ค\n์ด์ 3๊ตฌ๊ฐ ๋น๋๊ธฐ ๋ก๋", "๋
ธ๋ฉด ์ ์ฐฉ โ ๋ผ์ด๋ค 32ch ยท ๋ ์ด๋ 5๋\n๋ณต์
์๋ DDA (4 ms)", "drive_log.csv ยท 6์บ PNG\n๋ผ์ด๋ค .bin ยท ๋ ์ด๋ .txt"]
for i, x in enumerate(xs):
c.rect(x, yt, bw, bh, fc="white", ec=LIGHT, lw=1.0, r=0.08)
c.text(x + bw / 2, yt + bh + 0.22, titles[i], size=11.5, bold=True, color=NAVY)
c.text(x + bw / 2, yt + bh + 0.62, subs[i], size=9, color=GRAY)
if i < 5:
c.arrow(x + bw + 0.03, yt + bh / 2, xs[i + 1] - 0.03, yt + bh / 2, lw=2)
# โ ์ด์ ๋ ์์ด์ฝ
a = c.ax(xs[0], yt, bw, bh)
a.set_xlim(-1.4, 1.4)
a.set_ylim(-1.0, 1.0)
a.set_aspect("equal")
a.add_patch(Circle((0, 0), 0.75, fill=False, lw=6, color=NAVY))
a.add_patch(Circle((0, 0), 0.18, color=NAVY))
for ang in (90, 210, 330):
import numpy as np
a.plot([0, 0.72 * np.cos(np.radians(ang))], [0, 0.72 * np.sin(np.radians(ang))], color=NAVY, lw=5)
a.text(0, -0.93, "throttle ยท brake ยท steer", ha="center", fontsize=8.5, color=GRAY)
# โก ์์ ๊ฑฐ ๋ชจ๋ธ ๊ทธ๋ฆผ
a = c.ax(xs[1], yt, bw, bh)
a.set_xlim(-1.6, 1.6)
a.set_ylim(-1.15, 1.15)
a.set_aspect("equal")
a.add_patch(Rectangle((-0.45, -0.95), 0.9, 1.9, fc=LIGHT, ec=NAVY, lw=1.5))
for wx, wy, rot in ((-0.45, -0.6, 0), (0.45, -0.6, 0), (-0.45, 0.6, 18), (0.45, 0.6, 18)):
t = matplotlib.transforms.Affine2D().rotate_deg_around(wx, wy, rot) + a.transData
a.add_patch(Rectangle((wx - 0.08, wy - 0.22), 0.16, 0.44, fc=NAVY, ec="none", transform=t))
a.plot([0, 0], [-0.6, 0.6], color=ORANGE, lw=2)
a.annotate("", xy=(0.55, 1.05), xytext=(0, 0.6), arrowprops=dict(arrowstyle="->", color=ORANGE, lw=1.8))
a.text(0.75, 0.95, "ฮด", fontsize=13, color=ORANGE, fontweight="bold")
a.text(0.12, 0.0, "L", fontsize=12, color=ORANGE, fontweight="bold")
a.text(-1.5, -1.1, "แบaw = vยทtan ฮด / L", fontsize=9, color=GRAY)
c.img(P / "obstacles_crop.png", xs[2] + 0.3, yt + 0.02, 1.6, 1.56, border=None)
c.img(P / "segments_bev.png", xs[3] + 0.3, yt + 0.02, 1.6, 1.56, border=None)
c.img(EXTRA / "sensors_sim.png", xs[4] + 0.05, yt + 0.03, 2.1, 1.54, border=None)
c.img(P / "drive_log.png", xs[5] + 0.05, yt + 0.2, 2.1, 1.25, border=None)
c.arrow(xs[5] + bw / 2, yt - 0.02, xs[0] + bw / 2, yt - 0.02, color=ORANGE, lw=2, ls="--", rad=0.06)
c.text(7.6, 0.72, "๋ค์ ํ๋ ์์ ๊ด์ธก โ ๋ค์ โ (๋ชจ๋ธ์ ์ ์ด๊ฐ ๋ค์ ๊ด์ธก์ ๋ฐ๊พผ๋ค)", size=10, bold=True, color=ORANGE)
# (b) GPU ๋ ๋ ๊ทธ๋ํ
y0 = 4.05
c.text(0.25, y0, "(b) ๋ ๋ ๊ทธ๋ํ โ GPU, Vulkan (configs/render_graph.json, ๋ฐฐ๋ฆฌ์ด ์๋)", size=15, bold=True, color=NAVY, ha="left")
c.rect(0.15, y0 + 0.2, 15.7, 3.95, fc="#F7F9FD", ec=LIGHT, lw=1.2, r=0.12)
c.arrow(13.2, 3.8, 13.2, y0 + 0.62, color=GRAY, lw=1.8)
c.text(13.05, y0 + 0.42, "CPU โ GPU: ์นด๋ฉ๋ผ UBO ยท ๋์ ์ (์ผ์ ์ ยท ์์ฐจ ๋ฐ์ค) ยท ๊ตฌ๊ฐ ๊ต์ฒด", size=9.5, color=GRAY, ha="right")
bufs = [("gaussians", P / "gaussians_3d.png", "๊ฐ์ฐ์์ SSBO\n(๊ตฌ๊ฐ ๋ชจ๋ธ, โค 200๋ง)"),
("splats ยท keys", P / "splats.png", "ํ๋ฉด ํ์ ยท SH ์\n๋ณด์ด๋ ๊ฒ๋ง ์์ถ"),
("keys (์ ๋ ฌ)", P / "splats_sorted.png", "๊น์ด ์์\n(์ = ์ ๋ ฌ ์์)"),
("background", P / "sky_panorama.jpg", "ํ์ต ํ๋ ํ๋ธ๋งต\nยท IBL"),
("color ยท depth_acc", P / "render_front.jpg", "RGBA16F ์\n+ rg32f ๊ฑฐ๋ฆฌ ๋์ "),
("post โ ํ๋ฉด", EXTRA / "drive_6cam_still.jpg", "6์บ ยท 3์ธ์นญ ยท BEV\nPNG ์ฐ๊ธฐ ์ค๋ ๋")]
passes = [("preprocess", "compute", "2.0 ms"), ("sort", "radix 8bitร4", "0.44 ms"), ("background", "raster", ""),
("scene", "raster (๊ฐ์ )", "4.4 ms"), ("weather ยท fxaa", "compute", "")]
bx0, bw2, bh2, gap = 0.35, 1.8, 1.02, 0.92
for i, (nm, path, sub) in enumerate(bufs):
x = bx0 + i * (bw2 + gap)
c.img(path, x, y0 + 0.95, bw2, bh2, title=nm, tsize=10.5)
c.text(x + bw2 / 2, y0 + 2.35, sub, size=9, color=GRAY)
if i == 4:
c.img(P / "render_depth.png", x, y0 + 2.75, bw2, bh2)
c.text(x + bw2 / 2, y0 + 3.95, "depth_acc (rg32f ๊ฑฐ๋ฆฌ)", size=8.5, color=GRAY)
if i < 5:
pn, kind, tms = passes[i]
cx = x + bw2 + gap / 2
c.arrow(x + bw2 + 0.04, y0 + 1.5, x + bw2 + gap - 0.04, y0 + 1.5, color=NAVY, lw=2)
c.chip(cx, y0 + 1.2, pn, fc=NAVY, size=8, w=gap + 0.06, h=0.26)
c.text(cx, y0 + 1.85, kind, size=8, bold=True, color=ORANGE)
if tms:
c.text(cx, y0 + 2.07, tms, size=8, color=GRAY)
c.rect(0.4, y0 + 2.85, 9.9, 1.1, fc="white", ec=LIGHT, lw=1, r=0.08)
c.text(0.6, y0 + 3.1, "bindless โ ์
ฐ์ด๋๊ฐ ์ฌ๋กฏ ๋ฒํธ๋ก SSBO ยท ์ด๋ฏธ์ง๋ฅผ ๊ณ ๋ฅธ๋ค (์ ํจ์ค์ ๋์คํฌ๋ฆฝํฐ ์ฝ๋ ๋ถํ์)", size=9.5, color=GRAY, ha="left")
c.text(0.6, y0 + 3.4, "๋ ๋ ๊ทธ๋ํ โ ํจ์ค๋ง๋ค uses (์์ ยท ์ฉ๋) ์ ์ธ โ ๋ฐฐ๋ฆฌ์ด ยท ๋ ์ด์์ ์ ํ ์๋ ์ฝ์
", size=9.5, color=GRAY, ha="left")
c.text(0.6, y0 + 3.7, "์
ฐ์ด๋ ๊ทธ๋ํ โ ํ์ฒ๋ฆฌ ๋
ธ๋ (JSON) โ GLSL ์์ฑ ยท ๋ฆฌํ๋ ์
ยท Tracy ํจ์ค๋ณ GPU ์๊ฐ", size=9.5, color=GRAY, ha="left")
c.save(OUT / "fig_engine_pipeline.png")
split(OUT / "fig_engine_pipeline.png", 8.45, 3.79)
print("saved", OUT)
|