feat(web): finish RE 5000PBR lesson video and fix non-ASCII GLB import
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled

- Add 11:07 Chinese-narrated lesson video, VTT, poster and 13 chapter screenshots.
- Regenerate 20-render WebGL2 matrix and 15 operation captures on RTX 4060.
- Fix WASM staging for non-ASCII import filenames (猴头.glb); rebuild web_engine.
- Harden lesson video recording pipeline; fix stale lesson-link E2E selector.
- Add RE PBR derived libraries, lesson page, evidence and status report.

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
mes123456
2026-11-12 21:49:24 +08:00
parent a078648297
commit d5dd647881
276 changed files with 9632 additions and 314 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 726 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 518 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

View File

@@ -0,0 +1,20 @@
#__lesson_video_overlay { position: fixed; inset: 0; pointer-events: none; z-index: 2147483647; }
#__lesson_video_overlay[hidden] { display: none; }
#__lesson_video_cursor {
position: fixed; left: 0; top: 0; width: 18px; height: 18px;
margin: -9px 0 0 -9px; border: 2px solid #fff; border-radius: 50%;
background: rgba(255, 59, 48, 0.9); box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.5);
will-change: transform;
}
#__lesson_video_caption {
position: fixed; left: 50%; bottom: 28px; transform: translateX(-50%);
max-width: min(1100px, 88vw); padding: 12px 18px; border-radius: 10px;
background: rgba(12, 16, 24, 0.88); border: 1px solid #4a5870;
color: #f5f7fa; font: 600 22px/1.45 system-ui, "Noto Sans SC", sans-serif;
text-align: center; box-shadow: 0 8px 30px rgba(0, 0, 0, 0.55); pointer-events: none;
}
.__lesson_video_ripple {
position: fixed; left: 0; top: 0; width: 14px; height: 14px;
margin: -7px 0 0 -7px; border: 3px solid #7fb3ff; border-radius: 50%;
pointer-events: none;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View File

@@ -0,0 +1,40 @@
WEBVTT
00:00:03.630 --> 00:00:23.238
开场:会得到什么:这一课我们从灰色猴头开始。你会打开摄影棚,导入只有一个猴头网格的 GLB 文件,从 RE 五零零零 PBR 资产库分配六种材质,最后在浏览器里用显卡渲染、下载 PNG、保存工程并重新打开。
00:00:39.088 --> 00:00:59.080
载入摄影棚:先打开 Web Blender 的 Rendering 工作区。在 PBR 渲染练习面板里点击载入练习摄影棚。这个场景已经准备好相机、三点面光、太阳光、世界环境和地面。等待状态栏显示 Engine SceneIR,并且对象数是六。
00:01:14.925 --> 00:01:36.141
导入猴头 GLB:接下来点击导入猴头 GLB,选择课程目录里的 monkey head 点 GLB。导入会追加到当前场景,不会替换摄影棚。看到对象数从六变成七,活动对象是 Suzanne 就对了。此时猴头没有材质,所以是灰色的,这是正常的基线。
00:01:51.991 --> 00:02:14.167
认识 Shading 与 RE 资产库:切换到 Shading 工作区。左下角是 PBR 资产库,现在有二十个资产。用资产来源下拉框选择 RE 五零零零 PBR,只留下六张材质卡片。单击卡片只会选中,双击才会把材质分配出去。缩略图加载完成后就可以继续。
00:02:30.022 --> 00:02:58.630
分配六种材质:回到 Rendering 工作区。在 PBR 渲染练习面板下方,新加了 RE 五零零零 PBR 材质选择器,它显示完整材质名和缩略图,不受左侧窄栏影响。依次双击六种材质:防滑颗粒、砖墙、随机瓷砖、光亮瓷砖、规则砖墙和做旧砖墙。每次等待材质槽更新,并确认材质球显示 COMPILED。
00:04:43.150 --> 00:05:01.798
设置渲染:现在设置渲染。分辨率选一零二四,相机选场景相机,视图保持最终材质,教学曝光保持零,位移强度保持一倍,视角预设选场景相机对齐。这样得到的就是固定摄影棚下的标准成片。
00:05:17.656 --> 00:05:35.968
渲染与下载 PNG:点击渲染 PBR。面板会先等待纹理和环境贴图就绪,然后输出一张一零二四乘一零二四的 WebGL2 成片。结果出现后,点击下载 PNG,浏览器会保存 pbr 一零二四点 PNG。
00:06:18.906 --> 00:06:39.474
保存与重开:点击顶部的保存项目,下载点 blend 工程。然后再次导入刚才保存的工程;如果询问是否保存当前修改,选择不保存并继续。重新打开后对象数仍是七,材质槽仍然保留做旧砖墙,再渲染一次确认贴图没有丢失。
00:06:56.941 --> 00:07:17.821
诊断视图与教学曝光:深色材质只看整体亮度容易误判。把视图切到 Base Color,可以看到基础色贴图;切到 Normal,可以看到法线和砖缝;切到 Roughness,可以看到粗糙度。教学曝光可以加一档或两档 EV,只改变渲染曝光,不改变材质本身。
00:08:12.012 --> 00:08:33.060
位移与细分:Height 贴图现在会真正参与几何位移。位移强度一倍保留源材质零点零零一的 Scale,画面变化很细;切到一百倍只是渲染时的教学放大,不写回材质。静帧会把九百六十八个三角形细分到六万一千九百五十二个,再执行位移。
00:08:48.900 --> 00:09:06.420
对比视角:视角预设默认与场景相机精确对齐,所以场景和视口可能看起来一样。选择对比四十五度后,当前视口会以主体为中心偏转三十度,得到明显不同的构图;主视口导航不受影响。
00:09:22.279 --> 00:09:44.287
高清 2048 贴图:如果需要原始分辨率,点击加载高清贴图二零四八。素材会按需合并,材质名带 HQ 后缀。切换到高清来源,双击分配做旧砖墙 HQ,再渲染一次。五个纹理全部加载,显存预算约六十四点五兆,低于五百一十二兆上限。
00:10:25.130 --> 00:10:50.066
总结与教案:到这里,你已经完成从灰色猴头到六种 PBR 材质的完整流程:打开场景、导入 GLB、分配材质、渲染下载、保存重开,以及诊断、位移、对比相机和高清贴图。更多截图和文字步骤在渲染图文教案里,地址是 tutorial pbr render lesson 点 HTML。

View File

@@ -0,0 +1,235 @@
:root {
color-scheme: dark;
--bg: #121417;
--panel: #1b1e23;
--panel-soft: #22262c;
--text: #e8eaed;
--muted: #a7adb7;
--accent: #7fb3ff;
--accent-strong: #4d8ff0;
--border: #333943;
--code: #f0c674;
--max: 1120px;
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
margin: 0;
background: var(--bg);
color: var(--text);
font: 16px/1.7 "Noto Sans SC", "Source Han Sans SC", system-ui, -apple-system, "Segoe UI", sans-serif;
}
a { color: var(--accent); text-decoration: none; }
a:hover, a:focus-visible { color: #b9d4ff; text-decoration: underline; }
code {
color: var(--code);
background: #101216;
border: 1px solid #2b3038;
border-radius: 4px;
padding: 0.05em 0.35em;
font-size: 0.92em;
}
.lesson-hero, main, .lesson-footer {
width: min(var(--max), calc(100% - 32px));
margin: 0 auto;
}
.lesson-hero { padding: 48px 0 24px; }
.eyebrow {
margin: 0 0 8px;
color: var(--accent);
font-size: 0.9rem;
letter-spacing: 0.06em;
text-transform: uppercase;
}
h1 {
margin: 0 0 12px;
font-size: clamp(2rem, 4.5vw, 3.2rem);
line-height: 1.15;
}
h2 {
margin: 56px 0 16px;
padding-bottom: 8px;
border-bottom: 1px solid var(--border);
font-size: 1.55rem;
}
h3 { margin: 28px 0 10px; font-size: 1.18rem; }
p, li { color: var(--text); }
.lead { max-width: 78ch; color: var(--muted); font-size: 1.08rem; }
.lesson-nav {
display: flex;
flex-wrap: wrap;
gap: 8px 14px;
align-items: center;
margin: 24px 0 28px;
padding: 12px 14px;
background: var(--panel);
border: 1px solid var(--border);
border-radius: 10px;
font-size: 0.92rem;
}
.lesson-nav a { color: var(--muted); }
.lesson-nav a:hover { color: var(--text); }
.lesson-nav .nav-cta {
margin-left: auto;
padding: 4px 12px;
color: #0d1117;
background: var(--accent);
border-radius: 6px;
font-weight: 700;
}
.lesson-nav .nav-cta:hover { color: #0d1117; background: #a9ccff; }
figure { margin: 20px 0; }
figure img {
display: block;
width: 100%;
height: auto;
background: #0b0d10;
border: 1px solid var(--border);
border-radius: 10px;
}
figcaption {
margin-top: 8px;
color: var(--muted);
font-size: 0.88rem;
}
.hero-figure img { max-height: 640px; object-fit: cover; }
.callout {
margin: 20px 0;
padding: 14px 16px;
background: #172333;
border: 1px solid #2f4f78;
border-left: 4px solid var(--accent);
border-radius: 8px;
}
.terms { display: grid; gap: 10px; }
.terms dt { font-weight: 700; color: var(--accent); }
.terms dd { margin: 0 0 4px 0; color: var(--muted); }
.material-card {
margin: 24px 0;
padding: 16px 18px;
background: var(--panel);
border: 1px solid var(--border);
border-radius: 12px;
}
.material-card h3 { margin-top: 0; }
.material-card figure img { max-width: 720px; margin: 0 auto; }
ol, ul { padding-left: 1.3rem; }
li { margin: 4px 0; }
details {
margin: 16px 0;
padding: 10px 14px;
background: var(--panel-soft);
border: 1px solid var(--border);
border-radius: 8px;
}
summary { cursor: pointer; font-weight: 600; }
summary:hover { color: var(--accent); }
table {
width: 100%;
margin: 18px 0;
border-collapse: collapse;
font-size: 0.94rem;
}
th, td {
padding: 10px 12px;
border: 1px solid var(--border);
text-align: left;
vertical-align: top;
}
th { background: var(--panel-soft); color: var(--accent); }
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
gap: 16px;
}
.gallery figure { margin: 0; }
.gallery img { aspect-ratio: 1 / 1; object-fit: cover; }
.back { margin-top: 28px; }
.lesson-footer {
margin-top: 56px;
padding: 24px 0 48px;
border-top: 1px solid var(--border);
color: var(--muted);
font-size: 0.88rem;
}
@media (max-width: 620px) {
.lesson-hero { padding-top: 28px; }
.lesson-nav .nav-cta { margin-left: 0; }
.material-card { padding: 12px; }
}
@media print {
:root { color-scheme: light; }
body { background: #fff; color: #111; }
.lesson-nav, .nav-cta, .back { display: none; }
.lesson-hero, main, .lesson-footer { width: 100%; }
h1, h2, h3, p, li, td, th, figcaption { color: #111; }
h2 { break-after: avoid; }
figure, .material-card, .callout, table { break-inside: avoid; }
figure img { border: 1px solid #bbb; }
.gallery { grid-template-columns: repeat(2, 1fr); }
a { color: #111; text-decoration: underline; }
}
.lesson-video-section {
width: min(var(--max), calc(100% - 32px));
margin: 28px auto 0;
padding: 20px;
background: var(--panel);
border: 1px solid var(--border);
border-radius: 12px;
}
.lesson-video-section h2 { margin-top: 0; }
.lesson-video {
display: block;
width: 100%;
height: auto;
aspect-ratio: 16 / 9;
background: #000;
border: 1px solid var(--border);
border-radius: 10px;
}
.video-chapters {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
gap: 4px 18px;
margin: 16px 0 0;
color: var(--muted);
font-size: 0.9rem;
}
.video-chapters li { margin: 2px 0; }
@media print {
.lesson-video-section { display: none; }
}
.video-step-gallery { margin-top: 14px; }
.video-step-gallery img { aspect-ratio: 16 / 9; object-fit: cover; }

View File

@@ -0,0 +1,422 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Web Blender 渲染入门:5000PBR 材质 × 猴头 GLB</title>
<link rel="stylesheet" href="/tutorial/pbr/render-lesson.css">
</head>
<body>
<header class="lesson-hero">
<p class="eyebrow">Web Blender 互动教案 · 初学者 · 约 45–60 分钟</p>
<h1>从灰色猴头到六种 PBR 材质</h1>
<p class="lead">
在不安装桌面 Blender 的情况下,用浏览器里的 Web Blender 打开摄影棚、导入
<code>猴头.glb</code>、从 RE 5000PBR 资产库分配六种材质,并用 WebGL2 渲染、下载和保存。
本页所有成片都来自有头 Chromium 的真实操作,不是示意图。
</p>
<nav class="lesson-nav" aria-label="教案导航">
<a href="#video">视频</a>
<a href="#goals">课程目标</a>
<a href="#terms">术语</a>
<a href="#prepare">准备</a>
<a href="#import">导入</a>
<a href="#library">资产库</a>
<a href="#materials">六种材质</a>
<a href="#advanced">进阶</a>
<a href="#render">渲染</a>
<a href="#save">保存</a>
<a href="#gallery">矩阵</a>
<a href="#trouble">排查</a>
<a href="#limits">限制</a>
<a class="nav-cta" href="/?ui=web">打开 Web Blender</a>
</nav>
<figure class="hero-figure">
<img src="/tutorial/pbr/lesson/landing.jpg" alt="Web Blender 中导入猴头 GLB 并渲染 PBR 材质的界面" width="1440" height="900" loading="eager">
<figcaption>Rendering 工作区中的 WebGL2 成片;左侧是渲染设置,右侧是原生属性面板。</figcaption>
</figure>
</header>
<section id="video" class="lesson-video-section">
<h2>视频版:从灰色猴头到六种 PBR 材质</h2>
<p>
完整操作演示(有头 Chromium + NVIDIA GPU,中文配音,1280×720)。视频覆盖打开摄影棚、导入 GLB、
六种 RE 5000PBR 材质、渲染与下载、保存重开、诊断视图、位移、对比相机和 2048 高清贴图。
</p>
<video class="lesson-video" controls preload="metadata" playsinline width="1600" height="900"
poster="/tutorial/pbr/lesson/video/poster.jpg">
<source src="/tutorial/pbr/lesson/video/re-pbr-lesson-720p.mp4" type="video/mp4">
<track kind="captions" src="/tutorial/pbr/lesson/video/re-pbr-lesson.zh-Hans.vtt"
srclang="zh-Hans" label="简体中文" default>
<p>浏览器不支持 HTML5 视频;请使用 Chromium 打开本页,或直接阅读下方文字教案。</p>
</video>
<ol class="video-chapters">
<li>开场:会得到什么</li>
<li>载入摄影棚</li>
<li>导入猴头 GLB</li>
<li>认识 Shading 与 RE 资产库</li>
<li>分配六种材质</li>
<li>设置渲染</li>
<li>渲染与下载 PNG</li>
<li>保存与重开</li>
<li>诊断视图与教学曝光</li>
<li>位移与细分</li>
<li>对比视角</li>
<li>高清 2048 贴图</li>
<li>总结与教案</li>
</ol>
<h3>视频章节截图</h3>
<div class="gallery video-step-gallery">
<figure><img src="/tutorial/pbr/lesson/video-steps/intro.jpg" alt="开场" width="1600" height="900" loading="lazy"><figcaption>1 开场</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/video-steps/open-studio.jpg" alt="载入摄影棚" width="1600" height="900" loading="lazy"><figcaption>2 载入摄影棚</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/video-steps/import-glb.jpg" alt="导入猴头 GLB" width="1600" height="900" loading="lazy"><figcaption>3 导入猴头 GLB</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/video-steps/asset-library.jpg" alt="认识资产库" width="1600" height="900" loading="lazy"><figcaption>4 认识资产库</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/video-steps/assign-materials.jpg" alt="分配六种材质" width="1600" height="900" loading="lazy"><figcaption>5 分配六种材质</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/video-steps/render-settings.jpg" alt="设置渲染" width="1600" height="900" loading="lazy"><figcaption>6 设置渲染</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/video-steps/render-download.jpg" alt="渲染与下载" width="1600" height="900" loading="lazy"><figcaption>7 渲染与下载</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/video-steps/save-reopen.jpg" alt="保存与重开" width="1600" height="900" loading="lazy"><figcaption>8 保存与重开</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/video-steps/diagnostics.jpg" alt="诊断视图" width="1600" height="900" loading="lazy"><figcaption>9 诊断视图</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/video-steps/displacement.jpg" alt="位移" width="1600" height="900" loading="lazy"><figcaption>10 位移</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/video-steps/camera.jpg" alt="对比视角" width="1600" height="900" loading="lazy"><figcaption>11 对比视角</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/video-steps/hq-2048.jpg" alt="高清 2048" width="1600" height="900" loading="lazy"><figcaption>12 高清 2048</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/video-steps/summary.jpg" alt="总结" width="1600" height="900" loading="lazy"><figcaption>13 总结</figcaption></figure>
</div>
</section>
<main>
<section id="goals">
<h2>1. 课程目标与最终成果</h2>
<p>完成本课后,你应该能够:</p>
<ul>
<li>在 Web Blender 中打开一个带相机、灯光和环境的 <code>.blend</code> 摄影棚。</li>
<li>通过真实的文件入口导入一个没有材质的 <code>.glb</code> 模型。</li>
<li>在 Shading 工作区的 PBR 资产库中识别来源、搜索、查看缩略图并双击分配材质。</li>
<li>理解 Base Color、Normal、Roughness、Height 四类贴图分别改变什么。</li>
<li>选择分辨率与相机,渲染 PNG,保存工程并在重开后确认材质仍在。</li>
</ul>
<div class="callout">
<strong>最终成果:</strong>6 种材质 × 2 种相机 × 1024,加上 6 张 512、1 张未分配材质基线和
1 张保存重开复渲染,共 <strong>20 张 Web/WebGL2 成片</strong>,全部在本页画廊中。
</div>
</section>
<section id="terms">
<h2>2. 先认识五个词</h2>
<dl class="terms">
<dt>PBR</dt>
<dd>基于物理的渲染。材质用“基础色、金属度、粗糙度、法线”等参数描述表面,而不是靠手调高光。</dd>
<dt>IBL / 环境光</dt>
<dd>用一张环境图照亮场景。摄影棚的世界环境会让金属、粗糙表面和阴影更自然。</dd>
<dt>sRGB 与 Non-Color</dt>
<dd>Base Color 通常按 sRGB 解释;Normal、Roughness、Height 是数据图,必须按 Non-Color 读取,否则会偏亮或偏色。</dd>
<dt>平铺(Mapping Scale)</dt>
<dd>同一张图在 UV 上重复多少次。RE 材质用 Value 节点驱动 Mapping 的 Scale,本课会验证它生效。</dd>
<dt>AgX / 视图变换</dt>
<dd>Blender 的默认显示变换。它会把高光压回可见范围;看起来“灰”不一定是贴图失败。</dd>
</dl>
</section>
<section id="prepare">
<h2>3. 准备:打开摄影棚</h2>
<p>
先在浏览器打开 <code>/?ui=web</code>。点击顶部的“打开 .blend”(文件夹图标),选择课程摄影棚
<code>studio.blend</code>。这个场景已经包含:
</p>
<ul>
<li><strong>PBR Studio Camera</strong>:场景相机。</li>
<li><strong>Key / Fill / Rim</strong> 三盏面光,以及一盏 <strong>Sun</strong>。</li>
<li><strong>PBR Studio Ground</strong> 地面和深灰世界环境。</li>
</ul>
<figure>
<img src="/tutorial/pbr/lesson/steps/01-open-studio.jpg" alt="打开摄影棚后的 Web Blender 界面" width="1440" height="900" loading="lazy">
<figcaption>检查点:底部状态栏显示 <code>Engine: SceneIR</code>,并且场景里有 6 个对象。</figcaption>
</figure>
<details>
<summary>常见问题:打开后还是默认立方体?</summary>
<p>确认你选择的是 <code>studio.blend</code>,而不是新建工程;等待状态栏出现 <code>Engine: SceneIR</code> 再继续。</p>
</details>
</section>
<section id="import">
<h2>4. 导入猴头 GLB</h2>
<p>
继续使用同一个“打开 .blend”文件入口,选择 <code>monkey-head.glb</code>。GLB 会追加到当前场景,
而不是替换摄影棚;这样相机和灯光会保留。
</p>
<figure>
<img src="/tutorial/pbr/lesson/steps/02-import-glb.jpg" alt="导入猴头 GLB 后场景中出现 Suzanne 对象" width="1440" height="900" loading="lazy">
<figcaption>检查点:底部状态栏出现 <code>Active Suzanne</code>,对象数从 6 变成 7。</figcaption>
</figure>
<p>
这个 GLB 只有 1,221 个顶点、968 个三角形,带 UV 和法线,但<strong>没有材质、贴图、相机或灯光</strong>。
所以刚导入时它会是灰色的;灰色不是错误,而是等待你分配材质的基线。
</p>
<figure>
<img src="/tutorial/pbr/lesson/renders/baseline-unassigned-1024-scene.jpg" alt="未分配材质的灰色猴头基线渲染" width="1024" height="1024" loading="lazy">
<figcaption>基线:未分配材质时的 WebGL2 渲染。先记住这张图,后面用来判断“材质是否真的改变了表面”。</figcaption>
</figure>
</section>
<section id="library">
<h2>5. 认识 PBR 资产库</h2>
<p>
切换到 <strong>Shading</strong> 工作区。左下角的 PBR 资产库现在有 <strong>20 个资产</strong>:
原来的 PBR Essentials 14 个,加上从 RE 5000PBR 精简版派生的 6 个材质。用“资产来源”下拉框
选择 <strong>RE 5000PBR</strong>,可以只留下这 6 张卡片。
</p>
<figure>
<img src="/tutorial/pbr/lesson/steps/03-asset-library-black_worn_wall_brick.jpg" alt="Shading 工作区中筛选 RE 5000PBR 来源的资产库" width="1440" height="900" loading="lazy">
<figcaption>检查点:来源筛选为 RE 5000PBR,卡片缩略图全部加载;卡片下方显示 <code>Materials/RE5000PBR</code>。</figcaption>
</figure>
<p>
视频和 Rendering 工作区的练习面板还提供一个<strong>完整名称的 RE 5000PBR 材质选择器</strong>:
六张卡片显示全名和缩略图,双击即可分配,不受左侧窄栏影响。两种入口走同一个分配函数。
</p>
<ul>
<li><strong>单击</strong>卡片只会选中,不会修改场景。</li>
<li><strong>双击材质卡片</strong>才会把材质追加并分配到当前活动对象的材质槽。</li>
<li>如果缩略图空白,先等预览图从 OPFS 读取完成;仍然失败时点“修复资产库”。</li>
</ul>
</section>
<section id="materials">
<h2>6. 六种材质逐课</h2>
<p>
保持猴头为活动对象,依次双击下面六张材质卡片。每次分配后,Properties 的 Material Slots
会显示对应材质名。六种材质都属于黑色砖石/防滑表面,差异主要在砖缝、颗粒和法线细节。
</p>
<article class="material-card">
<h3>6.1 Black_Anti_Slip_grip</h3>
<p><strong>表现:</strong>深色防滑颗粒表面,法线细节明显,适合观察 Normal 贴图。</p>
<p><strong>操作:</strong>双击卡片 → 等 Material Slots 显示 <code>Black_Anti_Slip_grip</code>。</p>
<figure><img src="/tutorial/pbr/lesson/renders/material-Black_Anti_Slip_grip-1024-scene.jpg" alt="Black_Anti_Slip_grip 材质的猴头渲染" width="1024" height="1024" loading="lazy"><figcaption>场景相机,1024²。检查颗粒与高光是否随表面朝向变化。</figcaption></figure>
</article>
<article class="material-card">
<h3>6.2 Blackish_Brick_Wall_016</h3>
<p><strong>表现:</strong>深色砖墙,砖缝和表面磨损清楚。</p>
<figure><img src="/tutorial/pbr/lesson/renders/material-Blackish_Brick_Wall_016-1024-scene.jpg" alt="Blackish_Brick_Wall_016 材质的猴头渲染" width="1024" height="1024" loading="lazy"><figcaption>场景相机,1024²。检查砖缝是否沿 UV 连续。</figcaption></figure>
</article>
<article class="material-card">
<h3>6.3 black_randome_tile</h3>
<p><strong>表现:</strong>随机排列的黑色瓷砖,适合观察平铺和粗糙度变化。</p>
<figure><img src="/tutorial/pbr/lesson/renders/material-black_randome_tile-1024-scene.jpg" alt="black_randome_tile 材质的猴头渲染" width="1024" height="1024" loading="lazy"><figcaption>场景相机,1024²。如果砖块被拉得很长,先检查 UV 和 Mapping。</figcaption></figure>
</article>
<article class="material-card">
<h3>6.4 black_shinning_tile</h3>
<p><strong>表现:</strong>更光滑的黑色瓷砖,高光更集中。</p>
<figure><img src="/tutorial/pbr/lesson/renders/material-black_shinning_tile-1024-scene.jpg" alt="black_shinning_tile 材质的猴头渲染" width="1024" height="1024" loading="lazy"><figcaption>场景相机,1024²。高光位置应与三盏面光一致。</figcaption></figure>
</article>
<article class="material-card">
<h3>6.5 black_tiles_wall</h3>
<p><strong>表现:</strong>规则砖墙,砖缝间距均匀。</p>
<figure><img src="/tutorial/pbr/lesson/renders/material-black_tiles_wall-1024-scene.jpg" alt="black_tiles_wall 材质的猴头渲染" width="1024" height="1024" loading="lazy"><figcaption>场景相机,1024²。检查砖缝是否随曲面弯曲。</figcaption></figure>
</article>
<article class="material-card">
<h3>6.6 black_worn_wall_brick</h3>
<p><strong>表现:</strong>做旧砖墙,砖块边缘和破损细节最丰富,适合作为本课的“最终材质”。</p>
<figure><img src="/tutorial/pbr/lesson/renders/material-black_worn_wall_brick-1024-scene.jpg" alt="black_worn_wall_brick 材质的猴头渲染" width="1024" height="1024" loading="lazy"><figcaption>场景相机,1024²。记住这张图,后面保存/重开会复渲染它。</figcaption></figure>
</article>
<div class="callout">
<strong>四张贴图分别在做什么:</strong>
Base Color 决定颜色;Normal 决定表面朝向的细节;Roughness 决定高光扩散;
Height 在这套材质里连接到 Displacement,但 Web 渲染器不执行位移,只保留 Base Color、Normal、
Roughness 的可见效果。这是本课明确的限制,不是黑图。
</div>
</section>
<section id="advanced">
<h2>7. 进阶:位移、诊断视图与高清贴图</h2>
<h3>7.1 位移与细分</h3>
<p>
Web 端现在读取 Height 贴图的 HEIGHT 绑定,按 Displacement 节点的 Scale/Midlevel 设置
<code>MeshPhysicalMaterial.displacementMap</code>。静帧渲染时对低模做有界中点细分
(968 → 61,952 三角形,level 3),再由顶点着色器执行真实几何位移。交互视口使用原几何的
逐顶点位移,避免破坏编辑拾取。
</p>
<div class="gallery">
<figure><img src="/tutorial/pbr/lesson/displacement/1x-1024.png" alt="1 倍位移" width="1024" height="1024" loading="lazy"><figcaption>1× · 保留源 Scale=0.001 · 1024</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/displacement/100x-1024.png" alt="100 倍教学位移" width="1024" height="1024" loading="lazy"><figcaption>100× 教学放大 · 只改渲染时的 displacementScale</figcaption></figure>
</div>
<p>
源材质 Scale 只有 0.001,1× 的几何起伏非常细微;100× 用于课堂观察,不写回材质或 .blend。
位移证据:1× mean 93.96、100× mean 93.87,SHA 不同;细分三角形 61,952。
</p>
<h3>7.2 诊断视图与教学曝光</h3>
<p>
Rendering 面板新增“视图”选择:<strong>最终材质 / Base Color / Normal / Roughness</strong>。
诊断视图只临时替换活动对象的材质,地面保留最终材质;因此可以直接看砖缝、法线和粗糙度,
而不必靠整体亮度猜测“材质是否生效”。教学曝光提供 0/+1/+2 EV,只调整渲染曝光。
</p>
<div class="gallery">
<figure><img src="/tutorial/pbr/lesson/diagnostics/base-color-512.png" alt="Base Color 诊断视图" width="512" height="512" loading="lazy"><figcaption>Base Color · 贴图颜色</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/diagnostics/normal-512.png" alt="Normal 诊断视图" width="512" height="512" loading="lazy"><figcaption>Normal · 法线细节</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/diagnostics/roughness-512.png" alt="Roughness 诊断视图" width="512" height="512" loading="lazy"><figcaption>Roughness · 粗糙度</figcaption></figure>
</div>
<h3>7.3 对比视角</h3>
<p>
默认“场景相机对齐”让 VIEWPORT 与 SCENE 使用完全相同的场景相机姿态;选择“对比 45°”后,
练习视口以主体为中心偏转 30° 并抬高 0.18 rad,得到明显不同的构图。主视口不受影响。
</p>
<div class="gallery">
<figure><img src="/tutorial/pbr/lesson/camera/scene-camera-1024.png" alt="场景相机对齐" width="1024" height="1024" loading="lazy"><figcaption>场景相机对齐 · 1024</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/camera/comparison-45-1024.png" alt="对比 45 度视角" width="1024" height="1024" loading="lazy"><figcaption>对比 45° · 1024</figcaption></figure>
</div>
<h3>7.4 高清 2048 贴图</h3>
<p>
PBR 渲染练习面板提供“加载高清贴图 (2048)”,按需把 <code>library:re-pbr-hq-v1</code> 合并到
资产库;材质名带 <code>_HQ</code> 后缀,避免与标准库冲突。加载后资产来源筛选出现
“RE 5000PBR HQ”,默认标准库保持不变。
</p>
<figure>
<img src="/tutorial/pbr/lesson/hq/black_worn_wall_brick_HQ-1024.png" alt="HQ 2048 材质渲染" width="1024" height="1024" loading="lazy">
<figcaption>black_worn_wall_brick_HQ · 2048 原图 · 1024 输出</figcaption>
</figure>
<p>
预算证据:5 个纹理 loaded、0 rejected;GPU decoded 67,633,152 bytes(64.5 MiB),
payload 2,625,921 bytes,低于 WebGL2 的 512 MiB decoded 上限。HQ 按需加载,不进入默认首屏。
</p>
<h3>7.5 硬件 GPU</h3>
<p>
本课有头 Chromium 使用 ANGLE + NVIDIA GeForce RTX 4060 Laptop GPU(OpenGL 4.5),
不是 SwiftShader。采集报告记录了 <code>WEBGL_debug_renderer_info</code> 的 vendor/renderer/version;
硬件 lane 若回退到 SwiftShader 会失败关闭。Firefox/WebKit 按仓库策略不纳入验收。
</p>
</section>
<section id="render">
<h2>8. 渲染设置</h2>
<p>切换到 <strong>Rendering</strong> 工作区,找到“Web PBR 渲染”面板:</p>
<ol>
<li><strong>分辨率</strong>:先用 1024 × 1024。512 更快,2048 更慢。</li>
<li><strong>相机</strong>:<strong>场景相机</strong>使用摄影棚的 PBR Studio Camera;<strong>当前视口</strong>使用你正在看的视角。</li>
<li>点击 <strong>渲染 PBR</strong>。渲染前会等待贴图和 IBL 就绪,不会再用固定延时。</li>
<li>结果出现后,面板底部会显示尺寸、文件大小和 OPFS 摘要。</li>
</ol>
<figure>
<img src="/tutorial/pbr/lesson/renders/material-black_worn_wall_brick-1024-viewport.jpg" alt="当前视口相机下的猴头渲染" width="1024" height="1024" loading="lazy">
<figcaption>当前视口,1024²。本课的视口默认与场景相机对齐,所以两张成片可能相同;移动视口后再渲染就会出现差异。</figcaption>
</figure>
<p>
再选 512 × 512 渲染一次,观察砖缝细节变软;这不是错误,而是分辨率下降后的正常结果。
</p>
<figure>
<img src="/tutorial/pbr/lesson/renders/material-black_worn_wall_brick-512-scene.jpg" alt="512 分辨率的猴头渲染" width="512" height="512" loading="lazy">
<figcaption>场景相机,512²。适合快速检查构图和材质方向。</figcaption>
</figure>
<details>
<summary>为什么按钮点了没反应?</summary>
<p>检查是否已打开工程、是否选中了有材质的对象,以及面板是否显示“渲染中…”。如果状态栏提示纹理未就绪,等待缩略图加载完成或点“修复资产库”。</p>
</details>
</section>
<section id="save">
<h2>9. 下载 PNG、保存工程、重开验证</h2>
<p>渲染完成后:</p>
<ol>
<li>点击结果下方的 <strong>下载 PNG</strong>,得到 <code>pbr-1024.png</code>。</li>
<li>点击顶部 <strong>保存项目</strong>,下载 <code>.blend</code> 工程。</li>
<li>再次点击“打开 .blend”,选择刚保存的工程;出现“保存当前工程的修改?”时选择“不保存,继续”。</li>
<li>重开后对象数仍为 7,Material Slots 仍包含 <code>black_worn_wall_brick</code>。</li>
<li>再次渲染 1024/场景相机,确认贴图没有丢。</li>
</ol>
<figure>
<img src="/tutorial/pbr/lesson/steps/05-reopen.jpg" alt="保存工程重开后的 Material Slots 与渲染结果" width="1440" height="900" loading="lazy">
<figcaption>检查点:重开后活动对象仍是 Suzanne,材质槽保留,右下角能看到 packed 图片资源。</figcaption>
</figure>
<figure>
<img src="/tutorial/pbr/lesson/renders/material-black_worn_wall_brick-reopen-1024-scene.jpg" alt="保存重开后的复渲染" width="1024" height="1024" loading="lazy">
<figcaption>保存/重开后的复渲染。与保存前的图对比,砖缝和法线细节应一致。</figcaption>
</figure>
</section>
<section id="gallery">
<h2>10. 20 张渲染矩阵</h2>
<p>下面的每一张都由本课的有头 Chromium 实际渲染产生,标注了材质、分辨率和相机。</p>
<div class="gallery">
<figure><img src="/tutorial/pbr/lesson/renders/baseline-unassigned-1024-scene.jpg" alt="基线" width="1024" height="1024" loading="lazy"><figcaption>基线 · 未分配 · 1024 · 场景</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/renders/material-Black_Anti_Slip_grip-1024-scene.jpg" alt="Black_Anti_Slip_grip 场景" width="1024" height="1024" loading="lazy"><figcaption>Black_Anti_Slip_grip · 1024 · 场景</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/renders/material-Black_Anti_Slip_grip-1024-viewport.jpg" alt="Black_Anti_Slip_grip 视口" width="1024" height="1024" loading="lazy"><figcaption>Black_Anti_Slip_grip · 1024 · 视口</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/renders/material-Black_Anti_Slip_grip-512-scene.jpg" alt="Black_Anti_Slip_grip 512" width="512" height="512" loading="lazy"><figcaption>Black_Anti_Slip_grip · 512 · 场景</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/renders/material-Blackish_Brick_Wall_016-1024-scene.jpg" alt="Blackish_Brick_Wall_016 场景" width="1024" height="1024" loading="lazy"><figcaption>Blackish_Brick_Wall_016 · 1024 · 场景</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/renders/material-Blackish_Brick_Wall_016-1024-viewport.jpg" alt="Blackish_Brick_Wall_016 视口" width="1024" height="1024" loading="lazy"><figcaption>Blackish_Brick_Wall_016 · 1024 · 视口</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/renders/material-Blackish_Brick_Wall_016-512-scene.jpg" alt="Blackish_Brick_Wall_016 512" width="512" height="512" loading="lazy"><figcaption>Blackish_Brick_Wall_016 · 512 · 场景</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/renders/material-black_randome_tile-1024-scene.jpg" alt="black_randome_tile 场景" width="1024" height="1024" loading="lazy"><figcaption>black_randome_tile · 1024 · 场景</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/renders/material-black_randome_tile-1024-viewport.jpg" alt="black_randome_tile 视口" width="1024" height="1024" loading="lazy"><figcaption>black_randome_tile · 1024 · 视口</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/renders/material-black_randome_tile-512-scene.jpg" alt="black_randome_tile 512" width="512" height="512" loading="lazy"><figcaption>black_randome_tile · 512 · 场景</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/renders/material-black_shinning_tile-1024-scene.jpg" alt="black_shinning_tile 场景" width="1024" height="1024" loading="lazy"><figcaption>black_shinning_tile · 1024 · 场景</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/renders/material-black_shinning_tile-1024-viewport.jpg" alt="black_shinning_tile 视口" width="1024" height="1024" loading="lazy"><figcaption>black_shinning_tile · 1024 · 视口</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/renders/material-black_shinning_tile-512-scene.jpg" alt="black_shinning_tile 512" width="512" height="512" loading="lazy"><figcaption>black_shinning_tile · 512 · 场景</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/renders/material-black_tiles_wall-1024-scene.jpg" alt="black_tiles_wall 场景" width="1024" height="1024" loading="lazy"><figcaption>black_tiles_wall · 1024 · 场景</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/renders/material-black_tiles_wall-1024-viewport.jpg" alt="black_tiles_wall 视口" width="1024" height="1024" loading="lazy"><figcaption>black_tiles_wall · 1024 · 视口</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/renders/material-black_tiles_wall-512-scene.jpg" alt="black_tiles_wall 512" width="512" height="512" loading="lazy"><figcaption>black_tiles_wall · 512 · 场景</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/renders/material-black_worn_wall_brick-1024-scene.jpg" alt="black_worn_wall_brick 场景" width="1024" height="1024" loading="lazy"><figcaption>black_worn_wall_brick · 1024 · 场景</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/renders/material-black_worn_wall_brick-1024-viewport.jpg" alt="black_worn_wall_brick 视口" width="1024" height="1024" loading="lazy"><figcaption>black_worn_wall_brick · 1024 · 视口</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/renders/material-black_worn_wall_brick-512-scene.jpg" alt="black_worn_wall_brick 512" width="512" height="512" loading="lazy"><figcaption>black_worn_wall_brick · 512 · 场景</figcaption></figure>
<figure><img src="/tutorial/pbr/lesson/renders/material-black_worn_wall_brick-reopen-1024-scene.jpg" alt="保存重开复渲染" width="1024" height="1024" loading="lazy"><figcaption>black_worn_wall_brick · 保存重开 · 1024 · 场景</figcaption></figure>
</div>
</section>
<section id="trouble">
<h2>11. 黑图 / 贴图丢失排查表</h2>
<table>
<thead><tr><th>现象</th><th>先检查</th><th>处理</th></tr></thead>
<tbody>
<tr><td>猴头全黑</td><td>是否已经点了“渲染 PBR”;场景里是否有灯光</td><td>先渲染未分配材质的基线;确认摄影棚的 Key/Fill/Rim/Sun 存在</td></tr>
<tr><td>只有灰色,没有砖缝</td><td>Material Slots 是否显示目标材质;缩略图是否加载</td><td>双击卡片重新分配;点“修复资产库”</td></tr>
<tr><td>贴图方向被拉长</td><td>UV 是否存在;Mapping Scale 是否生效</td><td>本课材质使用 UV;检查 Shader Editor 的 Mapping 与 Value 节点</td></tr>
<tr><td>重开后材质丢失</td><td>是否保存了工程;重开时是否选择了保存的 .blend</td><td>重新分配材质并保存;确认 Material Slots</td></tr>
<tr><td>面板提示编译 BLOCKED</td><td>材质是否含 Web 不支持的节点</td><td>本课六种材质应显示 COMPILED;若 BLOCKED,记录材质名和节点类型</td></tr>
</tbody>
</table>
</section>
<section id="limits">
<h2>12. 本课的限制</h2>
<ul>
<li>Web 已执行 Height 位移;源材质 Scale=0.001,1× 很细微,课堂用 100× 观察。静帧会细分到 61,952 三角形,交互视口使用原几何逐顶点位移。</li>
<li>不做路径追踪、折射和 GI;玻璃/金属的物理精度与桌面 Cycles 不同。</li>
<li>默认派生资产把 Base Color/Normal 降采样到 1024²、Roughness/Height 到 512²;需要原始 2048 时使用“加载高清贴图 (2048)”。</li>
<li>六种材质都偏黑;用 Base Color/Normal/Roughness 诊断视图和教学曝光判断,而不是只看整体亮度。</li>
<li>默认 SCENE_CAMERA 与场景相机精确对齐;选择“对比 45°”后 VIEWPORT 才产生独立构图。</li>
<li>Firefox/WebKit 按仓库策略不纳入验收;2048 HQ 按需加载,mipmap 可能使实际显存比 base-level 预算高约 1/3。</li>
</ul>
</section>
<section id="appendix">
<h2>13. 附录</h2>
<h3>文件清单</h3>
<ul>
<li><code>/tutorial/pbr/studio.blend</code>:课程摄影棚。</li>
<li><code>/assets/re-pbr/re-pbr-library.blend</code>:RE 5000PBR 派生资产库(6 个材质)。</li>
<li><code>/tutorial/pbr/lesson/renders/</code>:20 张 WebGL2 成片。</li>
<li><code>/tutorial/pbr/lesson/steps/</code>:有头 Chromium 操作截图。</li>
<li><code>/tests/golden/RE-PBR-RENDER-001/report.json</code>:尺寸、SHA-256、mean/std、纹理状态。</li>
</ul>
<h3>常用操作</h3>
<ul>
<li>工作区:Shading(材质)、Rendering(渲染)。</li>
<li>资产库:单击选中,双击分配;来源筛选可只看 RE 5000PBR。</li>
<li>渲染:分辨率 256/512/1024/2048;相机场景/视口;下载 PNG。</li>
<li>保存:顶部“保存项目”下载 .blend;重开时选择“不保存,继续”。</li>
</ul>
<p class="back"><a href="/?ui=web">返回 Web Blender</a> · <a href="/?ui=web&amp;tutorial=pbr">打开 PBR 互动教程</a></p>
</section>
</main>
<footer class="lesson-footer">
<p>Web Blender · PBR 渲染入门教案 · 生成于 2026-11-11 · 所有成片来自有头 Chromium + WebGL2</p>
</footer>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

View File

@@ -0,0 +1,151 @@
{
"schemaVersion": 1,
"renderer": "DESKTOP_BLENDER_EEVEE",
"blenderVersion": "5.2.0",
"renders": [
{
"model": "PBR Suzanne",
"modelSlug": "suzanne",
"material": "PBR Metal Brushed",
"materialSlug": "metal-brushed",
"png": "web/app/public/tutorial/pbr/renders/suzanne-metal-brushed.png",
"jpg": "web/app/public/tutorial/pbr/renders/suzanne-metal-brushed.jpg",
"width": 1024,
"height": 1024,
"bytes": 195777,
"sha256": "5e3520a231bbf900a2fbf1cb7020ce2def1e4f3a488849b50f41d516b4584708"
},
{
"model": "PBR Suzanne",
"modelSlug": "suzanne",
"material": "PBR Glass",
"materialSlug": "glass",
"png": "web/app/public/tutorial/pbr/renders/suzanne-glass.png",
"jpg": "web/app/public/tutorial/pbr/renders/suzanne-glass.jpg",
"width": 1024,
"height": 1024,
"bytes": 184395,
"sha256": "0049584ec1aff343552c4a022fed0515d241fc622f8d9cff35fc0cc565cae8ec"
},
{
"model": "PBR Suzanne",
"modelSlug": "suzanne",
"material": "PBR Wood",
"materialSlug": "wood",
"png": "web/app/public/tutorial/pbr/renders/suzanne-wood.png",
"jpg": "web/app/public/tutorial/pbr/renders/suzanne-wood.jpg",
"width": 1024,
"height": 1024,
"bytes": 190672,
"sha256": "06f31bfb1c8d521c7c78f935165bf9eb21540042dbdd51f0084dff066d5881c0"
},
{
"model": "PBR Suzanne",
"modelSlug": "suzanne",
"material": "PBR Emission Cyan",
"materialSlug": "emission-cyan",
"png": "web/app/public/tutorial/pbr/renders/suzanne-emission-cyan.png",
"jpg": "web/app/public/tutorial/pbr/renders/suzanne-emission-cyan.jpg",
"width": 1024,
"height": 1024,
"bytes": 143481,
"sha256": "7b2cd6fab5372935282ac30e254ce98135e4ecc8fe0773ea2d957d159bcd0176"
},
{
"model": "PBR Cube",
"modelSlug": "cube",
"material": "PBR Metal Brushed",
"materialSlug": "metal-brushed",
"png": "web/app/public/tutorial/pbr/renders/cube-metal-brushed.png",
"jpg": "web/app/public/tutorial/pbr/renders/cube-metal-brushed.jpg",
"width": 1024,
"height": 1024,
"bytes": 141448,
"sha256": "c7aee896836a6a0a50864bd320178c8e523883e2b9ceee47fc909e7e9a75b5ff"
},
{
"model": "PBR Cube",
"modelSlug": "cube",
"material": "PBR Glass",
"materialSlug": "glass",
"png": "web/app/public/tutorial/pbr/renders/cube-glass.png",
"jpg": "web/app/public/tutorial/pbr/renders/cube-glass.jpg",
"width": 1024,
"height": 1024,
"bytes": 132350,
"sha256": "bffbb2092ecc45e021aa7d28912197ccd37fc64e246ca83e76327c1e6d89b60f"
},
{
"model": "PBR Cube",
"modelSlug": "cube",
"material": "PBR Wood",
"materialSlug": "wood",
"png": "web/app/public/tutorial/pbr/renders/cube-wood.png",
"jpg": "web/app/public/tutorial/pbr/renders/cube-wood.jpg",
"width": 1024,
"height": 1024,
"bytes": 136917,
"sha256": "7d01f9daaa535ac35dc91b4349ac98fc13a1a4bd418d789f34c3ee557a15bc79"
},
{
"model": "PBR Cube",
"modelSlug": "cube",
"material": "PBR Emission Cyan",
"materialSlug": "emission-cyan",
"png": "web/app/public/tutorial/pbr/renders/cube-emission-cyan.png",
"jpg": "web/app/public/tutorial/pbr/renders/cube-emission-cyan.jpg",
"width": 1024,
"height": 1024,
"bytes": 113949,
"sha256": "2f47ed7872e1974105b7090ae8fcd740c36e7f26d7eb1f635974207f6cec75b0"
},
{
"model": "PBR Torus",
"modelSlug": "torus",
"material": "PBR Metal Brushed",
"materialSlug": "metal-brushed",
"png": "web/app/public/tutorial/pbr/renders/torus-metal-brushed.png",
"jpg": "web/app/public/tutorial/pbr/renders/torus-metal-brushed.jpg",
"width": 1024,
"height": 1024,
"bytes": 195451,
"sha256": "10c4940ff01d91552f95eb5319540c16394624160f5ed2080998cbba7b8924ce"
},
{
"model": "PBR Torus",
"modelSlug": "torus",
"material": "PBR Glass",
"materialSlug": "glass",
"png": "web/app/public/tutorial/pbr/renders/torus-glass.png",
"jpg": "web/app/public/tutorial/pbr/renders/torus-glass.jpg",
"width": 1024,
"height": 1024,
"bytes": 187720,
"sha256": "89731f334578d40d36f32b1d37ef50be9e011ca66661d0bb9acd4c9e26562629"
},
{
"model": "PBR Torus",
"modelSlug": "torus",
"material": "PBR Wood",
"materialSlug": "wood",
"png": "web/app/public/tutorial/pbr/renders/torus-wood.png",
"jpg": "web/app/public/tutorial/pbr/renders/torus-wood.jpg",
"width": 1024,
"height": 1024,
"bytes": 187133,
"sha256": "04d1afd1d9adc6c651292c35a1c1e25afe667ecad41393ba25f26f78bc3afb97"
},
{
"model": "PBR Torus",
"modelSlug": "torus",
"material": "PBR Emission Cyan",
"materialSlug": "emission-cyan",
"png": "web/app/public/tutorial/pbr/renders/torus-emission-cyan.png",
"jpg": "web/app/public/tutorial/pbr/renders/torus-emission-cyan.jpg",
"width": 1024,
"height": 1024,
"bytes": 148579,
"sha256": "668187e0ee065ff376f22060403eeb877415447dc596a5c4ece0e8ebe039243b"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Some files were not shown because too many files have changed in this diff Show More