RenderMan で AO を計算するテスト

概要

  • (たまたま寝れなかったので,) RenderMan で AO を計算するサンプルを手元で動かすようにしてみました.
  • 下図は RenderMan 準拠のレンダラ 3Delight で描画した結果です.

AO あり


AO なし

内容

  • カメラから見える表面の各点において, AO (Ambient Occlusion)を計算してその結果をマテリアルのベースカラーに乗算しています.
  • AO をシェーダで計算するときには, 表面の各点の法線方向を中心とした半球状にレイを飛ばして, シーンとそのレイがぶつかるかどうかを判定することを繰り返します.
  • このとき, AO = (レイが衝突する回数) / (レイの総数) とすると, 埋まっている点だと AO = 1.0, 平面だと AO = 0.0 になります.
  • なので, 最終出力時には( 1.0 - AO )の値をベースカラーに乗算します.

動作環境

  • 無料版の 3DeLight Studio Pro Windows 64bit を使っています.
  • サンプルは Pixar の Web 上の参考文献のほぼそのままで, 違いは シェーダで faceforward() を使っていて, またガンマ補正をしているくらいです.

3DeLight での実行手順

  // シェーダのコンパイル
  $ C:\Program Files\3Delight\bin\shaderdl.exe ao_gather.sl  
  $ C:\Program Files\3Delight\bin\shaderdl.exe ao_occlusion.sl

  // rib を描画
  $ C:\Program Files\3Delight\bin\renderdl.exe test_ao.rib

コード

//////////////////////////////////////////////////
//
// ao_gather.sl
// AO を gather() で計算するシェーダ
//
//////////////////////////////////////////////////

surface ao_gather(float samples = 64)
{
    // 視点 I を向いている法線 Ns
    normal Ns = faceforward( normalize( N ), I );

    // レイの衝突回数
    float hits = 0;

    // 半球状のレイの飛ばし方
    gather( "illuminance", P, Ns, PI/2, samples, "distribution", "cosine" )
    {
        // 周囲にレイがぶつかった場合
        hits += 1;
    }

    // オクルージョンの値の計算
    float occlusion = hits / samples;
        
    // カラーに値を設定
    Ci = (1.0 - occlusion) * Cs;

    // 不透明度に値を設定
    Oi = 1;
}
//////////////////////////////////////////////////
// 
// ao_occlusion.sl
// AO を occlusion() で計算するシェーダ
//
//////////////////////////////////////////////////

surface ao_occlusion(float samples = 64)
{
    // 視点 I を向いている法線 Ns
    normal Ns = faceforward( normalize( N ), I );

    // 点 P, 法線 Ns 周りの AO
    float occ = occlusion( P, Ns, samples );

    occ = 0.0;

    // カラーに値を設定
    Ci = (1 - occ) * Cs * Os;

    // 不透明度
    Oi = Os;
}
##################################################
#
# test_ao.rib
# AO を使ったシーンの描画
#
##################################################

FrameBegin 1
    # フレームバッファの設定
    Format 400 300 1
    PixelSamples 4 4
    ShadingInterpolation "smooth"

    # Display "ao.bmp" "file" "rgba" 
    Display "" "framebuffer" "rgba"

    # ガンマ補正
    Exposure     1.0 2.2

    # カメラの設定
    Projection "perspective" "fov" 22
    Translate 0 -0.5 8
    Rotate -40 1 0 0
    Rotate -20 0 1 0

    # 可視性
    Attribute "visibility" "camera" [ 1 ]
    Attribute "visibility" "trace"  [ 1 ]
    Attribute "visibility" "photon" [ 0 ]
    Attribute "visibility" "transmission" [ "opaque" ]

    # レイトレース
    Option    "trace"      "maxdepth"         [ 3 ]
    Attribute "trace"      "maxdiffusedepth"  [ 2 ]
    Attribute "trace"      "maxspeculardepth" [ 2 ]

    # シーン
    WorldBegin
        Attribute "visibility" "trace" 0
        Attribute "trace" "bias" 0.005

        Attribute "visibility" "integer camera"      [ 1 ]
        Attribute "visibility" "integer trace"       [ 1 ]
        Attribute "visibility" "string transmission" [ "opaque" ]

        # 使用するシェーダの選択
        # Surface "ao_gather" "float samples" [ 64  ]
        # Surface "ao_gather" "float samples" [ 256 ]

        # Surface "ao_occlusion" "float samples" [ 64 ]
        Surface "ao_occlusion" "float samples" [ 256 ]

        # 白い床
        AttributeBegin
            Color [1 1 1]
            Polygon "P" [ -5 0 5 5 0 5 5 0 -5 -5 0 -5 ]
        AttributeEnd

        # 赤い球
        AttributeBegin
            Color 1 0 0
            Translate -0.7 0.5 0
            Sphere 0.5 -0.5 0.5 360
        AttributeEnd

        # カラフルな箱
        AttributeBegin
            Translate 0.3 0.01 0
            Rotate -30 0 1 0
            Color [0 1 1]
            Polygon "P" [ 0 0 0 0 0 1 0 1 1 0 1 0 ] # left side
            Polygon "P" [ 1 1 0 1 1 1 1 0 1 1 0 0 ] # right side
            Color [1 1 0]
            Polygon "P" [ 0 1 0 1 1 0 1 0 0 0 0 0 ] # front side
            Polygon "P" [ 0 0 1 1 0 1 1 1 1 0 1 1 ] # back side
            Color [0 1 0]
            Polygon "P" [ 0 1 1 1 1 1 1 1 0 0 1 0 ] # top
        AttributeEnd
    WorldEnd
FrameEnd