「ゲームプログラミング/3Dグラフィック」の版間の差分

削除された内容 追加された内容
→‎円柱面投影の透視投影: サブページに移動。
→‎手書きアニメ調の3D: サブページに移動。
2,404 行
 
== 手書きアニメ調の3D ==
* [[ゲームプログラミング/3Dグラフィック/手書きアニメ調の3D]]
よく、3D-CGなのに、まるで手書きアニメっぽい画像を表示するゲームが、何本もある。
 
あれらの仕組みはどうなっているのかというと、トゥーン・レンダリングといわれる技術を使っており、下記のような工夫がよくある。
 
トゥーンレンダリングといった場合、主に、
# 輪郭線の自動的な描画と、
# 色彩の階調化
がある。
 
しかし、ゲーム産業では、たとえアニメキャラ風のキャラクターデザインのゲームでも、あまり色彩の階調化は使われない。
 
いっぽう、アニメ絵風のゲームでも、輪郭線の自動的な描画は使われる作品が多い。
 
 
=== 輪郭線 ===
 
登場人物のCGの輪郭線を、マンガみたいに線を強調して表示したい場合、手法はいろいろとあるが、どれも仕組みは単純である。
 
==== 黒コピー拡大背景の方法 ====
;シルエットなんとか法
手法のひとつとして、単に人物の画像をコピーして、それをすべてシルエット上に真っ黒にコピーしてから、やや大きく拡大し、さらにその上にもとの画像(黒くしてない画像)を載せると、輪郭ちかくのハジッコのほうだけは手前の画像に隠されずに奥側の黒い画像が見えるので、あたかも輪郭線っぽく見えるという手法がある。
 
これは、3D計算が不要なので、簡便だが便利な方法である。
 
欠点としては、たとえば「腕をくんでるポーズの人」をカメラが見た場合のように、人物の胴体の手前に人物の手が重なっている等の、人体のパーツどうしが重なっている場合には、手間が増える(人物1体ごとの黒コピーに加えて、さらに身体各部の黒コピーをする必要がある)。
 
また、身体各部の黒コピーをした場合、間接のあたりに、妙な線が発生しやすい。普通の漫画家は、腕を曲げてない場合には肘の内側を見てるシーンでは間接のシワ線を書かないが、しかし黒コピー線が曲げてない間接のあたりで発生しやすい。
 
こうした想定外の間接線を除外する方法としては、間接の近くでは黒コピーを除外する、つまり、最初からコピーする時点ですでに間接ちかくの部分はコピーしないでおく、・・・といった方法もある。
 
このような、間接ちかくをコピー除外する方式の場合、もし間接を曲げても線が描写されない事になるので、そういう事態を受け入れるしかない。
 
こうしないと、手のひらのアップで指の拡大画像を描写するときとかに、指には多数の間接があるので、ナゾの間接ラインが多数に発生しかねない。
 
 
;黒ポリゴンを少し後ろに追加の方式(「裏ポリゴン」なんとか法)
なお、シルエットの2次元黒画像を転写するかわりに、黒色の3Dポリゴンを拡大コピーして、表画像から少しだけ奥の場所に黒ポリゴンを配置する方法もあるが、これだとポリゴン描画量が倍増してしまうので(単純計算で2倍のポリゴン数になる)、ゲームとしては(ゲームでは描画の軽量化・高速化が必要なので)、ややデメリットがある。
 
どうしても黒ポリゴン追加の方式をゲームで活用する場合、ローポリ(ポリゴン数を低くする)にする必要があるだろう。
 
 
なお、後述するポリゴンの法線には、表向きと符号を裏返した裏向きの2種類があるので、背景黒側の法線を裏返して、そして法線がカメラから見て裏向き(法線とカメラの向きが同じ向きのとき)の場合の被写体を黒く塗ることで、この方式の輪郭に流用できる。俗に「裏ポリゴン」なんとか方式とか言われる。
 
 
 
シルエット法も裏ポリゴン法も発想は同じで、違いは単に、黒い背景画像の追加をどの段階で行うかの違いだけである。
 
 
==== 画素ごとに比較する方法 ====
原理的には、下記の方法でも輪郭を検出できるが、画素ごとの計算が必要なのハズなで、メモリ負担が大きい。
 
ゲームとして使う場合、携帯モバイル機器では、画素ごとに計算する方法は利用が難しいだろう。
 
また、(非ゲームの)テレビ番組や映画などのアニメ作品などでは、メモリ負担は製作側が負担するので、画素ごとに計算する方法も有効だろう。
 
 
比較のため、掲載しておく。
 
 
===== 「深度」なんとか法 =====
[[File:立方体の等角図.svg|thumb|等角図での立方体]]
 
輪郭線の発生場所とは、幾何学的には、奥行き方向(z方向)に段差のある場所で輪郭線が発生しているわけである。なので、元画像の各画素ごとに、その画素の対応するz座標を記録しておいて、そして隣の画素とのz数値との差によって、輪郭の点を描画するかどうかを決める方法である。
 
この方法は、カメラから見た深度をもとに計算しているので、「深度」なんとか法などとも言われる。「なんとか」とか言ってるのは、新しい分野なので名前があまり統一しておらず、業界や会社によって微妙に用語が違い、「深度法」とか「深度バッファ法」とか用語にバラツキがあるので、とりあえず「深度なんとか」と言ってる。
 
 
欠点として、たとえば等角図のような図の、外側輪郭いがいの部分を検出しづらい。
 
また、ほかの欠点として、画素ごとに計算するので、計算の手間や、メモリなどへの計算量の負担が増える。
 
 
===== 法線なんとか法 =====
[[画像:Koch_curve.svg|250px|thumb|right|フラクタル図形のひとつ、コッホ曲線]]
さらに他の方法もある。
 
それは、各ポリゴン面ごとに、その面の垂直線(面の垂線の場合、正確には「法線」(ほうせん)という)をあらかじめ全部の面ごとに計算しておいて、そして垂直線がカメラ向きに対して90度近くの場合にだけ、「そこに輪郭がある」として黒い点を描画していく方法である。
 
 
なお、法線ベクトルとカメラ向きベクトルとの内積を計算してもいい、・・・というか、普通は法線の情報はベクトルによって与えられるので、向きの計算も内積で計算することになる。
 
直角に交わるベクトルどうし2個の内積は0なので、つまりベクトル内積の絶対値が(0ちかくの)一定値未満になれば、輪郭があると検出することになる。
 
 
ともかく、このような法線による輪郭検出の方式のことを、「法線」なんとか法と言う。
 
 
長所としては、法線を計算しておけば、ほかの計算にも流用できる。
 
また、市販の3D-CGモデリングソフトによっては、すでに法線の自動計算の機能がついているものもある。
 
欠点としては、フラクタル図形のような被写体があるとき、見る角度によっては、その図形すべてを描画したりしかねず、真っ黒に写りかねない。
 
もっとも、通常の市販の3D-CGモデリングソフトでは、フラクタルの描画ができないので、めったにその事態に遭遇することは無いだろう。
 
 
なお、等角図の描写について、もし単に、カメラ向きと法線とを比較した場合には、「法線」なんとか法では描けない。
 
===== エッジなんとか法 =====
「法線」なんとか法を改良した方式のエッジ検出方式では、等角図も描ける。
 
「エッジ検出方式」とは、各画素とその周囲の画素との法線を比較する方式である。「エッジ抽出方式」ともいう。
 
 
 
法線の計算はベクトル計算なので、エッジ法の場合は、ベクトル内積が一定未満の場合にだけ輪郭があると認定して検出方式である。(同じ向きの単位ベクトルの内積は、1である。向きの差が大きくなるほど、内積は1から下がっていく。直交するベクトルは内積0である。さらに、反対どうしの内積はマイマス1である。)
 
 
エッジ法の弱点としては、フラクタル的な図形が「法線」なんとか方式と同様に苦手だろうが、しかしそもそも手書き風3Dアニメでフラクタル図形を描画することは普通は無いので(SFとかの例外は考えないでおく)、あまり気にしなくていいだろう。
 
 
 
==== 弱点 ====
[[File:フィレット.svg|thumb|500px|フィレット<br>例では4箇所の角部がフィレットされている]]
[[File:Fillet emphasise japanese.svg|thumb|400px|フィレット]]
 
法線なんとか法やエッジ法などの法線ベクトルを使う手法の場合、弱点として、カドっこを丸めるフィレット処理などの処理をされると、とたんに輪郭の検出が描画が難しくなる。
 
「フィレット」とは、工業製品などで、エッジのある場所に丸みをつける加工をすることである。
 
 
なぜフィレットのような処理に弱いかというと、円柱側面状の丸みのある場合、その場所の傾きは連続的に変化していくので、微分していくと法線どうしの向きは一致していき、よって法線の向きの差分を検出しづらい。
 
 
かといって対策として、(1画素単位といった)微分ではなく、数画素単位~十数画素のような大きな単位での差分にすると、今度は、輪郭線を書きたくない場所に誤検出をする可能性がある。
 
 
 
ゲームやアニメなどの娯楽コンテンツでは、もとからエッジを強調したままのデザインにしとけばいいので、フィレットをしなくても問題にはならない。
 
だが、工業製品などの3D-CGでは、重要な問題である。工業製品では、(切り傷などのケガを防ぐための)安全のため、エッジをとがらせずに、(金属ヤスリなどでエッジを削るなどして、エッジを)丸めたりすることもある。
 
3D-CG屋さんは、ときどき、製造業メーカーなどから宣伝用CG動画などの製作を頼まれる場合もある。
 
 
フィレットがあってもどうしても輪郭を検出したい場合、後述の方法がある。
# テクスチャ的に、輪郭線として検出したい場所を最初から輪郭線の色でモデル表面に塗っておく方法。
 
===== 「材質」による方法 =====
市販の3Dモデリングソフトでは、各部分の「材質」(『マテリアル』ともいう)をパーツごとに登録できる。なので、エッジ法や深度法などでの、各部の画素どうしの法線の比較のついでに、材質の比較をすることで、材質の変化をした部分に輪郭線を引くこともできる。このため、たとえば材質「服」と材質「肌」との境目の画素のぶぶんに輪郭線を引くこともできる。
 
 
ただし、材質どうしの比較だと、たとえば手を胸(説明の簡単化のため、男の平らな胸にする)に当てている場合や、手を腹に当てている場合などは、手も胸も腹も材質は同じ「肌」なので、この方法では検出できない。
 
 
どうしても、このような場合でも、手と胸との境界線を「材質」比較の方法で描画したい場合、対策として、たとえば材質「肌-手」や材質「肌-胸」など、身体各部ごとに材質をつくっておけばいい。
 
 
なお、普通のアニメ絵では、胸と腹のあいだの境界線は書かないし、胸と肩のあいだの境界線も書かない。
 
なので、例外として、材質が違っていても境界線を書かない組み合わせをあらかじめ登録しておき、それ以外の組み合わせが隣りあった場合にだけ境界線を描けばいい。
 
もっとも、この方法を使わなくても、前述したような黒背景の方法や「法線」なんとか法などでも、手と男胸との輪郭線を描画できる可能性はある。
 
 
 
 
==== 輪郭線にしたい場所に3Dモデル側で黒く塗る ====
リアリティは乏しくなるが、輪郭線として検出したいエッジ部に場所に、最初から(周囲の色が黒くなければ)エッジに黒く色をぬっておく方法も、単純だが効果的である。
 
エッジがフィレットされて丸められても、そのエッジごと黒くぬれば、周囲の色と違うので、簡単に見分けがつくというワケである。
 
テクスチャ的な手法である。
 
アニメ調にデフォルメされた子供のCGキャラクターなどは、最初から鼻の下のカゲなどが、黒くぬっておかれる場合もよくある。
 
 
弱点として、リアル調のCGでは導入が困難である。
 
また、見る角度やデザインの画風によっては、テクスチャが目立ちかねない。近くで接写する構図だと難しい。
 
 
対策として、カメラと被写体の距離や角度によって、輪郭にしたい部分のモデルだけをこっそりと輪郭テクスチャなしのモデルに入れ替える手法だと(たとえばカメラが接写になるほど近くなった場合には、輪郭部テクスチャをオフにして、テクスチャ無し3Dモデルに入れ替えるなどの方法)などが考えられる。ただし、少しメンドウくさい。
 
 
==== 明暗差を使う方法 ====
レイ・トレーシングなどのあとで、明暗差を使う方法もある。明暗差の大きい場所を輪郭として認識する方式である。
 
ただし、レイトレーシング自体が、計算量が多いので、メモリ負担がキツイ。
 
また、明暗差が無ければ輪郭線として認識しないので、光源の位置によっては、輪郭線として表現したい場所に、かならずしも輪郭線を検出するとはかぎらない。
 
 
 
 
=== 色の階調化 ===
まず、2005年ていどまでの手書きアニメでは、色のグラデーションが無いのが普通である。
 
かつて、1980~90年代のアニメ業界では、アゴ下と顔の境目の影を強調したり、ワキの下などの影を強調する手法が流行した。
 
しかし2010年代の現代では絵柄の流行が変わっており、作品にもよるが、ゲームでは、このような影はあまり使われてない。
 
 
もし、アニメ風に階調化したいなら、下記のようになるだろう。
 
階調化を自動的にしたい場合、
たとえば、あらかじめ前提として、レイ・トレーシングによって、影の位置を算出しておいて、各部の明暗が連続的に変化するので、その明暗に応じて各部の地の色のていどを変化させることで、連続的なグラデーションのあるモデルを作る。
 
次に、これを、色情報などをもとに何段階かの階調に分類すればいいだけである。具体的には、たとえば、各部の色を、何階調かに近似すればいいのである。
 
また、階調は、色ごとに設定する。
たとえば、ある物体の、光(ふつうの白色光)の当たる前の標準状態の色が水色だった場合、たとえば3階調として
:やや白みのある水色
:水色
:ややカゲで暗くなった水色
のように、3階調に分割する。
 
 
色ごろに階調を設定しないと、アカっぽい色は、ぜんぶアカになったりとかして、役に立たなくなってしまう。
 
 
なお、現代コンピュータでは色データの濃淡は普通は255段階である。256×256×256 = 16777216 の約1600万色である。
 
 
 
 
ただし、実は2010年代のアニメ風ゲーム業界では、絵柄の流行が変わっており、もはや階調化した影の強調は、流行から外れている。(もしかしたら強調してないだけで階調化じたいはしている可能性も否定しきれないが、少なくとも影の階調が素人目には見つけられない作品が普通に多い。)
 
 
このため、そもそもの階調化の需要が、ゲーム産業では、乏しくなってきている。
 
 
 
どうしてもゲームでプレイヤーの操作できるシーンのCG動画に影や光沢を描きたい場合、テクスチャ的に被写体に影を貼り付ける場合もある。
 
 
たとえばアニメキャラの瞳の光沢など、テクスチャ的に最初から描いておくことも多いだろう。
 
顔のあご下の首の影になる部分も、最初から暗めの肌色で塗っておく作品も多いだろう。
 
 
もちろん、テクスチャなので、たとえば人物が暗い場所に入って、懐中電灯を顔より下の位置に持っていても(いわゆる逆光の状態)、なぜか目の光沢が瞳の上にあるような不整合は起きるだろうが、やむをえない(もしくは、逆光の場合のテクスチャを別途、用意するか)。
 
あご下の影テクスチャも、逆立ちしても、あごの下が暗かったりとかの不整合もあるが、やむをえない。
 
 
=== 半透明レイヤー合成による影などの方法 ===
もしも、レイ・トレーシングをそのまま実行すると、メモリに負担がけっこう掛かる。
 
なので、ゲームのジャンルによってはレイ・トレーシングをせずに、影や光沢による色の補正を行う必要にせまられる場合もありうる。
 
 
アニメ絵風のゲームで、もしも登場人物が日陰に入ったときなどに、人物をやや暗く表現するには、わざわざレイトレーシングする必要はなく、半透明の黒~灰色のレイヤーでも人物画像の上にでも載せて合成画像にして描画すればいい。
 
 
この方法は、日陰に入る前後の瞬間については物理学的には影の位置は不正確だが、しかしそもそもアニメ絵風のゲームでは、影の正確な位置なんぞにプレイヤーは興味ない。
 
そもそも、プレイヤーがもしも実写そっくりの位置にできる影に興味あるなら、そういうプレイヤーは実写キャラクター風のゲームをプレイしているからである。
 
== 参考文献 ==