Blenderには、絵の焼き方がまったく違うレンダラが2つ入っています。速いEEVEEと、正しいCyclesです。どちらを使うかは「時間か、画質か」の交換条件だと説明されることが多くて、eightもずっとそう理解していました😊

ただ、いざ自分で使おうとすると困ります。その交換条件が、具体的にどのあたりで釣り合うのかが分からないからです。「EEVEEで十分」と言う人もいれば「結局Cyclesに戻る」と言う人もいて、どちらも正しそうに聞こえます。

そこで今回は、同じシーンを両方で焼いて、時間と画質を並べて測りました。前回の Geometry Nodesで街を作る・実践編 で作った街も、比較用のシーンとしてそのまま使っています。

結果を先に言うと、eightが立てた3つの見込みのうち2つは当たり、1つは半分外れました。そして予想していなかった発見がひとつあり、それが記事のタイトルになっています。

「どこまでEEVEEで足りるのか」を数字で言いたかった

スポンサーリンク

「EEVEEとCyclesを比べてみた」という記事はたくさんあります。でも多くは絵を2枚並べて「Cyclesのほうが綺麗ですね」で終わってしまい、どのくらい違うのかが分かりません。「綺麗」は主観なので、そのままでは判断材料になりません。

そこで今回は、Cyclesを長時間かけて焼いた絵を「正解」と決めて、そこからどれだけ離れているかを数値にしました。基準があると「EEVEEはどれくらい違うのか」を印象ではなく距離で言えます。

この回で答えたいこと
どこまでEEVEEで足りて、どこからCyclesが要るのか。それを、同じシーンの実際の絵と実測時間で線引きする。

なお、OptiXやPersistent Dataといった「レンダリングを速くする手法」は今回は触りません。設定は固定したまま、素の状態での性格の違いを見ます。

用語集

この記事に出てくる言葉を先に片づけておきます。

用語意味
EEVEEBlenderに入っている速いほうのレンダラ。ゲームと同じ描き方(ラスタライズ)で、光の回り込みなどは「それらしく見せる近似」で済ませる。5.x系では単に「EEVEE」で、4.2の頃に呼ばれていた「EEVEE Next」という名前はもう使われていない
Cycles正しいほうのレンダラ。目から光線を飛ばして跳ね返りを追いかける(パストレーシング)。物理的に正しい代わりに時間がかかる
サンプル数Cyclesが1画素あたり何本の光線を撃つか。多いほど正確でザラつきが減るが、そのぶん時間がかかる。EEVEEにも同名の設定があるが、意味は「ぼかしや影を何回重ねるか」で別物
ノイズ除去(デノイズ)光線の本数が足りずにザラついた絵を、あとから均して整える機能。BlenderにはOpenImageDenoiseが入っている
GI(グローバルイルミネーション)光の回り込み。窓から入った日光が床で跳ね返って天井を照らす、といった間接的な明るさのこと
ライトプローブEEVEEが「この場所はどれくらい明るいか」を先に計算して保存しておく仕組み。屋内を扱うならほぼ必須。この事前計算を「ベイク」と呼ぶ
RMSE2枚の絵の食い違いを1つの数字にしたもの。0なら完全一致で、数字が大きいほど離れている。今回は0〜255の画素値で計算している

2つのレンダラの違いは、図にするとこうです。たどる向きが逆だと思うと分かりやすいと思います。

2つの描き方は、たどる向きが違うEEVEE = ラスタライズ「物を画面に貼っていく」。1回貼れば終わり。画面貼る跳ね返った光は「別のしくみ」で足す→ 画面の外にある物は、原理的に映せない→ サンプルを増やしても足りない分は埋まらないCycles = パストレーシング「目から光線を飛ばして追いかける」。何本も撃つ。跳ね返りもそのまま追う跳ね返りも映り込みも同じしくみで扱う→ 本数が少ないとザラつく(ノイズ)→ 本数を増やすほど正解に近づく

比べ方:Cyclesの4096サンプルを「正解」に置く

比べ方はこうしました。

  1. Cyclesの4096サンプル・ノイズ除去なしで焼いた絵を「正解」とする
  2. EEVEEとCyclesで、サンプル数を変えながら同じシーンを焼く
  3. それぞれの絵が「正解」からどれだけ離れているかをRMSEで測る
  4. かかった時間と並べて、時間と画質の曲線を描く

シーンは性格が正反対のものを2つ用意しました。1つの条件だけで決めると本番で崩れる、というのは前回の街の記事でも実際にやらかしています。

シーン中身狙い
A屋内(自作)窓から日射が入る6m×5m×3mの部屋。赤い壁・鏡の球・ガラス球・金属球・「開いた箱」光の回り込みで差が出る側
B屋外(p973の街)約2万インスタンスの街。反射も屈折も使わない物量で差が出る側

屋内シーンには、差が出そうな要素だけをわざと1カットに集めてあります。

仕込み何を見るか
窓からの日射が床で跳ね返る間接光で天井や壁が明るくなるか
正面の壁が赤い赤が白い箱や床に移るか(色の回り込み)
鏡の球カメラの後ろにある青い壁が映るか
ガラス球向こう側が歪むか、集光模様が出るか
開いた箱直射日光が一切入らない。中の球が見えるかどうかが、回り込みの有無そのもの

条件は5つです。EEVEEを3段階に分けたのは、5.xのEEVEEは既定でレイトレーシングが切れているからです。これを知らずに「EEVEEは映り込みが出ない」と結論すると、EEVEEに対して条件を揃えたことになりません。

BlenderのEEVEEのレンダー設定画面
EEVEEのレンダー設定。上がサンプル数(レンダー64)で、下のほうに「Raytracing」のチェックがある。これが既定ではオフ
条件中身
EEVEE 既定何も触らない状態
EEVEE レイトレONレイトレーシングを有効にした状態
EEVEE 設定を詰めた版さらにライトプローブを焼き、ガラスをレイトレース屈折にした「EEVEEでちゃんとやった」状態
Cycles ノイズ除去なし素のCycles
Cycles +ノイズ除去OpenImageDenoiseを有効にした状態

条件を揃えたところ

解像度1280×720/カラーマネジメントAgX/露出0/Cyclesの最大バウンス数は既定の12のまま(正解の絵も同じ12にして、サンプル数だけを変数にしています)。レンダリングはWindows機(RTX 3060・OptiX)で計測し、記事を書くのはMacという分担です。Blenderは5.2.0 LTSに固定しました。5.2ではEEVEEのエネルギー保存が修正されて「5.1より暗くなるシーンがある」と公式に明記されているので、版を混ぜると比較が壊れます。

★結論:Cyclesは8サンプルで足りた

まず、いちばん意外だった結果からいきます。

下の2枚を見比べてみてください。左が正解(4096サンプル・41.9秒)、右が8サンプル+ノイズ除去(3.59秒)です。

Cyclesの正解の絵と、8サンプル+ノイズ除去の絵の比較
左=Cycles 4096サンプル(41.9秒)/右=Cycles 8サンプル+ノイズ除去(3.59秒)。11.7分の1の時間で、ほぼ見分けがつかない

ぱっと見で違いが分かるでしょうか。eightは分かりませんでした😳 数値でもズレはわずか2.8です。11.7分の1の時間で、ここまで来ています。

ノイズ除去なしの8サンプルはズレ40.9で、見るからにザラザラです。つまりノイズ除去を入れるかどうかで、同じ8サンプルの絵が40.9から2.8まで変わるということになります。

★予想していなかった発見
「Cyclesは時間がかかる」という感覚の大部分は、ノイズ除去を使っていないことによるものでした。サンプル数を増やして正解に近づけようとすると確かに何十秒もかかりますが、ノイズ除去に任せれば8サンプルで足りてしまいます。

しかもノイズ除去のコストはほぼ固定費でした。屋内では8サンプルのとき+2.80秒、1024サンプルのときでも+2.61秒とほとんど変わりません。低いサンプル数ほど、相対的な負担は大きくなります。街の8サンプルでは、レンダー本体0.64秒に対してノイズ除去が1.95秒=本体の3倍でした。

裏を返すと、ノイズ除去を使うなら「サンプル数を削る」の効果はすぐ頭打ちになるということでもあります。固定費のほうが大きくなるからです。

★EEVEEはサンプルを増やしても近づかない

次が、この記事の背骨になった結果です。時間と画質の曲線を描くとこうなりました。

屋内シーン:かけた時間と、正解からのズレ横軸=1枚あたりのレンダリング時間(対数)/縦軸=基準の絵とのズレ(RMSE・0が正解)0.1秒0.3秒1秒3秒10秒30秒60秒010203040506070ズレ(RMSE)EEVEE 既定EEVEE レイトレONEEVEE 設定を詰めた版Cycles ノイズ除去なしCycles +ノイズ除去★Cyclesは8サンプルでここ3.59秒・ズレ2.8EEVEEは横に伸びるだけで、下がらないBlender 5.2.0 LTS / RTX 3060(OptiX) / 1280×720。EEVEEはサンプル4・16・64・256、Cyclesは8〜1024。

Cyclesの2本(青と緑)は、時間をかけるほど下に降りていきます。当たり前に見えますが、この「当たり前」がEEVEEには起きません。

EEVEEの3本は、完全に真横に伸びるだけです。

条件サンプル1サンプル4サンプル16サンプル64サンプル256
EEVEE 既定64.864.864.864.864.8
EEVEE レイトレON57.558.058.057.957.9
EEVEE 詰めた版34.631.330.730.630.5
Cycles ノイズ除去なし40.9(8サンプル)21.9(32)11.4(128)4.5(1024)

サンプル数を256倍にしても、EEVEEのズレは64.8から64.8です。時間だけが0.18秒から0.97秒に増えます。

★これがEEVEEとCyclesのいちばん本質的な違い
Cyclesのサンプル数は「正解にどれだけ近づけるか」のつまみですが、EEVEEのサンプル数は「EEVEE自身の答えにどれだけ近づけるか」のつまみです。近づく先がそもそも違うので、いくら回しても正解には寄っていきません。

これは「EEVEEが劣っている」という話ではありません。EEVEEのサンプル数は主にギザギザ(アンチエイリアス)や影の柔らかさを整えるためのもので、そこはちゃんと効いています。ただ、光の回り込みが足りない分は、回数では埋まらないのです。

なぜ近づかないのか──絵で見る3つの差

数値だけだと何が起きているか分からないので、実際の絵を並べます。

屋内シーンを4条件で焼き比べた画像
左上=正解(Cycles 4096)/右上=EEVEE既定/左下=EEVEEレイトレON/右下=EEVEE設定を詰めた版。いずれも256サンプル

右上のEEVEE既定が、いちばん分かりやすく壊れています。部屋全体が、窓の外の空の青で塗り潰されています。壁も床も球も、全部うすい青一色です。

これは、屋外の空の光が、壁を無視して部屋の中まで届いているために起きます。EEVEEは既定だと遮蔽をきちんと計算しないので、「外が明るいなら中も明るいはず」という状態になってしまうわけです。

3つの見どころを拡大して並べます。まず鏡の球です。

鏡の球の映り込みを3条件で比較した拡大画像
鏡の球の拡大。正解では青い壁(カメラの後ろ)と赤い壁の両方が映る。EEVEEのレイトレONでは赤しか映らない

正解では、カメラの後ろにある青い壁と、画面に写っている赤い壁の両方が球に映っています。ところがEEVEEのレイトレONでは、赤い壁は映るのに青い壁が映りません

理由は名前のとおりで、EEVEEの映り込みはスクリーン空間、つまり「画面に写っているもの」を材料にして作られるからです。画面の外にあるものは材料が無いので映しようがありません。これは設定でどうにかなる話ではなく、やり方の性質そのものです。

次が「開いた箱」の中です。ここには直射日光が一切入らないので、見えるとしたら跳ね返りの光だけです。

開いた箱の中を3条件で比較した拡大画像
開いた箱の中。正解では跳ね返りの光で中の球がやわらかく見える。EEVEE既定では外と同じ明るさになってしまう

正解では、中の球が跳ね返りの光でやわらかく浮かび上がります。EEVEE既定では箱の中も外と同じ明るさで、そもそも「箱の中」に見えません。遮蔽が効いていないことが、いちばん端的に出ている場所です。

EEVEEでちゃんとやる=ライトプローブを焼く

ここまでは「EEVEEが負ける」話ばかりでしたが、EEVEEには屋内向けの正攻法がありますライトプローブを置いて、事前に明るさを計算(ベイク)しておくやり方です。

部屋にライトプローブを置いた状態のBlenderのビューポート
部屋を覆うようにライトプローブ(Volume)を置いた状態。格子状の点それぞれについて、明るさを事前に計算しておく

これを入れたのが「設定を詰めた版」です。効果は、はっきり出ました。

ライトプローブの大きさによる絵の違い
左=プローブが小さすぎたときの絵(青かぶり・ズレ48.6)/右=シーンの実寸に合わせたとき(青かぶりが消え、ズレ30.5)

右の絵では、あれだけ強かった青かぶりが消えています。壁がニュートラルな灰色になり、赤い壁がちゃんと赤く、開いた箱の中の球も跳ね返りの光で見えるようになりました。ズレも48.6から30.5へ大きく改善しています。

ただ、正解になったわけではありません。2つ問題が残りました。

  • 今度は暗すぎる。明るさを合わせる倍率で見ると、プローブ前は正解の約1.65倍明るく、プローブ後は逆に約0.86倍まで暗くなりました。通り越しています
  • 壁と天井にまだら模様が出る。プローブの格子に由来する斑で、プローブを入れる前には無かったものです

そして相変わらず、サンプル数を増やしてもズレは30.6から30.5までしか動きません。EEVEEの天井が上がっただけで、天井があること自体は変わっていない、ということになります。

⚠つまずき:小さいプローブほどベイクが遅い

このライトプローブで、今回いちばん引っかかったつまずきに当たりました。

最初に組んだ測定用のスクリプトは、プローブの大きさを部屋のサイズで決め打ちしていました。屋内シーンのために書いたものをそのまま街にも使ってしまったわけです。結果、240m四方の街に対して、原点付近の6m×5m×3mだけを焼いていました

これは絵にも数値にも出ていて、街では「詰めた版」と「レイトレONだけ」の結果が小数点以下まで完全に一致していました。プローブが何の仕事もしていなかったわけです。

おかしいのは、その無意味なベイクに1回77秒かかっていたことでした。全体25分41秒のうち約9分がこれです。そこで、プローブの大きさだけを変えて測り直しました。

小さいプローブほど、ベイクが遅い(街シーン)240m四方の街に対してプローブの大きさだけを変えた。格子は32×32×16で固定。3.0 × 2.5 × 1.577.96秒決め打ち(最初の版)3.2 × 2.7 × 1.668.25秒15 × 15 × 11.35.97秒60 × 60 × 11.31.13秒123.4 × 123.4 × 11.30.61秒★シーンの実寸に合わせた位置ではなく大きさが原因。小さいプローブを同じ中心に置いても68秒かかった。

直感と逆でした。プローブを大きくするほど、ベイクは速くなります。77.96秒だったものが、シーンの実寸に合わせると0.61秒。約120倍の差です。位置ではなく大きさが原因で、小さいプローブを同じ中心に置き直しても68秒かかりました。

★なぜ小さいほうが遅いのか
プローブの格子の数は32×32×16で固定だからです。3mのプローブなら格子の間隔は約9cm。その細かさのまま240m四方の街全体を扱おうとすれば、当然爆発します。実寸に合わせると間隔が約7.7mになり、一気に軽くなります。
「重いから範囲を狭めよう」は、ここでは逆効果ということになります。

これは実務でも踏みやすい罠だと思います。ベイクが終わらないときは、まずプローブがシーンに対して小さすぎないかを疑うと早いかもしれません。

屋外ならEEVEEでいけるのか──天井は22で止まった

屋内はCyclesの独壇場でした。では屋外ならEEVEEでいけるのか。これがeightの見込みで、半分外れました

街シーンを4条件で焼き比べた画像
左上=正解(Cycles 2048)/右上=EEVEEレイトレON/左下=EEVEE+実寸プローブ/右下=Cycles 8サンプル+ノイズ除去

まず当たった側です。街のEEVEEは、屋内よりずっと健闘しています。ズレは屋内の57.9に対して22.0。建物の形も影の向きも遠景も、正解とほぼ同じに見えます。差は「街路の谷間の影がEEVEEだと浅い」「全体がわずかに明るい」程度です。閉じた部屋と違って、屋外は遮蔽の影響が小さいからだと思います。

外れたのはここからです。

条件ズレ時間(256サンプル)
EEVEE 既定29.21.18秒
EEVEE レイトレON22.01.90秒
EEVEE +実寸プローブ22.91.83秒
Cycles 8サンプル+ノイズ除去1.42.59秒

ひとつめ。ライトプローブを正しく置いても、屋外では良くなりませんでした(22.0→22.9とむしろ微増)。屋内であれだけ効いた手が、ここでは効きません。しかも絵を見ると、街路や建物の日陰側がほぼ黒に潰れています。屋内と同じで、正解に近づいたのではなく通り越して暗い側へ行った形です。

ふたつめ。屋外はCyclesもそもそも安いのです。屋内では1024サンプルに41.9秒かかったのに、街では4.5秒で終わります。53倍と7.1倍で、重さの伸び方がまるで違います。閉じた部屋では光線が壁の中で何度も跳ね返るのに対し、屋外では空へ抜けてしまうからだと思います。

結果として、街でもCycles+ノイズ除去が2.59秒でズレ1.4に届きます。EEVEEの1.83秒とほとんど変わらない時間で、ズレは16分の1です。

★「屋外はEEVEE有利」は半分外れ
確かにEEVEEは屋外のほうがずっと正解に近い(57.9→22.0)。ただし屋外ではCyclesも安くなるので、静止画1枚で比べるかぎり優位は逆転しませんでした。そしてEEVEEの天井は22前後で止まり、プローブを足しても動きません。

★アニメーションだけは話がひっくり返る

ここまでは静止画1枚の話です。アニメーションにすると、結論はひっくり返ります。

24フレーム焼いたときの合計時間1枚ずつの差は小さくても、枚数が増えると効いてくる屋内 EEVEE(詰めた版)17.9秒1枚 0.75秒屋内 Cycles+ノイズ除去187.92秒1枚 7.83秒 / ★10.5倍街 EEVEE(詰めた版)14.52秒1枚 0.61秒街 Cycles+ノイズ除去118.63秒1枚 4.94秒 / ★8.2倍EEVEEは詰めた版(プローブを焼いた状態)64サンプル、Cyclesは128サンプル+ノイズ除去。

24フレーム焼くと、屋内で10.5倍、街で8.2倍の差がつきます。1枚あたりでは0.75秒対7.83秒という差でも、24枚積み上がれば18秒対188秒です。

ここで効いてくるのがノイズ除去の固定費です。1枚あたり約2.6秒の固定費は、静止画1枚なら誤差の範囲ですが、24枚だと62秒になります。枚数に比例して増える固定費なので、アニメーションでは効き方が変わります。

つまり、こういう整理になります。

  • 静止画1枚なら、EEVEEで削れるのはせいぜい数秒。その数秒のために大きな画質差を受け入れることになる
  • 連番で何百枚も焼くなら、1枚あたり7秒の差が積み上がって効いてくる。ここはEEVEEの土俵

⚠つまずき:初回だけ15秒かかるのは誰のせいか

もうひとつ、測り方そのものでつまずいた話を書いておきます。

eightは事前に「EEVEEは1枚目に下ごしらえの時間がかかるはず」と見込んでいました。EEVEEはシェーダを事前にコンパイルする必要があるので、その分が最初に乗るだろう、という予想です。

これを測るために、Blenderを起動し直して1枚目を5回測るという手順を組みました。ところが結果は5回とも0.79〜0.81秒。まったく差がありません。予想が外れたのかと思いましたが、そうではありませんでした。

切り分けたところ、こうでした。

  1. 1つのプロセスの中でレイトレーシングをオン・オフに切り替えても、切替直後の1枚は定常値と同じ。設定の切替コストはゼロ
  2. Blender自身のシェーダキャッシュは、バックグラウンド実行では1ファイルも使われていない
  3. 本命はグラフィックドライバ側のシェーダキャッシュだった

ドライバのキャッシュを退避してから測り直すと、こうなりました。

キャッシュの状態プローブのベイク1枚目2枚目3枚目
温まった状態1.273秒0.218秒0.108秒0.144秒
消した直後13.369秒11.924秒0.191秒0.150秒
再度温めた後1.256秒0.228秒0.106秒0.142秒

レンダリングだけを見ても、キャッシュを消した直後は15.75秒かかり、2枚目からは0.68秒に戻ります。約23倍です。同じことをCyclesでやっても、増えるのは0.8秒だけでした。

★測り方が間違っていた
この下ごしらえはプロセスごとではなく、そのマシンで1回だけ払うものでした。だから何度起動し直しても捕まりません。最初の1回で払い切ったあと、残り全部が「2回目以降」を測っていたわけです。
さらに、払うのは「最初にGPUのシェーダを要求した処理」です。ライトプローブのベイクが先に走るなら、ベイクがそのコストを払います(1.27秒→13.37秒)。「最初のレンダーが遅くなる」と決めつけていると、原因を見失います。

実務的には、そのマシンで初めてEEVEEを回すときだけ15秒ほど余分にかかると思っておけば良さそうです。24枚焼くなら、その15秒を足してもEEVEEが5倍以上速いままなので結論は変わりません。ただし1枚だけ焼く場合は、この15秒で順位が入れ替わります(EEVEE約18秒 対 Cycles約9.9秒)。

★結局どう使い分けるか

測り終えて、eightの中では使い分けの基準が最初と変わりました。「時間か画質か」ではなく、「何枚焼くか」が先に来ます。

やりたいこと選ぶもの理由
静止画を1〜数枚Cycles+ノイズ除去8サンプルで数秒。EEVEEで削れるのはせいぜい数秒で、引き換えに大きな画質差を負う
連番を何百枚EEVEE1枚あたり7秒の差が積み上がる。屋内なら10.5倍、屋外でも8.2倍
作業中のプレビューEEVEE構図・大きさ・動きを見るには十分。正確さは最後に確かめればよい
屋内・映り込み・ガラスCyclesEEVEEは天井が低い。画面外のものは映せず、遮蔽も苦手
屋外・物量の多いシーンどちらでもEEVEEは屋外だと健闘する。ただしCyclesもここでは安い

それと、これは自分への戒めでもあるのですが、Cyclesを使うならノイズ除去を必ず入れる。今回いちばん実用的な発見はこれでした。入れるだけで、必要なサンプル数が2桁変わります。

逆にEEVEEでサンプル数を増やしても画質は上がりません。ギザギザや影の質は整いますが、光の回り込みが足りない分は埋まりません。時間をかけるつまみとしては期待できない、と覚えておくのが良さそうです。

まとめ

今回わかったことをまとめます。

  • 「Cyclesは遅い」の大部分はノイズ除去を使っていないだけだった。8サンプル・3.59秒でズレ2.8=正解とほぼ見分けがつかない
  • ノイズ除去は固定費(約2.6秒)。サンプル数によらずほぼ一定なので、低サンプルほど比率としては重い
  • EEVEEはサンプル数を増やしても正解に近づかない。1→256でズレ64.8→64.8。近づく先がそもそも違う
  • EEVEEは既定でレイトレーシングが切れている。屋内では空の光が壁を無視して回り込み、部屋が青く塗り潰される
  • ライトプローブを焼くと屋内は大きく改善(48.6→30.5)するが、今度は暗くなりすぎ、格子由来の斑も出る
  • 小さすぎるライトプローブは、小さいがゆえに致命的に遅い(77.96秒 → 実寸に合わせて0.61秒)。格子の数が固定だから
  • 屋外ではEEVEEが健闘する(ズレ57.9→22.0)が、屋外はCyclesも安くなるので静止画では優位が逆転しない。EEVEEの天井は22前後
  • アニメーション24枚では結論がひっくり返る。EEVEEが屋内10.5倍・屋外8.2倍速い
  • 「初回だけ遅い」の正体はドライバのシェーダキャッシュ。プロセスごとではなくマシンごとに1回で、最初にGPUシェーダを要求した処理が払う(EEVEEは約23倍、Cyclesは1.1倍)

「時間か画質か」という単純な交換条件だと思っていたものが、測ってみると「何枚焼くか」で答えが変わる問題だった、というのが今回いちばんの収穫でした。同じシーンを両方で焼いてみるのは、思っていたより発見が多かったです😊

今回使ったシーンの生成スクリプトと計測スクリプトは、どちらもBlenderのPython APIだけで書いてあります。手元のBlenderで blender -b --python scene_room.py のように回せば同じ部屋が作れるので、条件を変えて試すこともできると思います。

それでは、今回はここまで。最後までありがとうございました😊