本項では光源設定と陰面処理を行います。
前項で表示させた形状に陰影がつくようにしてみましょう。
光源の設定を行う関数を作成します。
視点方向から光が当たるように設定していきます。
1. SetLight の宣言
【STLViewerView.h】
class CSTLViewerView : public CView
{
/* 長くなるので一部省略、ここより上は変更なし */
private:
HGLRC m_hGLRC;
bool InitGL();
void DrawGL();
bool SetDCPixelFormat(HDC hdc);
void DrawLine(const CgsPoint& sp, const CgsPoint& ep, const COLORREF& color) const;
bool DrawSTL() const;
void SetLight() const;
public:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnSize(UINT nType, int cx, int cy);
};
2. SetLight の定義
【STLViewerView.cpp】
void CSTLViewerView::SetLight() const
{
const GLfloat ambient[4] = { 0.8f, 0.8f, 0.8f, 1.0f };
const GLfloat diffuse[4] = { 0.6f, 0.6f, 0.6f, 1.0f };
const GLfloat specular[4] = { 0.4f, 0.4f, 0.4f, 1.0f };
const GLfloat position[4] = { 200.0f, 200.0f, 200.0f, 1.0f };
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); // 環境光設定
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); // 拡散光設定
glLightfv(GL_LIGHT0, GL_SPECULAR, specular); // 鏡面光設定
glLightfv(GL_LIGHT0, GL_POSITION, position); // 光源座標
}
光源設定を呼び出します。
void CSTLViewerView::DrawGL()
{
/* 長くなるので一部省略、ここより上は変更なし */
// Z軸線描画
DrawLine({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 100.0 }, RGB(0, 0, 255));
// 光源の有効化
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
// 光源設定
SetLight();
// STL描画
DrawSTL();
// 光源の無効化
glDisable(GL_LIGHTING);
glDisable(GL_LIGHT0);
// OpenGL関数の実行強制
glFlush();
// オンスクリーンバッファーへのコピー
SwapBuffers(dc.m_hDC);
}
後から描画した三角形が優先して見えるようになっているので、視点に近い三角形が優先して見えるように設定します。
【STLViewerView.cpp】
void CSTLViewerView::DrawGL()
{
// カレントコンテキスト設定
CClientDC dc(this);
wglMakeCurrent(dc.m_hDC, m_hGLRC);
// バッファーのクリア
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 視点等変更
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(200.0, 200.0, 200.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
// X軸線描画
DrawLine({ 0.0, 0.0, 0.0 }, { 100.0, 0.0, 0.0 }, RGB(255, 0, 0));
// Y軸線描画
DrawLine({ 0.0, 0.0, 0.0 }, { 0.0, 100.0, 0.0 }, RGB(0, 255, 0));
// Z軸線描画
DrawLine({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 100.0 }, RGB(0, 0, 255));
// 光源と陰面処理の有効化
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
// 光源設定
SetLight();
// STL描画
DrawSTL();
// 光源と陰面処理の無効化
glDisable(GL_LIGHTING);
glDisable(GL_LIGHT0);
glDisable(GL_DEPTH_TEST);
// OpenGL関数の実行強制
glFlush();
// オンスクリーンバッファーへのコピー
SwapBuffers(dc.m_hDC);
}
光源が有効になっているときには glColor は効果がないので削除しておきます。
bool CSTLViewerView::DrawSTL() const
{
CSTLViewerDoc* pDoc = GetDocument();
if (!pDoc) {
return false;
}
glColor(RGB(192, 192, 192)); // 面色設定 ←この行を削除
glBegin(GL_TRIANGLES); // 3頂点を独立した三角形として描画開始
const CgsTriangles& triangles = pDoc->GetTriangles();
for (const auto& e : triangles) {
glNormal(e.GetNormal()); // 法線ベクトル設定
for (int i = 0; i < 3; ++i) {
glVertex(e.GetPoint(i)); // 頂点設定
}
}
glEnd(); // 描画終了
return true;
}
その代わりに glMaterialfv を使ってマテリアルパラメータの設定をを行います。
bool CSTLViewerView::DrawSTL() const
{
CSTLViewerDoc* pDoc = GetDocument();
if (!pDoc) {
return false;
}
GLfloat ambient[] = { 0.2f, 0.2f, 0.2f, 1.0f };
GLfloat diffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f };
GLfloat specular[] = { 0.0f, 0.0f, 0.0f, 1.0f };
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient); // 環境光設定
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse); // 拡散光設定
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); // 鏡面光設定
glBegin(GL_TRIANGLES); // 3頂点を独立した三角形として描画開始
const CgsTriangles& triangles = pDoc->GetTriangles();
for (const auto& e : triangles) {
glNormal(e.GetNormal()); // 法線ベクトル設定
for (int i = 0; i < 3; ++i) {
glVertex(e.GetPoint(i)); // 頂点設定
}
}
glEnd(); // 描画終了
return true;
}