この手法自体はOpenGLにもDirectXにも標準で組み込まれていて,設定するだけで簡単に利用できる.
OpenGLの場合,次のように設定する.
// OpenGLの場合 // 背面カリングを有効にする glEnable(GL_CULL_FACE); // 反時計回り(counter clockwise)の頂点を持つ面を表と見なす (デフォルト) // glFrontFace(GL_CCW); // 時計回り(clockwise)の頂点を持つ面を表と見なす // glFrontFace(GL_CW); // WebGLの場合 // var gl = canvas.getContext('webgl'); gl.enable(gl.CULL_FACE); // gl.frontFace(gl.CCW); // gl.frontFace(gl.CW);
DirectX 9の場合,次のように設定する.
// ID3DDevice9 * pD3DDevice; // 背面カリング無し // pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); // 反時計回り(counter clockwise)の頂点を持つ面を消す (デフォルト) // pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); // 時計回り(clockwise)の頂点を持つ面を消す // pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
DirectX 11の場合,次のように設定する.
// ID3D11Device * pDevice; // ID3D11DeviceContext * pContext; // ラスタライザーステートの設定に必要なパラメータを設定 D3D11_RASTERIZER_DESC rd; // 背面カリングをしない場合 // rd.CullMode = D3D11_CULL_NONE; // 表面を消す場合 // rd.CullMode = D3D11_CULL_FRONT; // 裏面を消す場合 (デフォルト) // rd.CullMode = D3D11_CULL_BACK; // 時計回り(clockwise)の頂点を持つ面を表と見なす (デフォルト) // rd.FrontCounterClockwise = FALSE; // 反時計回り(counter clockwise)の頂点を持つ面を表と見なす // rd.FrontCounterClockwise = TRUE; // その他のパラメータも設定 // ラスタライザーステートを生成して設定 ID3D11RasterizerState * pState; pDevice->CreateRasterizerState(&rd, &pState); pContext->RSSetState(pState); pState->Release();
デフォルトの設定を整理すると次のようになる.
OpenGL | DirectX | |
---|---|---|
消す面 | 裏 | 裏 |
表と見なす面 | 反時計回り(CCW) | 時計回り(CW) |
この設定手順の中で,OpenGLとDirectX 9を比較すると混乱してしまうのが,OpenGLは「表示する面」をCCW(counter clockwise)にするか,CW(clockwise)にするかを指定するのに対して,DirectX 9では「消す面」をCCWにするかCWにするかを指定する,ということだろう.同じような名前の定数を利用するので,同時に扱うと非常に混乱する気がする.
実際混乱している人がいるのか,OpenGLが右手座標系でDirectXは左手座標系だからだ,といった説明もあったが,頂点が時計回りか反時計回りかは座標系と関係が無いので,表示面指定と消去面指定で混乱しているのではないかと思われる.
調べて,実際にコードを書いて挙動を確認した限りでは合っていると思うのだけれど,実際のところ正しいのだろうか?
0 件のコメント:
コメントを投稿