Xangle/Yangle 05 - 明暗を設定しよう

影をつけると一気に3次元ぽくなりますよね。ということで前回(Xangle/Yangle 04 - エフェクトを組み合わせよう - MUGEN製作のメモ置き場)作った立方体を上からの光で照らしてみようと思います



上からの光とは言いましたが、とりあえず一般的な場合、自由な位置に光源を置いた場合を考えてみます
 
2つ考えてみました
A:光源からの光が面で反射し、カメラに入ってくる大きさで明るさを判断
B:光源からの光が面に当たるその面積で明るさを判断
 
光源の位置を(Lx,Ly,Lz)とします
面の位置を(x,y,z)とします
 

A
 
①光源から面までの直線L(の方向ベクトル)を考える
②面の法線ベクトル(面に直角な直線のベクトル)を考える
③Lの面での反射ベクトルを考える
④そのZ成分の大きさ(つまり反射した光のうちカメラに向かう大きさ)で明るさを判断する
 
①直線Lは、
 
L:
イメージ 3
 
で表されます。tが-∞から∞まで高速で反復すれば直線になるってことです
 
②angle,xangle,yangle全てが0(回転していない)のとき、面の法線ベクトルは(0,0,-1)なので、その面が行う回転と同じだけ(0,0,-1)を回転させれば、それが面の法線ベクトルになります
面が行う回転行列をかけて、
 
 
イメージ 4
=
イメージ 5
 
α:xangleの値
β:yangleの値
 
です
(x-y-zオイラー角)は、

Xangle/Yangle 02 - オイラー角を変換しよう - MUGEN製作のメモ置き場

を見てください。上の方の回転行列RxRyRzのとこ
 
反射ベクトル = 入射ベクトル + 2×(-入射ベクトル・法線ベクトル)×法線ベクトル
 
(入射ベクトル = Lの方向ベクトル)
 
=
 
イメージ 6
 
|(D)| = √[    (x - Lx)^2 + (y - Ly)^2 + (z - Lz)^2    ]   これで割るとベクトルの大きさ(長さ)が1になります
 
 
計算合ってる。。。よね?多分こうなります。
 
ただZ成分を抜き出すだけ
 
 
反射ベクトルZ成分 = 
 
イメージ 7
 
以上です。ただこれを記述するのはメンドウなので、簡略化します
光源が真上の太陽としましょう。昼間です
太陽は果てしなく遠くにあり、真上なので
Lx =   x
Ly <<  y ( |Ly| >> |y| )
Lz =   z
 
となります。(y軸は下方向正です)
|Ly| >> |y| なので、 (y - Ly)/|(D)| はほとんど -Ly/|(D)| なんです
これらを代入して、、、
 
反射ベクトル = 

2sinαcosα(cosβ)^2
 
とこうなります。随分簡単になりました。

B
①光源から面までの直線Lの方向ベクトルを考える
②面の法線ベクトル(面に直角な直線のベクトル)を考える
③その2つの角度で明るさを判断する
 
①、②はAと同じです
 
 
角度θ = arccos[   (2つのベクトルの内積) / ( | Lの方向ベクトル | | 面の法線ベクトル | )   ]
 
=
 
イメージ 8
 
|D1| = √[    (x - Lx)^2 + (y - Ly)^2 + (z - Lz)^2    ]
 
|D2| = √[    (sinβ)^2 + (-sinαcosβ)^2 + (-cosαcosβ)^2    ]
 
 
 
以上です。ただこれを記述するのはメンドウなので、簡略化します(Aと同じこと書きます)
光源が真上の太陽としましょう。昼間です
太陽は果てしなく遠くにあり、真上なので
Lx =   x
Ly <<  y ( |Ly| >> |y| )
Lz =   z
 
となります。(y軸は下方向正です)
|Ly| >> |y| なので、 (y - Ly)/|(D)| はほとんど -Ly/|(D)| なんです
これらを代入して、、、
 
角度θ = 

arccos[   (sinαcosβ) / √(sin^2β + sin^2αcos^2β + cos^2αcos^2β)  ]

=

arctan[  { √(sin^2β + cos^2αcos^2β) }/(sinαcosβ)  ]
 
 
となります。Aほど簡単にはなってくれませんね

ではこれをMUGENに記述します
 
ModifyExplodに、
 
type = ModifyExplod
Trans = AddAlpha
Alpha = x,0
 
の2行を追加します。xは0~256まで。x = 256で変化なし、x = 0で真っ暗になります
つまり明暗を記述するというよりは暗さ加減を記述します。SFF登録時点で明るめの画像を登録した方がいいかな
Explodのownpalを0にして本体の色を変える方法もありますが、ループ記述できませんので注意です
 
type = ModifyExplod
Trans = AddAlpha
Alpha = fvar(x),0
;          ↑(A)or(B)
 
とすると、Aなら
 
[State -2, var];明るさ:光沢
type = varset
trigger1 = 1
fvar(A) = (128 + (2*sin(fvar(α)*(pi/180))*cos(fvar(α)*(pi/180))*(cos(fvar(β)*(pi/180))**2))*64)
 
Aの場合、反射ベクトルZ成分 = 2sinαcosα(cosβ)^2 は、-2~2の範囲です。64倍して-128~128の範囲になります。さらに、128を足して0~256の範囲にします
つまり、128 + (反射ベクトルZ成分)*64
 
 
 
Bなら
[State -2, var];明るさ:通常
type = varset
trigger = 法線ベクトルが↑を向いているとき
fvar(B) = (180 - abs(atan((((sin(fvar(β)*(pi/180))**2) + (cos(fvar(α)*(pi/180))*cos(fvar(β)*(pi/180)))**2)**0.5)/(sin(fvar(α)*(pi/180))*cos(fvar(β)*(pi/180)))))*(180/pi))*(128/90)
 
[State -2, var];明るさ:通常
type = varset
trigger = 法線ベクトルが↓を向いているとき
fvar(B) = abs(atan((((sin(fvar(β)*(pi/180))**2) + (cos(fvar(α)*(pi/180))*cos(fvar(β)*(pi/180)))**2)**0.5)/(sin(fvar(α)*(pi/180))*cos(fvar(β)*(pi/180)))))*(180/pi)*(128/90)
 
 
Bの場合、角度が0に近いほど明るいことになります。arctanは-π/2~π/2までしか返しませんが、符号を考える必要がないので絶対値(abs)にします。これは法線ベクトルy成分が上を向いている場合です。
下を向いている場合は角度が0に近いほど光源と反対を向くので暗くなります。
絶対値にして0~π/2、*(180/pi)で0~90、上を向いているなら180からひいて90~180、90で割って128をかけると、下を向いているとき0~128、上を向いているとき128~256になります
つまり、 ( 180 - (角度)*(180/pi) )*(128/90) ...上を向いている場合
法線ベクトルは②で考えましたが、回転角度0で(0,0,-1)にしていることに注意です。面によっては(0,0,1)かもしれません。付属Explodを考えたときに基準Explodにたいしてどのように回転させたのかによって変わります
 

結果こうなります。これはAの場合。というか記述が楽だから全部Aでやればいいんじゃない
イメージ 1
 
おまけ。Alpha = 128,256としてみた
イメージ 2
 
 
 
 
 
 
でもまあ格ゲー再現にこんな技術使わないよね
MUGEN製作のメモ置き場
 
 
MUGENキャラの製作状況
現在:
沢田綱吉を製作中(家庭教師ヒットマンREBORN!

プッチ神父を公開中(AI付き)
岸辺露伴の外部AIを公開中
ジョナサン(旧)の外部AIを公開中
仗助の外部AIを公開中
エンポリオの外部AIを公開中
1部ディオを公開中(AI付き)
スティーリーダンを公開中(AI付き)
ステージ2つ公開中

あとたまにMUGEN1.1上で3Dモデル組み立てて遊んでいるので興味ある方はどうぞ
https://0011-mugen.hatenablog.com/archive/category/MUGEN%E5%B0%8F%E3%83%8D%E3%82%BF%E6%8A%80%E8%A1%93

公開先
https://onedrive.live.com/redir?resid=7C0630D7E27F52C3!569&authkey=!ALvVjJz8aRCBjXc&ithint=folder%2czip
Twitter(連絡先)
https://twitter.com/xyz_0011
一応メール
w0eleven@yahoo.co.jp