🌐
OpenGLでキューブを描画 GLFW入門 その1
環境
mac
macだとOpenGLの制限やGLMがうまく見つかんなかったりするから手動でやっていきます
GLADここからGIPをダウンロードして
作業デレクトリで解凍
目次
MakeFileの作成
advent_ogl/
├── build/
├── main.cpp <=3
├── CMakeLists.txt <= 1
└── glad/
├── CMakeLists.txt <=2
├── include/
└── src/
1
目次の1の部分です
cmake
CmakeList
cmake_minimum_required(VERSION 3.12)
# プロジェクト名の設定
project(advent_gl)
# C++11の設定
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 必須ライブラリの存在チェック
find_package(glfw3 REQUIRED)
# GLMのパスを手動で指定する windows linuxではここが変わります
find_path(GLM_INCLUDE_DIR glm/glm.hpp PATHS /opt/homebrew/include /opt/homebrew/Cellar/glm/1.0.1/include)
# GLMが見つかった場合、インクルードディレクトリを追加
if (GLM_INCLUDE_DIR)
include_directories(${GLM_INCLUDE_DIR})
else()
message(FATAL_ERROR "GLM not found")
endif()
# glad関係
include_directories(glad/include)
add_subdirectory(glad)
# コンパイルオプション
add_compile_options(-O2 -Wall)
# 実行ファイルの指定
add_executable(advent_gl main.cpp)
# 実行ファイルにリンクするライブラリの指定
target_link_libraries(advent_gl glad glfw ${CMAKE_DL_LIBS})
cmake
目次の2の部分です
CmakeList
cmake_minimum_required(VERSION 3.12)
# gladという名前でCMakeに認識させるライブラリを作成
# 静的ライブラリとしてコンパイル。含まれるソースを指定。
add_library(glad STATIC
src/glad.c
)
main.cpp
目次の3の部分です
main.cpp
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <iostream>
// ウィンドウサイズの定義
const unsigned int WINDOW_WIDTH = 1440;
const unsigned int WINDOW_HEIGHT = 810;
// カメラの位置と向きを管理する変数
glm::vec3 cameraPosition(0.0f, 0.0f, 3.0f);
glm::vec3 cameraFront(0.0f, 0.0f, -1.0f);
glm::vec3 cameraUp(0.0f, 1.0f, 0.0f);
// 移動速度の設定
float moveSpeed = 0.1f; // 移動速度を調整
// シェーダーのソースコード
const char* vertexShaderSource = R"(
#version 410 core
layout(location = 0) in vec3 aPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
}
)";
const char* fragmentShaderSource = R"(
#version 410 core
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0, 0.5, 0.2, 1.0); // オレンジ色
}
)";
void keyHandler(GLFWwindow*, int, int, int, int);
unsigned int compileShader(unsigned int type, const char* source);
unsigned int createShaderProgram();
int main()
{
// GLFWの初期化
if (!glfwInit()) {
std::cerr << "Failed to initialize GLFW." << std::endl;
return -1;
}
// OpenGLのバージョンとプロファイルの設定
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
// ウィンドウの作成
GLFWwindow* window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "advent_gl", nullptr, nullptr);
if (!window)
{
std::cerr << "Failed to create window." << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, keyHandler);
// GLADの初期化
if (!gladLoadGLLoader(reinterpret_cast<GLADloadproc>(glfwGetProcAddress)))
{
std::cerr << "Failed to initialize GLAD" << std::endl;
return -1;
}
// ビューポートの設定
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
// 深度テストの有効化
glEnable(GL_DEPTH_TEST);
// 背景色の設定
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
// シェーダープログラムの作成
unsigned int shaderProgram = createShaderProgram();
// キューブの頂点データ
float vertices[] = {
// 前面
-0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
// 背面
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
-0.5f, 0.5f, -0.5f
};
unsigned int indices[] = {
// 前面
0, 1, 2, 2, 3, 0,
// 背面
4, 5, 6, 6, 7, 4,
// 左側
4, 0, 3, 3, 7, 4,
// 右側
1, 5, 6, 6, 2, 1,
// 下側
4, 5, 1, 1, 0, 4,
// 上側
3, 2, 6, 6, 7, 3
};
// VAO, VBO, EBOの作成
unsigned int VAO, VBO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// 描画ループ
while (!glfwWindowShouldClose(window))
{
// バッファのクリア
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// シェーダープログラムの使用
glUseProgram(shaderProgram);
// 行列の設定
glm::mat4 model = glm::mat4(1.0f);
glm::mat4 view = glm::lookAt(cameraPosition, cameraPosition + cameraFront, cameraUp);
glm::mat4 projection = glm::perspective(glm::radians(45.0f), (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, 0.1f, 100.0f);
unsigned int modelLoc = glGetUniformLocation(shaderProgram, "model");
unsigned int viewLoc = glGetUniformLocation(shaderProgram, "view");
unsigned int projLoc = glGetUniformLocation(shaderProgram, "projection");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
// キューブを描画
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
// バッファのスワップとイベント処理
glfwSwapBuffers(window);
glfwPollEvents();
}
// リソース解放
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
glDeleteProgram(shaderProgram);
glfwTerminate();
return 0;
}
void keyHandler(GLFWwindow *window, int key, int scancode, int action, int mods)
{
if (action == GLFW_PRESS || action == GLFW_REPEAT)
{
if (key == GLFW_KEY_ESCAPE)
{
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
else if (key == GLFW_KEY_W) // 前進
{
cameraPosition += moveSpeed * cameraFront;
}
else if (key == GLFW_KEY_S) // 後退
{
cameraPosition -= moveSpeed * cameraFront;
}
else if (key == GLFW_KEY_A) // 左移動
{
cameraPosition -= glm::normalize(glm::cross(cameraFront, cameraUp)) * moveSpeed;
}
else if (key == GLFW_KEY_D) // 右移動
{
cameraPosition += glm::normalize(glm::cross(cameraFront, cameraUp)) * moveSpeed;
}
else if (key == GLFW_KEY_SPACE) // 上昇
{
cameraPosition += moveSpeed * cameraUp;
}
else if (key == GLFW_KEY_LEFT_SHIFT) // 下降
{
cameraPosition -= moveSpeed * cameraUp;
}
}
}
unsigned int compileShader(unsigned int type, const char* source)
{
unsigned int shader = glCreateShader(type);
glShaderSource(shader, 1, &source, nullptr);
glCompileShader(shader);
int success;
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success) {
char infoLog[512];
glGetShaderInfoLog(shader, 512, nullptr, infoLog);
std::cerr << "Error compiling shader: " << infoLog << std::endl;
}
return shader;
}
unsigned int createShaderProgram()
{
unsigned int vertexShader = compileShader(GL_VERTEX_SHADER, vertexShaderSource);
unsigned int fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragmentShaderSource);
unsigned int shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
int success;
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
char infoLog[512];
glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);
std::cerr << "Error linking shader program: " << infoLog << std::endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return shaderProgram;
}
最後に
macの場合
ライブラリをダウンロード
brew install glfw
brew install glm
brew install cmake
作成してビルド
mkdir build
cd build
cmake .
make
実行
./advent_gl
Discussion
これは、cmakeの部分を変更したら、クロスプラットフォームになると思います