住宅CADの3D表示をBlender Cyclesに分離した理由。再現性・描画性能・昼光問題の実測記録
自作している住宅向けCADの3D表示について、「画質が足りないのは描画エンジンのせいか、モデルの中身(形状・材質・照明)のせいか」を切り分けるため、Blender Cyclesを出力用の参照Rendererとして使う実験を2026年10月18日に行いました。この記事は、その記録から他の3Dアプリケーションでも使える設計判断と検証方法を取り出したものです。
先に結論を書きます。
- 今回の環境では、編集時の応答速度と高品質な画像出力を別のRendererに分担させる方針が適していると判断しました。Blender GUIを編集ビューにすると、内蔵GPU機では視点移動が1フレーム約78ms(Solid表示)まで落ちました。
- 3Dデータの正本を1つに保ち、GLBを中間形式として利用しました。同一マシン・同一Blender・描画条件固定のもとで、GLBのハッシュ一致とレンダリング画像の画素一致を確認しました。
- 室内に光が入らないとき、太陽の強さを上げる前に「その方向から床に光が届くか」を幾何的に調べると、原因が特定できました。
- 一方で、画質80点(販売用CGとして概ね許容)には届いていません。人間による画質評価も未了です。技術的PASSと視覚的PASSは別物として扱います。
なぜ描画方式を検討したか
住宅CADでは、編集中の操作感(モデルを動かしたとき即座に反応すること)と、お客様に見せる画像の質(影・間接光・材質感)が、別々の方向に要求を引っ張ります。リアルタイム描画の自前Viewerは軽い一方、空の光や間接光、落ち影を持たない擬似照明で、見た目が「CADっぽい」ままでした。
そこで、同じ形状データをBlender 4.5.14 LTSのCycles(パストレーシング)に渡し、同じカメラで比較しました。位置づけは重要で、これは製品エンジンの採用ではなく、原因切り分けのための測定器です。測定に使ったのは、パラメータから生成した切妻屋根の一戸建てのサンプルモデルで、実在する物件のデータではありません。
最初の比較(2×2:自前Viewer/Cycles × 窓が不透明な旧構成/ガラス窓の構成)で分かったのは、Rendererと内容(Content)の交互作用でした。窓が不透明な板のままの構成では、Cyclesに載せると室内は真っ暗になります。ガラス窓と照明器具を入れて初めて、Cyclesの間接光が効きます。つまり、高品質なRendererを載せても、内容が追いついていないと効果が見えません。以降の実験は、この前提で「内容を1つずつ改善しては同条件で描く」進め方にしました。
編集用Rendererと出力用Rendererの役割
| 編集用Renderer(自前Viewer) | 出力用Renderer(Blender Cycles) | |
|---|---|---|
| 目的 | 操作への即応、部分更新 | 販売用画像・診断用の高品質出力 |
| 照明 | 固定係数の擬似照明(空光・間接光・影なし) | 物理ベース(空光・間接光・落ち影) |
| 更新 | 編集のたびに部分更新 | バッチで全体を描画(CPU 128サンプル) |
| 再現性の要求 | 見た目が大きく崩れないこと | 同じ入力から同じ画素が出ること |
この分離で最も効くのは、3Dデータの正本を1つに保つことです。両方のRendererが同じHouseDoc(住宅の宣言データ)から派生するので、「Viewerと出力で形が違う」という不整合が構造的に起きにくくなります。逆に、Cycles側でモデルを手直しして保存し直すような運用は、正本が2つに割れるので避けました。
HouseDocからGLB、Cyclesまでの構成
HouseDoc(JSON、正本)
→ エクスポータ
→ GLB(1,447 Part / 43,488三角形 / 約7.8MB)
→ Blender 4.5.14 LTS Cycles(設定ファイル駆動)
→ PNG + 補助出力(ID画像・メタデータ・素材一覧)
GLB(glTF 2.0のバイナリ形式)を中間形式にした利点は次のとおりです。
- Blenderの標準importerでそのまま読め、Part構造・UV・テクスチャ・透明材質が再現された。
- カメラは縦画角と視点・注視点をそのまま設定でき、構図が一致した。
- ヘッドレス(
blender -b)で動き、1コマンドで入力から画像まで通せる。
制約もあります。自前Viewerの擬似照明の係数や、一部の材質パラメータ(床板の模様強度など)はGLBに載らず、Cycles側では再現されません。つまり、GLBを通すことは「見た目が同じになる」ことを保証しません。材質は、材質ID(matID)をキーにBlender側のテンプレートへ割り当て、設定ファイルに記録する形にしました。比較するときは「Rendererの差」と「材質変換の差」が混ざる点を、毎回断っておく必要があります。
主な描画設定は、Cycles/CPU/128サンプル/ノイズ除去はOpenImageDenoise/最大バウンス8/解像度1280×720/ビュー変換はKhronos PBR Neutral/乱数seedは0です。
低スペックPCでの操作性能
Blender自体を「編集中の常用ビュー」にできるかを、GUIで実測しました(外部Viewerとしての評価)。環境と条件は次のとおりです。測定はこの環境でのみ有効で、高性能GPU機では結果が変わる可能性があります。
- PC:Windows 10、Core i7-6700K(4コア8スレッド)、メモリ約15.7GB、GPUはIntel HD Graphics 530(CPU内蔵)
- Blender 4.5.14 LTS(GUI)、ウィンドウ1280×760(ビューポート1280×711)
- 読み込んだモデル:1,447メッシュのGLB。1フレームずつ描画時間を計測
| 表示モード | 静止表示 p50 / p95(ms) | 視点移動90フレーム p50 / p95(ms) | メモリ(ワーキングセット) |
|---|---|---|---|
| Solid | 15.5〜16.4 / 49.6〜60.9 | 78.4 / 105.7 | 687MB |
| Material Preview | 14.7〜115.0 / 157〜5,311 | 179.1 / 365.5 | 1,685MB |
| EEVEE Rendered | 14.4〜15.9 / 146.5〜184.6 | 316.8 / 960.3 | 1,701MB |
- 一番軽いSolid表示でも、視点移動の90フレーム全てが50msを超え、中央値は78.4ms(約13fps)でした。
- 表示モードの切り替えは、Solidへ戻るのが約0.1〜0.2秒、Material Previewへ約1秒、Renderedへ約1.2〜1.3秒でした。
- モデルの全再読み込みはSolidで約5.5秒、Renderedで約10.3秒(中央値)。一方、壁の1部品(48頂点)だけを差し替える部分更新は、Solidで約53ms、Renderedで約179msでした。
この結果から、Blender GUIを編集中の常用ビューにするのは、この環境では向かないと判断しました。静止した状態の表示は軽くても、動かすと重い。しかも編集のたびの全再読み込みは数秒〜十数秒かかります。部分更新なら現実的ですが、その仕組みは編集側のRendererが持つべきものです。判定は「部分PASS」で、Blenderは診断・高品質出力専用(推奨B)、Blenderを編集ビューとして使い続ける案は高性能GPUでの再計測が前提、としました。
同じ画像を再生成できるか
画質改善を比較するには、「何も変えなければ同じ画像が出る」ことが前提です。そうでないと、差が改善によるものかノイズによるものか区別できません。次の2段階で確認しました。
- 入力の同一性(ハッシュ):HouseDoc、カメラ、設定ファイル、材質設定、描画設定、生成したGLBのSHA-256を実行ごとのメタデータに保存する。Stage 1では、同じ入力から出力したGLBのハッシュが2回とも一致した(先頭
7aac4bf5、7,797,908バイト)。 - 出力の同一性(画素比較):同じ設定で再実行し、PNGのバイト列ではなく画素値を比べる。差の平均が0、PSNRが無限大なら画素一致とする。
PNGのバイト列は、画素が一致していても一致しないことがあります(Stage 2Aで確認)。だから比較は画素値で行います。
| 段階 | 再実行の対象 | 結果 | 所要時間(正式 / 再実行) |
|---|---|---|---|
| Stage 1 | 外観・キッチン内観(128サンプル) | 画素一致 | 865秒(5視点) / 298.5秒(2視点) |
| Stage 2A | 露出・トーンマップ候補A3 | 画素一致(PNGバイト列は不一致) | 420.1秒 / 428.3秒 |
| Stage 2B | 材質+木質扉候補B | 画素一致、GLBハッシュも同一 | 546.2秒 / 539.0秒 |
| Stage 2C | キッチン形状(取っ手) | 画素一致 | 550.0秒 / 578.5秒 |
これは同一マシン・同一Blender・CPU描画・seed固定の条件での結果です。別のPCやGPU描画で同じ画素が出ることまでは確認していません。あわせて、各段階の前後で、前段階のコード・設定・出力ファイルのSHA-256が変化していないことも確認し、既存の成果物を壊していないことを記録しました。
昼光が入らなかった原因と診断
まず露出とトーンマップを分離した(Stage 2A)
Stage 1の基準画像は、内観が黄みがかって明るく、白飛びが目立ちました(白飛び=最大チャンネルが250以上の画素の割合:リビング20.6%、キッチン34.2%)。そこで、露出とトーンマップだけを変える実験を、他の条件を固定して行いました。
| 構成 | 変更 | 白飛び率 リビング / キッチン | 平均輝度 リビング / キッチン |
|---|---|---|---|
| A0(Stage 1) | なし(+2.0EV、PBR Neutral) | 20.6% / 34.2% | 208 / 198 |
| A1 | 内観露出のみ +1.0EV | 0.2% / 1.1% | 174 / 167 |
| A3 | AgX+露出+1.5EV | 0.0% / 0.4% | 174 / 170 |

白飛びは解消し、輝度も保てました。ただし白飛び率や平均輝度は判断を補助する指標で、どちらが良い絵かは人間が見て決めるものとして扱い、数値から点数への換算はしていません。
太陽の強さを上げても変わらなかった
同じStage 2Aで、太陽の強さを3→6→12と上げ、方位も4方向試しました。しかし室内の直射は変わりませんでした。強さを上げても変わらない、ということは、そもそも太陽光が室内に届いていない可能性が高い。ここで描画の試行を重ねる代わりに、描画せずに幾何だけで診断する方法に切り替えました。
診断方法:床の点から太陽方向へレイを飛ばす
- 室内の床に格子点を取る(天井が上にあり、床が下にある点だけ。919点)。
- 太陽の方向を、方位12方向×仰角4段階(20°・35°・53°・70°)で振る。
- 各点から太陽方向へレイを飛ばし、ガラス・網戸は透過させ(最大6層)、壁や天井に当たれば「遮られた」とする。
- 「光が届いた点の割合」と「最初に遮った部材の種類」を記録する。
この診断は描画を伴わない幾何計算です。結果は次のとおりでした。
- Stage 1で使っていた太陽(仰角53°)は、室内の床の点に直射が0%届いていなかった。壁・天井・屋根に遮られ、窓の方向を向いていなかった。
- 窓から光が入る方向は、リビングとキッチン周辺の床で仰角35°付近に集中していた。この方向では、リビング周辺の床の最大25.2%、キッチン周辺の床の最大31.0%に直射が届く。
- 遮る部材の上位は、ほとんどが壁(壁そのもの・壁の仕上げ面)だった。
対処として、太陽を仰角35°・窓側に向けました(Viewerの座標系で方位262°)。直射が加わると白飛びするので、内観の露出は+2.0→+1.0EVに下げています。低サンプル(16)での確認では、リビングの床とラグに窓の形をした日だまりが出ました。キッチンの日だまりは画角の外でした。

ここでの教訓は、光量を上げる前に、可視性(その方向から光が届くか)を調べることです。可視性が0%なら、強さをいくら上げても無駄に終わります。なお、この診断は幾何的な可視性であり、ガラスの屈折や窓の細かな遮蔽は近似です。方位の数値は使った座標系に依存するため、仰角と届いた割合のほうを一般化できる結果として読んでください。昼光の原因を特定できたことと、画質全体が完成したことは別の話です。
材質・キッチン改善で変わったこと
PBR材質の適用(Stage 2B)
床・壁紙・天井・家具の木部・ソファとカーテンの布に、ambientCGのCC0テクスチャ(色・粗さ・法線)を割り当て、天板はステンレス(金属度0.9・粗さ0.28)、扉と本体は面取り付きにしました。出典URLとSHA-256は素材一覧に記録しています。色味の調整は設計上の選択で、設定ファイルに残しました。
候補は2つです。A:昼光+材質のみ(白いキッチン)。B:Aに加え、キッチンの扉を木質にして造作らしく見せる案。技術的には、昼光(原因の特定)と材質の適用はできたと言えます。一方、描画は2視点で約547秒と、Stage 1の約7分より遅くなりました(面取りと画像テクスチャが増えたため)。
キッチン形状:取っ手と水栓(Stage 2C)
Bの木質扉は、取っ手がなく、のっぺりした箱に見えました。そこで、下部収納の扉4枚と吊戸棚の扉4枚に長尺バーの取っ手を、水栓に吐水口とレバーを追加する形状変更を、既定OFFのスイッチ付きで試しました。

- 変化した画素はキッチン周辺の0.58%(差が8を超える画素)のみで、リビングの画像は変化なし。部屋全体への効果は限定的。
- スイッチOFFのときの出力は従来と画素まで一致(既定は従来動作を保つ)。
- 部品の名簿や識別子は変えず、取っ手は既存の扉メッシュに統合した。
- スイッチON時は、旧外形を前提にした既存テスト2件が失敗する(取っ手が基準外形から30mm突出するため)。テストは書き換えていない。ONを既定にするには、その2件を意図的に更新する判断が要る。
- 取っ手は扉と同じ材質(同じメッシュ)のため、金属感は出せない。
Stage 2Bは、昼光の原因特定と材質適用は進んだものの、人間による画質判断が済んでおらず、取っ手や目地の強調などは見送ったため、PARTIAL(部分的)として扱っています。
画質評価が未完了である理由
画質の評価軸は、形状・納まり(25点)、材質・テクスチャ(25点)、照明・陰影(20点)、統一感(20点)、遠景・近景の安定性(10点)の合計100点で、80点は「販売用CGとして概ね許容」の目安です。確認できた記録の範囲での現在地は、次のとおりです。
- Stage 1より前の暫定採点(AIによる採点で、人間の独立採点ではない):採用候補を入れた構成で、外観52点・内観52点(Stage 1の描画とは別の時点の採点)。目標80点との差は外観・内観とも約28点。
- 80点相当の参照画像として、外部の第三者の実績画像が候補にあるが、利用条件が不明なため、この記事にも検証にも複製・掲載していない。
- Stage 1以降の画像は、確認できた記録では点数化されていない。白飛び率などの補助指標はあるが、点数に換算していない。
ここで区別しておきたい言葉を整理します。
| 区分 | 意味 | 今回の状態 |
|---|---|---|
| Stage 1 PASS | 再現可能な出力基盤(入力→GLB→画像)ができた | 達成。画質80点を意味しない |
| Stage 2Aの技術改善 | 露出・トーンマップを変えて白飛びが解消した(数値で確認) | 達成。視覚的に良くなったかは別 |
| Stage 2B | 昼光の原因特定、PBR材質の適用 | PARTIAL。人間の画質判断は未了 |
| 視覚的PASS | 人間が画像を見て「良くなった」と判断した | 未了 |
技術的PASS(動く・再現できる・数値が改善した)と、視覚的PASS(人間が見て良いと判断した)は別物です。前者は自動で確認できますが、後者は人間が見るしかありません。同じAIが改善して同じAIが採点すると甘くなりがちなので、この実験では画像を人間確認の対象(Human Gate)として止めています。この考え方は別の記事で書いたものと同じです。
他の3D開発でも使える検証手順
- 編集用と出力用を分ける。応答速度の要求と画質の要求は同じRendererでは両立しにくい。まず測る。
- 正本を1つにする。出力側でモデルを直さず、必ず正本から再生成する。
- 中間形式のSHA-256を記録する。入力・設定・材質設定も含めて、実行ごとのメタデータに残す。
- 同条件で再実行し、画素値で比べる。PNGのバイト列ではなく、平均差とPSNRで判定する。seedも固定する。
- 変数は1回に1つ。露出、トーンマップ、太陽の向きを別々に動かし、どれが効いたかを分ける。
- 低サンプルで絞り、評価は高サンプルだけ。16サンプルなら1構成約70秒でスクリーニングでき、評価対象の画像は128サンプルだけにした。
- 光が入らないときは、強さより先に可視性を調べる。床の点から光源方向へのレイで、届く割合と遮る部材を数える。
- 補助指標は判断を置き換えない。白飛び率や平均輝度は人間の判断材料として使う。
- 前後でSHA-256を比べる。実験が既存の成果物を壊していないことを、ファイルのハッシュで示す。
- 技術的PASSと視覚的PASSを別々に書く。どちらかを他方の代わりに報告しない。
今後の課題
- 人間による画質評価と、80点相当の参照画像の選定(利用条件が確認できる画像で)。
- 取っ手以外の形状(引出しの表現、天板の前縁、シンク形状)と、家具・設備の簡略形状。これが最大の不足と見ている。
- 取っ手の金属感(現状は扉と同じ材質のため出ない)。
- 外観の画像:太陽方向を変えた影響が未検証(今回の設定は内観専用)。
- 高性能GPU機でのBlender GUIの再計測、別PCでの再現性(今回は同一マシンのみ)。
- 製品側に統合する方式。今回の実験はあくまで測定器としての利用で、製品エンジンの採用判断はしていない。
まとめ:画質を上げるには、Rendererを替える前に、再現できる出力基盤を作り、原因を1つずつ切り分ける。そのうえで、人間が見て判断する地点を残す。今回は、その基盤とやり方を実測で確認できた段階で、画質そのものはまだ途中です。
補足:画像は自作CADの試験用サンプルモデルをBlender Cyclesで描画したものです。材質のテクスチャはambientCGのCC0素材を使用しています。測定値は筆者の環境(Core i7-6700K、Intel HD Graphics 530、Blender 4.5.14 LTS)での結果です。