tag:blogger.com,1999:blog-50292516931781152792024-03-05T17:05:32.608+09:00ZinBox主にプログラミングやモンテカルロレイトレーシングについてメモしていきます.Zinhttp://www.blogger.com/profile/00473704352385380653noreply@blogger.comBlogger11125tag:blogger.com,1999:blog-5029251693178115279.post-88710175244859394752023-12-19T01:51:00.001+09:002023-12-19T02:50:05.191+09:00BlenderでAmazon Lumberyard Bistro を読み込む<h1>Blender で Amazon Lumberyard Bistro を読み込む</h1>
<p>この記事は <a href="https://qiita.com/advent-calendar/2023/raytracing">レイトレ(Raytracing) Advent Calendar 2023</a> の18日目の記事です。</p>
<h2>はじめに</h2>
<p>グラフィックス系の論文では実用的なレンダリングシーンの例として <a href="https://developer.nvidia.com/orca/amazon-lumberyard-bistro">Amazon Lumberyard Bistro</a> [1] がしばしば実験に用いられます。 自作のレンダラーでこのシーンを試す方法として <a href="https://www.blender.org/">Blender</a> [2] でシーンを読み込み glTF などの形式に変換して使用するという方法がありますが、ただ Blender に読み込むだけでは期待した動作にならなかったため、シーンを修正するために行ったことをノートとして残します。但し、シーンを修正するにあたりオブジェクトを手作業で一つ一つ編集するといった時間のかかる作業は行わないようにしています。また、この記事では Blender <em>4.0.2</em> で作業を行っています。</p>
<h3>Blender でのスクリプト実行について</h3>
<p>Blender は Python Interpreter を内蔵しており Python スクリプトを実行してシーンを編集することができます (Blender <em>4.0.2</em> 時での Python のバージョンは <em>3.10.13</em> です) 。
Python スクリプトを実行するにあたって、まずは UI 選択で <strong>Text Editor</strong> を選択しエディターを表示します。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEHZ1JufEV3hrqsBIQO41k8w2CObhUtLwljJtshYXOPIrKtPO3OLw-EfApk7r483EQAm7jS4zKgulb99zHEeNaszivwFIEmWnkNukSCSkpeEI-GFv5FAylQymWStuxM4g5iz19bAY06jI/w988-h284-s-no-gm/" width="100%"></p>
<p>エディター上で Python スクリプトを記述し実行ボタンを押すことでスクリプトを実行できます。</p>
<p><img src="https://lh3.googleusercontent.com/pw/ABLVV85XN3gWKjJVqL_ehrdPK8_Of6HLn1w9tfZuOBFQXVTjRYiGCEnYFW936VjuDYbbezYfeOvBV1unt9wYDaPg4F9_03RRNvtSXGzqo5KLbhELw2nh4_sq-VTOVgrVnOKXX4JLo-ea4kj1SVt7rofAC1YhwQ=w989-h69-s-no-gm" width="100%"></p>
<p>実行時に標準出力にテキストを出力したり、実行エラーメッセージを確認したい場合は Linux なら標準の端末 (端末からBlenderを実行している場合) 、 Windows なら Blender のメニューの "<em>Windows > Toggle System Console</em>" を選択してコンソールを表示することで確認することがきでます。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxuLObhWIHfI9Fura-RhAO8-ep-IY2LKNkVRnpkuJlVGQ98-3itkHsYpO8kMo0hE7W7N96AVmdK6sV4StcBS58t5AUyFYUElvcTH2TOeXwloase7I5B6Ajit2LY-qDEI0HvvnGlBoT2ys/w661-h408-s-no-gm/" width="70%">
<img src="https://lh3.googleusercontent.com/pw/ABLVV85W_Lq15ikUA81Z0IDD2jXFbtr4WvtpElXjlkPZCFEdsm-RoWoeJ2H8nnqz0HgOy_j2olDveEHi1UZWjoD4cZFxeaqpDGjaS5Pc4_5n1gIJQsLMn9aYE31vdZnRcGP9sa3SZzW9-zZi_MJfgi6CiV2HkQ=w1031-h321-s-no-gm" width="100%"></p>
<p>スクリプト実行でシーン編集した内容は Blender の Undo 操作で戻すことができるので、 試行錯誤しながら Python スクリプトを記述することもできます。
また、Blender のメニューの "<em>Edit > Preference > Interface</em>" にある <em>Python Tooltips</em> を有効にすることで GUI 上の各種メニューやボタンに相当する Python コマンドを確認できるようになるので、スクリプトを記述する上でとても便利です。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8T9OMXXP1_ZPMZd9oE2mYypYKS65390dQcJMUsm3Serz4jJPxoAkzZCBQihw8DD5jGkGJYq7RfIWVFMoKJItZJJQOpy49XJxvrMASIIjxvtEeEcuwMTC3E2eAHEUn0ZROZF5AMI_ZH5k/w861-h434-s-no-gm/" width="80%">
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFlPE02wWDDIfIwHJtQPak2lgBc9q4fID1pwsLezhdvQUDyYEefxFQB7jqjjud96VgoHCjPEO6yw83Pv-qyDZs4NKCIEyoIMqViH_U94nNc86LWrBwqLJp_gqSj1ISt1TL8c1MY1wTbRM/w1604-h705-s-no-gm/" width="100%"></p>
<p>Blender での Python スクリプトについてのより詳しい情報は <a href="https://docs.blender.org/api/current/index.html">Python API Documentation</a> を参照して下さい。</p>
<h2>シーンの読み込み</h2>
<h3>読み込み前の準備</h3>
<p>本記事ではオブジェクトがまったく無い状態からシーンの読み込みを行います (Blenderで新規シーンを作成してデフォルトで作成されたオブジェクトを全部削除した状態) 。IBL (Background) は無効にしています。また、レンダリングには <strong>Cycles</strong> レンダラーを用いてデノイザーをオフにして行っています (デバイスバックエンドは <strong>HIP</strong> を使用しています <a href="https://docs.blender.org/manual/en/latest/render/cycles/gpu_rendering.html">Cycles GPU Rendering</a>) 。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguUl4kPyEtyqKI-padhAay83ge1l53h6OHOR3lTx6t4fRWgHQM2EH3TR4ITMLVq3o28GENpNQhWyd9JsIrqXH8EdAYeJhvyLtOZUrvynnSxUa96dHBH1asbUFSUmkdVQQ1J5QWro7w0Mw/w647-h495-s-no-gm/" width="70%"></p>
<h3>Amazon Lumberyard Bistro (v5.2)</h3>
<p>配布ページに載っている <a href="https://d29g4g2dyqv443.cloudfront.net/sites/default/files/Bistro_Night.png">Bistro_Night.png</a> のような画像をレンダリングできることを目標にします。
まずはダウンロードした <strong>BistroExterior.fbx</strong> を Blender にインポートします。但し、本記事ではアニメーションは考慮しないので fbx をインポート時にアニメーションは無効にします。</p>
<p float="left">
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyjt0U0Pl47s3-Yfuax84RKYUUffc0qoIKi_aNc1NF733zR4merpP_IS1mvZT6JevRi9GDaBDStgtpWRFRVzqrlKteUwj30_XkToZOK3rHUlvZNSbqVV6Rgj4bxrtI783C36ysxWTwUzs/w694-h626-s-no-gm/" width="48%">
<img src="https://lh3.googleusercontent.com/pw/ABLVV85ZkzJwtYGxZvh6SEbgeP8ZAR7VcvAPsjyOlVyx51vA_eN4CZOTgqG8q2k-qMMtFTk-3uxvjlP4_RH_wltPRuBKy0AJM2PuSBfubBU2_H9IhxCW5zyXuZRQEb19YUMF7yldD1e7FyINFsZ1jIXM6VEnAw=w1339-h962-s-no-gm" width="48%">
</p>
<p>シーンをインポートしたら <a href="https://d29g4g2dyqv443.cloudfront.net/sites/default/files/Bistro_Night.png">Bistro_Night.png</a> と同じカメラアングルになるようにカメラを下の画像のように設定します。</p>
<p float="left">
<img src="https://lh3.googleusercontent.com/pw/ABLVV84YABPXaEPPxxTeG79gq6O6hpKY6pNDGjSr99GCeS4QX8_1CmKmY-BH6vRIgOQwl_nkuxMlgkFPU_GuoRC-k-fSQgpEf9mEM1HFQkdjkpnE91tcM9tnoIQ8NvP0OumTPA4t1dy18ktOhcsQLtefHugbtQ=w230-h342-s-no-gm" width="30%">
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhH7e9Df4fQdXwQBm9mIs74iLYOB2gVIah8hfbCIJcNB2MwKcJm3YDbx0jVGFQLboRjousuaA0qajwN-7vqubLBM4snVNSudTOPbUS2BhxUT8f4u8ODELcvpEhPpDbdag2GxFF8dbpmgvg/w695-h434-s-no-gm/" width="68%">
</p>
<p><img src="https://lh3.googleusercontent.com/pw/ABLVV85HCfuOVWJUM5FzYJfCosDgmwQPyZtHXwVhgrVBKbSnEvAB0rURyOHh60oQ7CWy0JaskgRZ3PMLje6KbjumYkbdwjsaifVTKto2KstBSd4OiCRseVTnnikVaJKcOXrJRlMMknE7zNjbM4tEFFuN6B5pwg=w3015-h1348-s-no-gm" width="70%"></p>
<p>また、指向性光源 (Sun Light) は使わないので <em>directionalLight1</em> オブジェクトをシーンから削除します。
この状態でレンダリングを開始すると、</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWZdkHDgL3qqx6T0kQIXeoHzpVG2RrvFyLuBgyi_RQlMD1CmQnfZh-OZhA36DJpeflMORblsbmUjhLKFRegePa_VK7r5Ur-SWzleAf7ouyzHCkJRVHJiRCJAiM9Koofgp60RoCeXE_e_Y/w1920-h1080-s-no-gm/" width="85%"></p>
<p>上画像のように光源以外ほとんど真っ暗な画像になります。
光源の Strength が足りないため以下のスクリプト (<strong>Emission.py</strong>) を実行して全ての光源マテリアルの Strength を上げます、</p>
<hr />
<pre><code>import bpy # Blenderのデータ構造にアクセスできるようにする
def strengthenEmission(material):
# マテリアルのノードツリーが無かったり'Principled BSDF'の無いマテリアルは無視する
if (not material.node_tree) or (material.node_tree.nodes.find("Principled BSDF") == -1):
return
# ノードツリーの中から'Principled BSDF'を取り出す
bsdf = material.node_tree.nodes["Principled BSDF"]
# Emissionカラーに黒以外が指定されていたりノードが接続されている場合はEmission Strengthを上げる
emission = bsdf.inputs[26]
if (len(emission.links) > 0) or ((emission.default_value[0] + emission.default_value[1] + emission.default_value[2]) > 0):
emission_strength = bsdf.inputs[27]
emission_strength.default_value *= 512
if __name__ == "__main__":
# 全てのマテリアルをチェックする
for material in bpy.data.materials:
strengthenEmission(material)
</code></pre>
<hr />
<p><img src="https://lh3.googleusercontent.com/pw/ABLVV84nXwxLEl0faB9hyWYm8eMFvxvm_3V7PKfTVP5rog63Y-PpWozdWE3Z-B0FVIEBbIy95mqu70cDBhSAtPqJq_Q0Ehaw4iobFc2U22_mc4SBB7V0HOszg6CQoaqJxYaOo2Ggk7s0lTfIM4WRQFxhQiSqKw=w1131-h364-s-no-gm" width="100%"></p>
<p>このスクリプトでは光源の Strength を <strong>512</strong> 倍しています。実行後、マテリアルは以下の画像のように変化しています、</p>
<p float="left">
<img src="https://lh3.googleusercontent.com/pw/ABLVV84knLN4E7bEnckwej2vbf9hv3ljCImBw8ru5wtfp-zul5jiKsl7X98m6qAp2jE7qkF8YOX5XqDcTMW9j1S8xp6G_3VZcxTAQOYdj7XvID-RF8rLyCph06kZNwiqU-8TuTszfX97GqRBsyJ5NI5_RYS8Fg=w582-h550-s-no-gm" width="45%">
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_3m3kNOqtOZle807BQuaB_gn1Ah-EP80LQPKvsHTciVT5tLLNFzdI7sVoA0IFCiJ7WBA_XRG1Q9tqmRQtRzG7qd4BIFlaF3kn236o36qCDNN_sMCMwa0QexyXTi3PrebHGZeiDA6JU5s/w582-h550-s-no-gm/" width="45%">
</p>
<p>レンダリング結果は、</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSxEEpO84M76Col8O4KcMrTCDMhyphenhyphenBxePBTQS66O0RJqU8VLTaDlv-OxR3HgDBhRatVM9pwCBPGYhlToFjE_zivs-0-9OxTuGJ2ZIpeBm2rZ0TR8HSYFi5u00gg2WXqJy1bn-p4LjE88sM/w1920-h1080-s-no-gm/" width="85%"></p>
<p>のようになり、明るさは <a href="https://d29g4g2dyqv443.cloudfront.net/sites/default/files/Bistro_Night.png">Bistro_Night.png</a> と比較してそれっぽくなりました。
しかし、床や手前のバイクを見てみるとスペキュラーな反射の具合がおかしく見えます。
Blender上でバイクのマテリアルを見てみると、</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHtOq_oXWynw48wS7uSUPlXiklvmDykinkTbAjaByRDf6RFoPoBRs_N41Yrs5kITnfeiE9JaXnEX2nT8yK7BeSTyS6CCYXFyqB3hBal0KgE9_S8kSuoDUu0KPe4JgUFDOJnubmV9IYvcs/w854-h614-s-no-gm/" width="70%"></p>
<p>スペキュラーテクスチャーが Principled BSDF の Specular のパラメータに接続されています。
一方で、ダウンロードした Bistro ファイル内の <strong>README.txt</strong> を読むと、</p>
<pre><code>Textures (compressed .DDS) designed for GGX-based metal-rough PBR material system with the following convention:
- BaseColor
RGB channels: BaseColor value
Alpha channel: Opacity
- Specular
Red channel: Occlusion
Green channel: Roughness
Blue channel: Metalness
- Normal (DirectX)
- Emissive
RGB channels: Emissive color
</code></pre>
<p>と記述されており、スペキュラーテクスチャーの緑成分は Roughness 、青成分は Metalness として使われる事が想定されています。
そこで、全てのスペキュラーテクスチャーの接続を修正するために以下のスクリプト (<strong>MetallicRoughness.py</strong>) を実行します、</p>
<hr />
<pre><code>import bpy # Blenderのデータ構造にアクセスできるようにする
def linkMetallicRoughnessTexture(material):
# マテリアルのノードツリーが無かったり'Principled BSDF'の無いマテリアルは無視する
if (not material.node_tree) or (material.node_tree.nodes.find("Principled BSDF") == -1):
return
# ノードツリーの中から'Principled BSDF'を取り出す
bsdf = material.node_tree.nodes["Principled BSDF"]
# Specularパラメータにノードが接続されている場合、MetallicとRoughnessパラメータに繋ぎかえる
specular = bsdf.inputs[12]
if len(specular.links) > 0:
specular_texture = specular.links[0].from_node
metallic = bsdf.inputs[1]
roughness = bsdf.inputs[2]
# テクスチャーの緑成分と青成分を取り出すために'SeparateColor'ノードを作成する
rgb = material.node_tree.nodes.new("ShaderNodeSeparateColor")
# スペキュラーテクスチャーノードのリンクを一度解除する
material.node_tree.links.remove(specular.links[0])
# スペキュラーテクスチャーノードを'SeparateColor'ノードに接続し、緑成分をRoughnessに青成分をMetallicパラメータに接続する
material.node_tree.links.new(specular_texture.outputs[0], rgb.inputs[0])
material.node_tree.links.new(rgb.outputs[1], roughness)
material.node_tree.links.new(rgb.outputs[2], metallic)
# スペキュラーパラメータはデフォルト値に戻す
specular.default_value = 0.5
if __name__ == "__main__":
# 全てのマテリアルをチェックする
for material in bpy.data.materials:
linkMetallicRoughnessTexture(material)
</code></pre>
<hr />
<p>実行後は以下のようにスペキュラーテクスチャーが Metallic と Roughness に繋がっている事が確認できます、</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicsoR_vG5nx0k1r4sAx_3voWHAhP0uic5w8qf9ooU97O5U_ck_cRCiy2Drz9mLM3NMP_Us105U4V_QQTH-Ac2IeKVCPB7DXWKUTljHEK2Hw4muFpr7DchYPSkSXhr0AekE3p1iONK4szQ/w1125-h614-s-no-gm/" width="80%"></p>
<p>この状態でのレンダリング結果は、</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaaLVjDExk9raEGetY2a4Rks6iV3x32ZeaHQFTwtrExtOsxLze8j9ax7j5LwKgcNncj0ebon-roItT3-H_1w-RTwcxIoaF7KID3emsWexYiZ1kkx7322-tXHLX73GyHe3VjvBeginczEo/w1920-h1080-s-no-gm/" width="85%"></p>
<p>となり <a href="https://d29g4g2dyqv443.cloudfront.net/sites/default/files/Bistro_Night.png">Bistro_Night.png</a> と似た画像をレンダリングすることができました。</p>
<h2>終わりに</h2>
<p>本記事では <a href="https://developer.nvidia.com/orca/amazon-lumberyard-bistro">Amazon Lumberyard Bistro</a> を Blender で読み込み <a href="https://d29g4g2dyqv443.cloudfront.net/sites/default/files/Bistro_Night.png">Bistro_Night.png</a> と似たレンダリングができるように Python スクリプトを用いてシーンの修正を行いました。
一度 Blender 上で期待したレンダリングが出来るか確認する作業は、その後で glTF 形式などで自作のレンダラーに読み込ませレンダリングする際の基準としても使えるので確認しておくのは良いと思います。</p>
<h2>参考</h2>
<ol>
<li>Amazon Lumberyard, <em>Amazon Lumberyard Bistro, Open Research Content Archive (ORCA)</em>, url=<a href="http://developer.nvidia.com/orca/amazon-lumberyard-bistro">http://developer.nvidia.com/orca/amazon-lumberyard-bistro</a></li>
<li>Blender Online Community, <em>Blender - a 3D modelling and rendering package</em>, url=<a href="http://www.blender.org">http://www.blender.org</a></li>
</ol>
Zinhttp://www.blogger.com/profile/00473704352385380653noreply@blogger.com0tag:blogger.com,1999:blog-5029251693178115279.post-1724953439059694062021-12-25T19:42:00.000+09:002021-12-25T19:42:51.010+09:00Godot4 に実装されるグローバルイルミネーションについて調べてみる<h1 id="godot4-に実装されるグローバルイルミネーションについて調べてみる">Godot4 に実装されるグローバルイルミネーションについて調べてみる</h1>
<p>このページは <a href="https://qiita.com/advent-calendar/2021/raytracing">レイトレーシング(レイトレ) Advent Calendar 2021</a> の14日目の記事です。</p>
<h2 id="はじめに">はじめに</h2>
<p><a href="https://godotengine.org/">Godot</a> は2D及び3Dゲームを製作できるクロスプラットフォームなゲームエンジンです。 Godot はオープンソースであり MIT ライセンスの下で開発・配布されており無料で利用することができます。 現在は Godot3 が最新のメジャーバージョンですが、既に次期メジャーバージョンである Godot4 の計画は発表されており開発も進んでいます。 Godot4 ではレンダリングバックエンドとして新しく Vulkan サポートが追加されるなど様々なアップデートが予定されており (<a href="https://github.com/godotengine/godot/milestone/9">マイルストーン</a>)、 その中の一つにリアルタイムグローバルイルミネーション (以降 GI と表記) の追加があります。 本記事ではそのリアルタイムGIの実装である Signed Distance Field Global Illumination (以降は SDFGI と表記) について簡単に紹介します。<br>
最新の Godot4 の実装は <a href="https://github.com/godotengine/godot">github</a> の master ブランチで見ることができます。 また、この記事は <a href="https://github.com/godotengine/godot/tree/e53e357a2bf738d624b1fe29ee967603395efdd0">commit e53e357</a> の時点での Godot4 を使用して書いています。</p>
<h2 id="signed-distance-field-について">Signed Distance Field について</h2>
<p>Signed Distance Field (以降 SDF と表記) はスカラー場で、ここでは空間上のある点からシーン内の最も近いジオメトリの表面までの距離を表します。また、 SDF が正の値の時は自分がジオメトリの外側にいる、負の値の時はジオメトリの内側に位置していることを意味します。<br>
レイキャスト時はこの SDF を用いてスフィアトレーシングを行います。下の図はレイがカメラ (点 <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>p</mi><mn>0</mn></msub></mrow><annotation encoding="application/x-tex">p_0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.625em; vertical-align: -0.19444em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.301108em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span>) から出て表面 (点 <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>p</mi><mn>4</mn></msub></mrow><annotation encoding="application/x-tex">p_4</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.625em; vertical-align: -0.19444em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.301108em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">4</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span>) にヒットするまでを表しています。始めに、レイは開始地点である点 <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>p</mi><mn>0</mn></msub></mrow><annotation encoding="application/x-tex">p_0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.625em; vertical-align: -0.19444em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.301108em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span> の SDF の値を見ます。 SDF が示している距離の間には何も無いことが判明しているのでレイは点 <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>p</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">p_1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.625em; vertical-align: -0.19444em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.301108em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span> まで進む事ができます。これを繰り返す事で表面にヒットする点 <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>p</mi><mn>4</mn></msub></mrow><annotation encoding="application/x-tex">p_4</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.625em; vertical-align: -0.19444em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.301108em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">4</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span> (点から表面までの距離が閾値以下) までレイを進めます。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZ0bewvEp267HjdHoLGfcBV1aosQ902jKIMZHCBKD84RZXAnPYoA5EPLV3Ud3M4eMUr7cV5AtA3SBiEHExE6WX6OyRoHaWrxgzgUiRW538eQiyiHzknOHp3ma0W962sNE5mxWooP2VfCs/w640-no/?authuser=0" alt=""></p>
<h2 id="sdfgi">SDFGI</h2>
<p>SDFGI は名前の通り SDF を利用した GI 実装です。Godot4 の SDFGI 実装はまだ完成ではないそうですが機能としては既に利用できます。また、Godot公式サイトの<a href="https://godotengine.org/article/godot-40-gets-sdf-based-real-time-global-illumination">記事</a>でデモを見ることができます。以下は SDFGI を無効/有効にした時のレンダリング画像です。<br>
<img src="https://lh3.googleusercontent.com/pw/AM-JKLVfE05mbLKG0qelsuTIHd8CYVFNfa2Aq27KAQ3m8YqMd0Qksit43tSy4Jm6FPAYe6mIXd5d6CMyKCD8wzFAyzi2SJOlrqvrCJ06eEZ9f8vbPqsTqzfI75zt8dt_rKhketT_uvhdKvkyHhsMvhpd8VW3=w430-no?authuser=0" alt="SDFGI無効"> <img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxCGhEQYrIz7DwbcWfS2YjuFhlniv9M5THYwtqGGhDw0O2awF1TRYhAZzti9hF5JMMWPDdvpqOLv5E7UYg1uk_iNDfjBqZ5EdXm5BjJyIPzAilf_rncXmlxNAUcn1DDSOqUAfF5DsUXBE/w430-no/?authuser=0" alt="SDFGI有効"><br>
このシーンでは 道路や建物がディレクショナルライトで照らされていますが SDFGI を有効にした場合は影になっている部分も間接光によって明るくなっているのがわかります。<br>
以下の画像はもう少し単純なシーンで SDFGI を試した例です。このシーンでは箱の中を天井にあるエリアライトで照らしています。真ん中に立っている小さな箱の側面を見ると GI 効果 (Color Bleeding) が出ているのがわかります (ただし現在エリアライトからの影はうまく出ないようです) 。<br>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWQ6OGbfBiiZYKXFYgZdBEXCpP1UGUNNuX8aL8P79ggeYEbBgTv_70FSrC3H-KW3jBKMjtFV_8koTlRdzc2S_lmG-etIKGZNaz7fr8ObvGBLKTquEBS03toKRTK9kuu4MTowjqcLor0ao/w430-no/?authuser=0" alt="CornellBox"><br>
SDFGI は RayTracing Core を使っていないので比較的古い GPU でも動きます。そして、古い GPU でもパフォーマンスが出て程良いクオリティの GI レンダリングができるように設計されています。</p>
<div class="separator" style="clear: both; text-align: left;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='640' height='532' src='https://www.blogger.com/video.g?token=AD6v5dyQ2-u-7QckxcKxw2nO7V_65HDe9-Xt5R0LniuP6WGBug19RZWqbZWCu85tI9lPqXGagH0xRh82NeynKpY3gg' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<p>ソースコード中では、SDFGI 関連の実装は C++側は <a href="https://github.com/godotengine/godot/tree/e53e357a2bf738d624b1fe29ee967603395efdd0/servers/rendering/renderer_rd">servers/rendering/renderer_rd/</a> 内の <a href="https://github.com/godotengine/godot/blob/e53e357a2bf738d624b1fe29ee967603395efdd0/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp">renderer_scene_render_rd.cpp</a> 、<a href="https://github.com/godotengine/godot/blob/e53e357a2bf738d624b1fe29ee967603395efdd0/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp">renderer_scene_gi_rd.cpp</a> や <a href="https://github.com/godotengine/godot/blob/e53e357a2bf738d624b1fe29ee967603395efdd0/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp">forward_clustered/render_forward_clustered.cpp</a> に記述されており、Shaderコードは <a href="https://github.com/godotengine/godot/tree/e53e357a2bf738d624b1fe29ee967603395efdd0/servers/rendering/renderer_rd/shaders">servers/rendering/renderer_rd/shaders/</a> 内に glsl で実装されています。 Godot4 でレンダリングを開始すると <code>renderer_scene_render_rd.cpp</code> 内の <code>RendererSceneRenderRD::render_scene()</code> が実行されているのでこの関数から見ていきます。<br>
<em>残念ながら私が実装の詳細まで理解することができなかったため、ここでは処理の概要のみ説明します</em>。</p>
<p>SDFGI に関して <code>render_scene()</code> 内の処理は大まかに以下のようになっています、</p>
<ol>
<li>SDF の構築</li>
<li>ライトプローブの更新</li>
<li>各ピクセルの GI の計算</li>
</ol>
<p>まずは SDF の構築を行い、シーン上に一定間隔毎で設置された各ライトプローブ上の放射照度を計算します。 最後に各ピクセルから見える点の GI を周囲にあるライトプローブから計算します。</p>
<h3 id="sdf-の構築">SDF の構築</h3>
<p>シーン中の空間をグリッドに区切り各セルの SDF を計算します。Godot4 のデフォルトでは 128 x 128 x 128 のグリッドに区切っています。 各セルはまず自分のセル内にジオメトリがあるか確認します。この時オリジナルのジオメトリでは処理が重たくなってしまうので、下図のように簡易化されたジオメトリを用いています。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuTQwxSfCdmqHSRRbuLxczjMc3tRd3Y1NvQsXt_B5FSIx9teDlvCeC27S4LTIq2e9aP0nxvaxUvDlpgOcYvIKy7m8aUMjWmDx10ZoF3D0TTl8oN-8gf2u3WzBM4RXLYvWKSAPDpg2LMKk/w430-no/?authuser=0" alt=""></p>
<p>ジオメトリが見つかった場合はその表面までの距離をセルに格納します。 ジオメトリが見つからなかった場合は、次はセルの周囲にある別のセルを参照します。周囲のセルのどれかにジオメトリがある (SDFの値がセルに格納されている) 場合は自身のセルからジオメトリの表面までの距離をセルに格納します。周囲のセルを参照する処理を何度か繰り返す事でシーン全体の SDF の構築を完成させます。</p>
<h3 id="ライトプローブの更新">ライトプローブの更新</h3>
<p>ここでは GI を計算するために、シーン中の各ライトプローブ上の放射照度を計算します。ライトプローブは下の画像のようにシーン中に一定間隔で配置されています。</p>
<p><img src="https://lh3.googleusercontent.com/pw/AM-JKLXslBG577qwbpx3thnFBKYiNJo-Aj9UPjV9u8oP5lv9TzelYb4vXb5LuXKVrsFRkNK0tvTX_xmC_QZjR5IwpCnvv5YYpFfzuhzb9G3rHQHmeOl2PTqEQBnLuRyX7zqJlSvn72NwRtS0aGNVMdsMSafG=w430-no?authuser=0" alt=""></p>
<p>このプローブ上からランダムな方向にレイを飛ばし当たった光源からの放射輝度を計算します。この時のレイキャストには SDF を用いたスフィアトレーシングを行います。デフォルトの設定では 1 プローブ当たり 16 本のレイを飛ばしています。また、ディレクショナルライトがある場合はその方向にもレイを飛ばし、ディレクショナルライトからの放射輝度も計算します。<br>
次に間接照明に関しては、今度は周囲にあるライトプローブを参照し、自身のライトプローブ方向への放射輝度を計算します。</p>
<h3 id="各ピクセルの-gi-の計算">各ピクセルの GI の計算</h3>
<p>ライトプローブの更新が終了したら、次は各ピクセルからの GI を計算します。ピクセルから見える頂点をデプスバッファから計算します。頂点を見つけたら、ライトプローブで間接照明を計算したときと同様に頂点の周囲にあるライトプローブから頂点への放射輝度を計算します。</p>
<h2 id="終わりに">終わりに</h2>
<p>本記事では Godot4 に実装された SDFGI について調べたことを簡単にまとめました。 ここで紹介した内容は SDFGI の概要程度で、実際の実装では色々な高速化が施されていますが私が解説できるほどの理解ができなかったためスキップしています。また、似た手法として <a href="http://www.cad.zju.edu.cn/home/jin/tvc2021/tvc2021.htm">SDFDDGI</a> が発表されているのでこちらを読んでみるのも良いかもしれません。 法線の八面体へのエンコード (<a href="https://github.com/godotengine/godot/blob/e53e357a2bf738d624b1fe29ee967603395efdd0/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl#L104">code</a>、<a href="https://jcgt.org/published/0003/02/01/">paper</a>) やRGB9995エンコード (<a href="https://github.com/godotengine/godot/blob/e53e357a2bf738d624b1fe29ee967603395efdd0/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl#L114">code</a>) など手軽に自分のレンダラーでも使えそうな圧縮手法もあったので、ここにコードへのリンクだけ貼っておきます。<br>
大規模なソースコードから使われている技術を読み解いていくのは慣れていない事ですが、自分の知らない技術が使われているのを見つけられるので今後も他のレンダラーのコードも読んでいこうと思います。</p>
<h2 id="参考文献">参考文献</h2>
<ol>
<li>Amazon Lumberyard, <em>Amazon Lumberyard Bistro, Open Research Content Archive (ORCA)</em>, url=http://developer.nvidia.com/orca/amazon-lumberyard-bistro</li>
<li>Jinkai H, Milo K. Y, Guillermo E. A, Shihao G, Xiangjun T, Xiaogang J <em>Efficient real-time dynamic diffuse global illumination using signed distance fields (2021)</em></li>
</ol>
Zinhttp://www.blogger.com/profile/00473704352385380653noreply@blogger.com0tag:blogger.com,1999:blog-5029251693178115279.post-5891470433945199852020-12-20T19:42:00.000+09:002020-12-20T19:42:00.422+09:00Resampled Importance Sampling & Weighted Reservoir Sampling<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>RIS and WRS</title>
<link rel="stylesheet" href="https://stackedit.io/style.css" />
</head>
<body class="stackedit" style="color:silver">
<div class="stackedit__html"><h1 id="resampled-importance-sampling--weighted-reservoir-sampling">Resampled Importance Sampling & Weighted Reservoir Sampling</h1>
<p>このページは <a href="https://qiita.com/advent-calendar/2020/raytracing">レイトレ Advent Calendar 2020</a> の20日目の記事です。</p>
<p><a href="https://cs.dartmouth.edu/wjarosz/publications/bitterli20spatiotemporal.html">Spatiotemporal Reservoir Resampling for Real-Time Ray Tracing with Dynamic Direct Lighting</a> を読んでみて <em>Resampled Importance Sampling</em> と <em>Weighted Reservoir Sampling</em> が面白いと思ったので少しまとめてみます。<br>
<em>Resampled Importance Sampling</em> は通常の <em>Importance Sampling</em> では用いられない <em>pdf</em> に従ったサンプリングも行うことができます。また、 <em>Resampled Importance Sampling</em> は通常の <em>Importance Sampling</em> よりも計算に必要なメモリ容量が多くなるので、 <em>Weighted Reservoir Sampling</em> を用いて計算に必要なメモリ容量を削減します。</p>
<h2 id="importance-sampling">Importance Sampling</h2>
<p>Direct Lighting では、ある点 <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>y</mi></mrow><annotation encoding="application/x-tex">y</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.625em; vertical-align: -0.19444em;"></span><span class="mord mathdefault" style="margin-right: 0.03588em;">y</span></span></span></span></span> から方向 <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>ω</mi></mrow><annotation encoding="application/x-tex">\omega</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.43056em; vertical-align: 0em;"></span><span class="mord mathdefault" style="margin-right: 0.03588em;">ω</span></span></span></span></span> への反射輝度 <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>L</mi></mrow><annotation encoding="application/x-tex">L</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.68333em; vertical-align: 0em;"></span><span class="mord mathdefault">L</span></span></span></span></span> は次のような積分で表されます、</p>
<p><span class="katex--display"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math><semantics><mtable width="100%"><mtr><mtd width="50%"></mtd><mtd><mrow><mi>L</mi><mrow><mo fence="true">(</mo><mi>y</mi><mo separator="true">,</mo><mi>ω</mi><mo fence="true">)</mo></mrow><mo>=</mo><msub><mo>∫</mo><mi>A</mi></msub><mi>ρ</mi><mrow><mo fence="true">(</mo><mi>y</mi><mo separator="true">,</mo><mover accent="true"><mrow><mi>x</mi><mi>y</mi></mrow><mo stretchy="true">→</mo></mover><mo>↔</mo><mi>ω</mi><mo fence="true">)</mo></mrow><msub><mi>L</mi><mi>e</mi></msub><mrow><mo fence="true">(</mo><mi>x</mi><mo>→</mo><mi>y</mi><mo fence="true">)</mo></mrow><mi>G</mi><mrow><mo fence="true">(</mo><mi>x</mi><mo>↔</mo><mi>y</mi><mo fence="true">)</mo></mrow><mi>V</mi><mrow><mo fence="true">(</mo><mi>x</mi><mo>↔</mo><mi>y</mi><mo fence="true">)</mo></mrow><mi>d</mi><msub><mi>A</mi><mi>x</mi></msub></mrow></mtd><mtd width="50%"></mtd><mtd><mtext>(1)</mtext></mtd></mtr></mtable><annotation encoding="application/x-tex">
L \left( y, \omega \right) = \int_A
\rho \left( y, \overrightarrow{xy} \leftrightarrow \omega \right)
L_e \left( x \rightarrow y \right)
G \left( x \leftrightarrow y \right)
V \left( x \leftrightarrow y \right) dA_x
\tag{1}
</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 1em; vertical-align: -0.25em;"></span><span class="mord mathdefault">L</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord mathdefault" style="margin-right: 0.03588em;">y</span><span class="mpunct">,</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord mathdefault" style="margin-right: 0.03588em;">ω</span><span class="mclose delimcenter" style="top: 0em;">)</span></span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 2.27195em; vertical-align: -0.91195em;"></span><span class="mop"><span class="mop op-symbol large-op" style="margin-right: 0.44445em; position: relative; top: -0.001125em;">∫</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="" style="top: -1.78805em; margin-left: -0.44445em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">A</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.91195em;"><span class=""></span></span></span></span></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord mathdefault">ρ</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;"><span class="delimsizing size2">(</span></span><span class="mord mathdefault" style="margin-right: 0.03588em;">y</span><span class="mpunct">,</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.95256em;"><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault">x</span><span class="mord mathdefault" style="margin-right: 0.03588em;">y</span></span></span><span class="svg-align" style="top: -3.43056em;"><span class="pstrut" style="height: 3em;"></span><span class="hide-tail" style="height: 0.522em; min-width: 0.888em;"><svg width="400em" height="0.522em" viewBox="0 0 400000 522" preserveAspectRatio="xMaxYMin slice"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.19444em;"><span class=""></span></span></span></span></span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">↔</span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mord mathdefault" style="margin-right: 0.03588em;">ω</span><span class="mclose delimcenter" style="top: 0em;"><span class="delimsizing size2">)</span></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord"><span class="mord mathdefault">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.151392em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">e</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord mathdefault">x</span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mord mathdefault" style="margin-right: 0.03588em;">y</span><span class="mclose delimcenter" style="top: 0em;">)</span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord mathdefault">G</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord mathdefault">x</span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">↔</span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mord mathdefault" style="margin-right: 0.03588em;">y</span><span class="mclose delimcenter" style="top: 0em;">)</span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord mathdefault" style="margin-right: 0.22222em;">V</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord mathdefault">x</span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">↔</span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mord mathdefault" style="margin-right: 0.03588em;">y</span><span class="mclose delimcenter" style="top: 0em;">)</span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord mathdefault">d</span><span class="mord"><span class="mord mathdefault">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.151392em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">x</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span><span class="tag"><span class="strut" style="height: 2.27195em; vertical-align: -0.91195em;"></span><span class="mord text"><span class="mord">(</span><span class="mord"><span class="mord">1</span></span><span class="mord">)</span></span></span></span></span></span></span></p>
<p><span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>ρ</mi></mrow><annotation encoding="application/x-tex">\rho</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.625em; vertical-align: -0.19444em;"></span><span class="mord mathdefault">ρ</span></span></span></span></span> は BSDF 、 <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>L</mi><mi>e</mi></msub></mrow><annotation encoding="application/x-tex">L_e</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.83333em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathdefault">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.151392em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">e</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span> は光源の放射輝度、 <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.68333em; vertical-align: 0em;"></span><span class="mord mathdefault">G</span></span></span></span></span> は幾何項、 <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>V</mi></mrow><annotation encoding="application/x-tex">V</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.68333em; vertical-align: 0em;"></span><span class="mord mathdefault" style="margin-right: 0.22222em;">V</span></span></span></span></span> は可視度項になります。簡単のために <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>y</mi></mrow><annotation encoding="application/x-tex">y</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.625em; vertical-align: -0.19444em;"></span><span class="mord mathdefault" style="margin-right: 0.03588em;">y</span></span></span></span></span> と <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>ω</mi></mrow><annotation encoding="application/x-tex">\omega</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.43056em; vertical-align: 0em;"></span><span class="mord mathdefault" style="margin-right: 0.03588em;">ω</span></span></span></span></span> の表記を省略すると式 <em>(1)</em> は、</p>
<p><span class="katex--display"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math><semantics><mtable width="100%"><mtr><mtd width="50%"></mtd><mtd><mrow><mi>L</mi><mo>=</mo><msub><mo>∫</mo><mi>A</mi></msub><mi>f</mi><mrow><mo fence="true">(</mo><mi>x</mi><mo fence="true">)</mo></mrow><mi>d</mi><mi>x</mi><mo separator="true">,</mo><mspace width="2em"></mspace><mi>w</mi><mi>h</mi><mi>e</mi><mi>r</mi><mi>e</mi><mspace width="1em"></mspace><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>≡</mo><mi>ρ</mi><mrow><mo fence="true">(</mo><mi>x</mi><mo fence="true">)</mo></mrow><msub><mi>L</mi><mi>e</mi></msub><mrow><mo fence="true">(</mo><mi>x</mi><mo fence="true">)</mo></mrow><mi>G</mi><mrow><mo fence="true">(</mo><mi>x</mi><mo fence="true">)</mo></mrow><mi>V</mi><mrow><mo fence="true">(</mo><mi>x</mi><mo fence="true">)</mo></mrow></mrow></mtd><mtd width="50%"></mtd><mtd><mtext>(2)</mtext></mtd></mtr></mtable><annotation encoding="application/x-tex">
L = \int_A f \left( x \right) dx, \qquad where \quad
f(x) \equiv \rho \left( x \right ) L_e \left( x \right) G \left( x \right) V \left( x \right)
\tag{2}
</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.68333em; vertical-align: 0em;"></span><span class="mord mathdefault">L</span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 2.27195em; vertical-align: -0.91195em;"></span><span class="mop"><span class="mop op-symbol large-op" style="margin-right: 0.44445em; position: relative; top: -0.001125em;">∫</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="" style="top: -1.78805em; margin-left: -0.44445em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">A</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.91195em;"><span class=""></span></span></span></span></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord mathdefault" style="margin-right: 0.10764em;">f</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord mathdefault">x</span><span class="mclose delimcenter" style="top: 0em;">)</span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord mathdefault">d</span><span class="mord mathdefault">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mspace" style="margin-right: 2em;"></span><span class="mord mathdefault" style="margin-right: 0.02691em;">w</span><span class="mord mathdefault">h</span><span class="mord mathdefault">e</span><span class="mord mathdefault" style="margin-right: 0.02778em;">r</span><span class="mord mathdefault">e</span><span class="mspace" style="margin-right: 1em;"></span><span class="mord mathdefault" style="margin-right: 0.10764em;">f</span><span class="mopen">(</span><span class="mord mathdefault">x</span><span class="mclose">)</span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 1em; vertical-align: -0.25em;"></span><span class="mord mathdefault">ρ</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord mathdefault">x</span><span class="mclose delimcenter" style="top: 0em;">)</span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord"><span class="mord mathdefault">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.151392em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">e</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord mathdefault">x</span><span class="mclose delimcenter" style="top: 0em;">)</span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord mathdefault">G</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord mathdefault">x</span><span class="mclose delimcenter" style="top: 0em;">)</span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord mathdefault" style="margin-right: 0.22222em;">V</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord mathdefault">x</span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span><span class="tag"><span class="strut" style="height: 2.27195em; vertical-align: -0.91195em;"></span><span class="mord text"><span class="mord">(</span><span class="mord"><span class="mord">2</span></span><span class="mord">)</span></span></span></span></span></span></span></p>
<p>と表せます。</p>
<p>式 <em>(2)</em> の積分は分析的に解くことは難しいため、通常 Monte Carlo 法を用いて解析的に解きます。 Monte Carlo 法は確率的手法であるため分散によるノイズが発生します。 分散を低減するために <em>Importance Sampling</em> (以降 <em>IS</em> と表記) がよく用いられます。<br>
<em>IS</em> では <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>N</mi></mrow><annotation encoding="application/x-tex">N</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.68333em; vertical-align: 0em;"></span><span class="mord mathdefault" style="margin-right: 0.10903em;">N</span></span></span></span></span> 個のサンプル <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>x</mi><mi>i</mi></msub></mrow><annotation encoding="application/x-tex">x_i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.58056em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.311664em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span> を pdf <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>p</mi><mrow><mo fence="true">(</mo><msub><mi>x</mi><mi>i</mi></msub><mo fence="true">)</mo></mrow></mrow><annotation encoding="application/x-tex">p \left( x_i \right)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 1em; vertical-align: -0.25em;"></span><span class="mord mathdefault">p</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.311664em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span></span></span> に従ってサンプリングします。その推定量は以下のようになります、</p>
<p><span class="katex--display"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math><semantics><mtable width="100%"><mtr><mtd width="50%"></mtd><mtd><mrow><msubsup><mrow><mo fence="true"><</mo><mi>L</mi><mo fence="true">></mo></mrow><mrow><mi>i</mi><mi>s</mi></mrow><mi>N</mi></msubsup><mo>=</mo><mfrac><mn>1</mn><mi>N</mi></mfrac><munderover><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>N</mi></munderover><mfrac><mrow><mi>f</mi><mrow><mo fence="true">(</mo><msub><mi>x</mi><mi>i</mi></msub><mo fence="true">)</mo></mrow></mrow><mrow><mi>p</mi><mrow><mo fence="true">(</mo><msub><mi>x</mi><mi>i</mi></msub><mo fence="true">)</mo></mrow></mrow></mfrac><mo>≈</mo><mi>L</mi></mrow></mtd><mtd width="50%"></mtd><mtd><mtext>(3)</mtext></mtd></mtr></mtable><annotation encoding="application/x-tex">
\left< L \right>_{is}^{N} = \frac{1}{N} \sum_{i=1}^{N}
\frac{f \left( x_i \right)}{p \left( x_i \right)} \approx L
\tag{3}
</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 1.28093em; vertical-align: -0.2997em;"></span><span class="minner"><span class="minner"><span class="mopen delimcenter" style="top: 0em;">⟨</span><span class="mord mathdefault">L</span><span class="mclose delimcenter" style="top: 0em;">⟩</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.981231em;"><span class="" style="top: -2.4003em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">i</span><span class="mord mathdefault mtight">s</span></span></span></span><span class="" style="top: -3.2029em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.10903em;">N</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.2997em;"><span class=""></span></span></span></span></span></span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 3.10601em; vertical-align: -1.27767em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 1.32144em;"><span class="" style="top: -2.314em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right: 0.10903em;">N</span></span></span><span class="" style="top: -3.23em;"><span class="pstrut" style="height: 3em;"></span><span class="frac-line" style="border-bottom-width: 0.04em;"></span></span><span class="" style="top: -3.677em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.686em;"><span class=""></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 1.82834em;"><span class="" style="top: -1.87233em; margin-left: 0em;"><span class="pstrut" style="height: 3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="" style="top: -3.05001em;"><span class="pstrut" style="height: 3.05em;"></span><span class=""><span class="mop op-symbol large-op">∑</span></span></span><span class="" style="top: -4.30001em; margin-left: 0em;"><span class="pstrut" style="height: 3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.10903em;">N</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 1.27767em;"><span class=""></span></span></span></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 1.427em;"><span class="" style="top: -2.314em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault">p</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.311664em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span><span class="" style="top: -3.23em;"><span class="pstrut" style="height: 3em;"></span><span class="frac-line" style="border-bottom-width: 0.04em;"></span></span><span class="" style="top: -3.677em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right: 0.10764em;">f</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.311664em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.936em;"><span class=""></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">≈</span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 0.68333em; vertical-align: 0em;"></span><span class="mord mathdefault">L</span></span><span class="tag"><span class="strut" style="height: 3.10601em; vertical-align: -1.27767em;"></span><span class="mord text"><span class="mord">(</span><span class="mord"><span class="mord">3</span></span><span class="mord">)</span></span></span></span></span></span></span></p>
<p><em>IS</em> は <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>f</mi><mrow><mo fence="true">(</mo><mi>x</mi><mo fence="true">)</mo></mrow><mi mathvariant="normal">≠</mi><mn>0</mn></mrow><annotation encoding="application/x-tex">f \left( x \right) \neq 0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 1em; vertical-align: -0.25em;"></span><span class="mord mathdefault" style="margin-right: 0.10764em;">f</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord mathdefault">x</span><span class="mclose delimcenter" style="top: 0em;">)</span></span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel"><span class="mrel"><span class="mord"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.69444em;"><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="rlap"><span class="strut" style="height: 0.88888em; vertical-align: -0.19444em;"></span><span class="inner"><span class="mrel"></span></span><span class="fix"></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.19444em;"><span class=""></span></span></span></span></span></span><span class="mrel">=</span></span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 0.64444em; vertical-align: 0em;"></span><span class="mord">0</span></span></span></span></span> となる <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.43056em; vertical-align: 0em;"></span><span class="mord mathdefault">x</span></span></span></span></span> に対して常に <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>p</mi><mrow><mo fence="true">(</mo><mi>x</mi><mo fence="true">)</mo></mrow><mo>></mo><mn>0</mn></mrow><annotation encoding="application/x-tex">p \left( x \right) \gt 0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 1em; vertical-align: -0.25em;"></span><span class="mord mathdefault">p</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord mathdefault">x</span><span class="mclose delimcenter" style="top: 0em;">)</span></span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">></span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 0.64444em; vertical-align: 0em;"></span><span class="mord">0</span></span></span></span></span> となる場合に unbiased となります。 また、 <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>p</mi><mrow><mo fence="true">(</mo><mi>x</mi><mo fence="true">)</mo></mrow></mrow><annotation encoding="application/x-tex">p \left( x \right)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 1em; vertical-align: -0.25em;"></span><span class="mord mathdefault">p</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord mathdefault">x</span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span></span></span> が <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>f</mi><mrow><mo fence="true">(</mo><mi>x</mi><mo fence="true">)</mo></mrow></mrow><annotation encoding="application/x-tex">f \left( x \right)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 1em; vertical-align: -0.25em;"></span><span class="mord mathdefault" style="margin-right: 0.10764em;">f</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord mathdefault">x</span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span></span></span> に対して相関が強いほど分散を低減することができます。<br>
<em>IS</em> を用いるためには pdf で定義される分布に従ってサンプルを生成できる必要があります。一般的にサンプリングの方法として <em>inverse cumulative distribution function (逆CDF)</em> や <em>rejection sampling</em> が用いられます。</p>
<h2 id="resampled-importance-sampling">Resampled Importance Sampling</h2>
<p>Direct Lighting を <em>IS</em> を用いて計算する場合は <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>ρ</mi><mo>⋅</mo><msub><mi>L</mi><mi>e</mi></msub><mo>⋅</mo><mi>G</mi><mo>⋅</mo><mi>V</mi></mrow><annotation encoding="application/x-tex">\rho \cdot L_e \cdot G \cdot V</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.63889em; vertical-align: -0.19444em;"></span><span class="mord mathdefault">ρ</span><span class="mspace" style="margin-right: 0.222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right: 0.222222em;"></span></span><span class="base"><span class="strut" style="height: 0.83333em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathdefault">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.151392em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">e</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span><span class="mspace" style="margin-right: 0.222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right: 0.222222em;"></span></span><span class="base"><span class="strut" style="height: 0.68333em; vertical-align: 0em;"></span><span class="mord mathdefault">G</span><span class="mspace" style="margin-right: 0.222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right: 0.222222em;"></span></span><span class="base"><span class="strut" style="height: 0.68333em; vertical-align: 0em;"></span><span class="mord mathdefault" style="margin-right: 0.22222em;">V</span></span></span></span></span> に比例した pdf に従ってサンプリングするのが理想ですが、このような pdf は closed-form で表現できず複雑なため <em>逆CDF</em> によるサンプリングは難しくなります。<br>
<em>Resampled Importance Sampling</em> (以降 <em>RIS</em> と表記) はこのような複雑な pdf を用いて <em>IS</em> を行うことができます。 <em>RIS</em> では2つの pdf を用います。1つはソース pdf <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>p</mi></mrow><annotation encoding="application/x-tex">p</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.625em; vertical-align: -0.19444em;"></span><span class="mord mathdefault">p</span></span></span></span></span> で <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>f</mi></mrow><annotation encoding="application/x-tex">f</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.88888em; vertical-align: -0.19444em;"></span><span class="mord mathdefault" style="margin-right: 0.10764em;">f</span></span></span></span></span> との相関は強くないが <em>逆CDF</em> ができる pdf です (例えば <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>p</mi><mo>∝</mo><msub><mi>L</mi><mi>e</mi></msub></mrow><annotation encoding="application/x-tex">p \propto L_e</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.625em; vertical-align: -0.19444em;"></span><span class="mord mathdefault">p</span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">∝</span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 0.83333em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathdefault">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.151392em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">e</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span> など)。もう1つは ターゲット pdf <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mover accent="true"><mi>p</mi><mo>^</mo></mover></mrow><annotation encoding="application/x-tex">\hat{p}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.88888em; vertical-align: -0.19444em;"></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.69444em;"><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault">p</span></span></span><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="accent-body" style="left: -0.16666em;">^</span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.19444em;"><span class=""></span></span></span></span></span></span></span></span></span> で <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>f</mi></mrow><annotation encoding="application/x-tex">f</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.88888em; vertical-align: -0.19444em;"></span><span class="mord mathdefault" style="margin-right: 0.10764em;">f</span></span></span></span></span> との相関は強いが正規化が難しく <em>逆CDF</em> ができない pdf です (例えば <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mover accent="true"><mi>p</mi><mo>^</mo></mover><mo>∝</mo><mi>ρ</mi><mo>⋅</mo><msub><mi>L</mi><mi>e</mi></msub><mo>⋅</mo><mi>G</mi></mrow><annotation encoding="application/x-tex">\hat{p} \propto \rho \cdot L_e \cdot G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.88888em; vertical-align: -0.19444em;"></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.69444em;"><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault">p</span></span></span><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="accent-body" style="left: -0.16666em;">^</span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.19444em;"><span class=""></span></span></span></span></span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">∝</span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 0.63889em; vertical-align: -0.19444em;"></span><span class="mord mathdefault">ρ</span><span class="mspace" style="margin-right: 0.222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right: 0.222222em;"></span></span><span class="base"><span class="strut" style="height: 0.83333em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathdefault">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.151392em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">e</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span><span class="mspace" style="margin-right: 0.222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right: 0.222222em;"></span></span><span class="base"><span class="strut" style="height: 0.68333em; vertical-align: 0em;"></span><span class="mord mathdefault">G</span></span></span></span></span> など)。</p>
<p>先ず、 <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>M</mi></mrow><annotation encoding="application/x-tex">M</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.68333em; vertical-align: 0em;"></span><span class="mord mathdefault" style="margin-right: 0.10903em;">M</span></span></span></span></span> 個 (<span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>M</mi><mo>≥</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">M \ge 1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.8193em; vertical-align: -0.13597em;"></span><span class="mord mathdefault" style="margin-right: 0.10903em;">M</span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 0.64444em; vertical-align: 0em;"></span><span class="mord">1</span></span></span></span></span>) の候補サンプル <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi mathvariant="bold-italic">x</mi><mo>=</mo><mrow><mo fence="true">{</mo><msub><mi>x</mi><mn>1</mn></msub><mo separator="true">,</mo><mo>…</mo><mo separator="true">,</mo><msub><mi>x</mi><mi>M</mi></msub><mo fence="true">}</mo></mrow></mrow><annotation encoding="application/x-tex">\boldsymbol{x} = \left\{ x_1, \ldots, x_M \right\}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.44444em; vertical-align: 0em;"></span><span class="mord"><span class="mord"><span class="mord boldsymbol">x</span></span></span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 1em; vertical-align: -0.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">{</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.301108em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner">…</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.328331em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right: 0.10903em;">M</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">}</span></span></span></span></span></span> を ソース pdf <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>p</mi></mrow><annotation encoding="application/x-tex">p</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.625em; vertical-align: -0.19444em;"></span><span class="mord mathdefault">p</span></span></span></span></span> に従ってサンプリングします。その候補サンプルの中から <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>z</mi></mrow><annotation encoding="application/x-tex">z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.43056em; vertical-align: 0em;"></span><span class="mord mathdefault" style="margin-right: 0.04398em;">z</span></span></span></span></span> 番目、 <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>x</mi><mi>z</mi></msub></mrow><annotation encoding="application/x-tex">x_z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.58056em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.151392em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right: 0.04398em;">z</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span> (<span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>z</mi><mo>∈</mo><mrow><mo fence="true">{</mo><mn>1</mn><mo separator="true">,</mo><mo>…</mo><mo separator="true">,</mo><mi>M</mi><mo fence="true">}</mo></mrow></mrow><annotation encoding="application/x-tex">z \in \left\{1, \ldots, M \right\}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.5782em; vertical-align: -0.0391em;"></span><span class="mord mathdefault" style="margin-right: 0.04398em;">z</span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 1em; vertical-align: -0.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">{</span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner">…</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord mathdefault" style="margin-right: 0.10903em;">M</span><span class="mclose delimcenter" style="top: 0em;">}</span></span></span></span></span></span>) を重み <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>w</mi><mrow><mo fence="true">(</mo><mi>x</mi><mo fence="true">)</mo></mrow><mo>=</mo><mfrac><mrow><mover accent="true"><mi>p</mi><mo>^</mo></mover><mrow><mo fence="true">(</mo><mi>x</mi><mo fence="true">)</mo></mrow></mrow><mrow><mi>p</mi><mrow><mo fence="true">(</mo><mi>x</mi><mo fence="true">)</mo></mrow></mrow></mfrac></mrow><annotation encoding="application/x-tex">w \left( x \right) = \frac{\hat{p} \left( x \right)}{p \left( x \right)}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 1em; vertical-align: -0.25em;"></span><span class="mord mathdefault" style="margin-right: 0.02691em;">w</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord mathdefault">x</span><span class="mclose delimcenter" style="top: 0em;">)</span></span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 1.53em; vertical-align: -0.52em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 1.01em;"><span class="" style="top: -2.655em;"><span class="pstrut" style="height: 3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">p</span><span class="minner mtight"><span class="mopen mtight delimcenter" style="top: 0em;"><span class="mtight">(</span></span><span class="mord mathdefault mtight">x</span><span class="mclose mtight delimcenter" style="top: 0em;"><span class="mtight">)</span></span></span></span></span></span><span class="" style="top: -3.23em;"><span class="pstrut" style="height: 3em;"></span><span class="frac-line" style="border-bottom-width: 0.04em;"></span></span><span class="" style="top: -3.485em;"><span class="pstrut" style="height: 3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord accent mtight"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.69444em;"><span class="" style="top: -2.7em;"><span class="pstrut" style="height: 2.7em;"></span><span class="mord mtight"><span class="mord mathdefault mtight">p</span></span></span><span class="" style="top: -2.7em;"><span class="pstrut" style="height: 2.7em;"></span><span class="accent-body" style="left: -0.16666em;"><span class="mtight">^</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.19444em;"><span class=""></span></span></span></span></span><span class="minner mtight"><span class="mopen mtight delimcenter" style="top: 0em;"><span class="mtight">(</span></span><span class="mord mathdefault mtight">x</span><span class="mclose mtight delimcenter" style="top: 0em;"><span class="mtight">)</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.52em;"><span class=""></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span> に従ってランダムに選びます。候補の中から <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>x</mi><mi>z</mi></msub></mrow><annotation encoding="application/x-tex">x_z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.58056em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.151392em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right: 0.04398em;">z</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span> が選択される確率は、</p>
<p><span class="katex--display"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math><semantics><mtable width="100%"><mtr><mtd width="50%"></mtd><mtd><mrow><mi>p</mi><mrow><mo fence="true">(</mo><mi>z</mi><mi mathvariant="normal">∣</mi><mi mathvariant="bold-italic">x</mi><mo fence="true">)</mo></mrow><mo>=</mo><mfrac><mrow><mi>w</mi><mrow><mo fence="true">(</mo><msub><mi>x</mi><mi>z</mi></msub><mo fence="true">)</mo></mrow></mrow><mrow><munderover><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>M</mi></munderover><mi>w</mi><mrow><mo fence="true">(</mo><msub><mi>x</mi><mi>i</mi></msub><mo fence="true">)</mo></mrow></mrow></mfrac></mrow></mtd><mtd width="50%"></mtd><mtd><mtext>(4)</mtext></mtd></mtr></mtable><annotation encoding="application/x-tex">
p \left( z | \boldsymbol{x} \right) =
\frac{w \left( x_z \right)}{\sum_{i=1}^{M} w \left( x_i \right)}
\tag{4}
</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 1em; vertical-align: -0.25em;"></span><span class="mord mathdefault">p</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord mathdefault" style="margin-right: 0.04398em;">z</span><span class="mord">∣</span><span class="mord"><span class="mord"><span class="mord boldsymbol">x</span></span></span><span class="mclose delimcenter" style="top: 0em;">)</span></span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 2.59794em; vertical-align: -1.17094em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 1.427em;"><span class="" style="top: -2.12877em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mop"><span class="mop op-symbol small-op" style="position: relative; top: -5e-06em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.981231em;"><span class="" style="top: -2.40029em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="" style="top: -3.2029em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.10903em;">M</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.29971em;"><span class=""></span></span></span></span></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord mathdefault" style="margin-right: 0.02691em;">w</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.311664em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span><span class="" style="top: -3.23em;"><span class="pstrut" style="height: 3em;"></span><span class="frac-line" style="border-bottom-width: 0.04em;"></span></span><span class="" style="top: -3.677em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right: 0.02691em;">w</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.151392em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right: 0.04398em;">z</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 1.17094em;"><span class=""></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span><span class="tag"><span class="strut" style="height: 2.59794em; vertical-align: -1.17094em;"></span><span class="mord text"><span class="mord">(</span><span class="mord"><span class="mord">4</span></span><span class="mord">)</span></span></span></span></span></span></span></p>
<p>となります。上記の手順でサンプリングされた <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>x</mi><mi>z</mi></msub></mrow><annotation encoding="application/x-tex">x_z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.58056em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.151392em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right: 0.04398em;">z</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span> はターゲット pdf <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mover accent="true"><mi>p</mi><mo>^</mo></mover></mrow><annotation encoding="application/x-tex">\hat{p}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.88888em; vertical-align: -0.19444em;"></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.69444em;"><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault">p</span></span></span><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="accent-body" style="left: -0.16666em;">^</span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.19444em;"><span class=""></span></span></span></span></span></span></span></span></span> に近似した分布になります。この <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>x</mi><mi>z</mi></msub></mrow><annotation encoding="application/x-tex">x_z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.58056em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.151392em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right: 0.04398em;">z</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span> を使った推定量は以下のようになります、</p>
<p><span class="katex--display"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math><semantics><mtable width="100%"><mtr><mtd width="50%"></mtd><mtd><mrow><msubsup><mrow><mo fence="true"><</mo><mi>L</mi><mo fence="true">></mo></mrow><mrow><mi>r</mi><mi>i</mi><mi>s</mi></mrow><mrow><mi>N</mi><mo separator="true">,</mo><mi>M</mi></mrow></msubsup><mo>=</mo><mfrac><mn>1</mn><mi>N</mi></mfrac><munderover><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>N</mi></munderover><mrow><mo fence="true">(</mo><mfrac><mrow><mi>f</mi><mrow><mo fence="true">(</mo><msub><mi>x</mi><mrow><mi>i</mi><mi>z</mi></mrow></msub><mo fence="true">)</mo></mrow></mrow><mrow><mover accent="true"><mi>p</mi><mo>^</mo></mover><mrow><mo fence="true">(</mo><msub><mi>x</mi><mrow><mi>i</mi><mi>z</mi></mrow></msub><mo fence="true">)</mo></mrow></mrow></mfrac><mo>⋅</mo><mrow><mo fence="true">(</mo><mfrac><mn>1</mn><mi>M</mi></mfrac><munderover><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mi>M</mi></munderover><mi>w</mi><mrow><mo fence="true">(</mo><msub><mi>x</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo fence="true">)</mo></mrow><mo fence="true">)</mo></mrow><mo fence="true">)</mo></mrow></mrow></mtd><mtd width="50%"></mtd><mtd><mtext>(5)</mtext></mtd></mtr></mtable><annotation encoding="application/x-tex">
\left< L \right>_{ris}^{N,M} = \frac{1}{N} \sum_{i=1}^{N} \left(
\frac{f \left( x_{iz} \right)}{\hat{p} \left( x_{iz} \right)} \cdot \left(
\frac{1}{M} \sum_{j=1}^{M} w \left( x_{ij} \right) \right) \right)
\tag{5}
</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 1.28093em; vertical-align: -0.2997em;"></span><span class="minner"><span class="minner"><span class="mopen delimcenter" style="top: 0em;">⟨</span><span class="mord mathdefault">L</span><span class="mclose delimcenter" style="top: 0em;">⟩</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.981231em;"><span class="" style="top: -2.4003em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.02778em;">r</span><span class="mord mathdefault mtight">i</span><span class="mord mathdefault mtight">s</span></span></span></span><span class="" style="top: -3.2029em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.10903em;">N</span><span class="mpunct mtight">,</span><span class="mord mathdefault mtight" style="margin-right: 0.10903em;">M</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.2997em;"><span class=""></span></span></span></span></span></span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 3.24211em; vertical-align: -1.41378em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 1.32144em;"><span class="" style="top: -2.314em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right: 0.10903em;">N</span></span></span><span class="" style="top: -3.23em;"><span class="pstrut" style="height: 3em;"></span><span class="frac-line" style="border-bottom-width: 0.04em;"></span></span><span class="" style="top: -3.677em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.686em;"><span class=""></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 1.82834em;"><span class="" style="top: -1.87233em; margin-left: 0em;"><span class="pstrut" style="height: 3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="" style="top: -3.05001em;"><span class="pstrut" style="height: 3.05em;"></span><span class=""><span class="mop op-symbol large-op">∑</span></span></span><span class="" style="top: -4.30001em; margin-left: 0em;"><span class="pstrut" style="height: 3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.10903em;">N</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 1.27767em;"><span class=""></span></span></span></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;"><span class="delimsizing size4">(</span></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 1.427em;"><span class="" style="top: -2.314em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.69444em;"><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault">p</span></span></span><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="accent-body" style="left: -0.16666em;">^</span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.19444em;"><span class=""></span></span></span></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.311664em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">i</span><span class="mord mathdefault mtight" style="margin-right: 0.04398em;">z</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span><span class="" style="top: -3.23em;"><span class="pstrut" style="height: 3em;"></span><span class="frac-line" style="border-bottom-width: 0.04em;"></span></span><span class="" style="top: -3.677em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right: 0.10764em;">f</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.311664em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">i</span><span class="mord mathdefault mtight" style="margin-right: 0.04398em;">z</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.936em;"><span class=""></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right: 0.222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right: 0.222222em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;"><span class="delimsizing size4">(</span></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 1.32144em;"><span class="" style="top: -2.314em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right: 0.10903em;">M</span></span></span><span class="" style="top: -3.23em;"><span class="pstrut" style="height: 3em;"></span><span class="frac-line" style="border-bottom-width: 0.04em;"></span></span><span class="" style="top: -3.677em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.686em;"><span class=""></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 1.82834em;"><span class="" style="top: -1.87233em; margin-left: 0em;"><span class="pstrut" style="height: 3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="" style="top: -3.05001em;"><span class="pstrut" style="height: 3.05em;"></span><span class=""><span class="mop op-symbol large-op">∑</span></span></span><span class="" style="top: -4.30001em; margin-left: 0em;"><span class="pstrut" style="height: 3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.10903em;">M</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 1.41378em;"><span class=""></span></span></span></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord mathdefault" style="margin-right: 0.02691em;">w</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.311664em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">i</span><span class="mord mathdefault mtight" style="margin-right: 0.05724em;">j</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.286108em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">)</span></span><span class="mclose delimcenter" style="top: 0em;"><span class="delimsizing size4">)</span></span></span><span class="mclose delimcenter" style="top: 0em;"><span class="delimsizing size4">)</span></span></span></span><span class="tag"><span class="strut" style="height: 3.24211em; vertical-align: -1.41378em;"></span><span class="mord text"><span class="mord">(</span><span class="mord"><span class="mord">5</span></span><span class="mord">)</span></span></span></span></span></span></span></p>
<p>式 <em>(5)</em> の直感的な理解は、この推定量は pdf <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mover accent="true"><mi>p</mi><mo>^</mo></mover><mrow><mo fence="true">(</mo><msub><mi>x</mi><mi>z</mi></msub><mo fence="true">)</mo></mrow></mrow><annotation encoding="application/x-tex">\hat{p} \left( x_z \right)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 1em; vertical-align: -0.25em;"></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.69444em;"><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault">p</span></span></span><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="accent-body" style="left: -0.16666em;">^</span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.19444em;"><span class=""></span></span></span></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.151392em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right: 0.04398em;">z</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span></span></span> に従って <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>x</mi><mi>z</mi></msub></mrow><annotation encoding="application/x-tex">x_z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.58056em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.151392em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right: 0.04398em;">z</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span> をサンプリングしているように振る舞いますが、 実際には <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mover accent="true"><mi>p</mi><mo>^</mo></mover></mrow><annotation encoding="application/x-tex">\hat{p}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.88888em; vertical-align: -0.19444em;"></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.69444em;"><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault">p</span></span></span><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="accent-body" style="left: -0.16666em;">^</span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.19444em;"><span class=""></span></span></span></span></span></span></span></span></span> は正規化されておらず <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>x</mi><mi>z</mi></msub></mrow><annotation encoding="application/x-tex">x_z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.58056em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.151392em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right: 0.04398em;">z</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span> は <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mover accent="true"><mi>p</mi><mo>^</mo></mover></mrow><annotation encoding="application/x-tex">\hat{p}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.88888em; vertical-align: -0.19444em;"></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.69444em;"><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault">p</span></span></span><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="accent-body" style="left: -0.16666em;">^</span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.19444em;"><span class=""></span></span></span></span></span></span></span></span></span> では無く <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mover accent="true"><mi>p</mi><mo>^</mo></mover></mrow><annotation encoding="application/x-tex">\hat{p}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.88888em; vertical-align: -0.19444em;"></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.69444em;"><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault">p</span></span></span><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="accent-body" style="left: -0.16666em;">^</span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.19444em;"><span class=""></span></span></span></span></span></span></span></span></span> に近似した分布に従ってサンプリングされているため、 <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mfrac><mn>1</mn><mi>M</mi></mfrac><msubsup><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mi>M</mi></msubsup><mi>w</mi><mrow><mo fence="true">(</mo><msub><mi>x</mi><mi>j</mi></msub><mo fence="true">)</mo></mrow></mrow><annotation encoding="application/x-tex">\frac{1}{M} \sum_{j=1}^{M} w \left( x_j \right)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 1.41705em; vertical-align: -0.435818em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.845108em;"><span class="" style="top: -2.655em;"><span class="pstrut" style="height: 3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.10903em;">M</span></span></span></span><span class="" style="top: -3.23em;"><span class="pstrut" style="height: 3em;"></span><span class="frac-line" style="border-bottom-width: 0.04em;"></span></span><span class="" style="top: -3.394em;"><span class="pstrut" style="height: 3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.345em;"><span class=""></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position: relative; top: -5e-06em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.981231em;"><span class="" style="top: -2.40029em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="" style="top: -3.2029em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.10903em;">M</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.435818em;"><span class=""></span></span></span></span></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord mathdefault" style="margin-right: 0.02691em;">w</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.311664em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right: 0.05724em;">j</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.286108em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span></span></span> の項でその補正をかけている形になります。</p>
<p>式 <em>(5)</em> は <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>M</mi><mo>=</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">M=1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.68333em; vertical-align: 0em;"></span><span class="mord mathdefault" style="margin-right: 0.10903em;">M</span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 0.64444em; vertical-align: 0em;"></span><span class="mord">1</span></span></span></span></span> の時は <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>p</mi></mrow><annotation encoding="application/x-tex">p</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.625em; vertical-align: -0.19444em;"></span><span class="mord mathdefault">p</span></span></span></span></span> を使って <em>IS</em> しているのと同じになり、 <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>M</mi><mo>=</mo><mi mathvariant="normal">∞</mi></mrow><annotation encoding="application/x-tex">M=\infty</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.68333em; vertical-align: 0em;"></span><span class="mord mathdefault" style="margin-right: 0.10903em;">M</span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 0.43056em; vertical-align: 0em;"></span><span class="mord">∞</span></span></span></span></span> の時は <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mover accent="true"><mi>p</mi><mo>^</mo></mover></mrow><annotation encoding="application/x-tex">\hat{p}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.88888em; vertical-align: -0.19444em;"></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.69444em;"><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault">p</span></span></span><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="accent-body" style="left: -0.16666em;">^</span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.19444em;"><span class=""></span></span></span></span></span></span></span></span></span> を使って <em>IS</em> しているのと同じになります。 <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>M</mi></mrow><annotation encoding="application/x-tex">M</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.68333em; vertical-align: 0em;"></span><span class="mord mathdefault" style="margin-right: 0.10903em;">M</span></span></span></span></span> が大きくなるほど <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mover accent="true"><mi>p</mi><mo>^</mo></mover></mrow><annotation encoding="application/x-tex">\hat{p}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.88888em; vertical-align: -0.19444em;"></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.69444em;"><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault">p</span></span></span><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="accent-body" style="left: -0.16666em;">^</span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.19444em;"><span class=""></span></span></span></span></span></span></span></span></span> に近い分布で <em>IS</em> できますが計算量は多くなります。<br>
以下の図は[1]からの引用ですが、ソース pdf <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>p</mi></mrow><annotation encoding="application/x-tex">p</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.625em; vertical-align: -0.19444em;"></span><span class="mord mathdefault">p</span></span></span></span></span> を一様分布、ターゲット pdf <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mover accent="true"><mi>p</mi><mo>^</mo></mover></mrow><annotation encoding="application/x-tex">\hat{p}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.88888em; vertical-align: -0.19444em;"></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.69444em;"><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault">p</span></span></span><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="accent-body" style="left: -0.16666em;">^</span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.19444em;"><span class=""></span></span></span></span></span></span></span></span></span> を <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mover accent="true"><mi>p</mi><mo>^</mo></mover><mo>∝</mo><mi>c</mi><mi>o</mi><mi>s</mi><mrow><mo fence="true">(</mo><mi>θ</mi><mo fence="true">)</mo></mrow><mo>+</mo><mi>s</mi><mi>i</mi><msup><mi>n</mi><mn>4</mn></msup><mrow><mo fence="true">(</mo><mn>6</mn><mi>θ</mi><mo fence="true">)</mo></mrow></mrow><annotation encoding="application/x-tex">\hat{p} \propto cos \left( \theta \right) + sin^4 \left( 6 \theta \right)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.88888em; vertical-align: -0.19444em;"></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.69444em;"><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault">p</span></span></span><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="accent-body" style="left: -0.16666em;">^</span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.19444em;"><span class=""></span></span></span></span></span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">∝</span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 1em; vertical-align: -0.25em;"></span><span class="mord mathdefault">c</span><span class="mord mathdefault">o</span><span class="mord mathdefault">s</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord mathdefault" style="margin-right: 0.02778em;">θ</span><span class="mclose delimcenter" style="top: 0em;">)</span></span><span class="mspace" style="margin-right: 0.222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right: 0.222222em;"></span></span><span class="base"><span class="strut" style="height: 1.06411em; vertical-align: -0.25em;"></span><span class="mord mathdefault">s</span><span class="mord mathdefault">i</span><span class="mord"><span class="mord mathdefault">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height: 0.814108em;"><span class="" style="top: -3.063em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">4</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord">6</span><span class="mord mathdefault" style="margin-right: 0.02778em;">θ</span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span></span></span> として <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>M</mi></mrow><annotation encoding="application/x-tex">M</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.68333em; vertical-align: 0em;"></span><span class="mord mathdefault" style="margin-right: 0.10903em;">M</span></span></span></span></span> を変化させた時の <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>x</mi><mi>z</mi></msub></mrow><annotation encoding="application/x-tex">x_z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.58056em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.151392em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right: 0.04398em;">z</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span> の分布を表しています、</p>
<p><img src="https://lh3.googleusercontent.com/pw/ACtC-3cRTyJR0SP5CQqZg2DmRx5v92wuuTqwPB7hXFJEs5wTa01t517tt9FmYxcOPebyeqeRCA3-AKTh--5fXxHEcfXE2N7ofUhpJMohlXgMGxY6S1IRUj7thm6IYzFvw8QPh49NXqHGy8p1c6E9DtYBmNFd=w640-no" alt=""></p>
<p><em>RIS</em> は <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>M</mi><mo separator="true">,</mo><mi>N</mi><mo>≥</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">M,N \ge 1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.87777em; vertical-align: -0.19444em;"></span><span class="mord mathdefault" style="margin-right: 0.10903em;">M</span><span class="mpunct">,</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord mathdefault" style="margin-right: 0.10903em;">N</span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 0.64444em; vertical-align: 0em;"></span><span class="mord">1</span></span></span></span></span> かつ <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>f</mi><mrow><mo fence="true">(</mo><mi>x</mi><mo fence="true">)</mo></mrow><mi mathvariant="normal">≠</mi><mn>0</mn></mrow><annotation encoding="application/x-tex">f \left( x \right) \neq 0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 1em; vertical-align: -0.25em;"></span><span class="mord mathdefault" style="margin-right: 0.10764em;">f</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord mathdefault">x</span><span class="mclose delimcenter" style="top: 0em;">)</span></span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel"><span class="mrel"><span class="mord"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.69444em;"><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="rlap"><span class="strut" style="height: 0.88888em; vertical-align: -0.19444em;"></span><span class="inner"><span class="mrel"></span></span><span class="fix"></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.19444em;"><span class=""></span></span></span></span></span></span><span class="mrel">=</span></span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 0.64444em; vertical-align: 0em;"></span><span class="mord">0</span></span></span></span></span> となる <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.43056em; vertical-align: 0em;"></span><span class="mord mathdefault">x</span></span></span></span></span> に対して常に <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>p</mi><mrow><mo fence="true">(</mo><mi>x</mi><mo fence="true">)</mo></mrow><mo>></mo><mn>0</mn><mo separator="true">,</mo><mover accent="true"><mi>p</mi><mo>^</mo></mover><mrow><mo fence="true">(</mo><mi>x</mi><mo fence="true">)</mo></mrow><mo>></mo><mn>0</mn></mrow><annotation encoding="application/x-tex">p \left( x \right) \gt 0, \hat{p} \left( x \right) \gt 0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 1em; vertical-align: -0.25em;"></span><span class="mord mathdefault">p</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord mathdefault">x</span><span class="mclose delimcenter" style="top: 0em;">)</span></span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">></span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 1em; vertical-align: -0.25em;"></span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.69444em;"><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault">p</span></span></span><span class="" style="top: -3em;"><span class="pstrut" style="height: 3em;"></span><span class="accent-body" style="left: -0.16666em;">^</span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.19444em;"><span class=""></span></span></span></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord mathdefault">x</span><span class="mclose delimcenter" style="top: 0em;">)</span></span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">></span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 0.64444em; vertical-align: 0em;"></span><span class="mord">0</span></span></span></span></span> となる場合に unbiased となります。</p>
<h2 id="weighted-reservoir-sampling">Weighted Reservoir Sampling</h2>
<p><em>RIS</em> を行う際に候補サンプルを一度に全て保持しようとすると <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>M</mi></mrow><annotation encoding="application/x-tex">M</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.68333em; vertical-align: 0em;"></span><span class="mord mathdefault" style="margin-right: 0.10903em;">M</span></span></span></span></span> 個分の候補サンプルのメモリ容量が必要となります。 <em>Weighted Reservoir Sampling</em> (以降 <em>WRS</em> と表記) を <em>RIS</em> と組み合わせることで <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>M</mi></mrow><annotation encoding="application/x-tex">M</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.68333em; vertical-align: 0em;"></span><span class="mord mathdefault" style="margin-right: 0.10903em;">M</span></span></span></span></span> 個の候補の中から <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.43056em; vertical-align: 0em;"></span><span class="mord mathdefault">n</span></span></span></span></span> 個を選択する場合 <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>n</mi><mo stretchy="false">(</mo><mo>+</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">n (+1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 1em; vertical-align: -0.25em;"></span><span class="mord mathdefault">n</span><span class="mopen">(</span><span class="mord">+</span><span class="mord">1</span><span class="mclose">)</span></span></span></span></span> 個分のメモリ消費のみで行うことができます。ここでは <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>n</mi><mo>=</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">n=1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.43056em; vertical-align: 0em;"></span><span class="mord mathdefault">n</span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 0.64444em; vertical-align: 0em;"></span><span class="mord">1</span></span></span></span></span> とした場合、つまり候補サンプルの中から1個を選択する場合について説明します。<br>
<em>WRS</em> は事前に候補数 <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>M</mi></mrow><annotation encoding="application/x-tex">M</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.68333em; vertical-align: 0em;"></span><span class="mord mathdefault" style="margin-right: 0.10903em;">M</span></span></span></span></span> を知っておく必要は無く、 <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mo fence="true">{</mo><msub><mi>x</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>x</mi><mn>2</mn></msub><mo separator="true">,</mo><mo>…</mo><mo separator="true">,</mo><msub><mi>x</mi><mi>M</mi></msub><mo fence="true">}</mo></mrow><annotation encoding="application/x-tex">\left\{ x_1, x_2, \ldots, x_M \right\}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 1em; vertical-align: -0.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">{</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.301108em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.301108em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner">…</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.328331em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right: 0.10903em;">M</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">}</span></span></span></span></span></span> を全て保持しておく必要もありません。例えば候補サンプルが <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>x</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">x_1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.58056em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.301108em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span> から順にストリーミング入力されて総数 <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>M</mi></mrow><annotation encoding="application/x-tex">M</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.68333em; vertical-align: 0em;"></span><span class="mord mathdefault" style="margin-right: 0.10903em;">M</span></span></span></span></span> がわからない場合でも 1 個を選択することができます。</p>
<p><em>WRS</em> では候補サンプルを <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>x</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">x_1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.58056em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.301108em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span> から順に処理していき、 <em>resevoir</em> と呼ぶ入れ物 (ここでは候補サンプル 1 個分のメモリ容量) に確率的に挿入 (既に他の候補が入っている場合は交換)していきます。 <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>x</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">x_1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.58056em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.301108em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span> から処理を始め <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.43056em; vertical-align: 0em;"></span><span class="mord mathdefault">m</span></span></span></span></span> 番目の <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>x</mi><mi>m</mi></msub></mrow><annotation encoding="application/x-tex">x_m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.58056em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.151392em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span> までの処理を行っている時、 <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>x</mi><mi>i</mi></msub></mrow><annotation encoding="application/x-tex">x_i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.58056em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.311664em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span> が <em>reservoir</em> に入っている確率は <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mfrac><mrow><mi>w</mi><mrow><mo fence="true">(</mo><msub><mi>x</mi><mi>i</mi></msub><mo fence="true">)</mo></mrow></mrow><mrow><msubsup><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mi>w</mi><mrow><mo fence="true">(</mo><msub><mi>x</mi><mi>j</mi></msub><mo fence="true">)</mo></mrow></mrow></mfrac></mrow><annotation encoding="application/x-tex">\frac{w \left( x_i \right)}{\sum_{j=1}^{m} w \left( x_j \right)}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 1.67723em; vertical-align: -0.667227em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 1.01em;"><span class="" style="top: -2.655em;"><span class="pstrut" style="height: 3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mop mtight"><span class="mop op-symbol small-op mtight" style="position: relative; top: -5e-06em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.704686em;"><span class="" style="top: -2.17856em; margin-left: 0em; margin-right: 0.0714286em;"><span class="pstrut" style="height: 2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="" style="top: -2.89714em; margin-right: 0.0714286em;"><span class="pstrut" style="height: 2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">m</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.460324em;"><span class=""></span></span></span></span></span></span><span class="mspace mtight" style="margin-right: 0.195167em;"></span><span class="mord mathdefault mtight" style="margin-right: 0.02691em;">w</span><span class="minner mtight"><span class="mopen mtight delimcenter" style="top: 0em;"><span class="mtight">(</span></span><span class="mord mtight"><span class="mord mathdefault mtight">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.328086em;"><span class="" style="top: -2.357em; margin-left: 0em; margin-right: 0.0714286em;"><span class="pstrut" style="height: 2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathdefault mtight" style="margin-right: 0.05724em;">j</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.281886em;"><span class=""></span></span></span></span></span></span><span class="mclose mtight delimcenter" style="top: 0em;"><span class="mtight">)</span></span></span></span></span></span><span class="" style="top: -3.23em;"><span class="pstrut" style="height: 3em;"></span><span class="frac-line" style="border-bottom-width: 0.04em;"></span></span><span class="" style="top: -3.485em;"><span class="pstrut" style="height: 3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.02691em;">w</span><span class="minner mtight"><span class="mopen mtight delimcenter" style="top: 0em;"><span class="mtight">(</span></span><span class="mord mtight"><span class="mord mathdefault mtight">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.328086em;"><span class="" style="top: -2.357em; margin-left: 0em; margin-right: 0.0714286em;"><span class="pstrut" style="height: 2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathdefault mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.143em;"><span class=""></span></span></span></span></span></span><span class="mclose mtight delimcenter" style="top: 0em;"><span class="mtight">)</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.667227em;"><span class=""></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span> です。ここで用いる <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>w</mi><mrow><mo fence="true">(</mo><mi>x</mi><mo fence="true">)</mo></mrow></mrow><annotation encoding="application/x-tex">w \left( x \right)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 1em; vertical-align: -0.25em;"></span><span class="mord mathdefault" style="margin-right: 0.02691em;">w</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord mathdefault">x</span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span></span></span> は <em>RIS</em> で用いる重みと同じものです。次の <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>x</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msub></mrow><annotation encoding="application/x-tex">x_{m+1}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.638891em; vertical-align: -0.208331em;"></span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.301108em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.208331em;"><span class=""></span></span></span></span></span></span></span></span></span></span> の処理では、<em>reservoir</em> に入っているものと以下の確率で交換します、</p>
<p><span class="katex--display"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math><semantics><mtable width="100%"><mtr><mtd width="50%"></mtd><mtd><mfrac><mrow><mi>w</mi><mrow><mo fence="true">(</mo><msub><mi>x</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msub><mo fence="true">)</mo></mrow></mrow><mrow><munderover><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></munderover><mi>w</mi><mrow><mo fence="true">(</mo><msub><mi>x</mi><mi>j</mi></msub><mo fence="true">)</mo></mrow></mrow></mfrac></mtd><mtd width="50%"></mtd><mtd><mtext>(6)</mtext></mtd></mtr></mtable><annotation encoding="application/x-tex">
\frac{w \left( x_{m+1} \right)}{\sum_{j=1}^{m+1} w \left( x_j \right)}
\tag{6}
</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 2.70683em; vertical-align: -1.27983em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 1.427em;"><span class="" style="top: -2.15599em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mop"><span class="mop op-symbol small-op" style="position: relative; top: -5e-06em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.954008em;"><span class="" style="top: -2.40029em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="" style="top: -3.2029em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.435818em;"><span class=""></span></span></span></span></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord mathdefault" style="margin-right: 0.02691em;">w</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.311664em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right: 0.05724em;">j</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.286108em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span><span class="" style="top: -3.23em;"><span class="pstrut" style="height: 3em;"></span><span class="frac-line" style="border-bottom-width: 0.04em;"></span></span><span class="" style="top: -3.677em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right: 0.02691em;">w</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.301108em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.208331em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 1.27983em;"><span class=""></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span><span class="tag"><span class="strut" style="height: 2.70683em; vertical-align: -1.27983em;"></span><span class="mord text"><span class="mord">(</span><span class="mord"><span class="mord">6</span></span><span class="mord">)</span></span></span></span></span></span></span></p>
<p>式 <em>(6)</em> から逆に <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>x</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msub></mrow><annotation encoding="application/x-tex">x_{m+1}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.638891em; vertical-align: -0.208331em;"></span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.301108em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.208331em;"><span class=""></span></span></span></span></span></span></span></span></span></span> が <em>reservoir</em> に入らず <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>x</mi><mi>i</mi></msub></mrow><annotation encoding="application/x-tex">x_i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.58056em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.311664em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span> が 残っている確率は、</p>
<p><span class="katex--display"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math><semantics><mtable width="100%"><mtr><mtd width="50%"></mtd><mtd><mrow><mfrac><mrow><mi>w</mi><mrow><mo fence="true">(</mo><msub><mi>x</mi><mi>i</mi></msub><mo fence="true">)</mo></mrow></mrow><mrow><munderover><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mi>m</mi></munderover><mi>w</mi><mrow><mo fence="true">(</mo><msub><mi>x</mi><mi>j</mi></msub><mo fence="true">)</mo></mrow></mrow></mfrac><mrow><mo fence="true">(</mo><mn>1</mn><mo>−</mo><mfrac><mrow><mi>w</mi><mrow><mo fence="true">(</mo><msub><mi>x</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msub><mo fence="true">)</mo></mrow></mrow><mrow><munderover><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></munderover><mi>w</mi><mrow><mo fence="true">(</mo><msub><mi>x</mi><mi>j</mi></msub><mo fence="true">)</mo></mrow></mrow></mfrac><mo fence="true">)</mo></mrow><mo>=</mo><mfrac><mrow><mi>w</mi><mrow><mo fence="true">(</mo><msub><mi>x</mi><mi>i</mi></msub><mo fence="true">)</mo></mrow></mrow><mrow><munderover><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></munderover><mi>w</mi><mrow><mo fence="true">(</mo><msub><mi>x</mi><mi>j</mi></msub><mo fence="true">)</mo></mrow></mrow></mfrac></mrow></mtd><mtd width="50%"></mtd><mtd><mtext>(7)</mtext></mtd></mtr></mtable><annotation encoding="application/x-tex">
\frac{w \left( x_i \right)}{\sum_{j=1}^{m} w \left( x_j \right)} \left(
1 - \frac{w \left( x_{m+1} \right)}{\sum_{j=1}^{m+1} w \left( x_j \right)} \right)
= \frac{w \left( x_i \right)}{\sum_{j=1}^{m+1} w \left( x_j \right)}
\tag{7}
</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 3.02983em; vertical-align: -1.27983em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 1.427em;"><span class="" style="top: -2.30571em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mop"><span class="mop op-symbol small-op" style="position: relative; top: -5e-06em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.804292em;"><span class="" style="top: -2.40029em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="" style="top: -3.2029em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">m</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.435818em;"><span class=""></span></span></span></span></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord mathdefault" style="margin-right: 0.02691em;">w</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.311664em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right: 0.05724em;">j</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.286108em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span><span class="" style="top: -3.23em;"><span class="pstrut" style="height: 3em;"></span><span class="frac-line" style="border-bottom-width: 0.04em;"></span></span><span class="" style="top: -3.677em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right: 0.02691em;">w</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.311664em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 1.13011em;"><span class=""></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;"><span class="delimsizing size4">(</span></span><span class="mord">1</span><span class="mspace" style="margin-right: 0.222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right: 0.222222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 1.427em;"><span class="" style="top: -2.15599em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mop"><span class="mop op-symbol small-op" style="position: relative; top: -5e-06em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.954008em;"><span class="" style="top: -2.40029em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="" style="top: -3.2029em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.435818em;"><span class=""></span></span></span></span></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord mathdefault" style="margin-right: 0.02691em;">w</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.311664em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right: 0.05724em;">j</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.286108em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span><span class="" style="top: -3.23em;"><span class="pstrut" style="height: 3em;"></span><span class="frac-line" style="border-bottom-width: 0.04em;"></span></span><span class="" style="top: -3.677em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right: 0.02691em;">w</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.301108em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.208331em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 1.27983em;"><span class=""></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose delimcenter" style="top: 0em;"><span class="delimsizing size4">)</span></span></span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 2.70683em; vertical-align: -1.27983em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 1.427em;"><span class="" style="top: -2.15599em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mop"><span class="mop op-symbol small-op" style="position: relative; top: -5e-06em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.954008em;"><span class="" style="top: -2.40029em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="" style="top: -3.2029em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.435818em;"><span class=""></span></span></span></span></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord mathdefault" style="margin-right: 0.02691em;">w</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.311664em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right: 0.05724em;">j</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.286108em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span><span class="" style="top: -3.23em;"><span class="pstrut" style="height: 3em;"></span><span class="frac-line" style="border-bottom-width: 0.04em;"></span></span><span class="" style="top: -3.677em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right: 0.02691em;">w</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.311664em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 1.27983em;"><span class=""></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span><span class="tag"><span class="strut" style="height: 3.02983em; vertical-align: -1.27983em;"></span><span class="mord text"><span class="mord">(</span><span class="mord"><span class="mord">7</span></span><span class="mord">)</span></span></span></span></span></span></span></p>
<p>となります。<span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>m</mi><mo>+</mo><mn>1</mn><mo>=</mo><mi>M</mi></mrow><annotation encoding="application/x-tex">m+1=M</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.66666em; vertical-align: -0.08333em;"></span><span class="mord mathdefault">m</span><span class="mspace" style="margin-right: 0.222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right: 0.222222em;"></span></span><span class="base"><span class="strut" style="height: 0.64444em; vertical-align: 0em;"></span><span class="mord">1</span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 0.68333em; vertical-align: 0em;"></span><span class="mord mathdefault" style="margin-right: 0.10903em;">M</span></span></span></span></span> まで処理が終了した段階で <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>x</mi><mi>i</mi></msub></mrow><annotation encoding="application/x-tex">x_i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.58056em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.311664em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span> が <em>reservoir</em> に入っている確率は、</p>
<p><span class="katex--display"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math><semantics><mtable width="100%"><mtr><mtd width="50%"></mtd><mtd><mfrac><mrow><mi>w</mi><mrow><mo fence="true">(</mo><msub><mi>x</mi><mi>i</mi></msub><mo fence="true">)</mo></mrow></mrow><mrow><munderover><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mi>M</mi></munderover><mi>w</mi><mrow><mo fence="true">(</mo><msub><mi>x</mi><mi>j</mi></msub><mo fence="true">)</mo></mrow></mrow></mfrac></mtd><mtd width="50%"></mtd><mtd><mtext>(8)</mtext></mtd></mtr></mtable><annotation encoding="application/x-tex">
\frac{w \left( x_i \right)}{\sum_{j=1}^{M} w \left( x_j \right)}
\tag{8}
</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 2.73405em; vertical-align: -1.30705em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 1.427em;"><span class="" style="top: -2.12877em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mop"><span class="mop op-symbol small-op" style="position: relative; top: -5e-06em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.981231em;"><span class="" style="top: -2.40029em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="" style="top: -3.2029em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.10903em;">M</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.435818em;"><span class=""></span></span></span></span></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord mathdefault" style="margin-right: 0.02691em;">w</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.311664em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right: 0.05724em;">j</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.286108em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span><span class="" style="top: -3.23em;"><span class="pstrut" style="height: 3em;"></span><span class="frac-line" style="border-bottom-width: 0.04em;"></span></span><span class="" style="top: -3.677em;"><span class="pstrut" style="height: 3em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right: 0.02691em;">w</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.311664em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 1.30705em;"><span class=""></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span><span class="tag"><span class="strut" style="height: 2.73405em; vertical-align: -1.30705em;"></span><span class="mord text"><span class="mord">(</span><span class="mord"><span class="mord">8</span></span><span class="mord">)</span></span></span></span></span></span></span></p>
<p>となり式 <em>(4)</em> と同じ形となります。このことから <em>RIS</em> と <em>WRS</em> を組み合わせても <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>x</mi><mi>z</mi></msub></mrow><annotation encoding="application/x-tex">x_z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.58056em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.151392em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right: 0.04398em;">z</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span> の分布を変えずにサンプリングできることがわかります。また、必要なメモリ容量を <em>reservoir</em> 分と重みの和 <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msubsup><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mi>w</mi><mrow><mo fence="true">(</mo><msub><mi>x</mi><mi>j</mi></msub><mo fence="true">)</mo></mrow></mrow><annotation encoding="application/x-tex">\sum_{j=1}^{m} w \left( x_j \right)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 1.24011em; vertical-align: -0.435818em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position: relative; top: -5e-06em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.804292em;"><span class="" style="top: -2.40029em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="" style="top: -3.2029em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">m</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.435818em;"><span class=""></span></span></span></span></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord mathdefault" style="margin-right: 0.02691em;">w</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.311664em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right: 0.05724em;">j</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.286108em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span></span></span> を保持する分のみに削減できます。</p>
<h2 id="終わりに">終わりに</h2>
<p><em>RIS</em> と <em>WRS</em> について調べましたが実はまだ試していません。以下の事についてまだ疑問が解決していないのでもう少し調べてみようと思っています。</p>
<ol>
<li><em>RIS</em> + <em>WRS</em> では乱数が多く必要になるが必要な個数を削減する方法はあるか</li>
<li><em>RIS</em> と他のサンプリング戦略の <em>Multiple Importance Sampling</em> (<em>MIS</em>) を行う際の <em>RIS</em> 戦略の pdf を決定論的に計算する方法はあるか</li>
</ol>
<p><strong>1</strong> については、通常の <em>IS</em> が <em>逆CDF</em> を用いてサンプリングする際に乱数を 1 個使うのに対し、 <em>RIS</em> + <em>WRS</em> では候補サンプルのサンプリングや <em>reservoir</em> への確率的交換で多くの乱数を必要とします。何か必要な乱数の数を減らす方法はないでしょうか。<br>
<strong>2</strong> については、式 <em>(5)</em> から <em>RIS</em> で用いる pdf を <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>p</mi><mrow><mi>r</mi><mi>i</mi><mi>s</mi></mrow></msub><mrow><mo fence="true">(</mo><msub><mi>x</mi><mi>z</mi></msub><mo fence="true">)</mo></mrow><mo>=</mo><mfrac><mrow><mover accent="true"><mi>p</mi><mo>^</mo></mover><mrow><mo fence="true">(</mo><msub><mi>x</mi><mi>z</mi></msub><mo fence="true">)</mo></mrow></mrow><mrow><mfrac><mn>1</mn><mi>M</mi></mfrac><msubsup><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mi>M</mi></msubsup><mi>w</mi><mrow><mo fence="true">(</mo><msub><mi>x</mi><mi>j</mi></msub><mo fence="true">)</mo></mrow></mrow></mfrac></mrow><annotation encoding="application/x-tex">p_{ris} \left( x_z \right) = \frac{\hat{p} \left( x_{z} \right)}{\frac{1}{M} \sum_{j=1}^{M} w \left( x_{j} \right)}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 1em; vertical-align: -0.25em;"></span><span class="mord"><span class="mord mathdefault">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.311664em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.02778em;">r</span><span class="mord mathdefault mtight">i</span><span class="mord mathdefault mtight">s</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.151392em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right: 0.04398em;">z</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">)</span></span><span class="mspace" style="margin-right: 0.277778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right: 0.277778em;"></span></span><span class="base"><span class="strut" style="height: 1.76189em; vertical-align: -0.751892em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 1.01em;"><span class="" style="top: -2.57034em;"><span class="pstrut" style="height: 3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mopen nulldelimiter sizing reset-size3 size6"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.844314em;"><span class="" style="top: -2.656em;"><span class="pstrut" style="height: 3em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.10903em;">M</span></span></span></span><span class="" style="top: -3.2255em;"><span class="pstrut" style="height: 3em;"></span><span class="frac-line mtight" style="border-bottom-width: 0.049em;"></span></span><span class="" style="top: -3.384em;"><span class="pstrut" style="height: 3em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.344em;"><span class=""></span></span></span></span></span><span class="mclose nulldelimiter sizing reset-size3 size6"></span></span><span class="mspace mtight" style="margin-right: 0.195167em;"></span><span class="mop mtight"><span class="mop op-symbol small-op mtight" style="position: relative; top: -5e-06em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.885236em;"><span class="" style="top: -2.17856em; margin-left: 0em; margin-right: 0.0714286em;"><span class="pstrut" style="height: 2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="" style="top: -2.89714em; margin-right: 0.0714286em;"><span class="pstrut" style="height: 2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.10903em;">M</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.460324em;"><span class=""></span></span></span></span></span></span><span class="mspace mtight" style="margin-right: 0.195167em;"></span><span class="mord mathdefault mtight" style="margin-right: 0.02691em;">w</span><span class="minner mtight"><span class="mopen mtight delimcenter" style="top: 0em;"><span class="mtight">(</span></span><span class="mord mtight"><span class="mord mathdefault mtight">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.328086em;"><span class="" style="top: -2.357em; margin-left: 0em; margin-right: 0.0714286em;"><span class="pstrut" style="height: 2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.05724em;">j</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.281886em;"><span class=""></span></span></span></span></span></span><span class="mclose mtight delimcenter" style="top: 0em;"><span class="mtight">)</span></span></span></span></span></span><span class="" style="top: -3.23em;"><span class="pstrut" style="height: 3em;"></span><span class="frac-line" style="border-bottom-width: 0.04em;"></span></span><span class="" style="top: -3.485em;"><span class="pstrut" style="height: 3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord accent mtight"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.69444em;"><span class="" style="top: -2.7em;"><span class="pstrut" style="height: 2.7em;"></span><span class="mord mtight"><span class="mord mathdefault mtight">p</span></span></span><span class="" style="top: -2.7em;"><span class="pstrut" style="height: 2.7em;"></span><span class="accent-body" style="left: -0.16666em;"><span class="mtight">^</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.19444em;"><span class=""></span></span></span></span></span><span class="minner mtight"><span class="mopen mtight delimcenter" style="top: 0em;"><span class="mtight">(</span></span><span class="mord mtight"><span class="mord mathdefault mtight">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.164543em;"><span class="" style="top: -2.357em; margin-left: 0em; margin-right: 0.0714286em;"><span class="pstrut" style="height: 2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.04398em;">z</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.143em;"><span class=""></span></span></span></span></span></span><span class="mclose mtight delimcenter" style="top: 0em;"><span class="mtight">)</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.751892em;"><span class=""></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span> とすると、例えば <em>MIS</em> 時に <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>x</mi><mi>z</mi></msub></mrow><annotation encoding="application/x-tex">x_z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.58056em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.151392em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right: 0.04398em;">z</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span> から <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>p</mi><mrow><mi>r</mi><mi>i</mi><mi>s</mi></mrow></msub><mrow><mo fence="true">(</mo><msub><mi>x</mi><mi>z</mi></msub><mo fence="true">)</mo></mrow></mrow><annotation encoding="application/x-tex">p_{ris} \left( x_z \right)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 1em; vertical-align: -0.25em;"></span><span class="mord"><span class="mord mathdefault">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.311664em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.02778em;">r</span><span class="mord mathdefault mtight">i</span><span class="mord mathdefault mtight">s</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.151392em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right: 0.04398em;">z</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span></span></span> を評価する際に <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msubsup><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mi>M</mi></msubsup><mi>w</mi><mrow><mo fence="true">(</mo><msub><mi>x</mi><mi>j</mi></msub><mo fence="true">)</mo></mrow></mrow><annotation encoding="application/x-tex">\sum_{j=1}^{M} w \left( x_{j} \right)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 1.41705em; vertical-align: -0.435818em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position: relative; top: -5e-06em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.981231em;"><span class="" style="top: -2.40029em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="" style="top: -3.2029em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.10903em;">M</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.435818em;"><span class=""></span></span></span></span></span></span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="mord mathdefault" style="margin-right: 0.02691em;">w</span><span class="mspace" style="margin-right: 0.166667em;"></span><span class="minner"><span class="mopen delimcenter" style="top: 0em;">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.311664em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.05724em;">j</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.286108em;"><span class=""></span></span></span></span></span></span><span class="mclose delimcenter" style="top: 0em;">)</span></span></span></span></span></span> を計算するために乱数を用いて他の候補をサンプルをサンプリングする事になると思います。もっと決定論的に <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>p</mi><mrow><mi>r</mi><mi>i</mi><mi>s</mi></mrow></msub></mrow><annotation encoding="application/x-tex">p_{ris}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height: 0.625em; vertical-align: -0.19444em;"></span><span class="mord"><span class="mord mathdefault">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.311664em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right: 0.02778em;">r</span><span class="mord mathdefault mtight">i</span><span class="mord mathdefault mtight">s</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span> を評価する方法はないでしょうか。</p>
<h2 id="参考文献">参考文献</h2>
<ol>
<li>Talbot J, Cline D, Egbert P: <em>Importance Resampling for Global Illumination</em> (2005)</li>
<li>Efraimidis PS, Spirakis PG: <em>Weighted Random Sampling with a Reservoir</em> (2006)</li>
<li>Efraimidis PS: <em>Weighted Random Sampling over Data Streams</em> (2015)</li>
<li>Bitterli B, Wyman C, Pharr M, Shirley P, Lefohn A, Jarosz W: <em>Spatiotemporal Reservoir Resampling for Real-Time Ray Tracing with Dynamic Direct Lighting</em> (2020)</li>
</ol>
</div>
</body>
</html>
Zinhttp://www.blogger.com/profile/00473704352385380653noreply@blogger.com0tag:blogger.com,1999:blog-5029251693178115279.post-72103221536608782012019-12-24T01:48:00.000+09:002019-12-24T10:38:05.103+09:00clspvを用いてopenclカーネルをvulkanで実行する<h1 id="clspvを用いてopenclカーネルをvulkanで実行する">Clspvを用いてOpenCLカーネルをVulkanで実行する</h1>
<p>こんにちは。このページは <a href="https://qiita.com/advent-calendar/2019/raytracing">レイトレ Advent Calendar 2019</a> の19日目の記事です。この記事では以下の事について紹介します、</p>
<ul>
<li>Vulkan SDK と Clspv のインストール</li>
<li>Clspv で OpenCL カーネルをビルド</li>
<li>ビルドした カーネルを Vulkan で実行する際の注意事項</li>
</ul>
<p>この記事では Vulkan 仕様や API の使い方については説明しません。Vulkan Compute Shader の使い方は Clspv を使った場合でも特別な事は無いため、他の資料などを参考にしてもらえればと思います。</p>
<p>Clspv を使った Vulkan のサンプルコードは <a href="https://github.com/byzin/VulkanClspvTest">github</a> にアップロードしていますので参考にしてください。</p>
<h2 id="vulkan-sdk-のインストール">Vulkan SDK のインストール</h2>
<p>まずは、下記のページから最新の Vulkan SDK をダウンロードします。</p>
<ul>
<li><a href="https://vulkan.lunarg.com/sdk/home">Vulkan.Lunarg.com</a></li>
</ul>
<p>SDKのインストール方法は Windows、Linux、macOS で異なります。</p>
<h3 id="windows">Windows</h3>
<p>ダウンロードしたインストーラーを起動しそのままインストールします。インストールが完了したら <code>VULKAN_SDK</code> という環境変数が作られ、Vulkan SDK へのパスが設定されます。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQul1yQInkWto654O9X_ZXiVPvbSuIXeXT5M3uIMk2ckKjkdOJ3-OEpfZQY0PbXSJxO_t5E9JXyj6XLqtuv3ZJwlS8e5KNsAE_Z6TRfg_BOyHUnxmWLFqVWqGw3lvyH412vNSwCJYsr9k/w430-no/" alt="Vulkan environment variable"></p>
<h3 id="linux">Linux</h3>
<p>ダウンロードした tar.gz を展開します。展開したディレクトリ内に <code>setup-env.sh</code> というファイルがあり、これをシェルに反映させると、SDK内のツールやライブラリへのパスを自動的に設定してくれます。また、 <code>VULKAN_SDK</code> という環境変数がつくられて、Vulkan SDKへのパスが設定されます。</p>
<pre class=" language-sh"><code class="prism language-sh">% source ${path-to-vulkan-sdk}/setup-env.sh
% echo ${VULKAN_SDK}
${path-to-vulkan-sdk}/x86_64
</code></pre>
<h3 id="macos">macOS</h3>
<p>ダウンロードした tar.gz を展開します。Linux版と違い展開したディレクトリ内に <code>setup-env.sh</code> が無いため以下のようなスクリプトを用意します。</p>
<pre class=" language-sh"><code class="prism language-sh">export VULKAN_SDK="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"/macOS
export PATH="${VULKAN_SDK}/bin:${PATH}"
export DYLD_LIBRARY_PATH="${VULKAN_SDK}/lib:${DYLD_LIBRARY_PATH}"
export VK_LAYER_PATH="${VULKAN_SDK}/etc/vulkan/explicit_layer.d"
export VK_ICD_FILENAMES="${VULKAN_SDK}/etc/vulkan/icd.d/MoltenVK_icd.json"
</code></pre>
<p>このスクリプトを展開したディレクトリ内に置きシェルに反映させると、SDK内のツールやライブラリへのパスを自動的に設定してくれます。</p>
<h3 id="vulkan-sdk-の動作確認">Vulkan SDK の動作確認</h3>
<p>Vulkan SDK をインストールしたのできちんと動作するか確認します。動作確認には <code>vkvia</code> を用います。<code>vkvia</code> は簡単なVulkanアプリケーションをいくつか動かして、その時のVulkanの状態をキャプチャーします。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi37z543oHeZmqLWFDw1XXfCy2Hm1lkYMethMgQcGyJGrOFx4tK4spMkWVcIobr9J5HVdupcpNoZqoYlHmL6dgQm546lNrDi0eR9-IzwouR6DQ2MtJttJdaGUt_qxSscnzF6VygSKA0_DU/w300-no/" alt="vkvia1"></p>
<p><code>vkvia</code> は <code>${VULKAN_SDK}/bin/</code> にあります。実行すると実行ディレクトリに <code>vkvia.html</code> が作成され、ブラウザで開くとキャプチャーしたVulkanの状態を見ることができます。例えば、 <strong>Physical Devices</strong> を開くとVulkanで使用できるハードウェアデバイスの情報を見ることができます。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoP883sTXQevUAg7cO6C9_-kciszDNPxBJ7qorl1CEhYuplqoNfTgV48LjlhWYp6boE5Lr5-4bAg4bk5ecNO1e_zZlTBYiYWRtN1tDoMg6IewayBMSvVvME0SApe6WFUPvL34VQkRlyxk/w640-no/" alt="vkvia2"></p>
<h2 id="clspv-のインストール">Clspv のインストール</h2>
<p>Clspvにはリリースバージョンの実行ファイルやソースコードはまだありません。github の <a href="https://github.com/google/clspv">google/clspv</a> から master ブランチを pull してビルドします。ビルドするのに必要なツールはREADMEに書いてあるように、</p>
<ul>
<li>CMake</li>
<li>Python</li>
<li>C++ compiler</li>
<li>git</li>
</ul>
<p>になります。まずはClspvが依存する外部プロジェクトのソースコードをダウンロードします。</p>
<pre class=" language-sh"><code class="prism language-sh">% python utils/fetch_sources.py
</code></pre>
<p>ダウンロードした後は CMake を実行して Clspv のビルドの準備をします。Windows の場合は (Visual Studio 2019 を使う場合)、</p>
<pre class=" language-sh"><code class="prism language-sh">% cmake -G"Visual Studio 16 2019" -Ax64 -Thost=x64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${path-to-dir} ..
</code></pre>
<p><code>${path-to-dir}</code> にはインストール先のパスが入ります。<br>
Linux や macOS の場合は、</p>
<pre class=" language-sh"><code class="prism language-sh">% cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${path-to-install} ..
</code></pre>
<p>です。 CMake でジェネレーターファイルを作成したら Clspv をビルドします。</p>
<pre class=" language-sh"><code class="prism language-sh">% cmake --build . --config Release --target install --parallel 8
</code></pre>
<p>ビルドが完了すると <code>${path-to-dir}</code> に <code>clspv</code> という実行ファイルがインストールされます。</p>
<h2 id="clspv-で-opencl-コードをビルド">Clspv で OpenCL コードをビルド</h2>
<p>Clspv は OpenCL C 1.2 のコードをビルドすることができますが、Vulkan が扱うことができない機能については Clspv 側でビルドができないように制限がかけられています。制限内容の詳細は <a href="https://github.com/google/clspv/blob/master/docs/OpenCLCOnVulkan.md#opencl-c-restrictions">OpenCL C Restrictions</a> を読んで下さい。いくつかピックアップすると、</p>
<ul>
<li>8や16長のベクトルは使用できない ( <code>int8</code> など)</li>
<li><code>double</code> は使用できない</li>
<li><code>cbrt</code> 、 <code>pown</code> 、 <code>rint</code> 、 <code>sincos</code> など使用できない Math 関数がある</li>
<li><code>printf</code> は使用できない</li>
</ul>
<p>などがあります。ただ、これらの制限は将来 Vulkan の仕様のアップデートに合わせて緩和されるかもしれません。</p>
<p>では、実際に Clspv で以下の OpenCL C コードをビルドしてみます。</p>
<pre class=" language-opencl"><code class="prism language-opencl"><span class="token comment">// vulkan_clspv_test0.cl</span>
<span class="token keyword">__kernel</span> <span class="token keyword">void</span> <span class="token function">test</span><span class="token punctuation">(</span><span class="token keyword">__global</span> <span class="token keyword">const</span> <span class="token keyword">float4</span><span class="token operator">*</span> inputs<span class="token punctuation">,</span> <span class="token keyword">__global</span> <span class="token keyword">float4</span><span class="token operator">*</span> outputs<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">const</span> <span class="token keyword">uint</span> index <span class="token operator">=</span> <span class="token function">get_global_id</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
outputs<span class="token punctuation">[</span>index<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">sqrt</span><span class="token punctuation">(</span>inputs<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre>
<p>コマンドは以下のようになります。</p>
<pre class=" language-sh"><code class="prism language-sh">% clspv -o=vulkan_clspv_test0.spv vulkan_clspv_test0.cl
</code></pre>
<p><code>-o</code> オプションで出力する SPIR-V ファイルのファイル名を指定できます。その他にも最適化オプション <code>-O=3</code> などがあり、オプション一覧は <code>clspv --help</code> で見ることができます。</p>
<h3 id="opencl-c-のビルド">OpenCL C++ のビルド</h3>
<p>Clspv は実験的ですが OpenCL C++ をサポートします。現状 OpenCL C++ の仕様を完全にサポートしているわけではく、いくつかの違いはあります。例えば、</p>
<ul>
<li>OpenCL C++ Standard Library は使用できない
<ul>
<li>Mathライブラリなどは OpenCL C の組み込み関数スタイルの物を使用する</li>
</ul>
</li>
<li>C++14 ではなく C++17 ベース
<ul>
<li><code>constexpr if</code> や <code>fold expression</code> など C++17 の機能も使うことができる</li>
</ul>
</li>
</ul>
<p>等の違いがあります。Clspv で OpenCL C++ のコードをビルドする場合は <code>--c++ --inline-entry-points</code> オプションを付けてビルドします。例として、以下の OpenCL C++ コードをビルドしてみます。</p>
<pre class=" language-opencl"><code class="prism language-opencl"><span class="token comment">// vulkan_clspv_test1.cl</span>
namespace clspvtest <span class="token punctuation">{</span>
<span class="token comment">// Forward declaration</span>
<span class="token keyword">float</span> <span class="token function">sum</span><span class="token punctuation">(</span><span class="token keyword">const</span> <span class="token keyword">float</span> x<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">float</span> <span class="token function">sum</span><span class="token punctuation">(</span><span class="token keyword">const</span> <span class="token keyword">float4</span> x<span class="token punctuation">)</span><span class="token punctuation">;</span>
template <span class="token operator"><</span>typename<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> Types<span class="token operator">></span> <span class="token keyword">float</span> <span class="token function">sum</span><span class="token punctuation">(</span><span class="token keyword">const</span> Types<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span>
class Matrix4x4<span class="token punctuation">;</span>
Matrix4x4 operator<span class="token operator">+</span><span class="token punctuation">(</span><span class="token keyword">const</span> Matrix4x4<span class="token operator">&</span> lhs<span class="token punctuation">,</span> <span class="token keyword">const</span> Matrix4x4<span class="token operator">&</span> rhs<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">float</span> <span class="token function">sum</span><span class="token punctuation">(</span><span class="token keyword">const</span> <span class="token keyword">float</span> x<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">return</span> x<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">float</span> <span class="token function">sum</span><span class="token punctuation">(</span><span class="token keyword">const</span> <span class="token keyword">float4</span> x<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">const</span> <span class="token keyword">float</span> s <span class="token operator">=</span> x<span class="token punctuation">.</span>x <span class="token operator">+</span> x<span class="token punctuation">.</span>y <span class="token operator">+</span> x<span class="token punctuation">.</span>z <span class="token operator">+</span> x<span class="token punctuation">.</span>w<span class="token punctuation">;</span>
<span class="token keyword">return</span> s<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
template <span class="token operator"><</span>typename<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> Types<span class="token operator">></span>
<span class="token keyword">float</span> <span class="token function">sum</span><span class="token punctuation">(</span><span class="token keyword">const</span> Types<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> args<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token comment">// Clspv can build C++17 features</span>
<span class="token keyword">if</span> <span class="token function">constexpr</span> <span class="token punctuation">(</span><span class="token number">0</span> <span class="token operator"><</span> <span class="token keyword">sizeof</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">(</span>Types<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> <span class="token keyword">auto</span> s <span class="token operator">=</span> <span class="token punctuation">(</span>args <span class="token operator">+</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token function">sum</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">else</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token number">0.0f</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
class Matrix4x4
<span class="token punctuation">{</span>
public<span class="token punctuation">:</span>
<span class="token function">Matrix4x4</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token function">Matrix4x4</span><span class="token punctuation">(</span><span class="token keyword">const</span> <span class="token keyword">float4</span> r1<span class="token punctuation">,</span> <span class="token keyword">const</span> <span class="token keyword">float4</span> r2<span class="token punctuation">,</span> <span class="token keyword">const</span> <span class="token keyword">float4</span> r3<span class="token punctuation">,</span> <span class="token keyword">const</span> <span class="token keyword">float4</span> r4<span class="token punctuation">)</span> <span class="token punctuation">:</span>
r1_<span class="token punctuation">{</span>r1<span class="token punctuation">}</span><span class="token punctuation">,</span> r2_<span class="token punctuation">{</span>r2<span class="token punctuation">}</span><span class="token punctuation">,</span> r3_<span class="token punctuation">{</span>r3<span class="token punctuation">}</span><span class="token punctuation">,</span> r4_<span class="token punctuation">{</span>r4<span class="token punctuation">}</span>
<span class="token punctuation">{</span>
<span class="token punctuation">}</span>
<span class="token comment">//! Return the sum of the elements</span>
<span class="token keyword">float</span> <span class="token function">sum</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">const</span>
<span class="token punctuation">{</span>
<span class="token keyword">const</span> <span class="token keyword">float</span> s <span class="token operator">=</span> clspvtest<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">sum</span><span class="token punctuation">(</span>r1_<span class="token punctuation">,</span> r2_<span class="token punctuation">,</span> r3_<span class="token punctuation">,</span> r4_<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> s<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">float4</span> r1_ <span class="token operator">=</span> <span class="token keyword">float4</span><span class="token punctuation">{</span><span class="token number">0.0f</span><span class="token punctuation">,</span> <span class="token number">0.0f</span><span class="token punctuation">,</span> <span class="token number">0.0f</span><span class="token punctuation">,</span> <span class="token number">0.0f</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
r2_ <span class="token operator">=</span> <span class="token keyword">float4</span><span class="token punctuation">{</span><span class="token number">0.0f</span><span class="token punctuation">,</span> <span class="token number">0.0f</span><span class="token punctuation">,</span> <span class="token number">0.0f</span><span class="token punctuation">,</span> <span class="token number">0.0f</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
r3_ <span class="token operator">=</span> <span class="token keyword">float4</span><span class="token punctuation">{</span><span class="token number">0.0f</span><span class="token punctuation">,</span> <span class="token number">0.0f</span><span class="token punctuation">,</span> <span class="token number">0.0f</span><span class="token punctuation">,</span> <span class="token number">0.0f</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
r4_ <span class="token operator">=</span> <span class="token keyword">float4</span><span class="token punctuation">{</span><span class="token number">0.0f</span><span class="token punctuation">,</span> <span class="token number">0.0f</span><span class="token punctuation">,</span> <span class="token number">0.0f</span><span class="token punctuation">,</span> <span class="token number">0.0f</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token comment">//! Add corresponding elements of the given two matrices</span>
Matrix4x4 operator<span class="token operator">+</span><span class="token punctuation">(</span><span class="token keyword">const</span> Matrix4x4<span class="token operator">&</span> lhs<span class="token punctuation">,</span> <span class="token keyword">const</span> Matrix4x4<span class="token operator">&</span> rhs<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">const</span> Matrix4x4 result<span class="token punctuation">{</span>lhs<span class="token punctuation">.</span>r1_ <span class="token operator">+</span> rhs<span class="token punctuation">.</span>r1_<span class="token punctuation">,</span> lhs<span class="token punctuation">.</span>r2_ <span class="token operator">+</span> rhs<span class="token punctuation">.</span>r2_<span class="token punctuation">,</span> lhs<span class="token punctuation">.</span>r3_ <span class="token operator">+</span> rhs<span class="token punctuation">.</span>r3_<span class="token punctuation">,</span> lhs<span class="token punctuation">.</span>r4_ <span class="token operator">+</span> rhs<span class="token punctuation">.</span>r4_<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> result<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span> <span class="token comment">// namespace clspvtest </span>
<span class="token keyword">__kernel</span> <span class="token keyword">void</span> <span class="token function">testSummation</span><span class="token punctuation">(</span><span class="token keyword">__global</span> clspvtest<span class="token punctuation">:</span><span class="token punctuation">:</span>Matrix4x4<span class="token operator">*</span> value<span class="token punctuation">,</span> <span class="token keyword">__global</span> <span class="token keyword">float</span><span class="token operator">*</span> outputs<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">const</span> <span class="token keyword">uint</span> index <span class="token operator">=</span> <span class="token function">get_global_id</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token number">0</span> <span class="token operator"><</span> index<span class="token punctuation">)</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
<span class="token comment">// Check clspvtest::Matrix4x4</span>
<span class="token function">static_assert</span><span class="token punctuation">(</span><span class="token keyword">sizeof</span><span class="token punctuation">(</span>clspvtest<span class="token punctuation">:</span><span class="token punctuation">:</span>Matrix4x4<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">64</span><span class="token punctuation">,</span> <span class="token string">"The size of clspvtest::Matrix4x4 isn't 64 bytes."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">static_assert</span><span class="token punctuation">(</span><span class="token function">alignof</span><span class="token punctuation">(</span>clspvtest<span class="token punctuation">:</span><span class="token punctuation">:</span>Matrix4x4<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">16</span><span class="token punctuation">,</span> <span class="token string">"The alignment of clspvtest::Matrix4x4 isn't 16 bytes."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Constant value</span>
<span class="token keyword">__constant</span> constexpr <span class="token keyword">float</span> k <span class="token operator">=</span> <span class="token number">4.0f</span><span class="token punctuation">;</span> <span class="token comment">// constant value must be in the outermost scope of a kernel</span>
<span class="token function">static_assert</span><span class="token punctuation">(</span>k <span class="token operator">==</span> <span class="token number">4.0f</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
outputs<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">=</span> clspvtest<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">sum</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
outputs<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">=</span> clspvtest<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">sum</span><span class="token punctuation">(</span><span class="token function">sqrt</span><span class="token punctuation">(</span>k<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Use OpenCL C style built-in function</span>
outputs<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span> <span class="token operator">=</span> clspvtest<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">sum</span><span class="token punctuation">(</span><span class="token number">1.0f</span><span class="token punctuation">,</span> <span class="token number">2.0f</span><span class="token punctuation">,</span> <span class="token number">3.0f</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Matrix4x4 in registers</span>
<span class="token punctuation">{</span>
<span class="token keyword">__private</span> <span class="token keyword">const</span> clspvtest<span class="token punctuation">:</span><span class="token punctuation">:</span>Matrix4x4 m<span class="token punctuation">;</span>
outputs<span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">]</span> <span class="token operator">=</span> m<span class="token punctuation">.</span><span class="token function">sum</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">{</span>
<span class="token keyword">__private</span> <span class="token keyword">const</span> clspvtest<span class="token punctuation">:</span><span class="token punctuation">:</span>Matrix4x4 m<span class="token punctuation">{</span><span class="token keyword">float4</span><span class="token punctuation">{</span>k<span class="token punctuation">,</span> k<span class="token punctuation">,</span> k<span class="token punctuation">,</span> k<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token keyword">float4</span><span class="token punctuation">{</span>k<span class="token punctuation">,</span> k<span class="token punctuation">,</span> k<span class="token punctuation">,</span> k<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token keyword">float4</span><span class="token punctuation">{</span>k<span class="token punctuation">,</span> k<span class="token punctuation">,</span> k<span class="token punctuation">,</span> k<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token keyword">float4</span><span class="token punctuation">{</span>k<span class="token punctuation">,</span> k<span class="token punctuation">,</span> k<span class="token punctuation">,</span> k<span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
outputs<span class="token punctuation">[</span><span class="token number">4</span><span class="token punctuation">]</span> <span class="token operator">=</span> m<span class="token punctuation">.</span><span class="token function">sum</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// Matrix4x4 in global memory</span>
<span class="token punctuation">{</span>
<span class="token keyword">__private</span> <span class="token keyword">const</span> clspvtest<span class="token punctuation">:</span><span class="token punctuation">:</span>Matrix4x4 m1<span class="token punctuation">{</span><span class="token keyword">float4</span><span class="token punctuation">{</span>k<span class="token punctuation">,</span> k<span class="token punctuation">,</span> k<span class="token punctuation">,</span> k<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token keyword">float4</span><span class="token punctuation">{</span>k<span class="token punctuation">,</span> k<span class="token punctuation">,</span> k<span class="token punctuation">,</span> k<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token keyword">float4</span><span class="token punctuation">{</span>k<span class="token punctuation">,</span> k<span class="token punctuation">,</span> k<span class="token punctuation">,</span> k<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token keyword">float4</span><span class="token punctuation">{</span>k<span class="token punctuation">,</span> k<span class="token punctuation">,</span> k<span class="token punctuation">,</span> k<span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">__private</span> <span class="token keyword">const</span> clspvtest<span class="token punctuation">:</span><span class="token punctuation">:</span>Matrix4x4 m2<span class="token punctuation">{</span><span class="token keyword">float4</span><span class="token punctuation">{</span><span class="token number">0.0f</span><span class="token punctuation">,</span> <span class="token number">1.0f</span><span class="token punctuation">,</span> <span class="token number">2.0f</span><span class="token punctuation">,</span> <span class="token number">3.0f</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token keyword">float4</span><span class="token punctuation">{</span><span class="token number">4.0f</span><span class="token punctuation">,</span> <span class="token number">5.0f</span><span class="token punctuation">,</span> <span class="token number">6.0f</span><span class="token punctuation">,</span> <span class="token number">7.0f</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token keyword">float4</span><span class="token punctuation">{</span><span class="token number">8.0f</span><span class="token punctuation">,</span> <span class="token number">9.0f</span><span class="token punctuation">,</span> <span class="token number">10.0f</span><span class="token punctuation">,</span> <span class="token number">11.0f</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token keyword">float4</span><span class="token punctuation">{</span><span class="token number">12.0f</span><span class="token punctuation">,</span> <span class="token number">13.0f</span><span class="token punctuation">,</span> <span class="token number">14.0f</span><span class="token punctuation">,</span> <span class="token number">15.0f</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
value<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">=</span> m1 <span class="token operator">+</span> m2<span class="token punctuation">;</span> <span class="token comment">// Initialize global Matrix4x4</span>
outputs<span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span> <span class="token operator">=</span> value<span class="token operator">-></span><span class="token function">sum</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// Matrix4x4 in local memory</span>
<span class="token keyword">__local</span> clspvtest<span class="token punctuation">:</span><span class="token punctuation">:</span>Matrix4x4 storage<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">// local variable must be in the outermost scope of a kernel</span>
<span class="token punctuation">{</span>
<span class="token keyword">__private</span> <span class="token keyword">const</span> clspvtest<span class="token punctuation">:</span><span class="token punctuation">:</span>Matrix4x4 m <span class="token operator">=</span> value<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
storage<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">=</span> m<span class="token punctuation">;</span>
outputs<span class="token punctuation">[</span><span class="token number">6</span><span class="token punctuation">]</span> <span class="token operator">=</span> storage<span class="token operator">-></span><span class="token function">sum</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre>
<p>以下のコマンドでビルドします。</p>
<pre class=" language-sh"><code class="prism language-sh">% clspv --c++ --inline-entry-points -o=vulkan_clspv_test1.spv vulkan_clspv_test1.cl
</code></pre>
<p>ビルドが成功して SPIR-V ファイルが生成されます。実行結果も以下のように、</p>
<pre class=" language-sh"><code class="prism language-sh">output[0] = 0
output[1] = 2
output[2] = 6
output[3] = 0
output[4] = 64
output[5] = 184
output[6] = 184
</code></pre>
<p>正しく実行されています。( github のサンプルコードをビルドすると実行できます。)</p>
<h2 id="vulkan-で-opencl-カーネルを実行する">Vulkan で OpenCL カーネルを実行する</h2>
<p>Clspv で生成した SPIR-V コードは Vulkan Compute Shader で実行できます。SPIR-V コードの実行方法は通常の方法と変わらないためここでは省略します。Clspv の SPIR-V を実行する上で気をつける点がいくつかあり、詳細については <a href="https://github.com/google/clspv/blob/master/docs/OpenCLCOnVulkan.md">OpenCL C 1.2 Language on Vulkan</a> を参照して下さい。ここでは大事なものをいくつかピックアップして説明します。</p>
<h3 id="descriptorset">DescriptorSet</h3>
<p>Clspv でビルドした OpenCL カーネルの引数は、 Vulkan では DescriptorSet にバインドしたバッファーに対応します。基本的に OpenCL カーネルの引数の順番と DescriptorSet にバインドしたバッファーの順番は対応しています。カーネル引数とバッファーの具体的な対応関係を確認したい場合は、Clspv で Descriptor map を出力できます。Descriptor map は Clspv でビルドする際に <code>--descriptorma=<filename></code>を付けることで出力できます。例えば、 前節の <code>vulkan_clspv_test1.cl</code> の場合は、</p>
<pre class=" language-sh"><code class="prism language-sh">% clspv --c++ --inline-entry-points --descriptormap=vulkan_clspv_test1.csv -o=vulkan_clspv_test1.spv vulkan_clspv_test1.cl
</code></pre>
<p>とすることで <code>vulkan_clspv_test1.csv</code> というファイル名のCSV形式の Descriptor map が出力されます。CSVファイルの内容は、</p>
<pre class=" language-csv"><code class="prism language-csv">kernel,testSummation,arg,value,argOrdinal,0,descriptorSet,0,binding,0,offset,0,argKind,buffer
kernel,testSummation,arg,outputs,argOrdinal,1,descriptorSet,0,binding,1,offset,0,argKind,buffer
</code></pre>
<p>のようになります。各行はそれぞれひとつの引数についての情報が載っています。行の内容は、フィールド名と値が交互に記述されています。行の内容は、</p>
<ul>
<li><code>kernel</code>: OpenCLカーネル名</li>
<li><code>arg</code>: 引数名</li>
<li><code>argOrdinal</code>: 引数のポジション</li>
<li><code>descriptorSet</code>: DescriptorSet のインデックス</li>
<li><code>binding</code>: 使用するバインドされたバッファーのポジション</li>
<li><code>offset</code>: バッファーにアクセスする際のアドレスのオフセット</li>
<li><code>argKind</code>: バッファの種類</li>
</ul>
<p>となります。この、<code>binding</code> の部分を見ればカーネルの引数がどのバッファーに対応するかわかります。</p>
<h3 id="work-group-size">Work-Group Size</h3>
<p>OpenCL では Work-Group のサイズは <code>clEnqueueNDRangeKernel</code> を呼ぶ時に引数として指定していました。Clspv でビルドしたカーネルの Work-Group サイズを指定する場合は、<code>reqd_work_group_size</code> を使ってカーネルの属性として指定するか、Specialization Constants を設定して指定する方法があります。Vulkan を動かす GPU が固定な場合は <code>reqd_work_group_size</code> を使用してハードコードする方法で良いですが、動かすGPUが複数あり、GPUによって Work-Group サイズを変える場合は Specialization constants で指定する方法が良いです。Specialization Constants は Compute Shader のパイプラインを作成する時に設定します。</p>
<pre class=" language-cpp"><code class="prism language-cpp">std<span class="token operator">::</span>array<span class="token operator"><</span>uint<span class="token punctuation">,</span> <span class="token number">3</span><span class="token operator">></span> work_group_size<span class="token punctuation">{</span><span class="token punctuation">{</span>x<span class="token punctuation">,</span> y<span class="token punctuation">,</span> z<span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token comment">// X、Y、Z次元の Work-Group サイズ</span>
<span class="token comment">// X、Y、Zの Work-Group サイズを設定するため、</span>
<span class="token comment">// それぞれの specialization constant の ID やデータサイズを設定する</span>
std<span class="token operator">::</span>array<span class="token operator"><</span>vk<span class="token operator">::</span>SpecializationMapEntry<span class="token punctuation">,</span> <span class="token number">3</span><span class="token operator">></span> entries<span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span>std<span class="token operator">::</span>size_t i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> entries<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token operator">++</span>i<span class="token punctuation">)</span> <span class="token punctuation">{</span>
entries<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>constantID <span class="token operator">=</span> <span class="token keyword">static_cast</span><span class="token operator"><</span>uint<span class="token operator">></span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">;</span>
entries<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>offset <span class="token operator">=</span> <span class="token keyword">static_cast</span><span class="token operator"><</span>uint<span class="token operator">></span><span class="token punctuation">(</span>i <span class="token operator">*</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>uint<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
entries<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>size <span class="token operator">=</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>uint<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> vk<span class="token operator">::</span>SpecializationInfo info<span class="token punctuation">{</span><span class="token number">3</span><span class="token punctuation">,</span> entries<span class="token punctuation">.</span><span class="token function">data</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">3</span> <span class="token operator">*</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>uint<span class="token punctuation">)</span><span class="token punctuation">,</span> work_group_size<span class="token punctuation">.</span><span class="token function">data</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token comment">// Work-Group サイズの情報を含めて パイプラインを作成する</span>
vk<span class="token operator">::</span>ShaderModule module <span class="token operator">=</span> <span class="token comment">/* Clspv でビルドした SPIR-V を読み込んだモジュール */</span>
<span class="token keyword">const</span> <span class="token keyword">char</span><span class="token operator">*</span> kernel_name <span class="token operator">=</span> <span class="token comment">/* OpenCL カーネル名 */</span>
<span class="token keyword">const</span> vk<span class="token operator">::</span>PipelineShaderStageCreateInfo shader_stage_create_info<span class="token punctuation">{</span>
vk<span class="token operator">::</span>PipelineShaderStageCreateFlags<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
vk<span class="token operator">::</span>ShaderStageFlagBits<span class="token operator">::</span>eCompute<span class="token punctuation">,</span>
module<span class="token punctuation">,</span>
kernel_name<span class="token punctuation">,</span>
<span class="token operator">&</span>info<span class="token punctuation">}</span><span class="token punctuation">;</span>
vk<span class="token operator">::</span>PipelineLayout pipeline_layout <span class="token operator">=</span> <span class="token comment">/* 作成した PipelineLayout */</span>
<span class="token keyword">const</span> vk<span class="token operator">::</span>ComputePipelineCreateInfo create_info<span class="token punctuation">{</span>
vk<span class="token operator">::</span>PipelineCreateFlags<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
shader_stage_create_info<span class="token punctuation">,</span>
pipeline_layout<span class="token punctuation">}</span><span class="token punctuation">;</span>
vk<span class="token operator">::</span><span class="token type-opencl-host-c++ keyword">Device</span> device <span class="token operator">=</span> <span class="token comment">/* 作成した Device */</span>
vk<span class="token operator">::</span>Pipeline pipeline <span class="token operator">=</span> device<span class="token punctuation">.</span><span class="token function">createComputePipelines</span><span class="token punctuation">(</span>vk<span class="token operator">::</span>PipelineCache<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> create_info<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<p>例えば、Work-Group の合計サイズを <strong>64</strong> で設定する場合、1次元の Work-Group にする場合は、<code>X=64</code>、<code>Y=1</code>、<code>Z=1</code> (<code>X * Y * Z = 64</code>) と指定すると、OpenCL 上では、</p>
<pre class=" language-opencl"><code class="prism language-opencl"><span class="token function">get_local_size</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// X = 64</span>
<span class="token function">get_local_size</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Y = 1</span>
<span class="token function">get_local_size</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Z = 1</span>
</code></pre>
<p>と反映されます。2次元の Work-Group にする場合は、<code>X=8</code>、<code>Y=8</code>、<code>Z=1</code> (<code>X * Y * Z = 64</code>) と指定すると、OpenCL 上では、</p>
<pre class=" language-opencl"><code class="prism language-opencl"><span class="token function">get_local_size</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// X = 8</span>
<span class="token function">get_local_size</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Y = 8</span>
<span class="token function">get_local_size</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Z = 1</span>
</code></pre>
<p>と反映されます。</p>
<h2 id="おわりに">おわりに</h2>
<p>この記事では Vulkan SDK と Clspv の導入を簡単に説明しました。Clspv の登場によって OpenCL コードを Vulkan で動かすことが可能になりました。OpenCL は C言語に慣れている方であれば書きやすい言語だと思いますが、OpenCL ドライバのバージョンが 1.2 で止まっていたりと実行環境周りに不安を覚えている方もいると思います。そのような場合は、 Clspv を使って Vulkan を始めてみるのも面白いと思います。</p>
<p>Clspv はまだ開発中のプロトタイプであるため色々と不具合が見つかるかもしれません。その時は github で issue を作って報告してあげて下さい。</p>
Zinhttp://www.blogger.com/profile/00473704352385380653noreply@blogger.com0tag:blogger.com,1999:blog-5029251693178115279.post-64831517754180406772018-07-08T19:22:00.001+09:002018-07-08T19:22:23.774+09:00Blenderから自作レンダラー向けに設定をエクスポート<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>blender_exporting_settings</title>
<style type="text/css">
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
</style>
<style type="text/css">
a.sourceLine { display: inline-block; line-height: 1.25; }
a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
a.sourceLine:empty { height: 1.2em; position: absolute; }
.sourceCode { overflow: visible; }
code.sourceCode { white-space: pre; position: relative; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
code.sourceCode { white-space: pre-wrap; }
a.sourceLine { text-indent: -1em; padding-left: 1em; }
}
pre.numberSource a.sourceLine
{ position: relative; }
pre.numberSource a.sourceLine:empty
{ position: absolute; }
pre.numberSource a.sourceLine::before
{ content: attr(data-line-number);
position: absolute; left: -5em; text-align: right; vertical-align: baseline;
border: none; pointer-events: all;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
a.sourceLine::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
</style>
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<h1 id="blenderから自作レンダラー向けに設定をエクスポート">Blenderから自作レンダラー向けに設定をエクスポート</h1>
<p>こんにちは。 このページは <a href="https://sites.google.com/site/raytracingcamp6/">レイトレ合宿6</a> の記事です.</p>
<p>今年もレイトレ合宿の日が近くなってきて どんなシーンをレンダリングしようかと考えている頃ではないでしょうか。 そこで、 <a href="#fn1" class="footnote-ref" id="fnref1"><sup>1</sup></a> Blenderで扱うシーンの設定を自作のレンダラー向けにエクスポートできるように してみます。 Blenderからエクスポートすることの利点は、</p>
<ul>
<li>Blenderという強力なGUIツールを用いて効率良くシーンを作成できる</li>
<li>Cyclesレンダラーなどの他のエンジンと同じ設定でレンダリングすることで、レンダリング結果を比較できる</li>
</ul>
<p>などが挙げられます。</p>
<h2 id="デモファイルのダウンロード">デモファイルのダウンロード</h2>
<p>設定をエクスポートするに当たって、 Blenderの公式サイトで配布されている ヘリコプターデモ “scene-Helicopter-27.Blend” を用います。</p>
<p><img src="https://lh3.googleusercontent.com/CJVf06xWOZ5MoZvlSYT8ZgikqU4j7U7xjfZjN2wn9kUqkrrXJr1a_gNqfG7vJSK8C3uSN_lsUeAwijWvXh_noxqnwnJ3HYBxSn_g6lYBwzXeS4qYg4I1mYiHRmVl40m28VVdlw6VdwnYKpf3bxqUKHYbVQHrlC4Z5D4N3-m8Y1WcvtSzi10Sj93hrYS36NXicN-5t3No7wHiWLQKir4jNM03NeLn2qMZdZNADR75q-GBCf_cK9RZH1Ng478N_pDlqnp_KRv4yElIzFV03MSMxWHHnvdvbCdqXXWZvIobIkYG4BAwGb-hc1t-fO31TNRA75gYk_3QzhjyBDpVxskst6OsRhnG52NLnB7EmMBcpQid_jUqMp_ihKvOSDHX-nh6JTNZ64SfzAuR0NqAdKW_s9MVDtMV61YZFoEdlfW7rnXJZhYwdSGvDNSyAcV1Yr07e31u13JqV06rb3EXG_S11Rnke8AESaMPYCuGx0Ar6a9hTZL6NoFArunzvwt0fkmcNjku-6q7HIphpgYhUGu59wy5Nl5-fpJs_UdQyFF00LuGPZ2UBqBB829o77o47FwUldUQGiYISMvwUa9VVCEcxRJmA7ZBBLTNTmDJhvs=w250-no" /></p>
<p><a href="https://www.blender.org/download/demo-files/">Blenderデモ</a></p>
<p>以下の画像の場所からダウンロードできます。感謝!。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiO_Lc0OqxphvPVSQdZy0AUzS4Ld0v5dB_myqNhHfn7Lwt9196xjHUEhzFs52ziGCYCZYrYBXsEQoj8OGcUH4aDTsuYDTnsnKx_8gw4H5iRCb1ph5S1pewOjVVqQI06uegwfBr67OwWPNg/w430-no/" /></p>
<h2 id="blenderの設定">Blenderの設定</h2>
<p>設定をエクスポートする前に、Blenderの設定を確認します。</p>
<h3 id="renderengineの設定">1. RenderEngineの設定</h3>
<p><img src="https://lh3.googleusercontent.com/zwiTmY7-zNgMkUyr8Bb1VxEeZlfMHfCj63rjxb-FRLVOsdE3iGVCKiVN_g4SQYIC-WkqV2ZHuhlGuqSmjJZtzN8HzE2GDJfAB5J7Tifpm8jHMIJOg6E-m4_e_8GyWNLPeTVg3JlOE8G6vFxLxPwg4g2LJ8OlxbPGOuefQDNRvEuceEwlWkIxE1x9XZUEiEhPGmD78D-GoDFjjkFJf5rgwdj6alCOhbDK8v0W_17TIw3JfOnXqBDzUL9fOThSHmwK9ghpmwuTdaOL5klTGaykUibgDDhsscbD_cQi2WzezeMhcQz-LoBxynV2_w2r8fLh5sd-OY7i0YmG1_ooEPc5DuunctHdSOH1gOFD58hL8vvniAvS6ODo0mMLGiRYTbvz3Z1Bfb_t_nAVacunHVbvgpmQyJEjRn_UJUgXTi-iDgHP_rTcV_1r24XYX-hzKKlDL9Oi7k0u_UyBFRVkozJ3zvOTSsgV-WME_GQP_UGDGDoOqH9Re3Z4fZNJALiUWnW0FW7c4NRA8YIv5P_PwJVquUJeHt9NKFJKcPFjGvvO7GMQpPiskcN5lxejl0GFICXuHMTz2iA_tNH_y68jAvqpefZKMGwb8NpberyITVE=w306-no" /></p>
<p>使用するレンダリングエンジンを選択します。 ここは <strong>Cycles Render</strong> を選択します (ヘリコプターデモの場合は既にCycles Renderが選択されています)。</p>
<h3 id="dimensionsの設定">2. Dimensionsの設定</h3>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtm1BGx_xCQcvx2Y0hURKWqSDahzQAYVbH9jfK9mAFGiEArpC3RKCCnRNX8mHddQNLjneYPqSfpQo-kd_-HXTh8AL5dopST3or5_lZGPZkr96uvVADqpPViCUo6JYZLeYkNqng1iePLng/w200-no/" /></p>
<p>出力する画像の解像度を設定します。 <em>Resolution</em> の項目を<strong>100%</strong>にし、<em>X</em>と<em>Y</em>に画像の解像度を設定します。</p>
<h3 id="samplingの設定">3. Samplingの設定</h3>
<p><img src="https://lh3.googleusercontent.com/0xSGVdQcfUur4OczvR-HEhHLrQdg9JkMc1saIc-PXadl-pPqwFZJ6tC6W-d4FZGu93pR8d8UEIaUWFjep7zm8jCQTNgmePEO6_YBkMsIkUND8dMN6En6Me9j85ZeAk2QoYvt3HUVFrrqhBqtvSHoihebfz5xqRFugzUL4vBzeNvNEB5heJV48wTZuoFphxzT36zjk7su8hyVygKVK-HBqBo5fV8bZeE7twEOcuabjmJF136hhPbdbeUuDeUwOS5kEP5y0hBXqLosGr-Vzta9foQHSK-9eRszFg6pZPHIRhDkeloQwr08Z_gjhGBTCcl4gCZ0vbR7ji3KHWjt0nn7HGNGSCmNlyIIgcfKmp4JM2SI1vXRFcs7Q_QgcuvxQBTWgYo2fkqu0962TDspR70vF6DpEFXUSB17LXiF0THLhgrZlRh-yvkM9W22Lu2pS6f0CiR_dBfpBfFi9g-nsvljWQIAHiMovHuUwPJ5IUOFdaGQbYysflWpMgy1Ityy7PoZ3DafvWbkXkxOCkEvPZgELGJrS4y12DldIuyCDoDE4mKII--_RpCzUCE_cvA_VisYqdIxaATPc1DVu9GtmulrLSMCtCmQpQqICdZ2Bxw=w200-no" /></p>
<p><em>Pattern</em> で使用する乱数のサンプラーを選択し、 <em>Settings</em> の <em>S</em> に乱数のシード値を指定しします。 <em>Samples</em> の <em>Render</em> に1ピクセル当りのレイのサンプル数を指定します。</p>
<h3 id="lightpathsの設定">4. LightPathsの設定</h3>
<p><img src="https://lh3.googleusercontent.com/6iJpzC53ii9NeGzEd3ihqsWV-OEDNytO3D6MhGKtkokVjH-DdoKEtovfTrdVmmbdRAY6O9ZWRSFhSLHnRcHeU7ovyrzetBDqX2wIIm3E2AUzP1ChVSJ7daC2J8DIyG_aWIbGwMiU9xtD35VbuhjyIwyNEbWD0bUkP5OdiF1B05lyqe5IhD4xq090EQcJ2vpvurq4hkY7z7xS3EH2JqM9ywsHaUXoJTrZAinjWslmjJ275mpRneD4eCAzpuTL8NHzyLCOQEExiw_mQJIWpYIVEISYKDdS232JYj1WE6KNjopGAYKV1G2XKBtK6qGSjIyKzYONbPkagD-vsuSlYbgKnnCpAXzwmEDXlchBLoDC0OGBspl5_wydYK6uMxtuEqP87fx6aMKNcegAJZXrz6ridej-S6zvNMOb-JIYvheGGQ38w_yt7yobVa-34XlAqQB5sKd2Zrqj4W8ofJqH4tcjQgPgM6fGw_8iOTS0tRWEgcjWflmcyJXXD8M6EMbKZAw2_uDt8JbSb0wcuOKCjR5TTQeyD-EC94G5dsCGx3TrPIUo4ioD9LpeNkYsYdeCbO2L9sIRixcGeGanbjvV61gkqmMairEK9_mqeTwDPt4=w200-no" /></p>
<p>様々な経路長のパスを考慮するため、<strong>Full Global Illumination</strong> を選択します。</p>
<h3 id="postprocessingの設定">5. PostProcessingの設定</h3>
<p><img src="https://lh3.googleusercontent.com/0nAQiOQSNQp24VR-J7zJKhSiOhmWuXaSrIVSV9uNrx5rkYOegRKILaH-qzxzu8h7dsCT_qwqssCVGb26KcSeDdxl4x8rbbOL4CJhjbdEKj0R5d_LW7rWXNHqUTUjMTDoxMgSZazgKM1eFcxFSQ5a50ZfddQC1AdrqEf7nQHviGFpX7c2DKMsOHU74RY7ys6DFH16gBYPyc3tewqxSpzvzgYpgEdn9Rt6cgBVKVlX6Koa4odh-PGawJ9jSRcZ-VrgntpzeKSaslibkVDcFw59-FPTNYGr_uOH48AxzidJVqeQVd5NKUW85jdUuo_nnPVdHvvScJTyc06ZsOURX78B7uKGK6qn0rO_-Zs9l8NaI8eGtjo2bd4VR_3wXaqa8OdStY-KhxGjRl7ipgRB-JZ1fmxpDdPgL7NaG3Ct4jeYyAn1hANtdSURq1XS7snOVZc_l_LvuxQZIIr1BeeXAJuLeeQlw9Nc1DKYRqtADDbVKFNR0vAuqPP_VcHFVoqBpH8kZOaYBFA0N_8p0niDlDQPIUhyZRecihBocix7w9VsiX8Yq74ACBuynNME2sQ59sD_JgbuqMQ616-c8BpbH7sj_ieKaB3lLZ766fzsgY0=w200-no" /></p>
<p>画像処理前のレンダリング画像を取得するため、 Post Processingのチェックを全て外しておきます。</p>
<h3 id="surfaceの設定">6. Surfaceの設定</h3>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdD29Un7rW7trJohbtjHJGXmHE_PHkUJYQ_NFy43vpWVYS5ErxsBtZ2uqMWcKTk53zT_KYXsospFkhCllsWY_5Fxzq6uFcDeWbf4G_6C4dDHmPNPgv81WlWKgfepUIzwvsY8dnXWuhEX4/w200-no/" /></p>
<p>Cyclesエンジンの初期設定で、うっすらとした環境光が設定されている場合があります。 意図しない光源が設定されていると比較の際に困るので、 <em>Background</em> の <em>Strength</em> が <strong>0</strong> になっているか確認しておきます。</p>
<h3 id="performanceの設定">7. Performanceの設定</h3>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEga4J_p26MfO7sEH7b1cTtAFm8gJBr6HGII-4APsz3FNp5sRkYo0R7OnJohaj4x6V5EMk53Ja2GygdnWOiE6QVSraHtpi0Olwmu66GC79IwPfrfd3yC5EEQfd8JjTZB0MG78maQmjlJWVo/w200-no/" /></p>
<p>パフォーマンスの比較を行う場合は、<em>Threads</em> で使用するスレッド数を指定します。</p>
<h3 id="リファレンスの作成">リファレンスの作成</h3>
<p>以上の設定を確認してレンダリングを行います。</p>
<p><img src="https://lh3.googleusercontent.com/CJVf06xWOZ5MoZvlSYT8ZgikqU4j7U7xjfZjN2wn9kUqkrrXJr1a_gNqfG7vJSK8C3uSN_lsUeAwijWvXh_noxqnwnJ3HYBxSn_g6lYBwzXeS4qYg4I1mYiHRmVl40m28VVdlw6VdwnYKpf3bxqUKHYbVQHrlC4Z5D4N3-m8Y1WcvtSzi10Sj93hrYS36NXicN-5t3No7wHiWLQKir4jNM03NeLn2qMZdZNADR75q-GBCf_cK9RZH1Ng478N_pDlqnp_KRv4yElIzFV03MSMxWHHnvdvbCdqXXWZvIobIkYG4BAwGb-hc1t-fO31TNRA75gYk_3QzhjyBDpVxskst6OsRhnG52NLnB7EmMBcpQid_jUqMp_ihKvOSDHX-nh6JTNZ64SfzAuR0NqAdKW_s9MVDtMV61YZFoEdlfW7rnXJZhYwdSGvDNSyAcV1Yr07e31u13JqV06rb3EXG_S11Rnke8AESaMPYCuGx0Ar6a9hTZL6NoFArunzvwt0fkmcNjku-6q7HIphpgYhUGu59wy5Nl5-fpJs_UdQyFF00LuGPZ2UBqBB829o77o47FwUldUQGiYISMvwUa9VVCEcxRJmA7ZBBLTNTmDJhvs=w400-no" /></p>
<p>自作レンダラーとの比較のために、マテリアルの設定をもう少しシンプルにしておきます。</p>
<p><img src="https://lh3.googleusercontent.com/9iSZHfmUlao7uH96lxvQg0KxZFJTAE6NbGGL-JsA4eDXrauFYsMLdUqMrEgujnG8Qt2ifCzPnUWVTenqLgNq7K8Q44tPDwubFelVlf90QF-WPLpXNM3kMVSeMgnzUaatgZUMngFXoe7yj36vEpEiOxfFaMWiS3wwtD7WCmd35-tLeb-SSHsfwWPle1cdJqAzlx2WhWT6-OvbnIVy5RmNqumVyplR0ySu0Pr0YCKrOIcuXNqvdh54XD8UrEOclLm7dp9a06E-4-ZFso42027nFLzc88u5CSr7rmP2wmQ9Z_2RbJBZCALehdgrTBbxDifssD0XFtM-iOcE4knrP1j3fulwVocmDVklxO0ZjVBG5zHlVDsvgsjzurCuwqpiz_ZbXcqipJbS4dmlUXypfXOsWZn2d7H-PH-QyjgwQa2sR54u5zNso_J6pGJidHNsB46qMZ5uglpGCA-0BXhIjJsFlYpPm8Qm2uxm9UhboWrebS9crlszEULdZo5IXl-G6ZG_KnOVhwczcfj0cK4Pn2uQn_uTMao9RBjxOHKPqRFWlSf6gPgBO6PaSRcMu5bie9MBUHmeYZZ6GH7Yb3baSbaygnqIzG6ukPPXuPBqRpg=w400-no" /></p>
<p>これで、設定をエクスポートする準備が整いました。</p>
<h2 id="blenderエクスポーターの作成">Blenderエクスポーターの作成</h2>
<p>Blenderから設定をエクスポートするツールを作成します。</p>
<p>BlenderはPythonインタプリタを内蔵しており、 Blender内でPythonスクリプトを実行することができます。 そこで、Blenderから設定をエクスポートするPythonスクリプトを作成してみます。</p>
<h3 id="pythonスクリプトの実行">Pythonスクリプトの実行</h3>
<p>Pythonスクリプトは、Blender起動時に引数として渡して実行することができます。 試しにスクリプトを実行してみます。 以下は.Blendファイルのファイル名を表示するスクリプトです。</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode python"><code class="sourceCode python"><a class="sourceLine" id="cb1-1" data-line-number="1"><span class="co">#</span></a>
<a class="sourceLine" id="cb1-2" data-line-number="2"><span class="co"># exporter1.py</span></a>
<a class="sourceLine" id="cb1-3" data-line-number="3"><span class="co">#</span></a>
<a class="sourceLine" id="cb1-4" data-line-number="4"></a>
<a class="sourceLine" id="cb1-5" data-line-number="5"><span class="im">import</span> bpy</a>
<a class="sourceLine" id="cb1-6" data-line-number="6"></a>
<a class="sourceLine" id="cb1-7" data-line-number="7">file_name <span class="op">=</span> bpy.path.display_name_from_filepath(bpy.data.filepath)</a>
<a class="sourceLine" id="cb1-8" data-line-number="8"><span class="bu">print</span>(<span class="st">"## FileName: </span><span class="sc">{0}</span><span class="st">"</span>.<span class="bu">format</span>(file_name))</a></code></pre></div>
<p>端末を開いて、Blenderに引数として渡して実行します。</p>
<pre class="console"><code>% blender --background Helicopter.blend --python exporter1.py
Read blend: Helicopter.blend
## FileName: Helicopter
Blender quit</code></pre>
<p>Blenderの実行ファイルの場所は、Windowsなら <code>C:\Program Files\Blender Foundation\Blender\blender.exe</code>、 macOSなら<code>/Applications/Blender/blender.app/Contents/MacOS/blender</code>にあると思います。</p>
<p><code>--background</code> オプションを指定すると、BlenderのGUIを起動せずに Pythonスクリプトを実行することができます。</p>
<p>実行する際のポイントは、<code>Helicopter.blend</code>よりも後に<code>--python exporter1.py</code> を指定することです。 <code>Helicopter.blend</code>の設定が読み込まれた後にスクリプトが実行されます。</p>
<p>スクリプト内で<code>import bpy</code> を実行することで、BlenderのAPIを利用できるようになります。 利用できるAPIの詳細は <a href="https://docs.blender.org/api/current/">Blender Documentation Python API</a> で参照できます。</p>
<h3 id="シーンデータの取得">シーンデータの取得</h3>
<p>.Blendファイルを読み込んだ際の各種設定は、 <code>bpy.data</code> に記録されます (<code>bpy.data</code>の構造については <a href="https://docs.blender.org/api/current/bpy.types.BlendData.html">BlendData</a> を参照して下さい)。</p>
<p>各シーンの情報については <code>bpy.data.scenes</code> に記録されています。 (<code>bpy.data.scenes</code>の構造については <a href="https://docs.blender.org/api/current/bpy.types.Scene.html">Scene</a> を参照して下さい)。</p>
<p>特定のシーンデータを取得する場合はシーン名を指定することで取得できます。 シーン名は <em>Outliner</em> で確認できます。</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkdUpfGqx6BUcC54COlKjvHDh6l9UxAtriTLo-ltuwZldCMDAsWEIdPUP6Z2iyYOxPlb8cqjj8Foeoj0Zur698ufcpm7ttkvsnSrhhYmOCsMdWaSKxoR2e1IB16tmK0c6FXg5HHTj22pw/w300-no/" /></p>
<p>以下は<strong>Scene</strong>という名前のシーンから情報を取得するスクリプトの例です。</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode python"><code class="sourceCode python"><a class="sourceLine" id="cb3-1" data-line-number="1"><span class="co">#</span></a>
<a class="sourceLine" id="cb3-2" data-line-number="2"><span class="co"># exporter2.py</span></a>
<a class="sourceLine" id="cb3-3" data-line-number="3"><span class="co">#</span></a>
<a class="sourceLine" id="cb3-4" data-line-number="4"></a>
<a class="sourceLine" id="cb3-5" data-line-number="5"><span class="im">import</span> bpy</a>
<a class="sourceLine" id="cb3-6" data-line-number="6"></a>
<a class="sourceLine" id="cb3-7" data-line-number="7"><span class="co"># Get a scene</span></a>
<a class="sourceLine" id="cb3-8" data-line-number="8">scene_name <span class="op">=</span> <span class="st">"Scene"</span></a>
<a class="sourceLine" id="cb3-9" data-line-number="9">scene <span class="op">=</span> bpy.data.scenes[scene_name]</a>
<a class="sourceLine" id="cb3-10" data-line-number="10"></a>
<a class="sourceLine" id="cb3-11" data-line-number="11"><span class="co"># Get a image resolution</span></a>
<a class="sourceLine" id="cb3-12" data-line-number="12">x <span class="op">=</span> scene.render.resolution_x</a>
<a class="sourceLine" id="cb3-13" data-line-number="13">y <span class="op">=</span> scene.render.resolution_y</a>
<a class="sourceLine" id="cb3-14" data-line-number="14"><span class="bu">print</span>(<span class="st">"Image resolution: </span><span class="sc">{0}</span><span class="st"> x </span><span class="sc">{1}</span><span class="st">"</span>.<span class="bu">format</span>(x, y))</a>
<a class="sourceLine" id="cb3-15" data-line-number="15"></a>
<a class="sourceLine" id="cb3-16" data-line-number="16"><span class="co"># Get a sampler type</span></a>
<a class="sourceLine" id="cb3-17" data-line-number="17">sampler <span class="op">=</span> scene.cycles.sampling_pattern</a>
<a class="sourceLine" id="cb3-18" data-line-number="18"><span class="bu">print</span>(<span class="st">"Sampler: </span><span class="sc">{0}</span><span class="st">"</span>.<span class="bu">format</span>(sampler))</a>
<a class="sourceLine" id="cb3-19" data-line-number="19"></a>
<a class="sourceLine" id="cb3-20" data-line-number="20"><span class="co"># Get a sampler seed</span></a>
<a class="sourceLine" id="cb3-21" data-line-number="21">seed <span class="op">=</span> scene.cycles.seed</a>
<a class="sourceLine" id="cb3-22" data-line-number="22"><span class="bu">print</span>(<span class="st">"Sampler seed: </span><span class="sc">{0}</span><span class="st">"</span>.<span class="bu">format</span>(seed))</a>
<a class="sourceLine" id="cb3-23" data-line-number="23"></a>
<a class="sourceLine" id="cb3-24" data-line-number="24"><span class="co"># Get the number of threads</span></a>
<a class="sourceLine" id="cb3-25" data-line-number="25">threads <span class="op">=</span> scene.render.threads</a>
<a class="sourceLine" id="cb3-26" data-line-number="26"><span class="bu">print</span>(<span class="st">"Threads: </span><span class="sc">{0}</span><span class="st">"</span>.<span class="bu">format</span>(threads))</a>
<a class="sourceLine" id="cb3-27" data-line-number="27"></a>
<a class="sourceLine" id="cb3-28" data-line-number="28"><span class="co"># Get a render samples</span></a>
<a class="sourceLine" id="cb3-29" data-line-number="29">samples <span class="op">=</span> scene.cycles.samples</a>
<a class="sourceLine" id="cb3-30" data-line-number="30"><span class="bu">print</span>(<span class="st">"Render samples: </span><span class="sc">{0}</span><span class="st">"</span>.<span class="bu">format</span>(samples))</a></code></pre></div>
<p>最初に、 <code>scene = bpy.data.scenes[scene_name]</code> で欲しいシーン情報を取得し、 シーンの各種情報を取得しています。 上のスクリプトでは、情報を標準出力に出力しているだけですが、 実際には自作レンダラーのフォーマットに加工してファイルに出力します。</p>
<p>実行結果は以下のようになります。</p>
<pre class="console"><code>% blender --background Helicopter.blend --python exporter2.py
Read blend: Helicopter.blend
Image resolution: 1920 x 1080
Sampler: CORRELATED_MULTI_JITTER
Sampler seed: 123456789
Threads: 4
Render samples: 512
Blender quit</code></pre>
<p>もし欲しい情報のAPIがわからない場合は、 BlenderのGUI上でその情報を編集するためのボタンやメニューの上に マウスカーソルを置いてみて下さい。 しばらくするとポップアップが現れて、その情報を利用するためのAPIを表示してくれます。 <img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRnL-KVmW5ulwEvhzzPGcpaELdIZMm1h5t4BexGmyC7N1Rs1_b9zir2mAOBhUajKLcMUv_SV2XbmxfoQvvd-cOv81iuC5YzuY3DPon7EKRVXa6-8eAfRd68mDaf41xDeqhQaP3SP_VDTU/w303-h221-no/" /></p>
<h4 id="カメラ">カメラ</h4>
<p>シーンのアクティブカメラの情報は、<code>scene.camera</code> に入っています。</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode python"><code class="sourceCode python"><a class="sourceLine" id="cb5-1" data-line-number="1"><span class="co">#</span></a>
<a class="sourceLine" id="cb5-2" data-line-number="2"><span class="co"># exporter3.py</span></a>
<a class="sourceLine" id="cb5-3" data-line-number="3"><span class="co">#</span></a>
<a class="sourceLine" id="cb5-4" data-line-number="4"></a>
<a class="sourceLine" id="cb5-5" data-line-number="5"><span class="im">import</span> bpy</a>
<a class="sourceLine" id="cb5-6" data-line-number="6"></a>
<a class="sourceLine" id="cb5-7" data-line-number="7"><span class="co"># Get a scene</span></a>
<a class="sourceLine" id="cb5-8" data-line-number="8">scene_name <span class="op">=</span> <span class="st">"Scene"</span></a>
<a class="sourceLine" id="cb5-9" data-line-number="9">scene <span class="op">=</span> bpy.data.scenes[scene_name]</a>
<a class="sourceLine" id="cb5-10" data-line-number="10"></a>
<a class="sourceLine" id="cb5-11" data-line-number="11"><span class="co"># Get an active camera</span></a>
<a class="sourceLine" id="cb5-12" data-line-number="12">camera_obj <span class="op">=</span> scene.camera</a>
<a class="sourceLine" id="cb5-13" data-line-number="13"></a>
<a class="sourceLine" id="cb5-14" data-line-number="14"><span class="co"># Get rotation angles</span></a>
<a class="sourceLine" id="cb5-15" data-line-number="15"><span class="cf">for</span> axis <span class="kw">in</span> camera_obj.rotation_euler.order:</a>
<a class="sourceLine" id="cb5-16" data-line-number="16"> axis_index <span class="op">=</span> <span class="bu">ord</span>(axis) <span class="op">-</span> <span class="bu">ord</span>(<span class="st">'X'</span>)</a>
<a class="sourceLine" id="cb5-17" data-line-number="17"> angle <span class="op">=</span> camera_obj.rotation_euler[axis_index]</a>
<a class="sourceLine" id="cb5-18" data-line-number="18"> <span class="bu">print</span>(<span class="st">"</span><span class="sc">{0}</span><span class="st"> axis rotation: </span><span class="sc">{1}</span><span class="st"> radian."</span>.<span class="bu">format</span>(axis, angle))</a>
<a class="sourceLine" id="cb5-19" data-line-number="19"></a>
<a class="sourceLine" id="cb5-20" data-line-number="20"><span class="co"># Get a camera position</span></a>
<a class="sourceLine" id="cb5-21" data-line-number="21">location <span class="op">=</span> camera_obj.location</a>
<a class="sourceLine" id="cb5-22" data-line-number="22"><span class="bu">print</span>(<span class="st">"position: (</span><span class="sc">{0}</span><span class="st">, </span><span class="sc">{1}</span><span class="st">, </span><span class="sc">{2}</span><span class="st">)"</span>.<span class="bu">format</span>(location[<span class="dv">0</span>], location[<span class="dv">1</span>], location[<span class="dv">2</span>]))</a>
<a class="sourceLine" id="cb5-23" data-line-number="23"></a>
<a class="sourceLine" id="cb5-24" data-line-number="24"><span class="co"># Get a field of view</span></a>
<a class="sourceLine" id="cb5-25" data-line-number="25"><span class="bu">print</span>(<span class="st">"Horizontal field of view: </span><span class="sc">{0}</span><span class="st">"</span>.<span class="bu">format</span>(camera_obj.data.angle_x))</a>
<a class="sourceLine" id="cb5-26" data-line-number="26"><span class="bu">print</span>(<span class="st">"Vertical field of view: </span><span class="sc">{0}</span><span class="st">"</span>.<span class="bu">format</span>(camera_obj.data.angle_y))</a></code></pre></div>
<p><code>scene.camera</code> 自体は <a href="https://docs.blender.org/api/current/bpy.types.Object.html">Object</a> 構造になっており、 カメラの位置や回転などの情報が入っています。 <code>scene.camera.data</code> にはカメラの画角やレンズなどの情報が入っています (<a href="https://docs.blender.org/api/current/bpy.types.Camera.html">Camera</a> を参照して下さい)。</p>
<p>実行結果は以下のようになります。</p>
<pre class="console"><code>% blender --background Helicopter.blend --python exporter3.py
Read blend: Helicopter.blend
X axis rotation: 4.169113636016846 radian.
Y axis rotation: 3.1490345001220703 radian.
Z axis rotation: 3.9584245681762695 radian.
position: (1.483912467956543, -1.3075470924377441, 1.6609470844268799)
Horizontal field of view: 0.8575560450553894
Vertical field of view: 0.5033799409866333
Blender quit</code></pre>
<h4 id="オブジェクト">オブジェクト</h4>
<p>シーン内のオブジェクトのデータは <code>scene.objects</code> に入っています (各オブジェクトの構造は <a href="https://docs.blender.org/api/current/bpy.types.Object.html">Object</a> を参照して下さい)。 例えば、シーン内のオブジェクト名を全て表示するスクリプトは、</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode python"><code class="sourceCode python"><a class="sourceLine" id="cb7-1" data-line-number="1"><span class="co">#</span></a>
<a class="sourceLine" id="cb7-2" data-line-number="2"><span class="co"># exporter4.py</span></a>
<a class="sourceLine" id="cb7-3" data-line-number="3"><span class="co">#</span></a>
<a class="sourceLine" id="cb7-4" data-line-number="4"></a>
<a class="sourceLine" id="cb7-5" data-line-number="5"><span class="im">import</span> bpy</a>
<a class="sourceLine" id="cb7-6" data-line-number="6"></a>
<a class="sourceLine" id="cb7-7" data-line-number="7"><span class="co"># Get a scene</span></a>
<a class="sourceLine" id="cb7-8" data-line-number="8">scene_name <span class="op">=</span> <span class="st">"Scene"</span></a>
<a class="sourceLine" id="cb7-9" data-line-number="9">scene <span class="op">=</span> bpy.data.scenes[scene_name]</a>
<a class="sourceLine" id="cb7-10" data-line-number="10"></a>
<a class="sourceLine" id="cb7-11" data-line-number="11"><span class="co"># Display object names</span></a>
<a class="sourceLine" id="cb7-12" data-line-number="12"><span class="cf">for</span> obj <span class="kw">in</span> scene.objects:</a>
<a class="sourceLine" id="cb7-13" data-line-number="13"> <span class="bu">print</span>(obj.name)</a></code></pre></div>
<p>のようになります。</p>
<p><img src="https://lh3.googleusercontent.com/AifyC4lQjxIAnWJoCySvMr1TcTycpAeRZqG9Uqepez-WzNQ4phdJGqtwZcSUs7JL6PHwP9cf8WBMYhfYl2Oo4jNI7QDnGRCs8iwxufLVku5Kx2wj6id9ER72TbuDNrbRBQS_DY9-Kf34n5IXjnz5MArJrSG4XTbPsL4i3LV3aPybVFGhmjwXjcG4HnGE_cl6tTauF7fqe0qasWhLkQ-iSBtdc8VXdIpTZ0Pd-0r87r8Tqr33z_jcdgbvz-m6de1lwWKxOB2e_dpMWJVhnJA82I1XqgxtsPzN395OoKMtW0JepJ2ikc7CwZ0guDSH_xzIGus0iPM-mvbRal1p5T0sE-K185IWzrRz3gpV-OXvQXzNNx7JzC_B6l1k_Qy3InfhEB5qF8eResre2pAQ8k_SJiRx3s8Txncwj0mYQA-aLiaGGrg5HEreoRMQo6WYaf6JGSitxQHG693AOo79ic43Jc_e2NV2FL1rmSVa4JhKgALFvTGtxbsN23Ai9SnY2WyFfWbNiET5RgrVUTbJWx3xfzacpKr2FDhDEeyObv9iJGF5oVWQE2pP60fZ1CazZMVePlh1bdFk3rnKuf0VBIjilbZ2ybZqngb1rFpIcA0=w313-no" /></p>
<p>試しに上画像のOutlinerのシーンで実行してみると、</p>
<pre class="console"><code>blender --background TestScene.blend --python exporter4.py
Read blend: TestScene.blend
ObjectB
ObjectA
ObjectA-2
ObjectA-1
Lamp
Camera
Blender quit</code></pre>
<p><code>scene.objects</code> にはオブジェクト同士の親子関係に関わらず全てのオブジェクトが 入っています。 親子関係を考慮する場合は、</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode python"><code class="sourceCode python"><a class="sourceLine" id="cb9-1" data-line-number="1"><span class="co">#</span></a>
<a class="sourceLine" id="cb9-2" data-line-number="2"><span class="co"># exporter5.py</span></a>
<a class="sourceLine" id="cb9-3" data-line-number="3"><span class="co">#</span></a>
<a class="sourceLine" id="cb9-4" data-line-number="4"></a>
<a class="sourceLine" id="cb9-5" data-line-number="5"><span class="im">import</span> bpy</a>
<a class="sourceLine" id="cb9-6" data-line-number="6"></a>
<a class="sourceLine" id="cb9-7" data-line-number="7"><span class="co"># Get a scene</span></a>
<a class="sourceLine" id="cb9-8" data-line-number="8">scene_name <span class="op">=</span> <span class="st">"Scene"</span></a>
<a class="sourceLine" id="cb9-9" data-line-number="9">scene <span class="op">=</span> bpy.data.scenes[scene_name]</a>
<a class="sourceLine" id="cb9-10" data-line-number="10"></a>
<a class="sourceLine" id="cb9-11" data-line-number="11"><span class="kw">def</span> printChildObjects(objects):</a>
<a class="sourceLine" id="cb9-12" data-line-number="12"> <span class="cf">for</span> obj <span class="kw">in</span> objects:</a>
<a class="sourceLine" id="cb9-13" data-line-number="13"> <span class="bu">print</span>(<span class="st">" child node: "</span> <span class="op">+</span> obj.name)</a>
<a class="sourceLine" id="cb9-14" data-line-number="14"></a>
<a class="sourceLine" id="cb9-15" data-line-number="15"><span class="co"># Display object names</span></a>
<a class="sourceLine" id="cb9-16" data-line-number="16"><span class="cf">for</span> obj <span class="kw">in</span> scene.objects:</a>
<a class="sourceLine" id="cb9-17" data-line-number="17"> <span class="cf">if</span> obj.parent <span class="op">==</span> <span class="va">None</span>:</a>
<a class="sourceLine" id="cb9-18" data-line-number="18"> <span class="bu">print</span>(obj.name)</a>
<a class="sourceLine" id="cb9-19" data-line-number="19"> printChildObjects(obj.children)</a></code></pre></div>
<p>のように書くことができます。 <code>obj.parent</code> には親となるオブジェクトが入っており (トップレベルの場合は <em>None</em>)、 <code>obj.children</code> は子となるオブジェクトの配列(子がいない場合は要素を持たない配列) となっており、これらを用いて親子階層を意識した処理を書くことができます。</p>
<p>実行結果は</p>
<pre class="console"><code>% blender --background TestScene.blend --python exporter5.py
Read blend: TestScene.blend
ObjectB
ObjectA
child node: ObjectA-1
child node: ObjectA-2
Lamp
Camera
Blender quit</code></pre>
<p>となります。</p>
<p>次は、オブジェクト内の情報をエクスポートしてみます。</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode python"><code class="sourceCode python"><a class="sourceLine" id="cb11-1" data-line-number="1"><span class="co">#</span></a>
<a class="sourceLine" id="cb11-2" data-line-number="2"><span class="co"># exporter6.py</span></a>
<a class="sourceLine" id="cb11-3" data-line-number="3"><span class="co">#</span></a>
<a class="sourceLine" id="cb11-4" data-line-number="4"></a>
<a class="sourceLine" id="cb11-5" data-line-number="5"><span class="im">import</span> bpy</a>
<a class="sourceLine" id="cb11-6" data-line-number="6"></a>
<a class="sourceLine" id="cb11-7" data-line-number="7"><span class="co"># Get a scene</span></a>
<a class="sourceLine" id="cb11-8" data-line-number="8">scene_name <span class="op">=</span> <span class="st">"Scene"</span></a>
<a class="sourceLine" id="cb11-9" data-line-number="9">scene <span class="op">=</span> bpy.data.scenes[scene_name]</a>
<a class="sourceLine" id="cb11-10" data-line-number="10"></a>
<a class="sourceLine" id="cb11-11" data-line-number="11"><span class="co"># Display object names</span></a>
<a class="sourceLine" id="cb11-12" data-line-number="12"><span class="cf">for</span> obj <span class="kw">in</span> scene.objects:</a>
<a class="sourceLine" id="cb11-13" data-line-number="13"> <span class="cf">if</span> <span class="kw">not</span> obj.<span class="bu">type</span> <span class="kw">in</span> {<span class="st">'MESH'</span>, <span class="st">'CURVE'</span>, <span class="st">'SURFACE'</span>}:</a>
<a class="sourceLine" id="cb11-14" data-line-number="14"> <span class="cf">continue</span></a>
<a class="sourceLine" id="cb11-15" data-line-number="15"></a>
<a class="sourceLine" id="cb11-16" data-line-number="16"> <span class="bu">print</span>(obj.name)</a>
<a class="sourceLine" id="cb11-17" data-line-number="17"></a>
<a class="sourceLine" id="cb11-18" data-line-number="18"> <span class="co"># Get the active material of an object</span></a>
<a class="sourceLine" id="cb11-19" data-line-number="19"> material <span class="op">=</span> obj.active_material</a>
<a class="sourceLine" id="cb11-20" data-line-number="20"> <span class="cf">if</span> material <span class="op">!=</span> <span class="va">None</span>:</a>
<a class="sourceLine" id="cb11-21" data-line-number="21"> <span class="bu">print</span>(<span class="st">" Material name: </span><span class="sc">{0}</span><span class="st">"</span>.<span class="bu">format</span>(material.name))</a>
<a class="sourceLine" id="cb11-22" data-line-number="22"> <span class="bu">print</span>(<span class="st">" Material index: </span><span class="sc">{0}</span><span class="st">"</span>.<span class="bu">format</span>(bpy.data.materials.find(material.name)))</a>
<a class="sourceLine" id="cb11-23" data-line-number="23"></a>
<a class="sourceLine" id="cb11-24" data-line-number="24"> <span class="co"># Export a object data to wavefromt format</span></a>
<a class="sourceLine" id="cb11-25" data-line-number="25"> bpy.ops.<span class="bu">object</span>.select_all(action<span class="op">=</span><span class="st">'DESELECT'</span>)</a>
<a class="sourceLine" id="cb11-26" data-line-number="26"> obj.select <span class="op">=</span> <span class="va">True</span></a>
<a class="sourceLine" id="cb11-27" data-line-number="27"> bpy.ops.export_scene.obj( <span class="op">\</span></a>
<a class="sourceLine" id="cb11-28" data-line-number="28"> filepath <span class="op">=</span> obj.name <span class="op">+</span> <span class="st">".obj"</span>, <span class="op">\</span></a>
<a class="sourceLine" id="cb11-29" data-line-number="29"> check_existing <span class="op">=</span> <span class="va">True</span>, <span class="op">\</span></a>
<a class="sourceLine" id="cb11-30" data-line-number="30"> axis_forward <span class="op">=</span> <span class="st">'Y'</span>, <span class="op">\</span></a>
<a class="sourceLine" id="cb11-31" data-line-number="31"> axis_up <span class="op">=</span> <span class="st">'Z'</span>, <span class="op">\</span></a>
<a class="sourceLine" id="cb11-32" data-line-number="32"> use_selection <span class="op">=</span> <span class="va">True</span>, <span class="op">\</span></a>
<a class="sourceLine" id="cb11-33" data-line-number="33"> use_animation <span class="op">=</span> <span class="va">False</span>, <span class="op">\</span></a>
<a class="sourceLine" id="cb11-34" data-line-number="34"> use_mesh_modifiers <span class="op">=</span> <span class="va">True</span>, <span class="op">\</span></a>
<a class="sourceLine" id="cb11-35" data-line-number="35"> use_edges <span class="op">=</span> <span class="va">False</span>, <span class="op">\</span></a>
<a class="sourceLine" id="cb11-36" data-line-number="36"> use_smooth_groups <span class="op">=</span> <span class="va">False</span>, <span class="op">\</span></a>
<a class="sourceLine" id="cb11-37" data-line-number="37"> use_smooth_groups_bitflags <span class="op">=</span> <span class="va">False</span>, <span class="op">\</span></a>
<a class="sourceLine" id="cb11-38" data-line-number="38"> use_normals <span class="op">=</span> <span class="va">True</span>, <span class="op">\</span></a>
<a class="sourceLine" id="cb11-39" data-line-number="39"> use_uvs <span class="op">=</span> <span class="va">True</span>, <span class="op">\</span></a>
<a class="sourceLine" id="cb11-40" data-line-number="40"> use_materials <span class="op">=</span> <span class="va">False</span>, <span class="op">\</span></a>
<a class="sourceLine" id="cb11-41" data-line-number="41"> use_triangles <span class="op">=</span> <span class="va">True</span>, <span class="op">\</span></a>
<a class="sourceLine" id="cb11-42" data-line-number="42"> use_nurbs <span class="op">=</span> <span class="va">False</span>, <span class="op">\</span></a>
<a class="sourceLine" id="cb11-43" data-line-number="43"> use_vertex_groups <span class="op">=</span> <span class="va">False</span>, <span class="op">\</span></a>
<a class="sourceLine" id="cb11-44" data-line-number="44"> use_blen_objects <span class="op">=</span> <span class="va">True</span>, <span class="op">\</span></a>
<a class="sourceLine" id="cb11-45" data-line-number="45"> group_by_object <span class="op">=</span> <span class="va">False</span>, <span class="op">\</span></a>
<a class="sourceLine" id="cb11-46" data-line-number="46"> group_by_material <span class="op">=</span> <span class="va">False</span>, <span class="op">\</span></a>
<a class="sourceLine" id="cb11-47" data-line-number="47"> keep_vertex_order <span class="op">=</span> <span class="va">True</span>, <span class="op">\</span></a>
<a class="sourceLine" id="cb11-48" data-line-number="48"> global_scale <span class="op">=</span> <span class="fl">1.0</span>, <span class="op">\</span></a>
<a class="sourceLine" id="cb11-49" data-line-number="49"> path_mode <span class="op">=</span> <span class="st">'AUTO'</span>)</a></code></pre></div>
<p><code>obj.type</code> を見ることで、どんな種類のオブジェクトなのかがわかります (例えば ‘MESH’、‘CURVE’、’CAMERA’など。<a href="https://docs.blender.org/api/current/bpy.types.Object.html#bpy.types.Object.type">Type of Object</a>)。 また、この種類の違いによって、 <code>obj.data</code> の構造も異なります (’MESH’なら <a href="https://docs.blender.org/api/current/bpy.types.Mesh.html">Mesh</a> 、’CURVE’なら <a href="https://docs.blender.org/api/current/bpy.types.Curve.html">Curve</a> など)。</p>
<p><code>bpy.ops.export_scene.obj</code> はオブジェクトを <code>.obj</code> 形式で書き出すAPIです (<a href="https://docs.blender.org/api/current/bpy.ops.export_scene.html#bpy.ops.export_scene.obj">Export Scene Operators</a> を参照)。 オブジェクトの種類毎に処理を変えるのは大変なので、 ここでは <code>bpy.ops.export_scene.obj</code> を用いて ’MESH’や’CURVE’などのオブジェクトは全て <code>.obj</code> 形式に書き出すようにしました。</p>
<p>以下は実行結果の一部を切り出したものです。</p>
<pre class="console"><code>% blender --background Helicopter.blend --python exporter6.py
Read blend: Helicopter.blend
...
Bolt+Nut.011
Material name: Metal
Material index: 3
( 0.0409 sec | 0.0000 sec) OBJ Export path: 'Bolt+Nut.011.obj'
( 0.2900 sec | 0.2481 sec) Finished writing geometry of 'Bolt+Nut.011'.
( 0.2964 sec | 0.2550 sec) Finished exporting geometry, now exporting materials
( 0.2964 sec | 0.2550 sec) OBJ Export Finished
Progress: 100.00%
...
Blender quit</code></pre>
<p>オブジェクト“Bolt+Nut.011”が“Bolt+Nut.011.obj”として書き出されました。 自作レンダラーでは、このobjファイルを読み込むように設定をエクスポートしています。</p>
<h3 id="マテリアル">マテリアル</h3>
<p>マテリアルの情報は <code>bpy.data.materials</code> に入っています (各マテリアルの構造は <a href="https://docs.blender.org/api/current/bpy.types.Material.html">Material</a> を参照して下さい)。 Blenderのマテリアルデータは複雑で、また、自作レンダラーのマテリアルデータとは 取るパラメータも異なるため、 マテリアルデータに関してはエクスポートは行わず後から手動で設定するようにしました。</p>
<h2 id="cyclesレンダラーと自作レンダラーの比較">Cyclesレンダラーと自作レンダラーの比較</h2>
<p>エクスポートした設定を自作レンダラーに読み込ませて実際にレンダリングしてみました。</p>
<p>以下はCyclesレンダラーとの比較になります。 <img src="https://lh3.googleusercontent.com/9iSZHfmUlao7uH96lxvQg0KxZFJTAE6NbGGL-JsA4eDXrauFYsMLdUqMrEgujnG8Qt2ifCzPnUWVTenqLgNq7K8Q44tPDwubFelVlf90QF-WPLpXNM3kMVSeMgnzUaatgZUMngFXoe7yj36vEpEiOxfFaMWiS3wwtD7WCmd35-tLeb-SSHsfwWPle1cdJqAzlx2WhWT6-OvbnIVy5RmNqumVyplR0ySu0Pr0YCKrOIcuXNqvdh54XD8UrEOclLm7dp9a06E-4-ZFso42027nFLzc88u5CSr7rmP2wmQ9Z_2RbJBZCALehdgrTBbxDifssD0XFtM-iOcE4knrP1j3fulwVocmDVklxO0ZjVBG5zHlVDsvgsjzurCuwqpiz_ZbXcqipJbS4dmlUXypfXOsWZn2d7H-PH-QyjgwQa2sR54u5zNso_J6pGJidHNsB46qMZ5uglpGCA-0BXhIjJsFlYpPm8Qm2uxm9UhboWrebS9crlszEULdZo5IXl-G6ZG_KnOVhwczcfj0cK4Pn2uQn_uTMao9RBjxOHKPqRFWlSf6gPgBO6PaSRcMu5bie9MBUHmeYZZ6GH7Yb3baSbaygnqIzG6ukPPXuPBqRpg=w800-no" /> <img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPpzxSyQqjB_AggK06soOwvNBUCZllcf7cW_5GHisOAzYqBhFJyY2bHSZXz-6ZfKVQCXGxbXfM8uWvqIZVDLKVzHB4Kfn4v4lCVgt1QsEMkR9XMZ1XCAlTxwXFXQiusPeba1bZl5_gIso/w800-no/" /></p>
<p>上画像がCyclesレンダラーでレンダリングした画像で、 下画像が自作レンダラーでレンダリングした画像です。 カメラ設定やオブジェクトの場所は一致させられたと思います。</p>
<p>しかし、レンダラー間でのマテリアルが取るパラメータの違いや係数の違い、 色空間設定の違いから、 結果を完全に一致させるにはまだ工夫が必要だと感じました。 一応今のままでも簡単な比較には使えそうです。</p>
<p>私のレンダラー向けのエクスポーターは、 <a href="https://github.com/byzin/Nanairo/blob/master/tool/blender_scene_exporter.py">blender_scene_exporter.py</a> にあります。 参考にどうぞ。</p>
<h2 id="参考">参考</h2>
<ol type="1">
<li>Blender Documentation Python API: <a href="https://docs.blender.org/api/current/" class="uri">https://docs.blender.org/api/current/</a></li>
</ol>
<section class="footnotes">
<hr />
<ol>
<li id="fn1"><p>この記事内で使用したBlenderのバージョンは <strong>2.79b</strong> です。<a href="#fnref1" class="footnote-back">↩</a></p></li>
</ol>
</section>
</body>
</html>
Zinhttp://www.blogger.com/profile/00473704352385380653noreply@blogger.com0tag:blogger.com,1999:blog-5029251693178115279.post-89844395513764712952017-12-17T11:59:00.000+09:002017-12-17T11:59:26.162+09:00レンダリング方程式の変数変換<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>rendering_equation_jacobian</title>
<style type="text/css">
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.line-block{white-space: pre-line;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-AMS_CHTML-full" type="text/javascript"></script>
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<h1 id="レンダリング方程式の変数変換">レンダリング方程式の変数変換</h1>
<p>このページは <a href="https://qiita.com/advent-calendar/2017/raytracing">レイトレ Advent Calendar 2017</a> の記事である. 本ページでは,レンダリング方程式の変数変換について考える.</p>
<p><strong>記号について</strong></p>
<p>本ページでは以下の記号は定義済として扱う.</p>
<table>
<thead>
<tr class="header">
<th style="text-align: center;">記号</th>
<th style="text-align: center;">説明</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;"><span class="math inline">\(\omega_{n}\)</span></td>
<td style="text-align: center;">単位法線ベクトル</td>
</tr>
<tr class="even">
<td style="text-align: center;"><span class="math inline">\(\omega_{i}\)</span></td>
<td style="text-align: center;">入射方向の単位ベクトル</td>
</tr>
<tr class="odd">
<td style="text-align: center;"><span class="math inline">\(\omega_{o}\)</span></td>
<td style="text-align: center;">反射方向の単位ベクトル</td>
</tr>
<tr class="even">
<td style="text-align: center;"><span class="math inline">\(L_{o}\)</span></td>
<td style="text-align: center;">ある点からの反射光の放射輝度</td>
</tr>
<tr class="odd">
<td style="text-align: center;"><span class="math inline">\(L_{e}\)</span></td>
<td style="text-align: center;">ある点が自発光している場合の放射輝度</td>
</tr>
<tr class="even">
<td style="text-align: center;"><span class="math inline">\(L_{i}\)</span></td>
<td style="text-align: center;">ある点への入射光の放射輝度</td>
</tr>
<tr class="odd">
<td style="text-align: center;"><span class="math inline">\(S^{2}\)</span></td>
<td style="text-align: center;">半球上の微小立体角の集合</td>
</tr>
<tr class="even">
<td style="text-align: center;"><span class="math inline">\(M\)</span></td>
<td style="text-align: center;">空間中にある物体上の微小面積の集合</td>
</tr>
<tr class="odd">
<td style="text-align: center;"><span class="math inline">\(f_{r}\)</span></td>
<td style="text-align: center;">BRDF</td>
</tr>
</tbody>
</table>
<p>微小立体角を積分する形のレンダリング方程式は式1で表される.</p>
<p><span class="math display">\[
\begin{align}
L_{o} \left( x, \boldsymbol{\omega_{o}} \right) =
L_{e} \left( x, \boldsymbol{\omega_{o}} \right) +
\int_{S^{2}}
f_{r} \left( x, \boldsymbol{\omega_{i}}, \boldsymbol{\omega_{o}} \right)
L_{i} \left( x, \boldsymbol{\omega_{i}} \right)
cos \theta_{\omega_{n}}
d \sigma \left( \boldsymbol{\omega_{i}} \right)
\tag{1}
\end{align}
\]</span></p>
<p>式1では, 方向 <span class="math inline">\(\omega_{i}\)</span> を中心とした微小立体角を半球上で積分することによって 放射輝度の計算を行っている.</p>
<p>一方で,入射方向 <span class="math inline">\(\omega_{i}\)</span> ,出射方向 <span class="math inline">\(\omega_{o}\)</span> の代わりに, 下図のように空間中の3点を接続する形のレンダリング方程式を考えることもできる.</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkdBSaITAPmut3NntpvXszTL5KDFVGmDNW0Se70HSfHZExeZOm1ugIULYPxVtImH3d2KDJcWhje6Mtop0bjO2kYRbQX9xOLHMGkmI7j3NEvYqNW6BnwlpC-9RvptjBsbsLfH-FMaPo7CI/w600-no/" /></p>
<p>3点接続のレンダリング方程式では, 点 <span class="math inline">\(x^{''}\)</span> を中心とした微小面積を 空間中の物体上で積分することで放射輝度の計算を行う.</p>
<p>微小面積の積分では,点 <span class="math inline">\(x\)</span> から半球を通して見える範囲の微小面積のみを積分したい. そこで次の関数を導入する.</p>
<p><span class="math display">\[
\begin{align}
V \left( x \leftrightarrow x^{''} \right) =
\begin{cases}
1 \ \ \left( x と x^{''} の間に遮蔽物が無い場合 \right) \\
0 \ \ \left( x と x^{''} の間に遮蔽物がある場合 \right)
\end{cases}
\tag{2}
\end{align}
\]</span></p>
<p>この関数によって,点 <span class="math inline">\(x\)</span> から半球を通して見えない微小面積をカットする.</p>
<p>次に,微小立体角 <span class="math inline">\(d \sigma\)</span> と微小面積 <span class="math inline">\(dA\)</span> の関係は,下図から式3のように表すことができる.</p>
<p><img src="https://lh3.googleusercontent.com/DrmCCOoncyaFIEK4hDEsAzhHOcGAQGBRzlz-hf6typQwkjHq_cYwKgue_iiSr-PvzeCzQQVvfFACjttP6cXpIsq6otJludLv-mbdjb4KSVf-YLAAy6Q4XHGkElNJSgqw40jF1VyviOwCYRjEcdfc5crIKIwaU2ffWJaQePWzO9WxKyxOtlMRB6vNvvr_H5Zq6HmUjXK03tlkNckO0P_xV6w0XwCMFGA9A9DhnCP1RTvaws7XetvcbY4hv_RwAet6-dHWwyLbvf-GPKwvBpPki0VXwjYDz7kIOQ6b_0Z0prBcO5Ui9WDsfsEBUGFHmteW_lEDprOOFZU4xRkDTmEHfwTw00JMW9Aee8iXYanleJouTffSbA9ZvHRx2YvEaVX8YSKW38UsdzLkmHwe2IW1qBx0nYBArgFIHQI6iIqn65HG-2g4zAYQAN15aCUZYC-5moOs85L577DqgN2ZkarQlYH1PTKAxEmjO-Z7cEfultgVRfPRH84IAfnvRqOeNfYTchlQVmSXl07b27auvJ5hHH994D8iewz-6sQwXCYim0U7eHlrA73p4shAEF4qbo5rtl8pYzQNXbHJ1CtASpCEk0o8NT0xWqBpLCW1cgf6nw=w600-no" /></p>
<p><span class="math display">\[
\begin{align}
d \sigma = \frac{dA cos \theta_{\omega_{n^{''}}}}{\left| x - x^{''} \right|^{2}}
\tag{3}
\end{align}
\]</span></p>
<p>式2,3から,式1を基にして微小面積を積分する形のレンダリング方程式は</p>
<p><span class="math display">\[
\begin{align}
L_{o} \left( x \rightarrow x^{'} \right) =
L_{e} \left( x \rightarrow x^{'} \right) +
\int_{M}
f_{r} \left( x^{'} \rightarrow x \rightarrow x^{''} \right)
L \left( x \leftarrow x^{''} \right)
V \left( x \leftrightarrow x^{''} \right)
\frac{cos \theta_{\omega_{n}} cos \theta_{\omega_{n^{''}}}}
{\left| x - x^{''} \right|^{2}}
dA \left( x^{''} \right)
\tag{4}
\end{align}
\]</span></p>
<p>となる.</p>
<h2 id="まとめ">まとめ</h2>
<p>本ページではレンダリング方程式の変数変換について簡単にまとめた. 積分の変数変換ができれば,論文の式の検証ができたり自分で新しい式を考えることができて 便利です.</p>
<h2 id="参考文献">参考文献</h2>
<ol type="1">
<li>James T. Kajiya: The rendering equation (1986)</li>
</ol>
</body>
</html>
Zinhttp://www.blogger.com/profile/00473704352385380653noreply@blogger.com0tag:blogger.com,1999:blog-5029251693178115279.post-4224536668459916822017-08-13T21:44:00.000+09:002017-08-13T21:44:43.920+09:00Layered Diffuse Surface (Interfaced Lambertian BRDF)<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="generator" content="pandoc">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title></title>
<style type="text/css">code{white-space: pre;}</style>
<script src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_CHTML-full" type="text/javascript"></script>
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<h1 id="layered-diffuse-surface-interfaced-lambertian-brdf">Layered Diffuse Surface (Interfaced Lambertian BRDF)</h1>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiseiTCW4xqD9nCCTus-88nP9C4Sq6UwWHmLhY5Vn8v0VPn1jZiC6FF8NgBh-MfnuWLWU5ylvfVFTzGRCHkbfDE9-j3TakDblZVrhHDeI0GKMzh6AH6jq1k6biK_Xqvaf5dgzIP3_f3MBE/w430-no/" /> <img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNuZ_3mr4RFX1eSthK79-fTQDjsdxJXkXJdB6Ok7uKF1ej0QQRWv-dqkjli2rCGt-8B4Le8UBY39vWw7myEPf74skWC2gP2Or9D3_5ik41agjnx-BMKw26SSKiaO31lUzEPeGA5ZPBeAU/w430-no/" /></p>
<p>このページは <a href="https://sites.google.com/site/raytracingcamp5/">レイトレ合宿5‽</a> アドベントカレンダー第9週目の記事です.</p>
<p>本ページでは,モンテカルロレイトレーシング法において, 上図のような鏡面反射する層を持った拡散反射基板の表面 (Interfaced Lambertian BRDF) をレンダリングする方法を説明します. Interfaced Lambertian BRDF の実装に必要な パラメータや数式,重点的サンプリングの方法を説明します.</p>
<p><strong>記号について</strong></p>
<p>本ページでは以下の記号は定義済として扱います.</p>
<table>
<thead>
<tr class="header">
<th style="text-align: center;">記号</th>
<th style="text-align: center;">説明</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;"><span class="math inline">\(\omega_{n}\)</span></td>
<td style="text-align: center;">Macrosurfaceの単位法線ベクトル</td>
</tr>
<tr class="even">
<td style="text-align: center;"><span class="math inline">\(\omega_{m}\)</span></td>
<td style="text-align: center;">Microsurfaceの単位法線ベクトル,本ページではマイクロファセット法線と呼ぶ</td>
</tr>
<tr class="odd">
<td style="text-align: center;"><span class="math inline">\(\omega_{i}\)</span></td>
<td style="text-align: center;">入射方向の単位ベクトル</td>
</tr>
<tr class="even">
<td style="text-align: center;"><span class="math inline">\(\omega_{o}\)</span></td>
<td style="text-align: center;">反射方向の単位ベクトル</td>
</tr>
<tr class="odd">
<td style="text-align: center;"><span class="math inline">\(f_{r}\)</span></td>
<td style="text-align: center;">BRDF</td>
</tr>
<tr class="even">
<td style="text-align: center;"><span class="math inline">\(n_{i}\)</span></td>
<td style="text-align: center;">入射側の媒体の屈折率</td>
</tr>
<tr class="odd">
<td style="text-align: center;"><span class="math inline">\(n_{o}\)</span></td>
<td style="text-align: center;">透過側の媒体の屈折率</td>
</tr>
<tr class="even">
<td style="text-align: center;"><span class="math inline">\(n\)</span></td>
<td style="text-align: center;"><span class="math inline">\(\frac{n_{o}}{n_{i}}\)</span></td>
</tr>
<tr class="odd">
<td style="text-align: center;"><span class="math inline">\(F\)</span></td>
<td style="text-align: center;">フレネル項</td>
</tr>
</tbody>
</table>
<h2 id="本モデルについて">本モデルについて</h2>
<p>Interfaced Lambertian BRDF は,下図のようにフレネル反射層と拡散反射基板から構成されます. このモデルは,フレネル反射層の境界での鏡面反射と 層内部の多重反射後の散乱を考慮しています. フレネル反射層と拡散反射基板はそれぞれ鏡面反射,拡散反射のMicrofacetモデルで表現され, 必要なパラメータもそれぞれのMicrofacetモデルのパラメータを組み合わせるだけの シンプルなモデルとなっています.</p>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjz8Je-fRpmHuE616rc4godYsLMCqZliGjl8ClucT-VZ1zGWLrLJjgg58YVBJiOkEuimTaOj_ovlNtVgqMfDUz93JUtCOJMcsRIPwRLOS1RmHBB6qAoTGwoda3dMuA5GI1ZjlHf6o4b_9U/w430-no/" /> <img src="https://lh3.googleusercontent.com/X6Nt0t61uaBx2G83c_GEFNVNq8nwIDnsOeMfZZKeBi7Wgj-fTJiVZIosyoHsL_grnaKGasYXYHdSPc0ZmvF1rJETFu6Mmh2AKg2lWl_rh0Btf63dud4P5ADTZEq5EFeVcFC8DOE31N5hgQWK9F_-9_CgoFd_vzfDB-8Is7IfmvTvgF1_DFoDsTZFLJk-cBlbcro-Cu61f_LfmCF-A29_CSQj2iBYsv8TO0UO8C_HM51DvG931y-ak0dIIsI-fR0r_a4IbMVyom6SbDDn59zn1GxcGtzy1BOf-bTArgv2z8gjzKx9l5izIbxxzuwiAhAcUprILDxAcWHamB1I08C9IxkedG662PPFyGFJ9NZDcsLnTcdK5ypIKL15FKyxiA2_z6pdd_R4QoPIYti9grNOz8QvbUiR6leOwyQCdE4E9XxhjwBBK_u4AkA3I2KoWMBfKO2AmAH34cUoRO0siHxNaY9UcRo0u4jksKvTOu5YXTGkkSWvcRWpYCX3BKA4_nbQt6cjBXIN1AUb1sEivWlJKPXMhzcS_6bjn-W21doh3EBRgsqaWBL9BYT-Ba8am7UZUaSFrd3BZzFt556cRH9FkzCiExNDF7FpkCZe_Zl-cJYjJNHW-ISdvtMc=w430-no" /></p>
<h2 id="interfaced-lambertian-brdf">Interfaced Lambertian BRDF</h2>
<p>Interfaced Lambertian BRDF の評価は, 入射光に対する鏡面反射 <span class="math inline">\(f_{s}\)</span> と, 多重反射後の散乱 <span class="math inline">\(f_{b}\)</span> に分けて行います.</p>
<p><span class="math display">\[
\begin{align}
f_{r} \left( x, \omega_{i}, \omega_{o} \right) =
f_{s} \left( x, \omega_{i}, \omega_{o} \right) +
f_{b} \left( x, \omega_{i}, \omega_{o} \right)
\tag{1}
\end{align}
\]</span></p>
<p>入射光に対する鏡面反射 <span class="math inline">\(f_{s}\)</span> には, 鏡面のMicrofacetモデルを用います (Beckman,GGXなど) .</p>
<p><span class="math display">\[
\begin{align}
f_{s} \left( x, \omega_{i}, \omega_{o} \right) =
\frac{1}{4 \left( \omega_{i} \cdot \omega_{n} \right)
\left( \omega_{o} \cdot \omega_{n} \right)}
F \left( \omega_{i}, \omega_{m} \right)
G_{2} \left( \omega_{i}, \omega_{o}, \omega_{m} \right)
D \left( \omega_{m} \right)
\tag{2}
\end{align}
\]</span></p>
<p>多重反射後の散乱 <span class="math inline">\(f_{b}\)</span> は, 拡散反射面のMicrofacetモデルに, 入射光の内部への屈折 <span class="math inline">\(T \left( \omega_{i}, \omega_{m} \right)\)</span> と 内部での多重反射 <span class="math inline">\(\frac{1}{\pi n^{2} \left( 1 - r_{i} \rho \right) }\)</span> と, 内部から外部へ散乱する時の屈折 <span class="math inline">\(T \left( \omega_{o}, \omega_{m} \right)\)</span> を 考慮したものになります.</p>
<p><span class="math display">\[
\begin{align}
f_{b} \left( x, \omega_{i}, \omega_{o} \right) = &
\frac{\rho}{\pi n^{2} \left( 1 - r_{i} \rho \right)}
\int T \left( \omega_{i}, \omega_{m_{b}} \right)
T \left( \omega_{i}, \omega_{m_{b}} \right)
D \left( \omega_{m_{b}} \right)
G \left( \omega_{i}, \omega_{o}, \omega_{m_{b}} \right)
\frac{ \left| \omega_{i} \cdot \omega_{m_{b}} \right|
\left| \omega_{o} \cdot \omega_{m_{b}} \right| }
{ \left| \omega_{i} \cdot \omega_{n} \right|
\left| \omega_{o} \cdot \omega_{n} \right| }
d \omega_{m_{b}}
\\
r_{i} = & 1 - \frac{1 - r_{e}}{n^{2}}
\\
r_{e} = & \frac{1}{2} -
\frac{2 n^{3} \left( n^{2} + 2 n - 1 \right)}
{\left( n^{2} + 1 \right) \left( n^{4} - 1 \right)} +
\frac{\left( n - 1 \right) \left( 3 n + 1 \right)}
{6 \left( n + 1 \right)^{2}} +
\frac{8 n^{4} \left( n^{4} + 1 \right)}
{\left( n^{2} + 1 \right) \left( n^{4} - 1 \right)^{2}}
ln \left( n \right) +
\frac{n^{2} \left( n^{2} - 1 \right)^{2}}
{\left( n^{2} + 1 \right)^{3}}
ln \left( \frac{n - 1}{n + 1} \right)
\tag{3}
\end{align}
\]</span></p>
<p>この式には積分が含まれているため,モンテカルロ法を用いて Microfacet法線 <span class="math inline">\(\omega_{m_{b}}\)</span> をサンプリングして解きます.</p>
<p><span class="math display">\[
\begin{align}
f_{b} \left( x, \omega_{i}, \omega_{o} \right) =
\frac{\rho}{\pi n^{2} \left( 1 - r_{i} \rho \right)}
\frac{
T \left( \omega_{i}, \omega_{m_{b}} \right)
T \left( \omega_{i}, \omega_{m_{b}} \right)
D \left( \omega_{m_{b}} \right)
G \left( \omega_{i}, \omega_{o}, \omega_{m_{b}} \right)
\frac{ \left| \omega_{i} \cdot \omega_{m_{b}} \right|
\left| \omega_{o} \cdot \omega_{m_{b}} \right| }
{ \left| \omega_{i} \cdot \omega_{n} \right|
\left| \omega_{o} \cdot \omega_{n} \right| }}
{p \left( \omega_{m_{b}} \right) }
\tag{4}
\end{align}
\]</span></p>
<h2 id="重点的サンプリング-importance-sampling">重点的サンプリング (Importance Sampling)</h2>
<p>Interfaced Lambertian BRDF の重点的サンプリングは, フレネル反射層の反射分布,もしくは拡散反射基板の反射分布に従ってサンプリングを行います.</p>
<p>まず最初は,フレネル反射層,拡散反射基板どちらの反射分布に従ってサンプリングを行うかを決定します. ここでは,フレネル反射層,拡散反射基板それぞれの総反射率をもとに確率的に決定します.</p>
<p><span class="math display">\[
\begin{align}
R_{s} = & r_{e}
\\
R_{b} = & \frac{ \left( 1 - r_{e} \right) ^{2} \rho }
{ n^{2} \left( 1 - r_{i} \rho \right) }
\tag{5}
\end{align}
\]</span></p>
<p><span class="math inline">\(R_{s}\)</span> ,<span class="math inline">\(R_{b}\)</span> はそれぞれフレネル反射層,拡散反射基板の総反射率です. <span class="math inline">\(u_{1} \in [0, 1)\)</span> となる一様乱数を用いて, <span class="math inline">\(u_{1} < \frac{R_{s}}{ \left( R_{s} + R_{b} \right) }\)</span> となる場合は フレネル反射層の反射分布に従ったサンプリングを行い,そうでない場合は, 拡散反射基板の反射分布に従ったサンプリングを行います.</p>
<p>フレネル反射層の反射分布のpdf <span class="math inline">\(p_{s} \left( \omega_{o} \right)\)</span> や 反射方向のサンプリング方法は層のMicrofacetモデルに従う (Beckman,GGXなど). 反射方向のサンプリングの方法については,<a href="http://tatsyblog.sakura.ne.jp/wordpress/applications/graphics/1742/">アドベントカレンダー第8回</a> や <a href="https://zin-box.blogspot.jp/2016/03/rough-specular-surface-ggx-brdf.html"><em>Rough Specular Surface (GGX BRDF)</em></a> を参照してください.</p>
<p>拡散反射基板の反射分布のpdf <span class="math inline">\(p_{b} \left( \omega_{o} \right)\)</span> は,</p>
<p><span class="math display">\[
\begin{align}
p_{b} \left( \omega_{o} \right) =
\frac{ \left( \omega_{o} \cdot \omega_{n} \right) }{\pi}
\tag{6}
\end{align}
\]</span></p>
<p>であり, <span class="math inline">\(p_{b} \left( \omega_{o} \right)\)</span> に従って反射方向をサンプリングします. 反射方向のサンプリング方法は <a href="https://zin-box.blogspot.jp/2015/11/lambert-brdf.html"><em>Smooth Diffuse Surface (Lambert BRDF)</em></a> を参照してください.</p>
<p>最終的な反射方向のpdf <span class="math inline">\(p \left( \omega_{o} \right)\)</span> は,</p>
<p><span class="math display">\[
\begin{align}
p \left( \omega_{o} \right) =
\frac{R_{s}}{ \left( R_{s} + R_{b} \right) }
p_{s} \left( \omega_{o} \right) +
\frac{R_{b}}{ \left( R_{s} + R_{b} \right) }
p_{b} \left( \omega_{o} \right)
\tag{7}
\end{align}
\]</span></p>
<p>となります.</p>
<h2 id="まとめ">まとめ</h2>
<p><strong>パラメータ</strong></p>
<table>
<thead>
<tr class="header">
<th style="text-align: center;">名称</th>
<th style="text-align: center;">記号</th>
<th style="text-align: center;">値</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;">拡散反射基板の反射率</td>
<td style="text-align: center;"><span class="math inline">\(\rho\)</span></td>
<td style="text-align: center;"><span class="math inline">\(0 \le \rho \le 1\)</span></td>
</tr>
<tr class="even">
<td style="text-align: center;">表面粗さ</td>
<td style="text-align: center;"><span class="math inline">\(roughness\)</span></td>
<td style="text-align: center;"><span class="math inline">\(0 < roughness \le 1\)</span></td>
</tr>
</tbody>
</table>
<p><strong>レンダリング</strong></p>
<table style="width:50%;">
<colgroup>
<col style="width: 16%" />
<col style="width: 16%" />
<col style="width: 16%" />
</colgroup>
<thead>
<tr class="header">
<th style="text-align: center;">名称</th>
<th style="text-align: center;">記号</th>
<th style="text-align: center;">値</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;">BRDF</td>
<td style="text-align: center;"><span class="math inline">\(f_{r} \left( x, \omega_{i}, \omega_{o} \right)\)</span></td>
<td style="text-align: center;"><span class="math inline">\(f_{s} \left( x, \omega_{i}, \omega_{o} \right) + f_{b} \left( x, \omega_{i}, \omega_{o} \right)\)</span></td>
</tr>
<tr class="even">
<td style="text-align: center;">pdf</td>
<td style="text-align: center;"><span class="math inline">\(p \left( \omega_{o} \right)\)</span></td>
<td style="text-align: center;"><span class="math inline">\(\frac{R_{s}}{ \left( R_{s} + R_{b} \right) } p_{s} \left( \omega_{o} \right) + \frac{R_{b}}{ \left( R_{s} + R_{b} \right) } p_{b} \left( \omega_{o} \right)\)</span></td>
</tr>
<tr class="odd">
<td style="text-align: center;">反射レイのWeight</td>
<td style="text-align: center;"><span class="math inline">\(\frac{f_{r} \left( x, \omega_{i}, \omega_{o} \right) \left( \omega_{o} \cdot \omega_{n} \right)} {p \left( \omega_{o} \right)}\)</span></td>
<td style="text-align: center;"><span class="math inline">\(\frac{f_{r} \left( x, \omega_{i}, \omega_{o} \right) \left( \omega_{o} \cdot \omega_{n} \right)} {p \left( \omega_{o} \right)}\)</span> (特にキャンセルできる項は無い)</td>
</tr>
</tbody>
</table>
<p>以上,Interfaced Lambertian BRDFについて簡単にまとめました.</p>
<h2 id="参考文献">参考文献</h2>
<ol type="1">
<li>Daniel Meneveaux: Rendering Rough Opaque Materials with Interfaced Lambertian Microfacets (2017)</li>
</ol>
</body>
</html>
Zinhttp://www.blogger.com/profile/00473704352385380653noreply@blogger.com0tag:blogger.com,1999:blog-5029251693178115279.post-20802202330818049052016-08-07T18:59:00.000+09:002016-08-07T18:59:30.064+09:00BRDFのテスト<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="generator" content="pandoc">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title></title>
<style type="text/css">code{white-space: pre;}</style>
<style type="text/css">
div.sourceCode { overflow-x: auto; }
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
</style>
<script src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_CHTML-full" type="text/javascript"></script>
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<h1 id="brdfのテスト">BRDFのテスト</h1>
<p>このページは <a href="https://sites.google.com/site/raytracingcamp4/">レイトレ合宿4!?</a> アドベントカレンダー第7週目の記事です. レイトレ合宿まで1ヶ月をきりました. そろそろ提出用のシーン作成やレンダラーのデバッグに集中しているころではないでしょうか.</p>
<p>私はレンダラーの実装に不具合があるかどうかは, レンダリングした画像を見て違和感を持つかどうかで判断しています. この方法は主観的であり, 画像に違和感を持たなくても不具合が含まれている可能性は大いにあります. そこで,自動テストを実装して客観的に不具合の判定をするようにします.</p>
<p>このページでは物理ベースなBRDFの自動テストについて考えます.</p>
<h2 id="物理ベースなbrdf">物理ベースなBRDF</h2>
<p>初めに,物理ベースなBRDFについて確認しておきます.</p>
<table>
<thead>
<tr class="header">
<th style="text-align: center;">定義済み記号</th>
<th style="text-align: center;">説明</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;"><span class="math inline">\(\omega_{n}\)</span></td>
<td style="text-align: center;">法線ベクトル</td>
</tr>
<tr class="even">
<td style="text-align: center;"><span class="math inline">\(\omega_{i}\)</span></td>
<td style="text-align: center;">入射方向の単位ベクトル</td>
</tr>
<tr class="odd">
<td style="text-align: center;"><span class="math inline">\(\omega_{o}\)</span></td>
<td style="text-align: center;">反射方向の単位ベクトル</td>
</tr>
<tr class="even">
<td style="text-align: center;"><span class="math inline">\(f_{r}\)</span></td>
<td style="text-align: center;">BRDF</td>
</tr>
</tbody>
</table>
<p>物理ベースなBRDFは,反射する放射エネルギーが負になることはないので</p>
<p><span class="math display">\[
\begin{align}
\forall \boldsymbol{\omega_{i}} \
\forall \boldsymbol{\omega_{o}}, \
f_{r}(x, \boldsymbol{\omega_{o}} \leftarrow \boldsymbol{\omega_{i}}) \
cos \theta_{\boldsymbol{\omega_{o}}} \ge 0
\end{align}
\]</span></p>
<p><span class="math inline">\(cos \theta_{\boldsymbol{\omega_{o}}} \ge 0\)</span> であるため,</p>
<p><span class="math display">\[
\begin{align}
\forall \boldsymbol{\omega_{i}} \
\forall \boldsymbol{\omega_{o}}, \
f_{r}(x, \boldsymbol{\omega_{o}} \leftarrow \boldsymbol{\omega_{i}}) \ge 0
\tag{1}
\end{align}
\]</span></p>
<p>となります. また,物理ベースなBRDFは以下の2つの特性を持ちます.</p>
<h3 id="ヘルムホルツの相反性-helmholtz-reciprocity">ヘルムホルツの相反性 (Helmholtz Reciprocity)</h3>
<p>BRDFの値は入射・出射方向が入れ替わっても変化しません.</p>
<p><span class="math display">\[
\begin{align}
f_{r}(x, \boldsymbol{\omega_{o}} \leftarrow \boldsymbol{\omega_{i}}) =
f_{r}(x, \boldsymbol{\omega_{i}} \leftarrow \boldsymbol{\omega_{o}})
\tag{2}
\end{align}
\]</span></p>
<h3 id="エネルギー保存則-energy-conservation">エネルギー保存則 (Energy Conservation)</h3>
<p>ある点から反射した総出射光束は総入射光束以下となります.</p>
<p><span class="math display">\[
\begin{align}
\forall \boldsymbol{\omega_{i}}, \
\int_{\Omega}
f_{r}(x, \boldsymbol{\omega_{o}} \leftarrow \boldsymbol{\omega_{i}}) \
cos \theta_{\boldsymbol{\omega_{o}}}
d \sigma(\boldsymbol{\omega_{o}})
\le 1
\tag{3}
\end{align}
\]</span></p>
<h2 id="モンテカルロ法によるテスト">モンテカルロ法によるテスト</h2>
<p>式<span class="math inline">\((1)\)</span>,<span class="math inline">\((2)\)</span>,<span class="math inline">\((3)\)</span>の自動テストを実装します. 式<span class="math inline">\((3)\)</span>は解析的に解くことが難しいため,モンテカルロ法を用いてテストを行います. モンテカルロ法を用いた場合,式<span class="math inline">\((3)\)</span>は以下のように書きかえられます.</p>
<p><span class="math display">\[
\begin{align}
\forall \boldsymbol{\omega_{i}},
\frac{1}{N}
\sum_{k=1}^{N}
\frac{f_{r}(x, \boldsymbol{\omega_{ok}} \leftarrow \boldsymbol{\omega_{i}})
cos \theta_{\boldsymbol{\omega_{ok}}}}
{p_{u} \left( \boldsymbol{\omega_{ok}} \right)}
\le 1
\tag{4}
\end{align}
\]</span></p>
<p>ここで,<span class="math inline">\({p_{u} \left( \boldsymbol{\omega_{o}} \right)}\)</span>は <span class="math inline">\(\boldsymbol{\omega_{o}}\)</span>の確率密度関数 (PDF) です. このテストでは,半球上の方向を一様にサンプルするようにします <span class="math inline">\(\left({p_{u} \left( \boldsymbol{\omega_{o}} \right)} = \frac{1}{2 \pi} \right)\)</span>.</p>
<p>C++言語で <a href="https://github.com/google/googletest">GoogleTest</a> を用いたテストの擬似コードを記述します.</p>
<div class="sourceCode" id="energy"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="co">// エネルギー保存則のテスト</span>
TEST(BrdfTest, EnergyConservationTest)
{
Brdf brdf; <span class="co">// テスト対象であるBRDFの宣言,初期化</span>
<span class="dt">const</span> <span class="dt">int</span> N = <span class="dv">1000000</span>;
<span class="co">// 様々な入射方向に対してテストを行う</span>
<span class="kw">for</span> (<span class="dt">int</span> i = <span class="dv">0</span>; i < N; ++i) {
<span class="dt">const</span> <span class="dt">float</span> energySum = <span class="fl">0.0</span>;
<span class="dt">const</span> Vector3 vin = sampleDirectionUniformly(); <span class="co">// 半球上の方向を一様にサンプル</span>
<span class="kw">for</span> (<span class="dt">int</span> o = <span class="dv">0</span>; o < N; ++i) {
<span class="dt">const</span> Vector3 vout = sampleDirectionUniformly();
<span class="dt">const</span> <span class="dt">float</span> f = brdf.f(vin, vout); <span class="co">// BRDFの評価</span>
ASSERT_LE(<span class="fl">0.0</span>, f); <span class="co">// 式(1)のテスト</span>
<span class="dt">const</span> <span class="dt">float</span> cosTheta = dot(normal, vout);
energySum += f * cosTheta * (<span class="fl">2.0</span> * pi); <span class="co">// pi は円周率</span>
}
<span class="dt">const</span> <span class="dt">float</span> energy = energySum / (<span class="dt">float</span>)N;
ASSERT_GE(<span class="fl">1.0</span>, energy); <span class="co">// 式(4)のテスト</span>
}
}</code></pre></div>
<div class="sourceCode" id="helmholtz"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="co">// ヘルムホルツの相反性のテスト</span>
TEST(BrdfTest, HelmHoltzReciprocityTest)
{
Brdf brdf;
<span class="dt">const</span> <span class="dt">int</span> N = <span class="dv">1000000</span>;
<span class="kw">for</span> (<span class="dt">int</span> i = <span class="dv">0</span>; i < N; ++i) {
<span class="dt">const</span> Vector3 vin = sampleDirectionUniformly();
<span class="dt">const</span> Vector3 vout = sampleDirectionUniformly();
<span class="dt">const</span> <span class="dt">float</span> f1 = brdf.f(vin, vout); <span class="co">// BRDFの評価</span>
<span class="dt">const</span> <span class="dt">float</span> f2 = brdf.f(-vout, -vin); <span class="co">// 方向を入れ替えたBRDFの評価</span>
<span class="dt">const</span> <span class="dt">float</span> error = <span class="fl">1.0e-5</span>; <span class="co">// 許容できる誤差を定義</span>
ASSERT_FLOAT_EQ(f1, f2, error); <span class="co">// 式(2)のテスト</span>
}
}</code></pre></div>
<p>実際にテストを実装する場合は, モンテカルロ法による<span class="math inline">\(N\)</span>回試行の和を求める際に情報落ちの危険があるため, 補正加算も考慮したほうがいいと思います.</p>
<h3 id="重点的サンプリング-importance-sampling-のテスト">重点的サンプリング (Importance sampling) のテスト</h3>
<p>BRDFによっては,反射方向を重点的サンプリングする式が定義してあることがあります. 重点的サンプリングの際の反射方向のPDFを <span class="math inline">\(p \left( \boldsymbol{\omega_{o}} \right)\)</span> とします. 確率密度関数の性質から,</p>
<p><span class="math display">\[
\begin{align}
\int_{\Omega}
p \left( \boldsymbol{\omega_{o}} \right)
d \sigma \left( \boldsymbol{\omega_{o}} \right)
= 1
\tag{5}
\end{align}
\]</span></p>
<p>となります.式<span class="math inline">\((3)\)</span>と同様に,解析的に解くことが難しいためモンテカルロ法を 用いて以下のように書きかえます.</p>
<p><span class="math display">\[
\begin{align}
\frac{1}{N}
\sum_{k=1}^{N}
\frac{p \left( \boldsymbol{\omega_{ok}} \right)}
{p_{u} \left( \boldsymbol{\omega_{ok}} \right)}
\approx 1
\tag{6}
\end{align}
\]</span></p>
<p>擬似コードを以下に記述します.</p>
<div class="sourceCode" id="pdf"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="co">// PDFのテスト</span>
TEST(BrdfTest, PdfTest)
{
Brdf brdf;
<span class="dt">const</span> <span class="dt">int</span> N = <span class="dv">1000000</span>;
<span class="co">// 様々な入射方向に対してテストを行う</span>
<span class="kw">for</span> (<span class="dt">int</span> i = <span class="dv">0</span>; i < N; ++i) {
<span class="dt">float</span> pdfSum = <span class="fl">0.0</span>;
<span class="dt">const</span> Vector3 vin = sampleDirectionUniformly();
<span class="kw">for</span> (<span class="dt">int</span> o = <span class="dv">0</span>; o < N; ++o) {
<span class="dt">const</span> Vector3 vout = sampleDirectionUniformly();
<span class="dt">const</span> <span class="dt">float</span> pdf = brdf.pdf(vin, vout); <span class="co">// 反射方向のPDFを評価</span>
pdfSum += pdf * (<span class="fl">2.0</span> * pi);
}
<span class="dt">const</span> <span class="dt">float</span> pdf = pdfSum / (<span class="dt">float</span>)N;
<span class="dt">const</span> <span class="dt">float</span> error = <span class="fl">1.0e-5</span>; <span class="co">// 許容できる誤差を定義</span>
ASSERT_FLOAT_NEAR(<span class="fl">1.0</span>, pdf, error); <span class="co">// 式(6)のテスト</span>
}
}</code></pre></div>
<h2 id="終わりに">終わりに</h2>
<p>BRDFのテストについて考えました. このテストで確認できたことは,物理に基づいたBRDFの定義を満たしているか ということであり,BRDFの反射分布が正しいかというところまでは確認できていません. ここからテスト項目を増やしていって,確認できることを広げていこうと思います.</p>
</body>
</html>Zinhttp://www.blogger.com/profile/00473704352385380653noreply@blogger.com0tag:blogger.com,1999:blog-5029251693178115279.post-65734163410667155542016-03-05T15:20:00.000+09:002016-03-06T11:00:44.172+09:00Rough Specular Surface (GGX BRDF)<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="generator" content="pandoc">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title></title>
<style type="text/css">code{white-space: pre;}</style>
<script src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"></script>
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<h1 id="rough-specular-surface-ggx-brdf">Rough Specular Surface (GGX BRDF)</h1>
<p><img src="https://lh3.googleusercontent.com/QuuihybEcyAi0bovw1T3tOsuKLehDfinvIryfw5a67FqX-Zx9rFaw8BzMXXQHOR3_VgLPCJ_Dhlkj3VCoXFj7IxINiRxwY2kA4LIEylxDxCYmRBPfWnwV3uPb8PRPx1u1C94YR0MIzai7G-2G8Zppw9rroHQWOGw8Q5CH_-Q4_zdvBrxOIZ3kSe6zi2ae3UN08V0mQP-u8-SJpS5aBjwrsiLvXzNgpRuTyGDEm7QrOZm02kqMQfH6nzBPk6vH8u79FfW1FpYRPvst9t3FYzwt7AZi0-VY62-XAUC-BTsuk8MVvJd_NdrN341QPfXdUOBZD8pJKVkWWmyLazI27Hgwx5261WexV5SjFD2ZArQMRxU-5sUVOSYIAsNgH6JyJygy270j40oQ-DMPN5IjKgXt4eondB69ULoci9iuLysH6egA4SKa_quF0ciMCCODp3hXvPkKa-ilropmui88dpqFlm-eGIvb56AuDbu9R_IVEbdXPLxpjd4iiMHoaGL8akRkBweITt8zNRQyha9OE-QUDqdZkvhXquIbQJKr-Aefka2ayGLptMJwPwxE7DisdwXEEcq=w400-no" /> <img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBWtT0sBkM5n5Sg5AfPWtsHUdxidSFKeIQecAqfQIrkzBPm0vKfvRZk_ZHwMRza93ggbsZRmRggwEFsXFEXpb7n-0svZUrddBUdKLuch1w7hFulVhn-OCDqlJ2YSteOSz4YiHtsHjHCXY/w400-no/" /></p>
<p>本ページでは,モンテカルロレイトレーシング法において, 金属など絶縁体の粗い表面を表現する方法を説明する. 言い換えると,粗い表面モデルのBRDFの実装に必要なパラメータや数式, 重点的サンプリングの方法を説明する. 本ページでは,粗い表面モデルとして[1]のGGXモデルを用いる.</p>
<p><strong>記号について</strong></p>
<p>本ページでは以下の記号は定義済として扱う.</p>
<table style="width:19%;">
<colgroup>
<col style="width: 9%" />
<col style="width: 9%" />
</colgroup>
<thead>
<tr class="header">
<th style="text-align: center;">記号</th>
<th style="text-align: center;">説明</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;"><span class="math inline">\(\omega_{n}\)</span></td>
<td style="text-align: center;">Macrosurfaceの単位法線ベクトル</td>
</tr>
<tr class="even">
<td style="text-align: center;"><span class="math inline">\(\omega_{m}\)</span></td>
<td style="text-align: center;">Microsurfaceの単位法線ベクトル,本ページではマイクロファセット法線と呼ぶ</td>
</tr>
<tr class="odd">
<td style="text-align: center;"><span class="math inline">\(\omega_{i}\)</span></td>
<td style="text-align: center;">入射方向の単位ベクトル</td>
</tr>
<tr class="even">
<td style="text-align: center;"><span class="math inline">\(\omega_{o}\)</span></td>
<td style="text-align: center;">反射方向の単位ベクトル</td>
</tr>
<tr class="odd">
<td style="text-align: center;"><span class="math inline">\(f_{r}\)</span></td>
<td style="text-align: center;">BRDF</td>
</tr>
<tr class="even">
<td style="text-align: center;"><span class="math inline">\(n_{i}\)</span></td>
<td style="text-align: center;">入射側の媒体の屈折率</td>
</tr>
<tr class="odd">
<td style="text-align: center;"><span class="math inline">\(n_{o}\)</span></td>
<td style="text-align: center;">透過側の媒体の屈折率</td>
</tr>
<tr class="even">
<td style="text-align: center;"><span class="math inline">\(\eta_{o}\)</span></td>
<td style="text-align: center;">透過側の媒体の消衰係数</td>
</tr>
<tr class="odd">
<td style="text-align: center;"><span class="math inline">\(n\)</span></td>
<td style="text-align: center;"><span class="math inline">\(\frac{n_{o}}{n_{i}}\)</span></td>
</tr>
<tr class="even">
<td style="text-align: center;"><span class="math inline">\(\eta\)</span></td>
<td style="text-align: center;"><span class="math inline">\(\frac{\eta_{o}}{n_{i}}\)</span></td>
</tr>
<tr class="odd">
<td style="text-align: center;"><span class="math inline">\(F\)</span></td>
<td style="text-align: center;">フレネル項</td>
</tr>
<tr class="even">
<td style="text-align: center;"><span class="math inline">\(\chi^{+} \left( x \right)\)</span></td>
<td style="text-align: center;"><span class="math inline">\(\begin{cases} 1 & (0 < x) \\ 0 & (otherwise) \end{cases}\)</span></td>
</tr>
</tbody>
</table>
<h2 id="マイクロファセットモデルとggx">マイクロファセットモデルとGGX</h2>
<figure>
<img src="https://lh3.googleusercontent.com/Wx0P5ODw_0a3oW0dCMGRG6RyPlIZLBziAcp5WrAnQx8z7KuLebGqKTRLOEEDIpcXmqVt6QvnBNOtB9-cqTFba-qmOpgkwwvhT0m5nKnGwK0wrRPiFQDn2JCWlmdBOhD2N9Te2TsltbEvpSnoUYjzc44lFfeyTLZZGdRIJVsrkX0AFbaWzzAOsclfsudMPVuxhgDnORZ6hQXlmC8INbk6z0xNKBgNI9PFAib33IVGI21EVDr2VmF377Pgl23SGh_lUCfhHRZjt_tiqChqyBXlwXZApG92cwT57ZhDh7LObImBNINyC7TLy0PvNm4gLs3EMZJnXhgWOr_-vyAYBmPCjNXtE1XZ990a-avA8fIXeLhFb1lQg2P2_eWHEROdPECxTQxaaGop06oJrCrG7wBtNLtMWWEJZ5oumwcH1o3BFqnXen3e_68pUB2QukkjDvF5XkSM_evchB05xmh_0ry8J1LTj5tsCtZ3pGYN2XMEphJH4MyPN7O8GhoFR4L3OZkdq1Th7VxKmrGKeIIK30m4uDhI_WfN7IUaCJ8et8SfjALsehxQ6pIyauxQmsgEaxWwP0zS=w743-h284-no" />
</figure>
<p>マイクロファセットモデルは様々な 方向を向いた微小平面で構成される表面(Microsurface)を 単純な平面(Macrosurface)で近似したモデルである. このモデルでは,単純化のため波動光学や表面での2回以上の反射は無視する. マイクロファセットモデルは2つの統計量, 法線分布関数 <span class="math inline">\(D\)</span> と Shadowing-Masking Function <span class="math inline">\(G\)</span> を用いて表される.</p>
<h3 id="表面の粗さについて">表面の粗さについて</h3>
<p>GGXは微小平面で見れば鏡面反射しかしていないが, 様々な法線を持った微小平面から構成されているため 表面が粗いほど拡散反射をしているように見える. 表面の粗さは <span class="math inline">\(roughness\)</span> パラメータを用いて制御する. <span class="math inline">\(roughness\)</span> がとる値の範囲は <span class="math inline">\(0 < roughness \le 1\)</span> である. 値が <span class="math inline">\(0\)</span> に近いほど理想的な鏡面反射に近くなり, <span class="math inline">\(1\)</span> に近いほど理想的な拡散反射に近くなる.</p>
<p>また,計算時に用いる表面粗さの値は, <span class="math inline">\(roughness\)</span> を直接用いるのではなく, [3]で解説してあるように</p>
<p><span class="math display">\[
\begin{align}
\alpha = \left( roughness \right)^{2}
\tag{1}
\end{align}
\]</span></p>
<p>を用いるほうがより視覚的に線形比例した変化となる. 本ページでも, <span class="math inline">\(\alpha\)</span> を計算時の表面粗さの値として用いる.</p>
<h3 id="法線分布関数-normal-distribution-function-d">法線分布関数 (Normal Distribution Function) <span class="math inline">\(D\)</span></h3>
<figure>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9LwC_EGGNpT0KE2YuMywTsJYH-h28hKQTasGX_bFd21wGMNmjciUQ5zSTHzIXbjKW3nSK73qZ1fBCWtmOY-XTmfKjAvqcd1ZdqqcN8ROuZXH62TQCRfZNne4wxEI1SYWL9nZyGW1ZNTg/w843-h308-no/" />
</figure>
<p>法線分布関数 <span class="math inline">\(D\)</span> はMicrosurface上にできる法線の統計分布を表したものである. GGXでは <span class="math inline">\(D\)</span> は以下の式で表される.</p>
<p><span class="math display">\[
\begin{align}
D \left( \omega_{m} \right) =
\chi^{+} \left( \omega_{n} \cdot \omega_{m} \right)
\frac{\alpha^{2}}
{\pi \left(
\left( \alpha^{2} - 1 \right)
\left( \omega_{n} \cdot \omega_{m} \right)^{2} + 1 \right)^{2}}
\tag{2}
\end{align}
\]</span></p>
<p>ここでは簡易表記のため, <span class="math inline">\(D \left( \omega_{n}, \omega_{m}, \alpha \right)\)</span> を <span class="math inline">\(D \left( \omega_{m} \right)\)</span> と表記している.</p>
<h3 id="shadowing-masking-function-g">Shadowing-Masking Function <span class="math inline">\(G\)</span></h3>
<figure>
<img src="https://lh3.googleusercontent.com/kzxqwq4wA9K6i-dGCAwTLuqyeQ9zfB6F1dLH88wIL_hTyzidJTylX-jL4QHpgEHIOZsrBD2p6Ve8a1Zx6saRup42scW9x0ik14jmkQDkutY8qHhH3g2qmkTMDkM8hR6KlVThfYiCOvolPTHxoOd5tUJipuVOKiKp9s7eoIMCn8ritvsE40ciKgNSld6DVn7UQpCc7N2SQWHzHIyockY4jYrPqZQN41FyXhN27oMW4X0FVvSJ8qhxnK8AfGRuoWJNJqxBW1jG-JJYMwiutYrbIba_6RFfm1RBl5hId_7TNpsQO0ndRTmih72T0xJsUpr6oxzXOeDy-HkziHhabsTamnUF24hlXA87nCDD74mW4UTzobNvXQE6dLjxKwcmrmneNg9r6d7QuIJrGXR5tU_Sl-hzUu0JLJWHyV3kEu-fc8_ADnwVjesAklr2tlNM5so5EQbJxQK_7p-CJUuAi3gTfqbYGhnKePi7qd4sHvKCxKA6igcmxGtJwC6OqxIZaLwHuKm9FDhzSw3Dls5eKqlTFi2ndmxp7PdTZ4lL-oRMXk4BFs5xbjVubWYSIfFYh9V8XSvL=w744-h204-no" />
</figure>
<p>Shadowing-Masking Function は[2]の論文では <strong>V-cavity</strong>モデルと<strong>Smith</strong>モデルの2通りのモデルを載せているが, ここではSmithモデルを説明する(V-cavityモデルについては[2]を参照).</p>
<p>Shadowing-Masking Function <span class="math inline">\(G\)</span> はある法線を持つMicrosurfaceが可視かどうかの比率 を表したものである. <span class="math inline">\(G_{2}\)</span>は入射方向,反射方向の双方向から可視かどうかの比率を表しており, <span class="math inline">\(G_{1}\)</span>は入射方向もしくは反射方向のどちらか単方向から可視かどうかの比率を表している.</p>
<p><span class="math display">\[
\begin{align}
G_{2} \left( \omega_{i}, \omega_{o}, \omega_{m} \right) = &
G_{1} \left( \omega_{i}, \omega_{m} \right)
G_{1} \left( \omega_{o}, \omega_{m} \right)
\tag{3}
\\
G_{1} \left( \omega, \omega_{m} \right) = &
\chi^{+} \left(
\left( \omega \cdot \omega_{n} \right)
\left( \omega \cdot \omega_{m} \right) \right)
\frac{2 \left( \omega \cdot \omega_{n} \right)}
{ \left( \omega \cdot \omega_{n} \right)
\sqrt{\alpha^{2} + \left( 1 - \alpha^{2} \right)
\left( \omega \cdot \omega_{n} \right)^{2} }}
\tag{4}
\end{align}
\]</span></p>
<p>ここでは簡易表記のため, <span class="math inline">\(G_{1} \left( \omega, \omega_{n}, \omega_{m}, \alpha \right)\)</span> を <span class="math inline">\(G_{1} \left( \omega, \omega_{m} \right)\)</span> と表記している.</p>
<h2 id="ggx-brdf">GGX BRDF</h2>
<p>GGXのBRDFは以下の式になる.</p>
<p><span class="math display">\[
\begin{align}
f_{r} \left( x, \omega_{i}, \omega_{o} \right) =
\frac{1}{4 \left( \omega_{i} \cdot \omega_{n} \right)
\left( \omega_{o} \cdot \omega_{n} \right)}
F \left( \omega_{i}, \omega_{m} \right)
G_{2} \left( \omega_{i}, \omega_{o}, \omega_{m} \right)
D \left( \omega_{m} \right)
\tag{5}
\end{align}
\]</span></p>
<p>ここでは簡易表現のため, <span class="math inline">\(F \left( \omega, \omega_{m}, n, \eta \right)\)</span> を <span class="math inline">\(F \left( \omega, \omega_{m} \right)\)</span> と表記している.</p>
<p>ExplicitConnection のように, マイクロファセット法線 <span class="math inline">\(\omega_{m}\)</span> がわからない状態で <span class="math inline">\(f_{r} \left( x, \omega_{i}, \omega_{o} \right)\)</span> を評価する場合は, <span class="math inline">\(\omega_{m}\)</span> は 反射ハーフベクトル <span class="math inline">\(\omega_{h_{r}}\)</span> を用いて,</p>
<p><span class="math display">\[
\begin{align}
\omega_{m} = & \frac{\omega_{h_{r}}}
{\left| \left| \omega_{h_{r}} \right| \right|}
\tag{6}
\\
\omega_{h_{r}} = & \omega_{i} + \omega_{o}
\tag{7}
\end{align}
\]</span></p>
<p>から求める.</p>
<h2 id="重点的サンプリング-importance-sampling">重点的サンプリング (Importance Sampling)</h2>
<figure>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyDRPLRqud4uDpLKJ6HeeeJWHtqVjTjsSXcBo1ychEKdbL5Ea514caDgwdA9QttTamZA8RToTi0qWY0YRbtkpRafQeR4UXOC8BYKs43OPSYmNA2mYeC38A6Th-BoAhPCENICAu1Cswvoo/w869-h486-no/" />
</figure>
<p>反射方向 <span class="math inline">\(\omega_{o}\)</span> の重点的サンプリングを行う. GGX BRDF では, マイクロファセット法線 <span class="math inline">\(\omega_{m}\)</span> を重点的サンプリングし, 入射方向 <span class="math inline">\(\omega_{i}\)</span> と <span class="math inline">\(\omega_{m}\)</span> から正反射方向 <span class="math inline">\(\omega_{o}\)</span> を求める.</p>
<p><span class="math inline">\(\omega_{m}\)</span> は 投影法線分布関数(Projected Normal Distribution Function) <span class="math inline">\(D_{\omega_{i}} \left( \omega_{m} \right)\)</span> に従ってサンプリングする. <span class="math inline">\(D_{\omega_{i}} \left( \omega_{m} \right)\)</span> は, <span class="math inline">\(D \left( \omega_{m} \right)\)</span> の中で 入射方向 <span class="math inline">\(\omega_{i}\)</span> から見える法線のみの分布を示したもので,</p>
<p><span class="math display">\[
\begin{align}
D_{\omega_{i}} \left( \omega_{m} \right) = \frac{
\left( \omega_{i} \cdot \omega_{m} \right) }
{ \left( \omega_{i} \cdot \omega_{n} \right) }
G_{1} \left( \omega_{i}, \omega_{m} \right)
D \left( \omega_{m} \right)
\tag{8}
\end{align}
\]</span></p>
<p>で定義される (ここでは簡易表記のため, <span class="math inline">\(D_{\omega_{i}} \left( \omega_{n}, \omega_{m} \right)\)</span> を <span class="math inline">\(D_{\omega_{i}} \left( \omega_{m} \right)\)</span> と表記している). マイクロファセット法線 <span class="math inline">\(\omega_{m}\)</span> の pdf <span class="math inline">\(p \left( \omega_{m} \right) = D_{\omega_{i}} \left(\omega_{m} \right)\)</span> から, 反射方向 <span class="math inline">\(\omega_{o}\)</span> とそのpdf <span class="math inline">\(p \left( \omega_{o} \right)\)</span>は</p>
<p><span class="math display">\[
\begin{align}
\omega_{o} = & 2 \left( \omega_{i} \cdot \omega_{m} \right) \omega_{m} - \omega_{i}
\tag{9}
\\
p \left( \omega_{o} \right)
= & \left| \left| \frac{\delta \omega_{m}}{\delta \omega_{i}} \right| \right|
p \left( \omega_{m} \right)
\\
= & \frac{1}{4 \left( \omega_{i} \cdot \omega_{m} \right)}
D_{\omega_{i}} \left( \omega_{m} \right)
\tag{10}
\end{align}
\]</span></p>
<p>で求められる. ここで,<span class="math inline">\(\left| \left| \frac{\delta \omega_{m}}{\delta \omega_{i}} \right| \right| = \frac{1}{4 \left( \omega_{m} \cdot \omega_{i} \right)}\)</span> はヤコビアンである.</p>
<p>重点的サンプリングの際の反射レイのWeightは</p>
<p><span class="math display">\[
\begin{align}
\frac{f_{r} \left( x, \omega_{i}, \omega_{o} \right)
\left( \omega_{o} \cdot \omega_{n} \right)}
{p \left( \omega_{o} \right)} =
F \left( \omega_{i}, \omega_{m} \right)
G_{1} \left( \omega_{o}, \omega_{m} \right)
\tag{11}
\end{align}
\]</span></p>
<p>となる.</p>
<h3 id="omega_m-のサンプリング"><span class="math inline">\(\omega_{m}\)</span> のサンプリング</h3>
<p><span class="math inline">\(D_{\omega_{i}}(\omega_{m})\)</span> に従ってマイクロファセット法線 <span class="math inline">\(\omega_{m}\)</span> をサンプリングする. サンプリング方法は<strong>V-cavity</strong>法と<strong>Smith</strong>法の2通りの方法があるが, ここではSmith法を載せる(V-cavity法については[2]を参照).</p>
<p>注意として,このサンプリング方法は macrosurfaceの法線が <span class="math inline">\(\omega_{n} = (0, 0, 1)\)</span> の時の 入射角 <span class="math inline">\(\omega_{i} = (x_{i}, y_{i}, z_{i})\)</span> を用いる. <span class="math inline">\(\omega_{n}\)</span> がそれ以外の場合は <span class="math inline">\(\omega_{n} = (0, 0, 1)\)</span> となるように <span class="math inline">\(\omega_{i}\)</span> の基底変換を行う. <span class="math inline">\(\omega_{m}\)</span> のサンプリング後は <span class="math inline">\(\omega_{i}\)</span> と <span class="math inline">\(\omega_{m}\)</span> を 元の基底に変換する.</p>
<p>Smith法による<span class="math inline">\(\omega_{m}\)</span>のサンプリング方法は 大きく分けて以下の5つのプロセスからなる.</p>
<ol type="1">
<li>Stretch <span class="math inline">\(\omega_{i}\)</span></li>
<li>Sample <span class="math inline">\(P_{\omega_{i}}^{22}(x_{\tilde{m}}, y_{\tilde{m}}, 1)\)</span></li>
<li>Rotate <span class="math inline">\(\omega_{m}\)</span></li>
<li>Unstretch <span class="math inline">\(\omega_{m}\)</span></li>
<li>Normalize <span class="math inline">\(\omega_{m}\)</span></li>
</ol>
<h4 id="stretch-omega_i">Stretch <span class="math inline">\(\omega_{i}\)</span></h4>
<p><span class="math display">\[
\begin{align}
\omega'_{i} \equiv \frac{(\alpha x_{i}, \alpha y_{i}, z_{i})}
{\sqrt{(\alpha x_{i})^{2} + (\alpha y_{i})^{2} + z_{i}^2}}
\end{align}
\]</span></p>
<h4 id="sample-p_omega_i22x_tildem-y_tildem-1">Sample <span class="math inline">\(P_{\omega_{i}}^{22}(x_{\tilde{m}}, y_{\tilde{m}}, 1)\)</span></h4>
<h5 id="x_tildem-のサンプリング"><span class="math inline">\(x_{\tilde{m}}\)</span> のサンプリング</h5>
<p><span class="math display">\[
\begin{align}
A \equiv & u_{1} \left( 1 + \sqrt{1 + tan^{2} \theta_{\omega'_{i}}} \right) - 1
\\
B \equiv & tan \theta_{\omega'_{i}}
\\
x_{\tilde{m}1} \equiv & \frac{B}{A^{2} - 1} -
\sqrt{\left(\frac{B}{A^{2} - 1}\right)^{2} -
\frac{A^{2} - B^{2}}{A^{2} - 1}}
\\
x_{\tilde{m}2} \equiv & \frac{B}{A^{2} - 1} +
\sqrt{\left(\frac{B}{A^{2} - 1}\right)^{2} -
\frac{A^{2} - B^{2}}{A^{2} - 1}}
\\
x_{\tilde{m}} \equiv &
\begin{cases}
x_{\tilde{m}1} & (A < 0 \ \ or \ \
cot \theta_{\omega'_{i}} < x_{\tilde{m}2})
\\
x_{\tilde{m}2} & (otherwise)
\end{cases}
\end{align}
\]</span></p>
<p>ここで,<span class="math inline">\(u_{1}\)</span> は <span class="math inline">\([0, 1)\)</span> の乱数である.</p>
<h5 id="y_tildem-のサンプリング"><span class="math inline">\(y_{\tilde{m}}\)</span> のサンプリング</h5>
<p><span class="math display">\[
\begin{align}
s \equiv &
\begin{cases}
1 & (0.5 \lt u_{2})
\\
-1 & (otherwise)
\end{cases}
\\
t \equiv & 2s(u_{2} - 0.5)
\\
z \equiv & s \frac{0.46341 t − 0.73369 t^{2} + 0.27385 t^{3}}
{0.597999 − t + 0.309420 t^{2} + 0.093073 t^{3}}
\\
y_{\tilde{m}} \equiv & z \sqrt{1 + x_{\tilde{m}}^{2}}
\end{align}
\]</span></p>
<p>ここで,<span class="math inline">\(u_{2}\)</span> は <span class="math inline">\([0, 1)\)</span> の乱数である.</p>
<h4 id="rotate-omega_m">Rotate <span class="math inline">\(\omega_{m}\)</span></h4>
<p><span class="math display">\[
\begin{align}
\left(
\begin{array}{c}
x_{\tilde{m}}
\\
y_{\tilde{m}}
\end{array}
\right) =
\left(
\begin{array}{c}
cos \phi_{\omega_{i}'} & -sin \phi_{\omega_{i}'}
\\
sin \phi_{\omega_{i}'} & cos \phi_{\omega_{i}'}
\end{array}
\right)
\left(
\begin{array}{c}
x_{\tilde{m}}
\\
y_{\tilde{m}}
\end{array}
\right)
\end{align}
\]</span></p>
<h4 id="unstretch-omega_m">Unstretch <span class="math inline">\(\omega_{m}\)</span></h4>
<p><span class="math display">\[
\begin{align}
\left(
\begin{array}{c}
x_{\tilde{m}}
\\
y_{\tilde{m}}
\end{array}
\right) =
\left(
\begin{array}{c}
\alpha x_{\tilde{m}}
\\
\alpha y_{\tilde{m}}
\end{array}
\right)
\end{align}
\]</span></p>
<h4 id="normalize-omega_m">Normalize <span class="math inline">\(\omega_{m}\)</span></h4>
<p><span class="math display">\[
\begin{align}
\omega_{m} \equiv \frac{(-x_{\tilde{m}}, -y_{\tilde{m}}, 1)}
{\sqrt{x_{\tilde{m}}^{2} + y_{\tilde{m}}^{2} + 1}}
\end{align}
\]</span></p>
<h2 id="まとめ">まとめ</h2>
<p><strong>パラメータ</strong></p>
<table>
<thead>
<tr class="header">
<th style="text-align: left;">名称</th>
<th style="text-align: center;">記号</th>
<th style="text-align: center;">値</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">表面粗さ</td>
<td style="text-align: center;"><span class="math inline">\(roughness\)</span></td>
<td style="text-align: center;"><span class="math inline">\(0 < roughness \le 1\)</span></td>
</tr>
</tbody>
</table>
<p><strong>レンダリング</strong></p>
<table style="width:26%;">
<colgroup>
<col style="width: 9%" />
<col style="width: 9%" />
<col style="width: 6%" />
</colgroup>
<thead>
<tr class="header">
<th style="text-align: left;">名称</th>
<th style="text-align: center;">記号</th>
<th style="text-align: center;">値</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">BRDF</td>
<td style="text-align: center;"><span class="math inline">\(f_{r} \left( x, \omega_{i}, \omega_{o} \right)\)</span></td>
<td style="text-align: center;"><span class="math inline">\(\frac{1}{4 \left( \omega_{i} \cdot \omega_{n} \right) \left( \omega_{o} \cdot \omega_{n} \right)} F \left( \omega_{i}, \omega_{m} \right) G_{2} \left( \omega_{i}, \omega_{o}, \omega_{m} \right) D \left( \omega_{m} \right)\)</span></td>
</tr>
<tr class="even">
<td style="text-align: left;">pdf</td>
<td style="text-align: center;"><span class="math inline">\(p \left( \omega_{o} \right)\)</span></td>
<td style="text-align: center;"><span class="math inline">\(\frac{1}{4 \left( \omega_{i} \cdot \omega_{m} \right)} D_{\omega_{i}} \left( \omega_{m} \right)\)</span></td>
</tr>
<tr class="odd">
<td style="text-align: left;">反射レイのWeight</td>
<td style="text-align: center;"><span class="math inline">\(\frac{f_{r} \left( x, \omega_{i}, \omega_{o} \right) \left( \omega_{o} \cdot \omega_{n} \right)} {p \left( \omega_{o} \right)}\)</span></td>
<td style="text-align: center;"><span class="math inline">\(F \left( \omega_{i}, \omega_{m} \right) G_{1} \left( \omega_{o}, \omega_{m} \right)\)</span></td>
</tr>
</tbody>
</table>
<p>以上,GGX BRDFについてまとめた.</p>
<h2 id="参考文献">参考文献</h2>
<ol type="1">
<li>B. Walter, S. R. Marschner, H. Li, K. E. Torrance: Microfacet models for refraction through rough surfaces (2007)</li>
<li>E. Heitz, E. D'Eon: Importance Sampling Microfacet-Based BSDFs using the Distribution of Visible Normals (2014)</li>
<li>B. Burley: Physically-Based Shading at Disney (2012)</li>
</ol>
</body>
</html>Zinhttp://www.blogger.com/profile/00473704352385380653noreply@blogger.com0tag:blogger.com,1999:blog-5029251693178115279.post-17051091741937859072015-11-29T01:03:00.001+09:002016-03-06T11:01:05.305+09:00Smooth Diffuse Surface (Lambert BRDF)<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="generator" content="pandoc">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title></title>
<style type="text/css">code{white-space: pre;}</style>
<script src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"></script>
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<h1 id="smoth-diffuse-surface-lambert-brdf">Smoth Diffuse Surface (Lambert BRDF)</h1>
<p><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4B_2fQFmjWDktcYrqAZNs_LNASWLuIJC4BnhB-jdA_UUXHVTxcEHoGxpm5c9EZohPfFXxN8ofwt5meOjLv8SM96sAWX2FzKTDZNGL-yXeu5LRc2Zs4eGi6vNUGeGdaFRzvxLB_AgRKaM/w400-no/" /> <img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiq3kVIMDba0dCjAX_qQ8D_som8C-RbN4qsMf_9VTVudMHp3xydw7Tgl7tsINive-rI5Jp-fD7PkqzXF8ysL-vJ5tYmsvqUYvO4j3lBKpywzfXZyh3crbSw3PWDwkjb08aCbijhsUxP-f8/w400-no/" /></p>
<p>本ページでは,モンテカルロレイトレーシング法において, 理想拡散反射表面をレンダリングする方法を説明する. 理想拡散反射表面として Lambert BRDF の実装に必要な パラメータや数式,重点的サンプリングの方法を説明する.</p>
<h2 id="lambert-brdf">Lambert BRDF</h2>
<p>Lambert BRDFは,全ての方向に放射輝度が等しく反射するBRDFで</p>
<p><span class="math display">\[
\begin{align}
f_{r} \left( x, \omega_{i}, \omega_{o} \right) = \frac{\rho}{\pi}
\tag{1}
\end{align}
\]</span></p>
<p>で定義される.ここで,<span class="math inline">\(\rho\)</span> は表面の反射率を表す.</p>
<h2 id="重点的サンプリング-importance-sampling">重点的サンプリング (Importance Sampling)</h2>
<p>反射方向 <span class="math inline">\(\omega_{o}\)</span> の重点的サンプリングを行う. Lambert BRDF では, <span class="math inline">\(\omega_{o}\)</span> は反射エネルギー分布に従ってサンプリングする. すなわち,反射方向のpdf <span class="math inline">\(p \left( \omega_{o} \right)\)</span> は</p>
<p><span class="math display">\[
\begin{align}
p \left( \omega_{o} \right) =
\frac{cos \theta_{\omega_{o}}}{\pi}
\tag{2}
\end{align}
\]</span></p>
<p>となる.ここで, <span class="math inline">\(cos \theta_{\omega_{o}} = \omega_{o} \cdot \omega_{n}\)</span> である.</p>
<p>重点的サンプリングの際の反射レイのWeightは</p>
<p><span class="math display">\[
\begin{align}
\frac{f_{r} \left( x, \omega_{i}, \omega_{o} \right)
\left( \omega_{o} \cdot \omega_{n} \right)}
{p \left( \omega_{o} \right)}
= \rho
\tag{3}
\end{align}
\]</span></p>
<p>となる.</p>
<h3 id="omega_o-のサンプリング"><span class="math inline">\(\omega_{o}\)</span> のサンプリング</h3>
<p>反射方向 <span class="math inline">\(\omega_{o}\)</span> のサンプリングには逆関数法を用いる.</p>
<p>注意として,このサンプリング方法は 法線が <span class="math inline">\(\omega_{n} = (0, 0, 1)\)</span> の時の 反射方向をサンプリングしているため, サンプリング後は任意の法線に対応するように基底変換をする.</p>
<p><span class="math display">\[
\begin{align}
P \left( \theta, \phi \right)
= & \int_{0}^{\phi} \int_{0}^{\theta} p \left( \theta^{\prime}, \phi^{\prime} \right) \
sin \theta^{\prime} \
d \theta^{\prime} d \phi^{\prime}
\\
= & \frac{\phi}{2 \pi} \cdot (1 - cos^{2} \theta)
\\
P \left( \theta \right) = & 1 - cos^{2} \theta
\\
P \left( \phi \right) = & \frac{\phi}{2 \pi}
\end{align}
\]</span></p>
<p>上記の <span class="math inline">\(P \left( \theta \right)\)</span>,<span class="math inline">\(P \left( \phi \right)\)</span> から, 反射方向の <span class="math inline">\(\theta\)</span>,<span class="math inline">\(\phi\)</span> は以下の式から求めることができる.</p>
<p><span class="math display">\[
\begin{align}
\theta = & cos^{-1} (\sqrt{1 - u_{1}})
\tag{4}
\\
\phi = & 2 \pi u_{2}
\tag{5}
\end{align}
\]</span></p>
<p>ここで, <span class="math inline">\(u_{1}\)</span>,<span class="math inline">\(u_{2}\)</span> は <span class="math inline">\([0, 1)\)</span> の乱数である.</p>
<h2 id="まとめ">まとめ</h2>
<p><strong>パラメータ</strong></p>
<table>
<thead>
<tr class="header">
<th style="text-align: center;">名称</th>
<th style="text-align: center;">記号</th>
<th style="text-align: center;">値</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;">反射率</td>
<td style="text-align: center;"><span class="math inline">\(\rho\)</span></td>
<td style="text-align: center;"><span class="math inline">\(0 \le \rho \le 1\)</span></td>
</tr>
</tbody>
</table>
<p><strong>レンダリング</strong></p>
<table style="width:50%;">
<colgroup>
<col style="width: 16%" />
<col style="width: 16%" />
<col style="width: 16%" />
</colgroup>
<thead>
<tr class="header">
<th style="text-align: center;">名称</th>
<th style="text-align: center;">記号</th>
<th style="text-align: center;">値</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;">BRDF</td>
<td style="text-align: center;"><span class="math inline">\(f_{r} \left( x, \omega_{i}, \omega_{o} \right)\)</span></td>
<td style="text-align: center;"><span class="math inline">\(\frac{\rho}{\pi}\)</span></td>
</tr>
<tr class="even">
<td style="text-align: center;">pdf</td>
<td style="text-align: center;"><span class="math inline">\(p \left( \omega_{o} \right)\)</span></td>
<td style="text-align: center;"><span class="math inline">\(\frac{cos \theta_{\omega_{o}}}{\pi}\)</span></td>
</tr>
<tr class="odd">
<td style="text-align: center;">反射レイのWeight</td>
<td style="text-align: center;"><span class="math inline">\(\frac{f_{r} \left( x, \omega_{i}, \omega_{o} \right) \left( \omega_{o} \cdot \omega_{n} \right)} {p \left( \omega_{o} \right)}\)</span></td>
<td style="text-align: center;"><span class="math inline">\(\rho\)</span></td>
</tr>
</tbody>
</table>
<p>以上,Lambert BRDFについてまとめた.</p>
<h2 id="参考文献">参考文献</h2>
<ol type="1">
<li>H. W. Jensen: Monte Carlo Ray Tracing (2003)</li>
<li>H. Son: Realistic Image Synthesis with Light Transport (2015)</li>
</ol>
</body>
</html>Zinhttp://www.blogger.com/profile/00473704352385380653noreply@blogger.com0tag:blogger.com,1999:blog-5029251693178115279.post-59673764376808764962015-11-23T16:43:00.000+09:002015-11-23T20:32:59.959+09:00双方向反射分布関数 (Bidirectional Reflectance Distribution Function: BRDF)<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="generator" content="pandoc">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title></title>
<style type="text/css">code{white-space: pre;}</style>
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<script src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"></script>
</head>
<body>
<h1 id="双方向反射分布関数-bidirectional-reflectance-distribution-function-brdf">双方向反射分布関数 (Bidirectional Reflectance Distribution Function: BRDF)</h1>
<p>BRDFの定義についてメモする. BRDFの実装やそのテストを実装する際は, 実装内容がBRDFの定義を満たしているかを確認することで バグを発見しやすくなると思われる.</p>
<h2 id="brdfとは">BRDFとは</h2>
<ul>
<li>表面の見た目を決定づける役割を果たす</li>
<li>入射光に対する反射光の方向の分布を表す</li>
</ul>
<h2 id="brdfの定義">BRDFの定義</h2>
<p>BRDFは数学的には放射照度に対する出射光の放射輝度の比を表し, 以下の関数 <span class="math inline">\(f_{r}\)</span> で定義される.</p>
<p><span class="math display">\[
\begin{align}
f_{r}(x, \boldsymbol{\omega_{o}} \leftarrow \boldsymbol{\omega_{i}})
\equiv & \frac{dL_{r}(x \rightarrow \boldsymbol{\omega_{o}})}
{dE(x \leftarrow \boldsymbol{\omega_{i}})}
\\
= & \frac{dL_{r}(x \rightarrow \boldsymbol{\omega_{o}})}
{L_{i}(x \leftarrow \boldsymbol{\omega_{i}}) \
d \sigma_{p}(\boldsymbol{\omega_{i}})}
\end{align}
\]</span></p>
<p>ここで, <span class="math inline">\(\boldsymbol{\omega_{i}}\)</span>・<span class="math inline">\(\boldsymbol{\omega_{o}}\)</span> は それぞれ光の入射方向・反射方向を表す単位ベクトルであり, 点 <span class="math inline">\(x\)</span> での法線ベクトルを <span class="math inline">\(\boldsymbol{n_{x}}\)</span> とするとき, <span class="math inline">\((\boldsymbol{n_{x}} \cdot \boldsymbol{\omega_{i}}) \geq 0\)</span> を満たす方向ベクトル <span class="math inline">\(\boldsymbol{\omega_{i}} \in \Omega_{x}\)</span> である( <span class="math inline">\(\boldsymbol{\omega_{o}}\)</span> に関しても同様). <span class="math inline">\(L_{i}, L_{r}\)</span> はそれぞれ点 <span class="math inline">\(x\)</span> に入射, 点 <span class="math inline">\(x\)</span> から反射する放射輝度を表す. <span class="math inline">\(\sigma_{p}\)</span> は <span class="math inline">\(\Omega_{x}\)</span> の投影立体角測度であり, <span class="math inline">\(\Omega_{x}\)</span> の立体角測度 <span class="math inline">\(\sigma\)</span> と</p>
<p><span class="math display">\[
\begin{align}
d\sigma_{p}(\boldsymbol{u}) \equiv cos \theta_{\boldsymbol{u}} \
d\sigma(\boldsymbol{u}),
\ \ \boldsymbol{u} \in \Omega_{s}
\end{align}
\]</span></p>
<p>を満たす関係である.ここで, <span class="math inline">\(cos \theta_{\boldsymbol{u}} = (\boldsymbol{n_{x}} \cdot \boldsymbol{u})\)</span> である.</p>
<h2 id="物理ベースなbrdf">物理ベースなBRDF</h2>
<p>物理ベースなBRDFは,反射する放射エネルギーが負になることはないので</p>
<p><span class="math display">\[
\begin{align}
\forall \boldsymbol{\omega_{i}} \
\forall \boldsymbol{\omega_{o}}, \
f_{r}(x, \boldsymbol{\omega_{o}} \leftarrow \boldsymbol{\omega_{i}}) \
cos \theta_{\boldsymbol{\omega_{o}}} \ge 0
\end{align}
\]</span></p>
<p><span class="math inline">\(cos \theta_{\boldsymbol{\omega_{o}}} \ge 0\)</span> であるため,</p>
<p><span class="math display">\[
\begin{align}
\forall \boldsymbol{\omega_{i}} \
\forall \boldsymbol{\omega_{o}}, \
f_{r}(x, \boldsymbol{\omega_{o}} \leftarrow \boldsymbol{\omega_{i}}) \ge 0
\end{align}
\]</span></p>
<p>である. また,物理ベースなBRDFは以下の2つの特性を持つ.</p>
<h3 id="ヘルムホルツの相反性-helmholtz-reciprocity">ヘルムホルツの相反性 (Helmholtz Reciprocity)</h3>
<p>BRDFの値は入射・出射方向が入れ替わっても変化しない.</p>
<p><span class="math display">\[
\begin{align}
f_{r}(x, \boldsymbol{\omega_{o}} \leftarrow \boldsymbol{\omega_{i}}) =
f_{r}(x, \boldsymbol{\omega_{i}} \leftarrow \boldsymbol{\omega_{o}})
\end{align}
\]</span></p>
<p>この特性があるため,Bidirectional Path TracingやPhoton Mappingのように 光源側とカメラ側の双方向から光の経路をトレースできる.</p>
<h3 id="エネルギー保存則-energy-conservation">エネルギー保存則 (Energy Conservation)</h3>
<p>ある点から反射した総出射光束は総入射光束以下となる.</p>
<p><span class="math display">\[
\begin{align}
\rho(x) =
\frac{\int_{\Omega}
L(x \rightarrow \boldsymbol{\omega_{o}}) \
d \sigma_{p}(\boldsymbol{\omega_{o}})}
{\int_{\Omega}
L(x \leftarrow \boldsymbol{\omega_{i}}) \
d \sigma_{p}(\boldsymbol{\omega_{i}})}
\le 1
\end{align}
\]</span></p>
<p>この式から以下の式を導くことができる</p>
<p><span class="math display">\[
\begin{align}
\forall \boldsymbol{\omega_{i}}, \
\int_{\Omega}
f_{r}(x, \boldsymbol{\omega_{o}} \leftarrow \boldsymbol{\omega_{i}}) \
d \sigma_{p}(\boldsymbol{\omega_{o}})
\le 1
\end{align}
\]</span></p>
<p>この式から,エネルギー保存則を満たすBRDFは 入射した放射エネルギー以上の放射エネルギーを反射しないことがわかる.</p>
<h2 id="まとめ">まとめ</h2>
<p><strong>BRDFの定義</strong></p>
<p><span class="math display">\[
\begin{align}
f_{r}(x, \boldsymbol{\omega_{o}} \leftarrow \boldsymbol{\omega_{i}})
\equiv \frac{dL_{r}(x \rightarrow \boldsymbol{\omega_{o}})}
{L_{i}(x \leftarrow \boldsymbol{\omega_{i}}) \
d \sigma_{p}(\boldsymbol{\omega_{i}})}
\end{align}
\]</span></p>
<p><strong>物理ベースなBRDF</strong></p>
<table>
<thead>
<tr class="header">
<th style="text-align: center;">名称</th>
<th style="text-align: center;">式</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;">非負</td>
<td style="text-align: center;"><span class="math inline">\(\forall \boldsymbol{\omega_{i}} \ \forall \boldsymbol{\omega_{o}}, \ f_{r}(x, \boldsymbol{\omega_{o}} \leftarrow \boldsymbol{\omega_{i}}) \ge 0\)</span></td>
</tr>
<tr class="even">
<td style="text-align: center;">ヘルムホルツの相反性</td>
<td style="text-align: center;"><span class="math inline">\(f_{r}(x, \boldsymbol{\omega_{o}} \leftarrow \boldsymbol{\omega_{i}}) = f_{r}(x, \boldsymbol{\omega_{i}} \leftarrow \boldsymbol{\omega_{o}})\)</span></td>
</tr>
<tr class="odd">
<td style="text-align: center;">エネルギー保存則</td>
<td style="text-align: center;"><span class="math inline">\(\forall \boldsymbol{\omega_{i}}, \ \int_{\Omega} f_{r}(x, \boldsymbol{\omega_{o}} \leftarrow \boldsymbol{\omega_{i}}) \ d \sigma_{p}(\boldsymbol{\omega_{o}}) \le 1\)</span></td>
</tr>
</tbody>
</table>
<p>以上,BRDFの定義についてまとめた. BRDFの実装やテストの実装の際は, これらの定義を満たしているかを確認することでバグを発見しやすくなると思われる.</p>
<h2 id="参考文献">参考文献</h2>
<ol type="1">
<li>R. Montes, C. Ureña: An Overview of BRDF Models (2012)</li>
<li>H. Son: Realistic Image Synthesis with Light Transport (2015)</li>
</ol>
</body>
</html>Zinhttp://www.blogger.com/profile/00473704352385380653noreply@blogger.com0