はじめに

こんにちはー!
今日は、3D描写するときのテストの話をします。

テストと聞いて何を思い浮かびますでしょうか。
試験とか、勉強とかそんなことをきっと思い浮かべるでしょう。

作成した3Dポリゴンの頂点を描写するときも、
本当に描写していいのか、無駄ではないのか試験をしています。

いくつかテスト方法を紹介しましょう。

背面カリング(裏面カリング)
モデルは多くの3角ポリゴンから構成されています。
モデルが回転すれば、裏を向いているポリゴンが出てきます。
そんな裏を向いている面を描写しないようにテストします。

クリッピング
視錐台(しすいだい)の中に、ポリゴンが収まっているかどうかテストします。
例えば、カメラより手前側にポリゴンが来ていないかといったチェックです。

バウンディングボリュームなど
見えている部分をより特定していく方法です。
衝突判定などにも、高速化のために使用するよ!

今回は、この中でも裏面カリングの設定方法について解説します。


カリングの仕組み

3Dオブジェクトは、細かな三角形ポリゴンによって構成されています。
それは三角形が最も小さな単位だからです。

では、この三角形の裏と表をどのように決めればいいのでしょうか。
まず前提条件として、ディスプレイに三角形を表示することを考えます。
三角形を構成するためには、3点の座標が必要です。
この3点の座標を囲めば、ポリゴンを作ることができるのです。

これに対して、裏と表を決める方法は、
三角形を結ぶ順番が、時計回りか、反時計回りかで決めればいいのです。
そう、決めの問題なのです!

例えば、表向きを時計回りと考えてみましょう。
3角形の頂点を裏返した場合は、
反時計回りの順序になるので裏と表が分かるわけなのです。


カリングの計算方法

3つの頂点が、時計回りか反時計回りかは簡単に計算できます。

下記の3つの頂点があり、a, b, c の3点を順番に通る三角形を考えます。
なお、2次元なので、 x と y 以外は 0 としています。

そして、
a, bへ向かうベクトルmを計算します。
a, cへ向かうベクトルnを計算します。

あとは、クロス積を計算しましょう。
計算にはmnの各ノルムと角度θを使用しますが、
ベクトルのまま計算することもできます。
なお、a, b, c の3次元目が 0 のため、下記のように簡略化されます。

クロス積の結果は、mnと直行するベクトルです。
従って3次元目の成分 、直行成分となっており、正負で方向が分かります。

ね!かんたん!


カリングの設定方法

各種エンジンでの設定方法をまとめてみます。
mk様の算譜記録帳にもまとまっております。

DirectX 9

次のように、裏面(描写しない面)が時計回りなのか、反時計回りなのかを設定します。
つまり、時計回りを表とみなす場合は、D3DCULL_CCWを設定する必要があります。

参考:D3DCULL

// 背面のカリングはしません。
SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);

// 三角形の頂点が時計回りならば裏向きと見なし描画しません。
SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);

// 三角形の頂点が反時計回りならば裏向きと見なし描画しません。(デフォルト)
SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);

DirectX 11

FrontCounterClockwise で表面の定義をして、
CullMode で描写しない面の設定が可能です。

参考:D3D11_RASTERIZER_DESC

// 三角形の頂点が反時計回りならば三角形は前向き
FrontCounterClockwise = TRUE;

// 三角形の頂点が時計回りならば三角形は前向き(デフォルト)
FrontCounterClockwise = FALSE;

// 常にすべての三角形を描画します。
CullMode = D3D11_CULL_NONE;

// 前向きの三角形を描画しません。
CullMode = D3D11_CULL_FRONT;

// 後ろ向きの三角形を描画しません。(デフォルト)
CullMode = D3D11_CULL_BACK;

OpenGL

glFrontFace で表面の定義をして、
glCullFace で描写しない面の設定が可能です。

参考:glFrontFace, glCullFace

// 三角形の頂点が時計回りならば三角形は前向き
glFrontFace(GL_CW);

// 三角形の頂点が反時計回りならば三角形は前向き(デフォルト)
glFrontFace(GL_CCW);

// 常にすべての三角形を描画します。
glDisable(GL_CULL_FACE);

// 前向きの三角形を描画しません。
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);

// 後ろ向きの三角形を描画しません。(デフォルト)
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);

おわりに

今回は、描写テストでも基本的なカリングの解説をしました。

カリングは計算も簡単で、
お手軽に描写負荷を下げることができます。

レンダラーを作る方や、
頂点とインデックスで構成された
モデルデータのローダーを作成する方などの参考になると幸いです。

では、またね!


関連記事

3DCGの座標系の紹介
DirectXとOpenGLの回転行列、回転軸、回転方向
DirectXとOpenGLのビュートランスフォーム行列の違い
DirectXとOpenGLの射影トランスフォーム行列の違い
DirectXとOpenGLのビューポート行列の違い
DirectXとOpenGLのベクトル/行列演算の違い

関連記事

  • DirectXとOpenGLのベクトル/行列演算の違いDirectXとOpenGLのベクトル/行列演算の違い はじめに こんにちー。 なたでです。 今日も引き続き勉強会です。 これまで、座標系とその変換を学んできました。 今回、実際にその計算を行うため、 具体的にはベクトルや行列演算について どのようにソースコード上で書けばいいか学んでいきましょう。 ということで・・・ DirectX、OpenGL、各シェーディング言語の型や計算の特徴をまとめるぞー!( […] Posted in アルゴリズム
  • DirectXとOpenGLの回転行列、回転軸、回転方向DirectXとOpenGLの回転行列、回転軸、回転方向 はじめに こんにちは! ハンドスピナーを最近買ったなたでです! 今日も勉強会をしましょう。 本日は、DirectXとOpenGLの軸の違いに焦点をあてて 回転行列をおさらいしてみましょう。 掛ける順序 3D環境といえば、DirectX、OpenGLです。 今回、回転用の標準関数を調査して比較していきたいと思います。 比較する前に基本的な掛 […] Posted in アルゴリズム
  • 3DCGの座標系の紹介3DCGの座標系の紹介 はじめに こんにちは! 今日は、3DCGにかかせない座標系の話をするよ! 座標系の種類 では、オブジェクトから画面まで、どのような座標系があるか紹介します。 . 座標系一覧 呼び方が変わりますが、細かく分けると次のような流れになっています。 各々の変換とよばれている部分が行列を掛け算することに相当します。 座標はベクトルとし、このベクトルに座標を掛け算して、次の座標系 […] Posted in アルゴリズム
  • DirectXとOpenGLのビューポート行列の違いDirectXとOpenGLのビューポート行列の違い はじめに こんにちは! 3DCGの再勉強中のなたでです! 今まで、次の変換行列の違いをみてきました。 ・DirectXとOpenGLのビュートランスフォーム行列の違い ・DirectXとOpenGLの射影トランスフォーム行列の違い 本日は変換の最後のビューポート行列の違いを調べてみましょう。 といっても、ここまでくると右手座標系・左手座標系という話はなくなっているので、 […] Posted in アルゴリズム
  • DirectXとOpenGLの射影トランスフォーム行列の違いDirectXとOpenGLの射影トランスフォーム行列の違い はじめに こんにちは! 引き続いて座標変換の話をします。 本日は射影トランスフォーム行列を覗いてみましょう。 前回の関連記事(予備知識として下から上に読んでおきましょう) ・DirectXとOpenGLのビュートランスフォーム行列の違い ・3DCGの座標系の紹介 ・DirectXとOpenGLの回転行列、回転軸、回転方向 数式の比較 . DirectXとOpenGL […] Posted in アルゴリズム
  • DirectXとOpenGLのビュートランスフォーム行列の違いDirectXとOpenGLのビュートランスフォーム行列の違い はじめに こんこん! 今回は、前回に引き続き座標変換の話をします。 特に、ビュートランスフォームの部分の計算式を見てみましょう。 気になっていたのは、DirectXとOpenGLとで違いがあるのかという点です。 おそらく違いはないはずですが、 前回の関連記事 ・3DCGの座標系の紹介 ・DirectXとOpenGLの回転行列、回転軸、回転方向 数式の比較 . Dir […] Posted in アルゴリズム