Ray-MMDでの肌の質感表現での私なりの解釈です。
ray-mmdのマニュアルはここにあります。内容がある程度わかる人向けのつもりで書いてます。
ここでのサンプルはサンプルは skybox に Fox_Kuzunoha さん作成の Helipad GoldenHour を使用しています。https://bowlroll.net/file/230061
夕日が反射しているサブ光源としてスポットライトを置く設定になっていますがここでの表示例に関しては行っていません。skyboxを設置してEnvLightに指定の Sky with lighting with rotation.fx を設定しているだけです。光源の値や位置は照明.vmdの通りです。
- 照明 R:191 G:154 B:102
- 向き X:-0.5 Y:-1.0 Z:+0.5
肌の透け感の処理として 「表面下散乱(SubSurface Scattering)」 というメカニズムが使われます。
略してSSSですね。詳しくはググれ。Wiki
で、それをクソ真面目に計算するんじゃなくてレンダリングした情報から簡易的に作り出すのが Screen Space Subsurface Scattering (SSSS) となるわけです。(厳密な説明だと違うかもしれませんがこのまま進めます。)
Ray-MMD には材質を割り当てるfxファイルとして [Materials] フォルダがあります。肌の質感サンプルはそのフォルダ下の [Skin] ですが、さてここで敢えて [Subsurface] フォルダ内の material_jade_white.fx を肌の材質と左手前のディルドと右の拳銃に材質として割り当てます。
material_jade_white.fx デフォルト状態
実際の白い翡翠のサンプル👇
白い色の翡翠の質感です。引いた画面ではよくわかりませんが二枚目のUP画像では指などの細い箇所が透けている感じが良く出ています。これはfx内のどの数値設定で得られているものでしょうか?
fxファイル内を見てみましょう。material_jade_white.fx👇
define ALBEDO_MAP_FROM 0
ALBEDO は材質の色です。 材質の色をどこから持ってくるか?の指定で 0 はモデルに設定された色(テクスチャ)ではなくこの後のconst float3 albedo = で設定された色を使うという意味になります。
const float3 albedo = 0.5;
色の指定なのでRGBの三つで指定するのですが省略した場合全てに同じ値が入ります。下記の二つは同じ意味になります。
- const float3 albedo = float3(0.5, 0.5, 0.5); 各RGBを0.0~1.0の範囲で表現
- const float3 albedo = float3(128, 128, 128) / 255; ペイントツールでよく見る各RGBを0~255で表現
👆 素材そのものの色はグレー一色ということ
define CUSTOM_ENABLE 7
CUSTOM_ENABLE は特殊なシェーダーの指定です。0だと標準。1が肌用 7がサブサーフェース用となっています。が1も7も動作は同じっぽいです。
const float customA = 0.8;
customA の値は CUSTOM_ENABLE 1or7 のとき curvature(曲率)として扱われます。「opacity(不透明度)とも呼ばれ、ぼかしの全体的な強度を定義する。」とあります。(サンプル画像で見える//は//の後ろを無視しろというヤツ。コメントアウトとか言われる。何かメモしておきたいときはコレ使うと便利)
const float3 customB = SSS_TRANSMITTANCE(0.75);
customB の値は Transmittance color(透過色) と解説されています。つまりここで設定された色が透けて見える色になると言う事になります。
なんだよ SSS_TRANSMITTANCE(0.75) って、色情報に見えねぇじゃんと思いますが、上の方の行にある#define SSS_TRANSMITTANCE(x) exp((1 - saturate(x)) * float3(-8, -10, -64))に当てはめて各RGBの成分を割り出しています。まぁなんか小難しい計算で各RGBの透過率を決めてるんですな。今は無視しちゃいます。
じゃあ customB の値を緑色にすれば緑色の翡翠になるんじゃないか?
こんなの👇
const float3 customB = float3(0.0, 0.5, 0.3);
てな感じです。
現実だと物体に光があたるとその物体からも照り返しが起きるので物体の面の最終的な色合いは複雑に回りの影響を受けることになります。そういったものも計算するのがレイトレーシングってヤツですが計算することが多くなるので重くなります。いかんともしがたい…
ここで逆転の発想。全ての反射を見るのは大変だけど反射しないところ…照り返しが起きにくい場所ってのは結構簡単にわかるぞ?って事で編み出されたのがアンビエントオクルージョン(Ambient Occlusion, AO)。奥まった場所や周りが囲まれていると光が入り込みにくくなるので暗くなりますよね。それを疑似的に計算したものがAOです。物体の境界の明暗が強調されてくっきりとして絵になります。
ray_controller の目の欄にあります 0.3 ぐらい入れましょうかSSAO+ 0.3
ここで ray_controller 側ではなく、skyboxにある項目を見て見ます。EnvSSSLight という項目があります。これをぐいっと1.0にするとどうなるかというと…EnvSSSLight+ 1.0
こんな感じでCustomBで設定した透けて見える色がCustomBの色で自己発光したみたいになるので結果的に透過色が濃く反映され影の色が黒くならずに済む感じになります。
これを踏まえて透け色を赤にしてみると…
透けて見える色を赤、AOを0.3かけた状態👇
設定:
- const float3 albedo = float3(0.5, 0.5, 0.5); //肌そのものの色 灰色
- const float customA = 0.8; //透け率 大(肌の厚さ 薄)
- const float3 customB = float3(1.0, 0.0, 0.0); //透けて見える色 赤
- AO +0.3
さらに EnvSSSLight を全開でかけると👇
設定:
- onst float3 albedo = float3(0.5, 0.5, 0.5); //肌そのものの色 灰色
- const float customA = 0.8; //透け率 大(肌の厚さ 薄)
- const float3 customB = float3(1.0, 0.0, 0.0); //透けて見える色 赤
- AO +0.3
- EnvSSSLight +1.0
これはかなり極端にしているので湯だったみたいになってますが、この辺の数値を弄ると何が起きるのかはわかってもらえるのではないでしょうか。
Amazing! The skin looks so soft! ❤️
nb
jyb,your haku and miku IS best
勉強になります!