📘
OpenGLで図形を表示する方法
OpenGLを使った基本図形の描画
OpenGLで図形を描画する方法について、頂点データを用いた四角形の描画手順について解説します。
必要なヘッダーのインクルード
まず、OpenGLの機能を使用するために必要なヘッダーをインクルードします。GLEWとGLFWを使用してOpenGLの拡張機能を簡単に扱えるようにします。
#include <iostream>
#include <sstream>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
ウィンドウサイズの設定
ウィンドウの幅と高さを指定します。これは、後でGLFWウィンドウの作成時に使用されます。
int Width = 800, Height = 600;
頂点シェーダーとフラグメントシェーダーのソースコード
頂点シェーダーとフラグメントシェーダーは、OpenGLのグラフィックスパイプラインで使用されます。頂点シェーダーは頂点の位置を設定し、フラグメントシェーダーはピクセルの色を決定します。
const GLchar* vertexShaderSrc =
"#version 330 core \n"
"layout (location = 0) in vec3 pos;"
"uniform vec2 posOffset;"
"void main()"
"{"
" gl_Position = vec4(pos.x + posOffset.x, pos.y + posOffset.y, pos.z, 1.0f);"
"}";
const GLchar* fragmentShaderSrc =
"#version 330 core \n"
"uniform vec4 vertColor;"
"out vec4 frag_color;"
"void main()"
"{"
" frag_color = vertColor;"
"}";
キー入力のコールバック関数
GLFWを使って、ESCキーが押されたらウィンドウを閉じるコールバック関数を設定しま
void glfw_onKey(GLFWwindow* window, int key, int scancode, int action, int mode) {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GL_TRUE);
}
}
メイン関数
GLFWを初期化し、ウィンドウを作成します。
glfwInit();
GLFWwindow* gWindow = glfwCreateWindow(Width, Height, "Window", NULL, NULL);
glfwMakeContextCurrent(gWindow);
glewExperimental = GL_TRUE;
glewInit();
glfwSetKeyCallback(gWindow, glfw_onKey);
頂点データとインデックスデータの設定
四角形を描画するための頂点データとインデックスデータを設定します。
GLfloat vertices[] = {
-0.5f, 0.5f, 0.0f, // Top left
0.5f, 0.5f, 0.0f, // Top right
0.5f, -0.5f, 0.0f, // Bottom right
-0.5f, -0.5f, 0.0f // Bottom left
};
GLuint indices[] = {
0, 1, 2, // First Triangle
0, 2, 3 // Second Triangle
};
バッファと頂点配列オブジェクトの生成
頂点データとインデックスデータをGPUに送るために、バッファと頂点配列オブジェクトを生成します。
GLuint vbo, ibo, vao;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
シェーダーのコンパイルとリンク
シェーダーをコンパイルし、プログラムにリンクします。
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vertexShaderSrc, NULL);
glCreateShader(vs);
GLint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fragmentShaderSrc, NULL);
glCreateShader(fs);
GLint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vs);
glAttachShader(shaderProgram, fs);
glLinkProgram(shaderProgram);
GLchar infoLog[512];
glGetProgramInfoLog(shaderProgram, sizeof(infoLog), NULL, infoLog);
std::cout << infoLog << std::endl;
glDeleteShader(vs);
glDeleteShader(fs);
メインループ
ウィンドウが閉じられるまで、以下の処理をループします。
背景色の設定と画面のクリア
シェーダープログラムの使用
時間に応じた色と位置のオフセットの変更
四角形の描画
while (!glfwWindowShouldClose(gWindow)) {
glfwPollEvents();
glClearColor(0.f, 0.5f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
GLfloat time = (GLfloat)glfwGetTime();
GLfloat blueColor = (sin(time) / 2) + 0.5f;
glm::vec2 posoffset;
posoffset.x = sin(time) / 2;
posoffset.y = cos(time) / 2;
GLint posOffsetLoc = glGetUniformLocation(shaderProgram, "posOffset");
glUniform2f(posOffsetLoc, posoffset.x, posoffset.y);
GLint vertColorLoc = glGetUniformLocation(shaderProgram, "vertColor");
glUniform4f(vertColorLoc, 0.0f, 0.0f, blueColor, 1.0f);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glfwSwapBuffers(gWindow);
}
後片付けと終了
使用したシェーダープログラム、バッファ、VAOを削除し、GLFWを終了します。
glDeleteProgram(shaderProgram);
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vbo);
glDeleteBuffers(1, &ibo);
glfwTerminate();
return 0;
Discussion