第 8 章 形状の表現
8.3 図形の塗りつぶし
8.3.1 三角形の描画
GLSL のバージョン 3.3 以降 (#version 330) であれば、このバーテックスシェーダの attribute 変数の場所やフラグメントシェーダの出力変数の場所は、シェーダのソースプログラム中で変数 を宣言する際に layout 修飾子を使って指定することができます。また、この機能は GLSL のバ ージョン 3.2 でも GPU の拡張機能として用意されている場合があります。その場合はバーテッ クスシェーダのソースプログラムの冒頭に #extension GL_ARB_explicit_attrib_location: enable を 付ければ、この機能を使用できるようになります。
l バーテックスシェーダ
#version 150 core
#extension GL_ARB_explicit_attrib_location: enable uniform mat4 modelview;
uniform mat4 projection;
layout (location = 0) in vec4 position;
layout (location = 1) in vec4 color;
out vec4 vertex_color;
void main() {
vertex_color = color;
gl_Position = projection * modelview * position;
}
l フラグメントシェーダ
#version 150 core
#extension GL_ARB_explicit_attrib_location: enable in vec4 vertex_color;
layout (location = 0) out vec4 fragment;
void main() {
fragment = vertex_color;
}
8.3 図形の塗りつぶし
図 118 三角形で表現した正六面体
このデータは表 7 の頂点表と三角形表のように表すことができます。
表 7 頂点表と三角形表
l インデックスを使って三角形による描画を行うクラス SolidShapeIndex (SolidShapeIndex.h)
インデックスを使って六面体を 12 枚の三角形 で描画するクラス SolidShapeIndex を、
SolidShapeIndex.h というヘッダファイルに ShapeIndex クラスを継承して定義します。このクラ
スは ShapeIndex クラスの execute() メソッドのオーバーライドだけを行います。このコンストラ
クタの引数は、そのまま ShapeIndex のコンストラクタに渡します。また、三角形を描画するの で、execute() で実行する glDrawElements() の第一引数 mode を GL_TRIANGLES にします。
#pragma once
// インデックスを使った図形の描画
#include "ShapeIndex.h"
インデックスを使った三角形による描画
3 2 7 4
0 1 6 5
5 6
4
0
1 2
3
4
5
6 7
3
4
5
⇥
⇤
⌅
⇧
⌃
(1, -1, 1) (-1, -1, 1)
(-1, 1, 1)
(-1, 1, -1)
(1, 1, 1)
(1, 1, -1)
(-1, -1, -1)
(1, -1, -1)
⌅
⇥ ⇧
⇤
⌃
GL_TRIANGLES
頂点
0 1 2 3 4 5 6 7
x -1 -1 -1 -1 1 1 1 1
y -1 -1 1 1 1 -1 -1 1
z -1
1 1 -1 -1 -1 1 1
面 インデックス
左 裏 下 右 上 前
三角形 (1) 三角形 (2) 0
0 0 7 7 7
1 3 5 6 4 2
2 4 6 5 3 1
0 0 0 7 7 7
2 4 6 5 3 1
3 5 1 4 2 6 位置
頂点表
三角形表
class SolidShapeIndex : public ShapeIndex {
public:
// コンストラクタ
// size: 頂点の位置の次元 // vertexcount: 頂点の数
// vertex: 頂点属性を格納した配列
// indexcount: 頂点のインデックスの要素数 // index: 頂点のインデックスを格納した配列
SolidShapeIndex(GLint size, GLsizei vertexcount, const Object::Vertex *vertex, GLsizei indexcount, const GLuint *index)
: ShapeIndex(size, vertexcount, vertex, indexcount, index) {
}
// 描画の実行
virtual void execute() const {
// 三角形で描画する
glDrawElements(GL_TRIANGLES, indexcount, GL_UNSIGNED_INT, 0);
} };
l メインプログラム (main.cpp) の変更点
SolidShapeIndex クラスを定義しているヘッダファイル SolidShapeIndex.h を main.cpp の冒頭 で #include します。
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <vector>
#include <memory>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "Window.h"
#include "Matrix.h"
#include "Shape.h"
#include "ShapeIndex.h"
#include "SolidShapeIndex.h"
main() 関数より前に、六面体を塗りつぶす三角形の頂点のインデックス (表 7 の三角形表) の
データ solidCubeIndex を追加します。そして main() 内でこれと六面体の頂点の位置 cubeVertex を使って SolidShapeIndex クラスのインスタンスを生成します。データの頂点の数は 8 個ですが、
描画する頂点の数 (インデックスの数) は三角形が 12 枚なので 36 個になります。
// 六面体の面を塗りつぶす三角形の頂点のインデックス constexpr GLuint solidCubeIndex[] =
{
0, 1, 2, 0, 2, 3, // 左 0, 3, 4, 0, 4, 5, // 裏
0, 5, 6, 0, 6, 1, // 下 7, 6, 5, 7, 5, 4, // 右 7, 4, 3, 7, 3, 2, // 上 7, 2, 1, 7, 1, 6 // 前 };
int main() {
《省略》
// 図形データを作成する
std::unique_ptr<const Shape> shape(new SolidShapeIndex(3, 8, cubeVertex, 36, solidCubeIndex));
// ウィンドウが開いている間繰り返す
while (window.shouldClose() == GL_FALSE) {
《省略》
} }
n サンプルプログラム step21
l 実行結果
図 119 三角形を使って描画した結果