MSYS2のMINGW64 → pacman やOpenGL関連ライブラリがインストール可能 な環境でGLSLを描画できた。 FBX Viewerを作る Vol.3 テクスチャとカメラのタンブル、トラック、ドリー、ロール、ズーム

memo.txt

fbx_viewer/
├── CMakeLists.txt
├── include/
│   ├── glad/
│   ├── KHR/
│   ├── glfw/
│   ├── glm/
│   └── stb/
├── lib/
│   ├── glfw3.lib など
├── src/
│   ├── main.cpp
│   ├── shader.cpp
│   └── glad.c

├── shader.vert
├── shader.frag
├── model.fbx
└── texture.png




pacman -S mingw-w64-x86_64-glfw mingw-w64-x86_64-glew mingw-w64-x86_64-assimp mingw-w64-x86_64-glm

pacman -S mingw-w64-x86_64-glad

cd fbx_viewer
mkdir build && cd build
cmake -G "MinGW Makefiles" ..
mingw32-make
./fbx_viewer

shader.vert

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoord;

uniform mat4 u_model;
uniform mat4 u_view;
uniform mat4 u_proj;

out vec2 TexCoord;

void main() {
    gl_Position = u_proj * u_view * u_model * vec4(aPos, 1.0);
    TexCoord = aTexCoord;
}

shader.frag

#version 330 core
out vec4 FragColor;

in vec2 TexCoord;
uniform sampler2D u_texture;

void main() {
    FragColor = texture(u_texture, TexCoord);
}

src/main.cpp

#define GLFW_INCLUDE_NONE  // ← glad を使うので OpenGL ヘッダーを GLFW 側で除外
#include <glad/glad.h> 
#include <GLFW/glfw3.h>

#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include <stb_image.h>

#include <iostream>
#include <vector>
#include "shader.h"

struct Vertex {
    glm::vec3 position;
    glm::vec3 normal;
    glm::vec2 texCoord;
};

std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
GLuint textureID;

float yaw = 0.0f, pitch = 0.0f, roll = 0.0f;
float zoom = 3.0f;
glm::vec2 lastMouse;
bool leftPressed = false, middlePressed = false, rightPressed = false;
glm::vec3 cameraOffset(0.0f);

void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
    if (button == GLFW_MOUSE_BUTTON_LEFT) leftPressed = (action == GLFW_PRESS);
    if (button == GLFW_MOUSE_BUTTON_MIDDLE) middlePressed = (action == GLFW_PRESS);
    if (button == GLFW_MOUSE_BUTTON_RIGHT) rightPressed = (action == GLFW_PRESS);
}

void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {
    zoom -= yoffset * 0.1f;
    if (zoom < 0.1f) zoom = 0.1f;
}

void cursor_position_callback(GLFWwindow* window, double xpos, double ypos) {
    glm::vec2 current(xpos, ypos);
    glm::vec2 delta = current - lastMouse;
    lastMouse = current;

    if (leftPressed) {
        yaw += delta.x * 0.3f;
        pitch += delta.y * 0.3f;
    }
    if (middlePressed) {
        cameraOffset.x -= delta.x * 0.005f;
        cameraOffset.y += delta.y * 0.005f;
    }
    if (rightPressed) {
        roll += delta.x * 0.2f;
    }
}

bool loadFBX(const std::string& path) {
    Assimp::Importer importer;
    const aiScene* scene = importer.ReadFile(path,
        aiProcess_Triangulate |
        aiProcess_GenSmoothNormals |
        aiProcess_CalcTangentSpace |
        aiProcess_JoinIdenticalVertices);

    if (!scene || !scene->HasMeshes()) return false;

    const aiMesh* mesh = scene->mMeshes[0];
    vertices.reserve(mesh->mNumVertices);
    for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
        Vertex v;
        v.position = glm::vec3(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z);
        v.normal = glm::vec3(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z);
        if (mesh->HasTextureCoords(0)) {
            v.texCoord = glm::vec2(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y);
        } else {
            v.texCoord = glm::vec2(0.0f);
        }
        vertices.push_back(v);
    }

    for (unsigned int i = 0; i < mesh->mNumFaces; ++i) {
        aiFace& face = mesh->mFaces[i];
        for (unsigned int j = 0; j < face.mNumIndices; ++j) {
            indices.push_back(face.mIndices[j]);
        }
    }

    return true;
}

GLuint loadTexture(const char* path) {
    int w, h, ch;
    stbi_set_flip_vertically_on_load(true);
    unsigned char* data = stbi_load(path, &w, &h, &ch, 0);
    if (!data) {
        std::cerr << "Failed to load texture\n";
        return 0;
    }

    GLuint tex;
    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);
    GLenum format = ch == 3 ? GL_RGB : GL_RGBA;
    glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, data);
    glGenerateMipmap(GL_TEXTURE_2D);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    stbi_image_free(data);
    return tex;
}

int main() {
    // GLFW 初期化
    if (!glfwInit()) return -1;

    // OpenGLバージョンの指定
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    // ウィンドウ作成
    GLFWwindow* window = glfwCreateWindow(800, 600, "FBX Viewer", NULL, NULL);
    if (!window) {
        std::cerr << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }

    // コンテキストを現在にする
    glfwMakeContextCurrent(window);

    // GLAD の初期化(ここが重要)
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
        std::cerr << "Failed to initialize GLAD" << std::endl;
        return -1;
    }

    // 続き
    glfwSetCursorPosCallback(window, cursor_position_callback);
    glfwSetMouseButtonCallback(window, mouse_button_callback);
    glfwSetScrollCallback(window, scroll_callback);


    glfwSetCursorPosCallback(window, cursor_position_callback);
    glfwSetMouseButtonCallback(window, mouse_button_callback);
    glfwSetScrollCallback(window, scroll_callback);

    Shader shader("../shader.vert", "../shader.frag");

    if (!loadFBX("../model.fbx")) {
        std::cerr << "Failed to load model\n";
        return -1;
    }
    textureID = loadTexture("../texture.png");

    GLuint VAO, VBO, EBO;
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);

    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);

    glGenBuffers(1, &EBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, normal));
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, texCoord));
    glEnableVertexAttribArray(2);

    shader.use();
    shader.setInt("u_texture", 0);

    glEnable(GL_DEPTH_TEST);

    while (!glfwWindowShouldClose(window)) {
        glfwPollEvents();
        glClearColor(0.2f, 0.2f, 0.25f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glm::mat4 view(1.0f);
        view = glm::translate(view, glm::vec3(0, 0, -zoom));
        view = glm::rotate(view, glm::radians(pitch), glm::vec3(1, 0, 0));
        view = glm::rotate(view, glm::radians(yaw), glm::vec3(0, 1, 0));
        view = glm::rotate(view, glm::radians(roll), glm::vec3(0, 0, 1));
        view = glm::translate(view, cameraOffset);

        glm::mat4 proj = glm::perspective(glm::radians(45.0f), 800.f / 600.f, 0.1f, 100.0f);
        glm::mat4 model(1.0f);

        shader.setMat4("u_model", model);
        shader.setMat4("u_view", view);
        shader.setMat4("u_proj", proj);

        glBindTexture(GL_TEXTURE_2D, textureID);
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);

        glfwSwapBuffers(window);
    }

    glfwTerminate();
    return 0;
}

src/shader.h

#ifndef SHADER_H
#define SHADER_H

#include <glad/glad.h>
#include <glm/glm.hpp>
#include <string>

class Shader {
public:
    Shader(const char* vertexPath, const char* fragmentPath);
    void use() const;
    GLuint getID() const;

    // Uniform setters
    void setInt(const std::string &name, int value) const;
    void setMat4(const std::string &name, const glm::mat4 &mat) const;

private:
    GLuint ID;
    std::string loadShaderSource(const char* path);
    GLuint compileShader(const char* source, GLenum type);
};

#endif

src/shader.cpp


#include "shader.h"
#include <fstream>
#include <sstream>
#include <iostream>
#include <glm/gtc/type_ptr.hpp>

Shader::Shader(const char* vertexPath, const char* fragmentPath) {
    std::string vertexCode = loadShaderSource(vertexPath);
    std::string fragmentCode = loadShaderSource(fragmentPath);

    GLuint vertex = compileShader(vertexCode.c_str(), GL_VERTEX_SHADER);
    GLuint fragment = compileShader(fragmentCode.c_str(), GL_FRAGMENT_SHADER);

    ID = glCreateProgram();
    glAttachShader(ID, vertex);
    glAttachShader(ID, fragment);
    glLinkProgram(ID);

    int success;
    glGetProgramiv(ID, GL_LINK_STATUS, &success);
    if (!success) {
        char infoLog[512];
        glGetProgramInfoLog(ID, 512, NULL, infoLog);
        std::cerr << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
    }

    glDeleteShader(vertex);
    glDeleteShader(fragment);
}

std::string Shader::loadShaderSource(const char* path) {
    std::ifstream file(path);
    std::stringstream buffer;
    buffer << file.rdbuf();
    return buffer.str();
}

GLuint Shader::compileShader(const char* source, GLenum type) {
    GLuint shader = glCreateShader(type);
    glShaderSource(shader, 1, &source, NULL);
    glCompileShader(shader);

    int success;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
    if (!success) {
        char infoLog[512];
        glGetShaderInfoLog(shader, 512, NULL, infoLog);
        std::cerr << "ERROR::SHADER::COMPILATION_FAILED\n" << infoLog << std::endl;
    }

    return shader;
}

void Shader::use() const {
    glUseProgram(ID);
}

GLuint Shader::getID() const {
    return ID;
}

void Shader::setInt(const std::string &name, int value) const {
    glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
}

void Shader::setMat4(const std::string &name, const glm::mat4 &mat) const {
    glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, glm::value_ptr(mat));
}

src/stb_image.cpp

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

src/glad.c

https://glad.dav1d.de/    でとってくる
    Language/Generator: C/C++
    Specification: gl
    APIs: gl=3.3
    Profile: core
  Extensions:Add All

include/stb_image.h https://github.com/nothings/stb/blob/master/stb_image.h

glad/glad.h

https://glad.dav1d.de/    でとってくる
    Language/Generator: C/C++
    Specification: gl
    APIs: gl=3.3
    Profile: core
  Extensions:Add All

KHR/khrplatform.h

https://glad.dav1d.de/    でとってくる
    Language/Generator: C/C++
    Specification: gl
    APIs: gl=3.3
    Profile: core
  Extensions:Add All

external/glad/src/glad.c

https://glad.dav1d.de/    でとってくる
    Language/Generator: C/C++
    Specification: gl
    APIs: gl=3.3
    Profile: core
  Extensions:Add All

external/glad/CMakeLists.txt

からっぽ

external/stb_image/stb_image.cpp

#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>

cmd


furcr@furcraea_built MINGW64 ~
$ cd c:

furcr@furcraea_built MINGW64 /c
$ cd glsl_sample

furcr@furcraea_built MINGW64 /c/glsl_sample
$ cd fbx_viewer_3_uv_texture_dorry

furcr@furcraea_built MINGW64 /c/glsl_sample/fbx_viewer_3_uv_texture_dorry
$ cd build

furcr@furcraea_built MINGW64 /c/glsl_sample/fbx_viewer_3_uv_texture_dorry/build
$ pacman -S mingw-w64-x86_64-glfw mingw-w64-x86_64-glew mingw-w64-x86_64-assimp mingw-w64-x86_64-glm
warning: mingw-w64-x86_64-glfw-3.4-1 is up to date -- reinstalling
warning: mingw-w64-x86_64-glew-2.2.0-3 is up to date -- reinstalling
warning: mingw-w64-x86_64-assimp-6.0.2-1 is up to date -- reinstalling
warning: mingw-w64-x86_64-glm-1.0.1-1 is up to date -- reinstalling
resolving dependencies...
looking for conflicting packages...

Packages (4) mingw-w64-x86_64-assimp-6.0.2-1  mingw-w64-x86_64-glew-2.2.0-3
             mingw-w64-x86_64-glfw-3.4-1  mingw-w64-x86_64-glm-1.0.1-1

Total Installed Size:  38.25 MiB
Net Upgrade Size:       0.00 MiB

:: Proceed with installation? [Y/n]
(4/4) checking keys in keyring                               [###############################] 100%
(4/4) checking package integrity                             [###############################] 100%
(4/4) loading package files                                  [###############################] 100%
(4/4) checking for file conflicts                            [###############################] 100%
(4/4) checking available disk space                          [###############################] 100%
:: Processing package changes...
(1/4) reinstalling mingw-w64-x86_64-glfw                     [###############################] 100%
(2/4) reinstalling mingw-w64-x86_64-glew                     [###############################] 100%
(3/4) reinstalling mingw-w64-x86_64-assimp                   [###############################] 100%
(4/4) reinstalling mingw-w64-x86_64-glm                      [###############################] 100%

furcr@furcraea_built MINGW64 /c/glsl_sample/fbx_viewer_3_uv_texture_dorry/build
$ pacman -S mingw-w64-x86_64-glad
error: target not found: mingw-w64-x86_64-glad

furcr@furcraea_built MINGW64 /c/glsl_sample/fbx_viewer_3_uv_texture_dorry/build
$ cmake -G "MSYS Makefiles" ..
-- The C compiler identification is GNU 15.1.0
-- The CXX compiler identification is GNU 15.1.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/msys64/mingw64/bin/cc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/msys64/mingw64/bin/c++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (1.2s)
-- Generating done (0.0s)
-- Build files have been written to: C:/glsl_sample/fbx_viewer_3_uv_texture_dorry/build

furcr@furcraea_built MINGW64 /c/glsl_sample/fbx_viewer_3_uv_texture_dorry/build
$ mingw32-make
[ 20%] Building CXX object CMakeFiles/fbx_viewer.dir/src/main.cpp.obj
[ 40%] Building CXX object CMakeFiles/fbx_viewer.dir/src/shader.cpp.obj
[ 60%] Building C object CMakeFiles/fbx_viewer.dir/src/glad.c.obj
[ 80%] Building CXX object CMakeFiles/fbx_viewer.dir/src/stb_image.cpp.obj
[100%] Linking CXX executable fbx_viewer.exe
[100%] Built target fbx_viewer

furcr@furcraea_built MINGW64 /c/glsl_sample/fbx_viewer_3_uv_texture_dorry/build
$ ./fbx_viewer

MSYS2のMINGW64 → pacman やOpenGL関連ライブラリがインストール可能 な環境でGLSLを描画できた。 FBX Viewerを作る Vol.2 テクスチャ

memo.txt

fbx_viewer/
├── main.cpp
├── shader.h
├── vertex.glsl
├── fragment.glsl
├── model.fbx
├── texture.png
├── stb_image.h
├── stb_image.cpp
└── CMakeLists.txt


cd fbx_viewer
mkdir build && cd build
cmake -G "MinGW Makefiles" ..
mingw32-make
./fbx_viewer

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(fbx_viewer)

set(CMAKE_CXX_STANDARD 17)

include_directories(
    ${PROJECT_SOURCE_DIR}
    ${PROJECT_SOURCE_DIR}/../
)

add_executable(fbx_viewer main.cpp stb_image.cpp)

# GLEW, GLFW, ASSIMP
find_package(OpenGL REQUIRED)
find_package(glfw3 REQUIRED)
find_package(assimp REQUIRED)

target_link_libraries(fbx_viewer
    OpenGL::GL
    glfw
    assimp
    glew32
)

main.cpp

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#include <stb_image.h>
#include <iostream>
#include <vector>
#include "shader.h"

struct Vertex {
    float position[3];
    float normal[3];
    float texcoord[2];
};

std::vector<Vertex> vertices;
std::vector<unsigned int> indices;

void processMesh(aiMesh* mesh) {
    for (unsigned int i = 0; i < mesh->mNumVertices; i++) {
        Vertex v;
        memcpy(v.position, &mesh->mVertices[i], sizeof(float) * 3);
        memcpy(v.normal, &mesh->mNormals[i], sizeof(float) * 3);
        if (mesh->HasTextureCoords(0))
            memcpy(v.texcoord, &mesh->mTextureCoords[0][i], sizeof(float) * 2);
        else
            v.texcoord[0] = v.texcoord[1] = 0.0f;
        vertices.push_back(v);
    }

    for (unsigned int i = 0; i < mesh->mNumFaces; i++) {
        aiFace face = mesh->mFaces[i];
        for (unsigned int j = 0; j < face.mNumIndices; j++) {
            indices.push_back(face.mIndices[j]);
        }
    }
}

GLuint loadTexture(const char* path) {
    int width, height, nrChannels;
    stbi_set_flip_vertically_on_load(true);
    unsigned char* data = stbi_load(path, &width, &height, &nrChannels, 0);
    if (!data) {
        std::cerr << "Failed to load texture\n";
        return 0;
    }

    GLuint tex;
    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);

    GLenum format = (nrChannels == 4) ? GL_RGBA : GL_RGB;
    glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);

    glGenerateMipmap(GL_TEXTURE_2D);
    stbi_image_free(data);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    return tex;
}

int main() {
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "FBX Viewer", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewInit();

    Shader shader("../vertex.glsl", "../fragment.glsl");

    Assimp::Importer importer;
    const aiScene* scene = importer.ReadFile("../model.fbx",
        aiProcess_Triangulate | aiProcess_GenSmoothNormals |
        aiProcess_JoinIdenticalVertices | aiProcess_FlipUVs);

    if (!scene || !scene->HasMeshes()) {
        std::cerr << "Failed to load model: " << importer.GetErrorString() << std::endl;
        return -1;
    }

    processMesh(scene->mMeshes[0]);

    GLuint VAO, VBO, EBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);

    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0); // position
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof(float) * 3)); // normal
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof(float) * 6)); // texcoord
    glEnableVertexAttribArray(2);

    GLuint texture = loadTexture("../texture.png");
    shader.use();
    shader.setInt("u_texture", 0);

    glEnable(GL_DEPTH_TEST);

    while (!glfwWindowShouldClose(window)) {
        glClearColor(0.2f, 0.2f, 0.25f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        shader.use();
        glBindTexture(GL_TEXTURE_2D, texture);
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}

shader.h

#ifndef SHADER_H
#define SHADER_H

#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <GL/glew.h>

class Shader {
public:
    GLuint ID;
    Shader(const char* vertexPath, const char* fragmentPath) {
        std::string vCode, fCode;
        std::ifstream vFile(vertexPath), fFile(fragmentPath);
        std::stringstream vStream, fStream;
        vStream << vFile.rdbuf();
        fStream << fFile.rdbuf();
        vCode = vStream.str();
        fCode = fStream.str();

        const char* vShaderCode = vCode.c_str();
        const char* fShaderCode = fCode.c_str();

        GLuint vertex = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertex, 1, &vShaderCode, nullptr);
        glCompileShader(vertex);

        GLuint fragment = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fragment, 1, &fShaderCode, nullptr);
        glCompileShader(fragment);

        ID = glCreateProgram();
        glAttachShader(ID, vertex);
        glAttachShader(ID, fragment);
        glLinkProgram(ID);

        glDeleteShader(vertex);
        glDeleteShader(fragment);
    }

    void use() { glUseProgram(ID); }
    void setInt(const std::string& name, int value) {
        glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
    }
};

#endif

vertex.glsl

#version 330 core
layout(location = 0) in vec3 a_position;
layout(location = 1) in vec3 a_normal;
layout(location = 2) in vec2 a_texcoord;

out vec2 v_texcoord;

void main() {
    gl_Position = vec4(a_position, 1.0);
    v_texcoord = a_texcoord;
}

fragment.glsl

#version 330 core
in vec2 v_texcoord;
out vec4 fragColor;

uniform sampler2D u_texture;

void main() {
    fragColor = texture(u_texture, v_texcoord);
}

stb_image.cpp  

#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>

stb_image.h  https://github.com/nothings/stb/blob/master/stb_image.h

cmd


furcr@furcraea_built MINGW64 ~
$ cd c:

furcr@furcraea_built MINGW64 /c
$ cd glsl_sample

furcr@furcraea_built MINGW64 /c/glsl_sample
$ cd fbx_viewer

furcr@furcraea_built MINGW64 /c/glsl_sample/fbx_viewer
$ cd ..

furcr@furcraea_built MINGW64 /c/glsl_sample
$ cd fbx_viewer_uv_texture

furcr@furcraea_built MINGW64 /c/glsl_sample/fbx_viewer_uv_texture
$ cd build

furcr@furcraea_built MINGW64 /c/glsl_sample/fbx_viewer_uv_texture/build
$ cmake -G "MSYS Makefiles" ..
-- The C compiler identification is GNU 15.1.0
-- The CXX compiler identification is GNU 15.1.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/msys64/mingw64/bin/cc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/msys64/mingw64/bin/c++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found OpenGL: opengl32
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE
-- Configuring done (1.8s)
-- Generating done (0.0s)
-- Build files have been written to: C:/glsl_sample/fbx_viewer_uv_texture/build

furcr@furcraea_built MINGW64 /c/glsl_sample/fbx_viewer_uv_texture/build
$ mingw32-make
[ 33%] Building CXX object CMakeFiles/fbx_viewer.dir/main.cpp.obj
[ 66%] Building CXX object CMakeFiles/fbx_viewer.dir/stb_image.cpp.obj
[100%] Linking CXX executable fbx_viewer.exe
[100%] Built target fbx_viewer

furcr@furcraea_built MINGW64 /c/glsl_sample/fbx_viewer_uv_texture/build
$ ./fbx_viewer

texture.png

カメラがめりこんでる

MSYS2のMINGW64 → pacman やOpenGL関連ライブラリがインストール可能 な環境でGLSLを描画できた。 FBX Viewerを作る Vol.1

memo.txt

fbx_viewer/
├── main.cpp
├── shader.h
├── vertex.glsl
├── fragment.glsl
├── model.fbx
└── CMakeLists.txt

pacman -S mingw-w64-x86_64-assimp


cd fbx_viewer
mkdir build && cd build
cmake -G "MinGW Makefiles" ..
mingw32-make
./fbx_viewer

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(fbx_viewer)

set(CMAKE_CXX_STANDARD 17)

find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED)
find_package(GLFW3 REQUIRED)
find_package(assimp REQUIRED)

include_directories(
    ${OPENGL_INCLUDE_DIRS}
    ${GLEW_INCLUDE_DIRS}
    ${GLFW3_INCLUDE_DIRS}
    ${ASSIMP_INCLUDE_DIRS}
)

add_executable(fbx_viewer main.cpp shader.h)

target_link_libraries(fbx_viewer
    ${OPENGL_LIBRARIES}
    GLEW::GLEW
    glfw
    assimp
)

main.cpp

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include <iostream>
#include <vector>
#include "shader.h"

struct Vertex {
    float position[3];
    float normal[3];
};

std::vector<Vertex> vertices;
std::vector<unsigned int> indices;

void processMesh(aiMesh* mesh) {
    for (unsigned int i = 0; i < mesh->mNumVertices; i++) {
        Vertex v;
        memcpy(v.position, &mesh->mVertices[i], sizeof(float) * 3);
        memcpy(v.normal, &mesh->mNormals[i], sizeof(float) * 3);
        vertices.push_back(v);
    }
    for (unsigned int i = 0; i < mesh->mNumFaces; i++) {
        aiFace face = mesh->mFaces[i];
        for (unsigned int j = 0; j < face.mNumIndices; j++) {
            indices.push_back(face.mIndices[j]);
        }
    }
}

int main() {
    if (!glfwInit()) return -1;
    GLFWwindow* window = glfwCreateWindow(800, 600, "FBX Viewer", nullptr, nullptr);
    if (!window) return -1;
    glfwMakeContextCurrent(window);
    glewInit();

    Shader shader("../vertex.glsl", "../fragment.glsl");

    Assimp::Importer importer;
    const aiScene* scene = importer.ReadFile("../model.fbx",
        aiProcess_Triangulate |
        aiProcess_GenSmoothNormals |
        aiProcess_JoinIdenticalVertices |
        aiProcess_FlipUVs);

    if (!scene || !scene->HasMeshes()) {
        std::cerr << "Failed to load model: " << importer.GetErrorString() << std::endl;
        return -1;
    }

    processMesh(scene->mMeshes[0]);

    GLuint VAO, VBO, EBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);

    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof(float) * 3));
    glEnableVertexAttribArray(1);

    glEnable(GL_DEPTH_TEST);

    while (!glfwWindowShouldClose(window)) {
        glClearColor(0.1f, 0.1f, 0.2f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        shader.use();

        glm::mat4 model = glm::mat4(1.0f);
        glm::mat4 view = glm::lookAt(glm::vec3(0.0f, 1.0f, 3.0f),
                                     glm::vec3(0.0f, 0.0f, 0.0f),
                                     glm::vec3(0.0f, 1.0f, 0.0f));
        glm::mat4 projection = glm::perspective(glm::radians(45.0f),
                                                800.0f / 600.0f, 0.1f, 100.0f);

        glUniformMatrix4fv(glGetUniformLocation(shader.ID, "model"), 1, GL_FALSE, glm::value_ptr(model));
        glUniformMatrix4fv(glGetUniformLocation(shader.ID, "view"), 1, GL_FALSE, glm::value_ptr(view));
        glUniformMatrix4fv(glGetUniformLocation(shader.ID, "projection"), 1, GL_FALSE, glm::value_ptr(projection));

        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}

shader.h

#ifndef SHADER_H
#define SHADER_H

#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <GL/glew.h>

class Shader {
public:
    GLuint ID;
    Shader(const char* vertexPath, const char* fragmentPath) {
        std::string vCode, fCode;
        std::ifstream vFile(vertexPath), fFile(fragmentPath);
        std::stringstream vStream, fStream;
        vStream << vFile.rdbuf();
        fStream << fFile.rdbuf();
        vCode = vStream.str();
        fCode = fStream.str();
        const char* vShaderCode = vCode.c_str();
        const char* fShaderCode = fCode.c_str();

        GLuint vertex = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertex, 1, &vShaderCode, NULL);
        glCompileShader(vertex);

        GLuint fragment = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fragment, 1, &fShaderCode, NULL);
        glCompileShader(fragment);

        ID = glCreateProgram();
        glAttachShader(ID, vertex);
        glAttachShader(ID, fragment);
        glLinkProgram(ID);

        glDeleteShader(vertex);
        glDeleteShader(fragment);
    }
    void use() { glUseProgram(ID); }
};

#endif

vertex.glsl

#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aNormal;

out vec3 FragPos;
out vec3 Normal;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main() {
    FragPos = vec3(model * vec4(aPos, 1.0));
    Normal = mat3(transpose(inverse(model))) * aNormal;
    gl_Position = projection * view * vec4(FragPos, 1.0);
}

fragment.glsl

#version 330 core
in vec3 FragPos;
in vec3 Normal;

out vec4 FragColor;

void main() {
    vec3 lightDir = normalize(vec3(0.5, 1.0, 0.3));
    float diff = max(dot(normalize(Normal), lightDir), 0.0);
    vec3 color = vec3(0.2, 0.3, 0.1) * diff;
    FragColor = vec4(color, 1.0);
}

cmd

furcr@furcraea_built MINGW64 ~
$ cd c:

furcr@furcraea_built MINGW64 /c
$ cd glsl_sample

furcr@furcraea_built MINGW64 /c/glsl_sample
$ cd fbx_viewer

furcr@furcraea_built MINGW64 /c/glsl_sample/fbx_viewer
$ cd build

furcr@furcraea_built MINGW64 /c/glsl_sample/fbx_viewer/build
$ cmake -G "MSYS Makefiles" ..
-- The C compiler identification is GNU 15.1.0
-- The CXX compiler identification is GNU 15.1.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/msys64/mingw64/bin/cc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/msys64/mingw64/bin/c++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found OpenGL: opengl32
-- Found GLEW: C:/msys64/mingw64/lib/cmake/glew/glew-config.cmake
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE
CMake Error at CMakeLists.txt:9 (find_package):
  By not providing "Findassimp.cmake" in CMAKE_MODULE_PATH this project has
  asked CMake to find a package configuration file provided by "assimp", but
  CMake did not find one.

  Could not find a package configuration file provided by "assimp" with any
  of the following names:

    assimpConfig.cmake
    assimp-config.cmake

  Add the installation prefix of "assimp" to CMAKE_PREFIX_PATH or set
  "assimp_DIR" to a directory containing one of the above files.  If "assimp"
  provides a separate development package or SDK, be sure it has been
  installed.


-- Configuring incomplete, errors occurred!

furcr@furcraea_built MINGW64 /c/glsl_sample/fbx_viewer/build
$ pacman -S mingw-w64-x86_64-assimp
resolving dependencies...
looking for conflicting packages...

Packages (2) mingw-w64-x86_64-minizip-1.3.1-1  mingw-w64-x86_64-assimp-6.0.2-1

Total Download Size:    3.11 MiB
Total Installed Size:  12.02 MiB

:: Proceed with installation? [Y/n]
:: Retrieving packages...
 mingw-w64-x86_64-minizip-1...    83.1 KiB  32.7 KiB/s 00:03 [###############################] 100%
 mingw-w64-x86_64-assimp-6....     3.0 MiB   960 KiB/s 00:03 [###############################] 100%
 Total (2/2)                       3.1 MiB   882 KiB/s 00:04 [###############################] 100%
(2/2) checking keys in keyring                               [###############################] 100%
(2/2) checking package integrity                             [###############################] 100%
(2/2) loading package files                                  [###############################] 100%
(2/2) checking for file conflicts                            [###############################] 100%
(2/2) checking available disk space                          [###############################] 100%
:: Processing package changes...
(1/2) installing mingw-w64-x86_64-minizip                    [###############################] 100%
(2/2) installing mingw-w64-x86_64-assimp                     [###############################] 100%

furcr@furcraea_built MINGW64 /c/glsl_sample/fbx_viewer/build
$ cmake -G "MSYS Makefiles" ..
-- The C compiler identification is GNU 15.1.0
-- The CXX compiler identification is GNU 15.1.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/msys64/mingw64/bin/cc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/msys64/mingw64/bin/c++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found OpenGL: opengl32
-- Found GLEW: C:/msys64/mingw64/lib/cmake/glew/glew-config.cmake
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE
-- Configuring done (1.8s)
-- Generating done (0.0s)
-- Build files have been written to: C:/glsl_sample/fbx_viewer/build

furcr@furcraea_built MINGW64 /c/glsl_sample/fbx_viewer/build
$ mingw32-make
[ 50%] Building CXX object CMakeFiles/fbx_viewer.dir/main.cpp.obj
[100%] Linking CXX executable fbx_viewer.exe
[100%] Built target fbx_viewer

furcr@furcraea_built MINGW64 /c/glsl_sample/fbx_viewer/build
$ ./fbx_viewer

MSYS2のMINGW64 → pacman やOpenGL関連ライブラリがインストール可能 な環境でGLSLを描画できた。その6

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(OpenGLShapes)

set(CMAKE_CXX_STANDARD 17)

# GLFW
find_package(glfw3 REQUIRED)

# OpenGL
find_package(OpenGL REQUIRED)

# GLEW(手動で入れた場合)
find_path(GLEW_INCLUDE_DIR GL/glew.h)
find_library(GLEW_LIBRARY NAMES GLEW glew32 glew glew_s)

# stb_image(ヘッダオンリーなので include だけでOK)
include_directories(${CMAKE_SOURCE_DIR})
include_directories(${CMAKE_SOURCE_DIR}/external)

# ソース
add_executable(OpenGLShapes
    main.cpp
    shapes.cpp
    shader.cpp
)

target_include_directories(OpenGLShapes PRIVATE
    ${GLEW_INCLUDE_DIR}
    ${OPENGL_INCLUDE_DIR}
    ${CMAKE_SOURCE_DIR}
)

target_link_libraries(OpenGLShapes
    glfw
    ${GLEW_LIBRARY}
    ${OPENGL_gl_LIBRARY}
)

# Windows用 GLEW は glew32s のこともあるので注意

main.cpp

#include <iostream> // Required for std::cout
#include <string>   // Required for std::string
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <vector>
#include "shader.h"
#include "shapes.hpp"
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

GLuint createVAO(const std::vector<float>& vertices, const std::vector<unsigned int>& indices) {
    GLuint VAO, VBO, EBO;
    glGenVertexArrays(1,&VAO);
    glGenBuffers(1,&VBO);
    glGenBuffers(1,&EBO);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER,VBO);
    glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(float), vertices.data(), GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(unsigned int), indices.data(), GL_STATIC_DRAW);

    // position
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,8*sizeof(float),(void*)0);
    glEnableVertexAttribArray(0);
    // normal
    glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,8*sizeof(float),(void*)(3*sizeof(float)));
    glEnableVertexAttribArray(1);
    // texcoord
    glVertexAttribPointer(2,2,GL_FLOAT,GL_FALSE,8*sizeof(float),(void*)(6*sizeof(float)));
    glEnableVertexAttribArray(2);

    glBindVertexArray(0);
    return VAO;
}
void print(const std::string& message) {
    std::cout << message << std::endl;
}
int main() {
    if (!glfwInit()) {
        std::cerr << "GLFW初期化失敗\n";
        return -1;
    }

    GLFWwindow* window = glfwCreateWindow(800,600,"OpenGL 3D Shapes with Textures",NULL,NULL);
    if (!window) {
        std::cerr << "ウィンドウ作成失敗\n";
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    glewExperimental = true;
    if(glewInit() != GLEW_OK) {
        std::cerr << "GLEW初期化失敗\n";
        return -1;
    }
    glEnable(GL_DEPTH_TEST);

    Shader shader("../shader.vert", "../shader.frag");

    // シェイプ作成
    std::vector<float> boxVertices, sphereVertices, torusVertices;
    std::vector<unsigned int> boxIndices, sphereIndices, torusIndices;

    createBox(boxVertices, boxIndices);
    createSphere(sphereVertices, sphereIndices);
    createTorus(torusVertices, torusIndices);

    GLuint vaoBox = createVAO(boxVertices, boxIndices);
    GLuint vaoSphere = createVAO(sphereVertices, sphereIndices);
    GLuint vaoTorus = createVAO(torusVertices, torusIndices);

    // テクスチャ読み込み関数
    auto loadTexture = [](const char* path) -> GLuint {
        int width, height, nrChannels;
        stbi_set_flip_vertically_on_load(true); // テクスチャ上下反転して読み込み(OpenGL標準に合わせる)
        unsigned char* data = stbi_load(path, &width, &height, &nrChannels, 0);
        if (!data) {
            std::cerr << "Failed to load texture: " << path << std::endl;
            return 0;
        }
        GLuint textureID;
        glGenTextures(1, &textureID);
        glBindTexture(GL_TEXTURE_2D, textureID);

        GLenum format = GL_RGB;
        if (nrChannels == 1)
            format = GL_RED;
        else if (nrChannels == 3)
            format = GL_RGB;
        else if (nrChannels == 4)
            format = GL_RGBA;

        glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
        glGenerateMipmap(GL_TEXTURE_2D);

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        stbi_image_free(data);
        return textureID;
    };

    GLuint texBox = loadTexture("../texture_1.png");
    GLuint texSphere = loadTexture("../texture_2.png");
    GLuint texTorus = loadTexture("../texture_3.png");

    if (texBox == 0 || texSphere == 0 || texTorus == 0) {
        std::cerr << "テクスチャの読み込みに失敗しました。\n";
        return -1;
    }

    shader.use();
    shader.setInt("texture1", 0);
    //----------------------mouse----------------------------------
    double mouseX, mouseY;
    int winW, winH;
    //----------------------mouse----------------------------------
    // 行列初期化
    glm::mat4 projection = glm::perspective(glm::radians(45.0f), 800.f/600.f, 0.1f, 100.f);
    glm::mat4 view = glm::lookAt(glm::vec3(3,3,3), glm::vec3(0,0,0), glm::vec3(0,1,0));

    while(!glfwWindowShouldClose(window)) {

        //----------------------mouse----------------------------------
        glfwGetCursorPos(window, &mouseX, &mouseY);
        glfwGetWindowSize(window, &winW, &winH);
        //mouseY = winH - mouseY;  // 上下反転
        mouseX = mouseX/winW;  //
        mouseY = mouseY/winH;  //
        
        GLint mouseLoc = glGetUniformLocation(shader.ID, "u_mouse");
        glUniform2f(mouseLoc, (float)mouseX, (float)mouseY);
        //print(std::string("mouseX=") + std::to_string(mouseX));
        //----------------------mouse----------------------------------


        // 行列初期化
        glm::mat4 projection = glm::perspective(glm::radians(45.0f), 800.f/600.f, 0.1f, 100.f);
        glm::mat4 view = glm::lookAt(glm::vec3(3+mouseX*5,3+mouseY*5,3), glm::vec3(0,0,0), glm::vec3(0,1,0));


        glClearColor(0.1f,0.1f,0.1f,1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        shader.use();
        shader.setMat4("projection", glm::value_ptr(projection));
        shader.setMat4("view", glm::value_ptr(view));

        // ボックス描画
        glm::mat4 model = glm::mat4(1.0f);
        model = glm::translate(model, glm::vec3(-2.0f,0.0f,0.0f));
        shader.setMat4("model", glm::value_ptr(model));
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texBox);
        glBindVertexArray(vaoBox);
        glDrawElements(GL_TRIANGLES, (GLsizei)boxIndices.size(), GL_UNSIGNED_INT, 0);

        // 球描画
        model = glm::mat4(1.0f);
        model = glm::translate(model, glm::vec3(0.0f,0.0f,0.0f));
        shader.setMat4("model", glm::value_ptr(model));
        glBindTexture(GL_TEXTURE_2D, texSphere);
        glBindVertexArray(vaoSphere);
        glDrawElements(GL_TRIANGLES, (GLsizei)sphereIndices.size(), GL_UNSIGNED_INT, 0);

        // トーラス描画
        model = glm::mat4(1.0f);
        model = glm::translate(model, glm::vec3(2.0f,0.0f,0.0f));
        shader.setMat4("model", glm::value_ptr(model));
        glBindTexture(GL_TEXTURE_2D, texTorus);
        glBindVertexArray(vaoTorus);
        glDrawElements(GL_TRIANGLES, (GLsizei)torusIndices.size(), GL_UNSIGNED_INT, 0);

        glfwSwapBuffers(window);
        glfwPollEvents();



    }

    // 解放
    glDeleteVertexArrays(1, &vaoBox);
    glDeleteVertexArrays(1, &vaoSphere);
    glDeleteVertexArrays(1, &vaoTorus);
    glDeleteTextures(1, &texBox);
    glDeleteTextures(1, &texSphere);
    glDeleteTextures(1, &texTorus);

    glfwDestroyWindow(window);
    glfwTerminate();
    return 0;
}

shader.cpp

#include "shader.h"
#include <fstream>
#include <sstream>
#include <iostream>

Shader::Shader(const char* vertexPath, const char* fragmentPath) {
    std::string vertexCode, fragmentCode;
    std::ifstream vShaderFile, fShaderFile;
    vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
    fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
    try {
        vShaderFile.open(vertexPath);
        fShaderFile.open(fragmentPath);
        std::stringstream vShaderStream, fShaderStream;
        vShaderStream << vShaderFile.rdbuf();
        fShaderStream << fShaderFile.rdbuf();
        vShaderFile.close();
        fShaderFile.close();
        vertexCode = vShaderStream.str();
        fragmentCode = fShaderStream.str();
    } catch(std::ifstream::failure& e) {
        std::cerr << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ\n";
    }

    const char* vShaderCode = vertexCode.c_str();
    const char* fShaderCode = fragmentCode.c_str();

    GLuint vertex = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertex, 1, &vShaderCode, NULL);
    glCompileShader(vertex);
    checkCompileErrors(vertex, "VERTEX");

    GLuint fragment = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragment, 1, &fShaderCode, NULL);
    glCompileShader(fragment);
    checkCompileErrors(fragment, "FRAGMENT");

    ID = glCreateProgram();
    glAttachShader(ID, vertex);
    glAttachShader(ID, fragment);
    glLinkProgram(ID);
    checkCompileErrors(ID, "PROGRAM");

    glDeleteShader(vertex);
    glDeleteShader(fragment);
}

void Shader::use() {
    glUseProgram(ID);
}

void Shader::setBool(const std::string &name, bool value) const {
    glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
}

void Shader::setInt(const std::string &name, int value) const {
    glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
}

void Shader::setFloat(const std::string &name, float value) const {
    glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
}

void Shader::setVec2(const std::string &name, float x, float y) const {
    glUniform2f(glGetUniformLocation(ID, name.c_str()), x, y);
}

void Shader::setVec3(const std::string &name, float x, float y, float z) const {
    glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z);
}

void Shader::setMat4(const std::string &name, const float* mat) const {
    glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, mat);
}

void Shader::checkCompileErrors(GLuint shader, std::string type) {
    GLint success;
    GLchar infoLog[1024];
    if (type != "PROGRAM") {
        glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
        if (!success) {
            glGetShaderInfoLog(shader, 1024, NULL, infoLog);
            std::cerr << "| ERROR::SHADER-COMPILATION_ERROR of type: " << type << "\n"
                      << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
        }
    } else {
        glGetProgramiv(shader, GL_LINK_STATUS, &success);
        if (!success) {
            glGetProgramInfoLog(shader, 1024, NULL, infoLog);
            std::cerr << "| ERROR::PROGRAM-LINKING_ERROR of type: " << type << "\n"
                      << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
        }
    }
}

shader.frag

#version 330 core

in vec2 TexCoord;
in vec3 Normal;
in vec3 FragPos;

out vec4 FragColor;
uniform vec2 u_mouse;      // 
uniform sampler2D texture1;
uniform vec3 lightPos;
uniform vec3 viewPos;

void main()
{
    // Lighting
    vec3 ambient = 0.2 * texture(texture1, TexCoord).rgb;

    vec3 norm = normalize(Normal);
    vec3 lightDir = normalize(lightPos - FragPos);
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = diff * texture(texture1, TexCoord).rgb;

    vec3 result = ambient + diffuse;
    FragColor = vec4(result, 1.0);
}

shader.h

#ifndef SHADER_H
#define SHADER_H

#include <string>
#include <GL/glew.h>

class Shader {
public:
    GLuint ID;
    Shader(const char* vertexPath, const char* fragmentPath);
    void use();
    void setBool(const std::string &name, bool value) const;
    void setInt(const std::string &name, int value) const;
    void setFloat(const std::string &name, float value) const;
    void setVec2(const std::string &name, float x, float y) const;
    void setVec3(const std::string &name, float x, float y, float z) const;
    void setMat4(const std::string &name, const float* mat) const;

private:
    void checkCompileErrors(GLuint shader, std::string type);
};

#endif

shader.vert

#version 330 core

layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
layout (location = 2) in vec3 aNormal;

out vec2 TexCoord;
out vec3 Normal;
out vec3 FragPos;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    FragPos = vec3(model * vec4(aPos, 1.0));
    Normal = mat3(transpose(inverse(model))) * aNormal;
    TexCoord = aTexCoord;
    gl_Position = projection * view * vec4(FragPos, 1.0);
}

shapes.cpp

#include "shapes.hpp"
#include <cmath>

void createBox(std::vector<float>& vertices, std::vector<unsigned int>& indices) {
    vertices = {
        // positions        // texcoords     // normals
        -1, -1, -1,  0, 0,   0,  0, -1,
         1, -1, -1,  1, 0,   0,  0, -1,
         1,  1, -1,  1, 1,   0,  0, -1,
        -1,  1, -1,  0, 1,   0,  0, -1,

        -1, -1,  1,  0, 0,   0,  0,  1,
         1, -1,  1,  1, 0,   0,  0,  1,
         1,  1,  1,  1, 1,   0,  0,  1,
        -1,  1,  1,  0, 1,   0,  0,  1,

        -1, -1, -1,  0, 0,  -1,  0,  0,
        -1,  1, -1,  1, 0,  -1,  0,  0,
        -1,  1,  1,  1, 1,  -1,  0,  0,
        -1, -1,  1,  0, 1,  -1,  0,  0,

         1, -1, -1,  0, 0,   1,  0,  0,
         1,  1, -1,  1, 0,   1,  0,  0,
         1,  1,  1,  1, 1,   1,  0,  0,
         1, -1,  1,  0, 1,   1,  0,  0,

        -1, -1, -1,  0, 0,   0, -1,  0,
        -1, -1,  1,  1, 0,   0, -1,  0,
         1, -1,  1,  1, 1,   0, -1,  0,
         1, -1, -1,  0, 1,   0, -1,  0,

        -1,  1, -1,  0, 0,   0,  1,  0,
        -1,  1,  1,  1, 0,   0,  1,  0,
         1,  1,  1,  1, 1,   0,  1,  0,
         1,  1, -1,  0, 1,   0,  1,  0,
    };

    indices = {
         0,  1,  2,  2,  3,  0,    // front
         4,  5,  6,  6,  7,  4,    // back
         8,  9, 10, 10, 11,  8,    // left
        12, 13, 14, 14, 15, 12,    // right
        16, 17, 18, 18, 19, 16,    // bottom
        20, 21, 22, 22, 23, 20     // top
    };
}

void createSphere(std::vector<float>& vertices, std::vector<unsigned int>& indices, float radius, int sectorCount, int stackCount) {
    vertices.clear();
    indices.clear();

    for (int i = 0; i <= stackCount; ++i) {
        float stackAngle = M_PI / 2 - i * (M_PI / stackCount);
        float xy = radius * cosf(stackAngle);
        float z = radius * sinf(stackAngle);

        for (int j = 0; j <= sectorCount; ++j) {
            float sectorAngle = j * 2 * M_PI / sectorCount;

            float x = xy * cosf(sectorAngle);
            float y = xy * sinf(sectorAngle);

            float u = (float)j / sectorCount;
            float v = (float)i / stackCount;

            float nx = x / radius;
            float ny = y / radius;
            float nz = z / radius;

            vertices.insert(vertices.end(), {x, y, z, u, v, nx, ny, nz});
        }
    }

    for (int i = 0; i < stackCount; ++i) {
        for (int j = 0; j < sectorCount; ++j) {
            unsigned int first  = i * (sectorCount + 1) + j;
            unsigned int second = first + sectorCount + 1;

            indices.insert(indices.end(), {
                first, second, first + 1,
                second, second + 1, first + 1
            });
        }
    }
}

void createTorus(std::vector<float>& vertices, std::vector<unsigned int>& indices, float innerRadius, float outerRadius, int nsides, int rings) {
    vertices.clear();
    indices.clear();

    for (int i = 0; i <= rings; ++i) {
        float phi = 2 * M_PI * i / rings;
        float cosPhi = cosf(phi);
        float sinPhi = sinf(phi);

        for (int j = 0; j <= nsides; ++j) {
            float theta = 2 * M_PI * j / nsides;
            float cosTheta = cosf(theta);
            float sinTheta = sinf(theta);

            float x = (outerRadius + innerRadius * cosTheta) * cosPhi;
            float y = (outerRadius + innerRadius * cosTheta) * sinPhi;
            float z = innerRadius * sinTheta;

            float u = (float)i / rings;
            float v = (float)j / nsides;

            float nx = cosTheta * cosPhi;
            float ny = cosTheta * sinPhi;
            float nz = sinTheta;

            vertices.insert(vertices.end(), {x, y, z, u, v, nx, ny, nz});
        }
    }

    for (int i = 0; i < rings; ++i) {
        for (int j = 0; j < nsides; ++j) {
            unsigned int first = i * (nsides + 1) + j;
            unsigned int second = first + nsides + 1;

            indices.insert(indices.end(), {
                first, second, first + 1,
                second, second + 1, first + 1
            });
        }
    }
}

shapes.hpp

#ifndef SHAPES_HPP
#define SHAPES_HPP

#include <vector>

void createBox(std::vector<float>& vertices, std::vector<unsigned int>& indices);
void createSphere(std::vector<float>& vertices, std::vector<unsigned int>& indices, float radius = 1.0f, int sectorCount = 36, int stackCount = 18);
void createTorus(std::vector<float>& vertices, std::vector<unsigned int>& indices, float ringRadius = 0.7f, float tubeRadius = 0.3f, int ringSegments = 36, int tubeSegments = 18);

#endif

external/stb_image.h https://github.com/nothings/stb/blob/master/stb_image.h

texture_1.png

texture_2.png

texture_3.png

cmd


furcr@furcraea_built MINGW64 ~
$ cd c:

furcr@furcraea_built MINGW64 /c
$ cd glsl_sample

furcr@furcraea_built MINGW64 /c/glsl_sample
$ cd glsl_sample_233_3texture

furcr@furcraea_built MINGW64 /c/glsl_sample/glsl_sample_233_3texture
$ cd build

furcr@furcraea_built MINGW64 /c/glsl_sample/glsl_sample_233_3texture/build
$ cmake -G "MSYS Makefiles" ..
-- The C compiler identification is GNU 15.1.0
-- The CXX compiler identification is GNU 15.1.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/msys64/mingw64/bin/cc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/msys64/mingw64/bin/c++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE
-- Found OpenGL: opengl32
-- Configuring done (1.9s)
-- Generating done (0.0s)
-- Build files have been written to: C:/glsl_sample/glsl_sample_233_3texture/build

furcr@furcraea_built MINGW64 /c/glsl_sample/glsl_sample_233_3texture/build
$ mingw32-make
[ 25%] Building CXX object CMakeFiles/OpenGLShapes.dir/main.cpp.obj
[ 50%] Building CXX object CMakeFiles/OpenGLShapes.dir/shapes.cpp.obj
[ 75%] Building CXX object CMakeFiles/OpenGLShapes.dir/shader.cpp.obj
[100%] Linking CXX executable OpenGLShapes.exe
[100%] Built target OpenGLShapes

furcr@furcraea_built MINGW64 /c/glsl_sample/glsl_sample_233_3texture/build
$ ./OpenGLShapes

MSYS2のMINGW64 → pacman やOpenGL関連ライブラリがインストール可能 な環境でGLSLを描画できた。その5

CMakeLists.txt

cmake_minimum_required(VERSION 3.5)
project(glsl_sample)

set(CMAKE_C_STANDARD 99)

add_executable(glsl_sample main.c)

include_directories("C:/msys64/mingw64/include/stb")

find_package(OpenGL REQUIRED)
include_directories(${OPENGL_INCLUDE_DIRS})

# MSYS2パス用のヒント(MINGW64環境)
include_directories("C:/msys64/mingw64/include")
link_directories("C:/msys64/mingw64/lib")

target_link_libraries(glsl_sample glfw3 glew32 opengl32 gdi32)

main.c

#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>

// ファイル読み込み
char* load_shader_source(const char* filepath) {
    FILE* file = fopen(filepath, "rb");
    if (!file) {
        fprintf(stderr, "Failed to open %s\n", filepath);
        exit(1);
    }
    fseek(file, 0, SEEK_END);
    long len = ftell(file);
    rewind(file);
    char* buffer = (char*)malloc(len + 1);
    fread(buffer, 1, len, file);
    buffer[len] = '\0';
    fclose(file);
    return buffer;
}

GLuint compile_shader(GLenum type, const char* source) {
    GLuint shader = glCreateShader(type);
    glShaderSource(shader, 1, &source, NULL);
    glCompileShader(shader);
    GLint success;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
    if (!success) {
        char infoLog[512];
        glGetShaderInfoLog(shader, 512, NULL, infoLog);
        fprintf(stderr, "Shader compile error: %s\n", infoLog);
        exit(1);
    }
    return shader;
}

int main() {
    if (!glfwInit()) {
        fprintf(stderr, "GLFW init failed\n");
        return -1;
    }

    GLFWwindow* window = glfwCreateWindow(800, 600, "GLSL Sample", NULL, NULL);
    if (!window) {
        glfwTerminate();
        return -1;
    }

    glfwMakeContextCurrent(window);
    glewInit();

    char* vertexSource = load_shader_source("../shader.vert");
    char* fragmentSource = load_shader_source("../shader.frag");

    GLuint vertexShader = compile_shader(GL_VERTEX_SHADER, vertexSource);
    GLuint fragmentShader = compile_shader(GL_FRAGMENT_SHADER, fragmentSource);

    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);

    glUseProgram(shaderProgram);

    double mouseX, mouseY;
    glfwGetCursorPos(window, &mouseX, &mouseY);

    int winW, winH;
    glfwGetWindowSize(window, &winW, &winH);
    //mouseY = winH - mouseY;  // 上下反転
    mouseX = mouseX/winW;  //
    mouseY = mouseY/winH;  //
    
    GLint mouseLoc = glGetUniformLocation(shaderProgram, "u_mouse");
    glUniform2f(mouseLoc, (float)mouseX, (float)mouseY);

    GLint resolutionLoc = glGetUniformLocation(shaderProgram, "u_resolution");

    GLint timeLoc = glGetUniformLocation(shaderProgram, "u_time");
    glUniform1i(glGetUniformLocation(shaderProgram, "u_texture"), 0); // sampler2D

    // 頂点データ
    float vertices[] = {
        // x, y, u, v
        -1.0f,  1.0f,  0.0f, 1.0f,
         1.0f,  1.0f,  1.0f, 1.0f,
         1.0f, -1.0f,  1.0f, 0.0f,
        -1.0f, -1.0f,  0.0f, 0.0f
    };

    unsigned int indices[] = {
        0, 1, 2,
        2, 3, 0
    };

    // VAO/VBO/EBO初期化
    GLuint 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, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    // UV属性
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
    glEnableVertexAttribArray(1);

    // テクスチャ読み込み
    int width, height, nrChannels;
    unsigned char *data = stbi_load("../texture.png", &width, &height, &nrChannels, 0);
    if (!data) {
        fprintf(stderr, "Failed to load texture\n");
        return -1;
    }

    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    GLenum format = (nrChannels == 4) ? GL_RGBA : GL_RGB;

    glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
    glGenerateMipmap(GL_TEXTURE_2D);
    stbi_image_free(data);

    // ループ
    while (!glfwWindowShouldClose(window)) {
        float timeValue = (float)glfwGetTime();
        
        glfwGetCursorPos(window, &mouseX, &mouseY);
        glfwGetWindowSize(window, &winW, &winH);
        mouseX = mouseX/winW;  //
        mouseY = mouseY/winH;  //

        glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        glUseProgram(shaderProgram);
        glUniform1f(timeLoc, timeValue);
        glUniform2f(mouseLoc, (float)mouseX, (float)mouseY);
        glUniform2f(resolutionLoc, (float)winW, (float)winH);

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture);

        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glDeleteProgram(shaderProgram);
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    glfwTerminate();
    return 0;
}

shader.vert

#version 330 core
layout(location = 0) in vec2 aPos;
layout(location = 1) in vec2 aTexCoord;

out vec2 TexCoord;

void main()
{
    gl_Position = vec4(aPos, 0.0, 1.0);
    TexCoord = aTexCoord;
}

shader.frag

#version 330 core
out vec4 fragColor;

uniform sampler2D u_texture;
uniform vec2 u_mouse;       // マウス座標(0.0〜1.0)
uniform vec2 u_resolution;
uniform float u_time;

// カメラのレイ生成
vec3 getCameraRay(vec2 fragCoord, vec3 ro, vec3 ta) {
    vec2 uv = (fragCoord - 0.5 * u_resolution) / u_resolution.y;

    vec3 f = normalize(ta - ro);
    vec3 r = normalize(cross(f, vec3(0.0, 1.0, 0.0)));
    vec3 u = cross(r, f);

    return normalize(uv.x * r + uv.y * u + f);
}

// トーラスSDF
vec2 sdTorus(vec3 p, vec2 t) {
    vec2 q = vec2(length(p.xz) - t.x, p.y);
    float d = length(q) - t.y;
    return vec2(d, 1.0); // object ID = 1
}

// トーラスの中心位置(マウスに連動)
vec3 getTorusCenter() {
    // マウスを [-1,+1] に変換しXYにマッピング(Z位置固定)
    return vec3(
        (u_mouse.x * 2.0 - 1.0) * 1.5,
        (1.0 - u_mouse.y * 2.0) * 1.5,
        0.0
    );
}

// シーンの距離関数
vec2 map(vec3 p) {
    vec3 center = getTorusCenter();

    // 回転のみ(ローカル空間での処理)
    float angle = u_time * 0.5;
    mat3 rotY = mat3(
        cos(angle), 0.0, -sin(angle),
        0.0,        1.0,  0.0,
        sin(angle), 0.0,  cos(angle)
    );

    vec3 localP = (p - center) * rotY; // ローカル空間変換
    return sdTorus(localP, vec2(0.6, 0.2));
}

// 法線計算
vec3 getNormal(vec3 p) {
    float e = 0.001;
    vec2 h = vec2(e, 0.0);
    float dx = map(p + h.xyy).x - map(p - h.xyy).x;
    float dy = map(p + h.yxy).x - map(p - h.yxy).x;
    float dz = map(p + h.yyx).x - map(p - h.yyx).x;
    return normalize(vec3(dx, dy, dz));
}

// トーラスUV(ローカル空間UV)
vec2 torusUV(vec3 worldPos) {
    float angle = u_time * 0.5;
    mat3 rotY = mat3(
        cos(angle), 0.0, -sin(angle),
        0.0,        1.0,  0.0,
        sin(angle), 0.0,  cos(angle)
    );

    vec3 center = getTorusCenter();
    //vec3 localP = (worldPos - center) * rotY;
    vec3 localP = (worldPos - center) ;
    float u = atan(localP.z, localP.x) / (2.0 * 3.14159265) + 0.5;
    float r = length(localP.xz);
    float v = atan(localP.y, r - 0.6) / (2.0 * 3.14159265) + 0.5;
    return vec2(u, v);
}

// レイマーチング
vec3 raymarch(vec3 ro, vec3 rd) {
    float t = 0.0;
    vec3 p;
    float id = -1.0;

    for (int i = 0; i < 128; i++) {
        p = ro + rd * t;
        vec2 d = map(p);
        if (d.x < 0.001) {
            id = d.y;
            break;
        }
        if (t > 10.0) break;
        t += d.x;
    }

    if (id == 1.0) {
        vec2 uv = torusUV(p);
        vec3 tex = texture(u_texture, uv).rgb;
        vec3 n = getNormal(p);
        vec3 lightDir = normalize(vec3(0.4, 0.6, 0.3));
        float diff = clamp(dot(n, lightDir), 0.0, 1.0);
        return tex * diff + tex * 0.1;
    }

    return vec3(0.0); // background
}

void main() {
    vec2 fragCoord = gl_FragCoord.xy;
    vec3 ro = vec3(0.0, 0.0, 3.0);
    vec3 ta = vec3(0.0, 0.0, 0.0);
    vec3 rd = getCameraRay(fragCoord, ro, ta);

    vec3 col = raymarch(ro, rd);
    fragColor = vec4(col, 1.0);
}

cmd

furcr@furcraea_built MINGW64 ~
$ cd c:

furcr@furcraea_built MINGW64 /c
$ cd glsl_sample

furcr@furcraea_built MINGW64 /c/glsl_sample
$ cd glsl_sample_201_3texture

furcr@furcraea_built MINGW64 /c/glsl_sample/glsl_sample_201_3texture
$ cd build

furcr@furcraea_built MINGW64 /c/glsl_sample/glsl_sample_201_3texture/build
$ cmake -G "MSYS Makefiles" ..
CMake Deprecation Warning at CMakeLists.txt:1 (cmake_minimum_required):
  Compatibility with CMake < 3.10 will be removed from a future version of
  CMake.

  Update the VERSION argument <min> value.  Or, use the <min>...<max> syntax
  to tell CMake that the project requires at least <min> but has been updated
  to work with policies introduced by <max> or earlier.


-- The C compiler identification is GNU 15.1.0
-- The CXX compiler identification is GNU 15.1.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/msys64/mingw64/bin/cc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/msys64/mingw64/bin/c++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found OpenGL: opengl32
-- Configuring done (2.4s)
-- Generating done (0.0s)
-- Build files have been written to: C:/glsl_sample/glsl_sample_201_3texture/build

furcr@furcraea_built MINGW64 /c/glsl_sample/glsl_sample_201_3texture/build
$ make
[ 50%] Building C object CMakeFiles/glsl_sample.dir/main.c.obj
[100%] Linking C executable glsl_sample.exe
[100%] Built target glsl_sample

furcr@furcraea_built MINGW64 /c/glsl_sample/glsl_sample_201_3texture/build
$ ./glsl_sample

MSYS2のMINGW64 → pacman やOpenGL関連ライブラリがインストール可能 な環境でGLSLを描画できた。その4

CMakeLists.txt

cmake_minimum_required(VERSION 3.5)
project(glsl_sample)

set(CMAKE_C_STANDARD 99)

add_executable(glsl_sample main.c)

find_package(OpenGL REQUIRED)
include_directories("C:/msys64/mingw64/include/stb") 
include_directories(${OPENGL_INCLUDE_DIRS})

# MSYS2パス用のヒント(MINGW64環境)
include_directories("C:/msys64/mingw64/include")
link_directories("C:/msys64/mingw64/lib")

target_link_libraries(glsl_sample glfw3 glew32 opengl32 gdi32)

main.c

#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>

char* load_shader_source(const char* filepath) {
    FILE* file = fopen(filepath, "rb");
    if (!file) {
        fprintf(stderr, "Failed to open %s\n", filepath);
        exit(1);
    }
    fseek(file, 0, SEEK_END);
    long len = ftell(file);
    rewind(file);
    char* buffer = (char*)malloc(len + 1);
    fread(buffer, 1, len, file);
    buffer[len] = '\0';
    fclose(file);
    return buffer;
}

GLuint compile_shader(GLenum type, const char* source) {
    GLuint shader = glCreateShader(type);
    glShaderSource(shader, 1, &source, NULL);
    glCompileShader(shader);
    GLint success;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
    if (!success) {
        char infoLog[512];
        glGetShaderInfoLog(shader, 512, NULL, infoLog);
        fprintf(stderr, "Shader compile error: %s\n", infoLog);
        exit(1);
    }
    return shader;
}

int main() {
    if (!glfwInit()) {
        fprintf(stderr, "GLFW init failed\n");
        return -1;
    }

    GLFWwindow* window = glfwCreateWindow(800, 600, "GLSL Sample", NULL, NULL);
    if (!window) {
        glfwTerminate();
        return -1;
    }

    glfwMakeContextCurrent(window);
    glewInit();

    char* vertexSource = load_shader_source("../shader.vert");
    char* fragmentSource = load_shader_source("../shader.frag");

    GLuint vertexShader = compile_shader(GL_VERTEX_SHADER, vertexSource);
    GLuint fragmentShader = compile_shader(GL_FRAGMENT_SHADER, fragmentSource);

    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);

    glUseProgram(shaderProgram);

    GLint mouseLoc = glGetUniformLocation(shaderProgram, "u_mouse");
    GLint timeLoc = glGetUniformLocation(shaderProgram, "u_time");
    GLint resLoc   = glGetUniformLocation(shaderProgram, "u_resolution");
    glUniform1i(glGetUniformLocation(shaderProgram, "u_texture"), 0);

    float vertices[] = {
        // x, y, u, v
        -1.0f,  1.0f,  0.0f, 1.0f,
         1.0f,  1.0f,  1.0f, 1.0f,
         1.0f, -1.0f,  1.0f, 0.0f,
        -1.0f, -1.0f,  0.0f, 0.0f
    };
    unsigned int indices[] = {
        0, 1, 2,
        2, 3, 0
    };

    GLuint 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, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
    glEnableVertexAttribArray(1);

    int width, height, nrChannels;
    unsigned char *data = stbi_load("../texture.png", &width, &height, &nrChannels, 0);
    if (!data) {
        fprintf(stderr, "Failed to load texture\n");
        return -1;
    }

    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    GLenum format = (nrChannels == 4) ? GL_RGBA : GL_RGB;
    glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
    glGenerateMipmap(GL_TEXTURE_2D);
    stbi_image_free(data);

    while (!glfwWindowShouldClose(window)) {
        float timeValue = (float)glfwGetTime();
        int winW, winH;
        double mouseX, mouseY;

        glfwGetCursorPos(window, &mouseX, &mouseY);
        glfwGetWindowSize(window, &winW, &winH);
        mouseX = mouseX/winW;
		mouseY = mouseY/winH;
		
        glClearColor(0.1f, 0.1f, 0.15f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        glUseProgram(shaderProgram);
        glUniform1f(timeLoc, timeValue);
        glUniform2f(mouseLoc, (float)mouseX, (float)mouseY);
        glUniform2f(resLoc, (float)winW, (float)winH);

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture);
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glDeleteProgram(shaderProgram);
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    glfwTerminate();
    return 0;
}

shader.vert

#version 330 core

layout(location = 0) in vec2 aPos;
layout(location = 1) in vec2 aTexCoord;

out vec2 vTexCoord;

void main() {
    gl_Position = vec4(aPos, 0.0, 1.0);
    vTexCoord   = aTexCoord;
}

shader.frag

#version 330 core

out vec4 fragColor;

uniform vec2  u_resolution;
uniform float u_time;

// Signed Distance for Torus
float sdTorus(vec3 p, vec2 t) {
    vec2 q = vec2(length(p.xz) - t.x, p.y);
    return length(q) - t.y;
}

// シーン全体の SDF(ここではトーラスのみ)
float map(vec3 p) {
    return sdTorus(p, vec2(0.6, 0.2));
}

// 法線(数値微分)
vec3 getNormal(vec3 p) {
    float eps = 0.0005;
    return normalize(vec3(
        map(p + vec3(eps,0,0)) - map(p - vec3(eps,0,0)),
        map(p + vec3(0,eps,0)) - map(p - vec3(0,eps,0)),
        map(p + vec3(0,0,eps)) - map(p - vec3(0,0,eps))
    ));
}

// レイマーチング本体
float raymarch(vec3 ro, vec3 rd) {
    float t = 0.0;
    for (int i = 0; i < 128; i++) {
        float d = map(ro + rd * t);
        if (d < 0.001) break;
        t += d;
        if (t > 20.0) break;
    }
    return t;
}

void main() {
    // 画面座標 → 正規化デバイス空間
    vec2 uv = (gl_FragCoord.xy - 0.5 * u_resolution) / u_resolution.y;

    // カメラ設定:斜め上方から原点を見る
    vec3 ro = vec3(2.0, 1.5, 2.0);   // カメラ位置
    vec3 ta = vec3(0.0, 0.0, 0.0);   // 注視点(原点)
    vec3 up = vec3(0.0, 1.0, 0.0);   // 上方向ベクトル

    // カメラ座標系の計算
    vec3 f = normalize(ta - ro);
    vec3 r = normalize(cross(f, up));
    vec3 u = cross(r, f);
    vec3 rd = normalize(r * uv.x + u * uv.y + f);

    // レイマーチングで交差距離を取得
    float t = raymarch(ro, rd);

    vec3 col;
    if (t < 20.0) {
        // ヒット時のライティング
        vec3 p        = ro + rd * t;
        vec3 normal   = getNormal(p);
        vec3 lightDir = normalize(vec3(-0.5, 0.8, -0.3));
        float diff    = clamp(dot(normal, lightDir), 0.0, 1.0);
        col = vec3(0.8, 0.6, 0.3) * diff;  // トーラス本体の色
    }
    else {
        // 背景色
        col = vec3(0.1, 0.1, 0.15);
    }

    fragColor = vec4(col, 1.0);
}

cmd

$ cd c:

furcr@furcraea_built MINGW64 /c
$ cd glsl_sample

furcr@furcraea_built MINGW64 /c/glsl_sample
$ cd glsl_sample_201_3texture

furcr@furcraea_built MINGW64 /c/glsl_sample/glsl_sample_201_3texture
$ cd build

furcr@furcraea_built MINGW64 /c/glsl_sample/glsl_sample_201_3texture/build
$ cmake -G "MSYS Makefiles" ..
CMake Deprecation Warning at CMakeLists.txt:1 (cmake_minimum_required):
  Compatibility with CMake < 3.10 will be removed from a future version of
  CMake.

  Update the VERSION argument <min> value.  Or, use the <min>...<max> syntax
  to tell CMake that the project requires at least <min> but has been updated
  to work with policies introduced by <max> or earlier.


-- The C compiler identification is GNU 15.1.0
-- The CXX compiler identification is GNU 15.1.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/msys64/mingw64/bin/cc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/msys64/mingw64/bin/c++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found OpenGL: opengl32
-- Configuring done (2.4s)
-- Generating done (0.0s)
-- Build files have been written to: C:/glsl_sample/glsl_sample_201_3texture/build

furcr@furcraea_built MINGW64 /c/glsl_sample/glsl_sample_201_3texture/build
$ make
[ 50%] Building C object CMakeFiles/glsl_sample.dir/main.c.obj
[100%] Linking C executable glsl_sample.exe
[100%] Built target glsl_sample

furcr@furcraea_built MINGW64 /c/glsl_sample/glsl_sample_201_3texture/build
$ ./glsl_sample

MSYS2のMINGW64 → pacman やOpenGL関連ライブラリがインストール可能 な環境でGLSLを描画できた。その3

こちらが
マウス追従・時間変化付き・テクスチャあり・GLSLフル対応の完全版です

🔵
main.c(Cのグラフィックコード)

#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>

char* load_shader_source(const char* filepath) {
    FILE* file = fopen(filepath, "rb");
    if (!file) {
        fprintf(stderr, "Failed to open %s\n", filepath);
        exit(1);
    }
    fseek(file, 0, SEEK_END);
    long len = ftell(file);
    rewind(file);
    char* buffer = (char*)malloc(len + 1);
    fread(buffer, 1, len, file);
    buffer[len] = '\0';
    fclose(file);
    return buffer;
}

GLuint compile_shader(GLenum type, const char* source) {
    GLuint shader = glCreateShader(type);
    glShaderSource(shader, 1, &source, NULL);
    glCompileShader(shader);
    GLint success;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
    if (!success) {
        char infoLog[512];
        glGetShaderInfoLog(shader, 512, NULL, infoLog);
        fprintf(stderr, "Shader compile error: %s\n", infoLog);
        exit(1);
    }
    return shader;
}

int main() {
    if (!glfwInit()) {
        fprintf(stderr, "GLFW init failed\n");
        return -1;
    }

    GLFWwindow* window = glfwCreateWindow(800, 600, "GLSL Sample", NULL, NULL);
    if (!window) {
        glfwTerminate();
        return -1;
    }

    glfwMakeContextCurrent(window);
    glewInit();

    char* vertexSource = load_shader_source("../shader.vert");
    char* fragmentSource = load_shader_source("../shader.frag");

    GLuint vertexShader = compile_shader(GL_VERTEX_SHADER, vertexSource);
    GLuint fragmentShader = compile_shader(GL_FRAGMENT_SHADER, fragmentSource);

    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);

    glUseProgram(shaderProgram);

    GLint mouseLoc = glGetUniformLocation(shaderProgram, "u_mouse");
    GLint timeLoc = glGetUniformLocation(shaderProgram, "u_time");
    GLint resLoc   = glGetUniformLocation(shaderProgram, "u_resolution");
    glUniform1i(glGetUniformLocation(shaderProgram, "u_texture"), 0);

    float vertices[] = {
        // x, y, u, v
        -1.0f,  1.0f,  0.0f, 1.0f,
         1.0f,  1.0f,  1.0f, 1.0f,
         1.0f, -1.0f,  1.0f, 0.0f,
        -1.0f, -1.0f,  0.0f, 0.0f
    };
    unsigned int indices[] = {
        0, 1, 2,
        2, 3, 0
    };

    GLuint 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, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
    glEnableVertexAttribArray(1);

    int width, height, nrChannels;
    unsigned char *data = stbi_load("../texture.png", &width, &height, &nrChannels, 0);
    if (!data) {
        fprintf(stderr, "Failed to load texture\n");
        return -1;
    }

    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    GLenum format = (nrChannels == 4) ? GL_RGBA : GL_RGB;
    glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
    glGenerateMipmap(GL_TEXTURE_2D);
    stbi_image_free(data);

    while (!glfwWindowShouldClose(window)) {
        float timeValue = (float)glfwGetTime();
        int winW, winH;
        double mouseX, mouseY;

        glfwGetCursorPos(window, &mouseX, &mouseY);
        glfwGetWindowSize(window, &winW, &winH);
        mouseY = winH - mouseY;

        glClearColor(0.1f, 0.1f, 0.15f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        glUseProgram(shaderProgram);
        glUniform1f(timeLoc, timeValue);
        glUniform2f(mouseLoc, (float)mouseX, (float)mouseY);
        glUniform2f(resLoc, (float)winW, (float)winH);

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture);
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glDeleteProgram(shaderProgram);
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    glfwTerminate();
    return 0;
}

🔴
shader.vert(頂点シェーダー)

#version 330 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec2 aTexCoord;

out vec2 TexCoord;

void main() {
    gl_Position = vec4(aPos, 0.0, 1.0);
    TexCoord = aTexCoord;
}

🟣
shader.frag(フラグメントシェーダー)

#version 330 core
out vec4 fragColor;

in vec2 TexCoord;

uniform sampler2D u_texture;
uniform vec2 u_mouse;
uniform vec2 u_resolution;
uniform float u_time;

void main() {
    vec2 fragCoord = gl_FragCoord.xy;
    float dist = distance(fragCoord, u_mouse);
    float glow = 1.0 - smoothstep(0.0, 100.0, dist);

    vec4 tex = texture(u_texture, TexCoord);
    vec3 color = mix(tex.rgb, vec3(1.0, 1.0, 1.0), glow);

    fragColor = vec4(color, 1.0);
}

で実行


furcr@furcraea_built MINGW64 /c/glsl_sample
$ cd glsl_sample_040

furcr@furcraea_built MINGW64 /c/glsl_sample/glsl_sample_040
$ mkdir build

furcr@furcraea_built MINGW64 /c/glsl_sample/glsl_sample_040
$ cd build

furcr@furcraea_built MINGW64 /c/glsl_sample/glsl_sample_040/build
$ cmake -G "MSYS Makefiles" ..
CMake Deprecation Warning at CMakeLists.txt:1 (cmake_minimum_required):
  Compatibility with CMake < 3.10 will be removed from a future version of
  CMake.

  Update the VERSION argument <min> value.  Or, use the <min>...<max> syntax
  to tell CMake that the project requires at least <min> but has been updated
  to work with policies introduced by <max> or earlier.


-- The C compiler identification is GNU 15.1.0
-- The CXX compiler identification is GNU 15.1.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/msys64/mingw64/bin/cc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/msys64/mingw64/bin/c++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found OpenGL: opengl32
-- Configuring done (1.2s)
-- Generating done (0.0s)
-- Build files have been written to: C:/glsl_sample/glsl_sample_040/build

furcr@furcraea_built MINGW64 /c/glsl_sample/glsl_sample_040/build
$ make
[ 50%] Building C object CMakeFiles/glsl_sample.dir/main.c.obj
[100%] Linking C executable glsl_sample.exe
[100%] Built target glsl_sample

furcr@furcraea_built MINGW64 /c/glsl_sample/glsl_sample_040/build
$ ./glsl_sample.exe

MSYS2のMINGW64 → pacman やOpenGL関連ライブラリがインストール可能 な環境でGLSLを描画できた。その2

テクスチャを扱いたい

texture.png

pacman -S mingw-w64-x86_64-stb

読み込む

cmake_minimum_required(VERSION 3.5)
project(glsl_sample)

set(CMAKE_C_STANDARD 99)

add_executable(glsl_sample main.c)

find_package(OpenGL REQUIRED)
include_directories("C:/msys64/mingw64/include/stb") 
include_directories(${OPENGL_INCLUDE_DIRS})

# MSYS2パス用のヒント(MINGW64環境)
include_directories("C:/msys64/mingw64/include")
link_directories("C:/msys64/mingw64/lib")

target_link_libraries(glsl_sample glfw3 glew32 opengl32 gdi32)

完全修正版
main.c(OpenGLテクスチャ+UV付き四角形)

#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>

// ファイル読み込み
char* load_shader_source(const char* filepath) {
    FILE* file = fopen(filepath, "rb");
    if (!file) {
        fprintf(stderr, "Failed to open %s\n", filepath);
        exit(1);
    }
    fseek(file, 0, SEEK_END);
    long len = ftell(file);
    rewind(file);
    char* buffer = (char*)malloc(len + 1);
    fread(buffer, 1, len, file);
    buffer[len] = '\0';
    fclose(file);
    return buffer;
}

GLuint compile_shader(GLenum type, const char* source) {
    GLuint shader = glCreateShader(type);
    glShaderSource(shader, 1, &source, NULL);
    glCompileShader(shader);
    GLint success;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
    if (!success) {
        char infoLog[512];
        glGetShaderInfoLog(shader, 512, NULL, infoLog);
        fprintf(stderr, "Shader compile error: %s\n", infoLog);
        exit(1);
    }
    return shader;
}

int main() {
    if (!glfwInit()) {
        fprintf(stderr, "GLFW init failed\n");
        return -1;
    }

    GLFWwindow* window = glfwCreateWindow(800, 600, "GLSL Sample", NULL, NULL);
    if (!window) {
        glfwTerminate();
        return -1;
    }

    glfwMakeContextCurrent(window);
    glewInit();

    char* vertexSource = load_shader_source("../shader.vert");
    char* fragmentSource = load_shader_source("../shader.frag");

    GLuint vertexShader = compile_shader(GL_VERTEX_SHADER, vertexSource);
    GLuint fragmentShader = compile_shader(GL_FRAGMENT_SHADER, fragmentSource);

    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);

    glUseProgram(shaderProgram);
    GLint timeLoc = glGetUniformLocation(shaderProgram, "u_time");
    glUniform1i(glGetUniformLocation(shaderProgram, "u_texture"), 0); // sampler2D

    // 頂点データ
    float vertices[] = {
        // x, y, u, v
        -1.0f,  1.0f,  0.0f, 1.0f,
         1.0f,  1.0f,  1.0f, 1.0f,
         1.0f, -1.0f,  1.0f, 0.0f,
        -1.0f, -1.0f,  0.0f, 0.0f
    };

    unsigned int indices[] = {
        0, 1, 2,
        2, 3, 0
    };

    // VAO/VBO/EBO初期化
    GLuint 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, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    // UV属性
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
    glEnableVertexAttribArray(1);

    // テクスチャ読み込み
    int width, height, nrChannels;
    unsigned char *data = stbi_load("../texture.png", &width, &height, &nrChannels, 0);
    if (!data) {
        fprintf(stderr, "Failed to load texture\n");
        return -1;
    }

    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    GLenum format = (nrChannels == 4) ? GL_RGBA : GL_RGB;

    glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
    glGenerateMipmap(GL_TEXTURE_2D);
    stbi_image_free(data);

    // ループ
    while (!glfwWindowShouldClose(window)) {
        float timeValue = (float)glfwGetTime();

        glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        glUseProgram(shaderProgram);
        glUniform1f(timeLoc, timeValue);

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture);

        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glDeleteProgram(shaderProgram);
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    glfwTerminate();
    return 0;
}

✅必要な
shader.vert

#version 330 core
layout(location = 0) in vec2 aPos;
layout(location = 1) in vec2 aUV;

out vec2 vUV;

void main() {
    vUV = aUV;
    gl_Position = vec4(aPos, 0.0, 1.0);
}

✅必要な
shader.frag

#version 330 core
out vec4 FragColor;

in vec2 vUV;
uniform sampler2D u_texture;
uniform float u_time;

void main() {
    vec4 tex = texture(u_texture, vUV);
    FragColor = tex * (0.5 + 0.5 * sin(u_time));  // ゆらゆらする色
}

furcr@furcraea_built MINGW64 /c
$ cd glsl_sample

furcr@furcraea_built MINGW64 /c/glsl_sample
$ cd glsl_sample_030

furcr@furcraea_built MINGW64 /c/glsl_sample/glsl_sample_030
$ mkdir build

furcr@furcraea_built MINGW64 /c/glsl_sample/glsl_sample_030
$ cd build

furcr@furcraea_built MINGW64 /c/glsl_sample/glsl_sample_030/build
$ cmake -G "MSYS Makefiles" ..
CMake Deprecation Warning at CMakeLists.txt:1 (cmake_minimum_required):
  Compatibility with CMake < 3.10 will be removed from a future version of
  CMake.

  Update the VERSION argument <min> value.  Or, use the <min>...<max> syntax
  to tell CMake that the project requires at least <min> but has been updated
  to work with policies introduced by <max> or earlier.


-- The C compiler identification is GNU 15.1.0
-- The CXX compiler identification is GNU 15.1.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/msys64/mingw64/bin/cc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/msys64/mingw64/bin/c++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found OpenGL: opengl32
-- Configuring done (2.6s)
-- Generating done (0.0s)
-- Build files have been written to: C:/glsl_sample/glsl_sample_030/build

furcr@furcraea_built MINGW64 /c/glsl_sample/glsl_sample_030/build
$ make
[ 50%] Building C object CMakeFiles/glsl_sample.dir/main.c.obj
[100%] Linking C executable glsl_sample.exe
[100%] Built target glsl_sample

furcr@furcraea_built MINGW64 /c/glsl_sample/glsl_sample_030/build
$

できた。

MSYS2のMINGW64 → pacman やOpenGL関連ライブラリがインストール可能 な環境でGLSLを描画できた。

bash: pacman: command not found

なるほど、そのメッセージは**MSYS2のMINGW64ではなく、単体のGit Bash(MINGW64)**を使っていることを示しています。
Git Bash の MINGW64 環境は 名前に「MINGW64」と付いていても、MSYS2 とは別物であり、pacman などのパッケージマネージャーは含まれていません。


✅ 何が起きているかまとめ

  • Git BashのMINGW64pacman や開発用ライブラリなし
  • MSYS2のMINGW64pacman やOpenGL関連ライブラリがインストール可能

🔄 解決方法:MSYS2の導入

GLSLやOpenGLを本格的に使いたい場合、MSYS2を導入するのが一番簡単かつ強力です。

1. MSYS2をダウンロード・インストール

MSYS2公式サイト からインストーラーをダウンロードしてインストールします。

MSYS2 は「Windows 向けソフトウェア配布および構築プラットフォーム」です。

しょぼいウィルスソフトが反応する可能性があるので切っておく

  1. プロジェクトのコンパイルを開始するには、mingw-w64 GCCなどのツールをインストールする必要があるでしょう。以下のコマンドを実行してください。
pacman -S mingw-w64-ucrt-x86_64-gcc
  1. ターミナルウィンドウに以下の出力が表示されます。「Enter」キーを押して続行してください。

furcr@furcraea_built UCRT64 ~
$ pacman -S mingw-w64-ucrt-x86_64-gcc
resolving dependencies...
looking for conflicting packages...

Packages (16) mingw-w64-ucrt-x86_64-binutils-2.44-4
              mingw-w64-ucrt-x86_64-crt-git-13.0.0.r21.gf5469ff36-1
              mingw-w64-ucrt-x86_64-gcc-libs-15.1.0-5  mingw-w64-ucrt-x86_64-gettext-runtime-0.25-1
              mingw-w64-ucrt-x86_64-gmp-6.3.0-2
              mingw-w64-ucrt-x86_64-headers-git-13.0.0.r21.gf5469ff36-1
              mingw-w64-ucrt-x86_64-isl-0.27-1  mingw-w64-ucrt-x86_64-libiconv-1.18-1
              mingw-w64-ucrt-x86_64-libwinpthread-13.0.0.r21.gf5469ff36-1
              mingw-w64-ucrt-x86_64-mpc-1.3.1-2  mingw-w64-ucrt-x86_64-mpfr-4.2.2-1
              mingw-w64-ucrt-x86_64-windows-default-manifest-6.4-4
              mingw-w64-ucrt-x86_64-winpthreads-13.0.0.r21.gf5469ff36-1
              mingw-w64-ucrt-x86_64-zlib-1.3.1-1  mingw-w64-ucrt-x86_64-zstd-1.5.7-1
              mingw-w64-ucrt-x86_64-gcc-15.1.0-5

Total Download Size:    69.02 MiB
Total Installed Size:  540.65 MiB

:: Proceed with installation? [Y/n]
:: Retrieving packages...
 mingw-w64-ucrt-x86_64-crt-...     4.6 MiB  1740 KiB/s 00:03 [###############################] 100%
 mingw-w64-ucrt-x86_64-isl-...  1453.5 KiB   502 KiB/s 00:03 [###############################] 100%
 mingw-w64-ucrt-x86_64-binu...     6.0 MiB  1980 KiB/s 00:03 [###############################] 100%
 mingw-w64-ucrt-x86_64-gcc-...  1043.5 KiB  2.24 MiB/s 00:00 [###############################] 100%
 mingw-w64-ucrt-x86_64-libi...   725.4 KiB  1656 KiB/s 00:00 [###############################] 100%
 mingw-w64-ucrt-x86_64-head...     6.4 MiB  1811 KiB/s 00:04 [###############################] 100%
 mingw-w64-ucrt-x86_64-gmp-...   578.5 KiB  1297 KiB/s 00:00 [###############################] 100%
 mingw-w64-ucrt-x86_64-mpfr...   541.9 KiB  1234 KiB/s 00:00 [###############################] 100%
 mingw-w64-ucrt-x86_64-gett...   333.5 KiB   836 KiB/s 00:00 [###############################] 100%
 mingw-w64-ucrt-x86_64-gcc-...    46.6 MiB  11.1 MiB/s 00:04 [###############################] 100%
 mingw-w64-ucrt-x86_64-zstd...   642.3 KiB   605 KiB/s 00:01 [###############################] 100%
 mingw-w64-ucrt-x86_64-mpc-...   128.3 KiB   276 KiB/s 00:00 [###############################] 100%
 mingw-w64-ucrt-x86_64-zlib...    92.1 KiB   242 KiB/s 00:00 [###############################] 100%
 mingw-w64-ucrt-x86_64-winp...    41.8 KiB   109 KiB/s 00:00 [###############################] 100%
 mingw-w64-ucrt-x86_64-libw...    29.5 KiB  79.2 KiB/s 00:00 [###############################] 100%
 mingw-w64-ucrt-x86_64-wind...     3.0 KiB  5.10 KiB/s 00:01 [###############################] 100%
 Total (16/16)                    69.0 MiB  12.9 MiB/s 00:05 [###############################] 100%
(16/16) checking keys in keyring                             [###############################] 100%
(16/16) checking package integrity                           [###############################] 100%
(16/16) loading package files                                [###############################] 100%
(16/16) checking for file conflicts                          [###############################] 100%
(16/16) checking available disk space                        [###############################] 100%
:: Processing package changes...
( 1/16) installing mingw-w64-ucrt-x86_64-libwinpthread       [###############################] 100%
( 2/16) installing mingw-w64-ucrt-x86_64-gcc-libs            [###############################] 100%
( 3/16) installing mingw-w64-ucrt-x86_64-libiconv            [###############################] 100%
( 4/16) installing mingw-w64-ucrt-x86_64-gettext-runtime     [###############################] 100%
( 5/16) installing mingw-w64-ucrt-x86_64-zlib                [###############################] 100%
( 6/16) installing mingw-w64-ucrt-x86_64-zstd                [###############################] 100%
( 7/16) installing mingw-w64-ucrt-x86_64-binutils            [###############################] 100%
( 8/16) installing mingw-w64-ucrt-x86_64-headers-git         [###############################] 100%
( 9/16) installing mingw-w64-ucrt-x86_64-crt-git             [###############################] 100%
(10/16) installing mingw-w64-ucrt-x86_64-gmp                 [###############################] 100%
(11/16) installing mingw-w64-ucrt-x86_64-isl                 [###############################] 100%
(12/16) installing mingw-w64-ucrt-x86_64-mpfr                [###############################] 100%
(13/16) installing mingw-w64-ucrt-x86_64-mpc                 [###############################] 100%
(14/16) installing mingw-w64-ucrt-x86_64-windows-default...  [###############################] 100%
(15/16) installing mingw-w64-ucrt-x86_64-winpthreads         [###############################] 100%
(16/16) installing mingw-w64-ucrt-x86_64-gcc                 [###############################] 100%

furcr@furcraea_built UCRT64 ~
$

gccこれで、Windows 用のソフトウェアをビルドするために
呼び出すことができます。

gcc --version
gcc.exe (Rev5, Built by MSYS2 project) 15.1.0
Copyright (C) 2025 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


furcr@furcraea_built UCRT64 ~
$

MSYS2 をインストールすると、 経由で自動的に更新されます。
詳細については、
更新ガイドを
pacman参照してください。

2. シェルの選択(重要)

インストール後、以下のいずれかのターミナルを起動:

  • MSYS2 MinGW 64-bit(おすすめ)
    /mingw64/bin 環境になり、pacmanも使える

開発ツールとライブラリのインストール

pacman -Syu   # はじめに全体アップデート


furcr@furcraea_built MINGW64 ~
$ pacman -Syu
:: Synchronizing package databases...
 clangarm64 is up to date
 mingw32 is up to date
 mingw64 is up to date
 ucrt64 is up to date
 clang64 is up to date
 msys is up to date
:: Starting core system upgrade...
 there is nothing to do
:: Starting full system upgrade...
resolving dependencies...
looking for conflicting packages...

Packages (19) curl-8.14.1-2  gcc-libs-15.1.0-2  libcurl-8.14.1-2  libffi-3.5.1-1
              libhogweed-3.10.2-1  libnettle-3.10.2-1  libnghttp3-1.10.1-1  libngtcp2-1.13.0-2
              libopenssl-3.5.1-1  libsqlite-3.50.2-1
              mingw-w64-ucrt-x86_64-crt-git-13.0.0.r57.gc1a7f831b-1
              mingw-w64-ucrt-x86_64-gcc-15.1.0-6  mingw-w64-ucrt-x86_64-gcc-libs-15.1.0-6
              mingw-w64-ucrt-x86_64-gettext-runtime-0.25.1-1
              mingw-w64-ucrt-x86_64-headers-git-13.0.0.r57.gc1a7f831b-1
              mingw-w64-ucrt-x86_64-libwinpthread-13.0.0.r57.gc1a7f831b-1
              mingw-w64-ucrt-x86_64-winpthreads-13.0.0.r57.gc1a7f831b-1  nettle-3.10.2-1
              openssl-3.5.1-1

Total Download Size:    65.09 MiB
Total Installed Size:  489.36 MiB
Net Upgrade Size:        1.06 MiB

:: Proceed with installation? [Y/n]

必要なライブラリ

pacman -S mingw-w64-x86_64-toolchain mingw-w64-x86_64-glfw mingw-w64-x86_64-glew mingw-w64-x86_64-glm

furcr@furcraea_built MINGW64 ~
$ pacman -S mingw-w64-x86_64-toolchain mingw-w64-x86_64-glfw mingw-w64-x86_64-glew mingw-w64-x86_64-glm
:: There are 13 members in group mingw-w64-x86_64-toolchain:
:: Repository mingw64
   1) mingw-w64-x86_64-binutils  2) mingw-w64-x86_64-crt-git  3) mingw-w64-x86_64-gcc
   4) mingw-w64-x86_64-gdb  5) mingw-w64-x86_64-gdb-multiarch  6) mingw-w64-x86_64-headers-git
   7) mingw-w64-x86_64-libmangle-git  8) mingw-w64-x86_64-libwinpthread  9) mingw-w64-x86_64-make
   10) mingw-w64-x86_64-pkgconf  11) mingw-w64-x86_64-tools-git  12) mingw-w64-x86_64-winpthreads
   13) mingw-w64-x86_64-winstorecompat-git

Enter a selection (default=all):そのまま Enter キーを押す(default=all)

resolving dependencies...
looking for conflicting packages...

Packages (43) mingw-w64-x86_64-bzip2-1.0.8-3  mingw-w64-x86_64-expat-2.7.1-2
              mingw-w64-x86_64-gcc-libs-15.1.0-6  mingw-w64-x86_64-gettext-runtime-0.25.1-1
              mingw-w64-x86_64-gmp-6.3.0-2  mingw-w64-x86_64-isl-0.27-1
              mingw-w64-x86_64-libffi-3.5.1-1  mingw-w64-x86_64-libiconv-1.18-1
              mingw-w64-x86_64-libsystre-1.0.2-1  mingw-w64-x86_64-libtre-0.9.0-1
              mingw-w64-x86_64-mpc-1.3.1-2  mingw-w64-x86_64-mpdecimal-4.0.1-1
              mingw-w64-x86_64-mpfr-4.2.2-1  mingw-w64-x86_64-ncurses-6.5.20241228-3
              mingw-w64-x86_64-openssl-3.5.1-1  mingw-w64-x86_64-python-3.12.11-1
              mingw-w64-x86_64-readline-8.2.013-1  mingw-w64-x86_64-sqlite3-3.50.2-1
              mingw-w64-x86_64-tcl-8.6.16-1  mingw-w64-x86_64-termcap-1.3.1-7
              mingw-w64-x86_64-tk-8.6.16-1  mingw-w64-x86_64-tzdata-2025b-2
              mingw-w64-x86_64-windows-default-manifest-6.4-4  mingw-w64-x86_64-xxhash-0.8.3-1
              mingw-w64-x86_64-xz-5.8.1-2  mingw-w64-x86_64-zlib-1.3.1-1
              mingw-w64-x86_64-zstd-1.5.7-1  mingw-w64-x86_64-binutils-2.44-4
              mingw-w64-x86_64-crt-git-13.0.0.r57.gc1a7f831b-1  mingw-w64-x86_64-gcc-15.1.0-6
              mingw-w64-x86_64-gdb-16.3-1  mingw-w64-x86_64-gdb-multiarch-16.3-1
              mingw-w64-x86_64-glew-2.2.0-3  mingw-w64-x86_64-glfw-3.4-1
              mingw-w64-x86_64-glm-1.0.1-1  mingw-w64-x86_64-headers-git-13.0.0.r57.gc1a7f831b-1
              mingw-w64-x86_64-libmangle-git-13.0.0.r57.gc1a7f831b-1
              mingw-w64-x86_64-libwinpthread-13.0.0.r57.gc1a7f831b-1  mingw-w64-x86_64-make-4.4.1-3
              mingw-w64-x86_64-pkgconf-1~2.5.1-1
              mingw-w64-x86_64-tools-git-13.0.0.r57.gc1a7f831b-1
              mingw-w64-x86_64-winpthreads-13.0.0.r57.gc1a7f831b-1
              mingw-w64-x86_64-winstorecompat-git-13.0.0.r57.gc1a7f831b-1

Total Download Size:   126.25 MiB
Total Installed Size:  918.18 MiB

:: Proceed with installation? [Y/n] そのまま Enter キーを押す
:: Retrieving packages...
 mingw-w64-x86_64-gdb-multi...     6.4 MiB  2.83 MiB/s 00:02 [###############################] 100%
 mingw-w64-x86_64-headers-g...     6.4 MiB  2.55 MiB/s 00:02 [###############################] 100%
 mingw-w64-x86_64-openssl-3...     7.9 MiB  3.04 MiB/s 00:03 [###############################] 100%
 mingw-w64-x86_64-binutils-...     6.0 MiB  9.99 MiB/s 00:01 [###############################] 100%
 mingw-w64-x86_64-python-3....    23.2 MiB  7.71 MiB/s 00:03 [###############################] 100%
 mingw-w64-x86_64-gcc-15.1....    46.6 MiB  14.2 MiB/s 00:03 [###############################] 100%
 mingw-w64-x86_64-gdb-16.3-...     4.6 MiB  5.62 MiB/s 00:01 [###############################] 100%
 mingw-w64-x86_64-glm-1.0.1...     3.4 MiB  6.33 MiB/s 00:01 [###############################] 100%
 mingw-w64-x86_64-tcl-8.6.1...     2.7 MiB  5.43 MiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-crt-git-1...     4.5 MiB  4.20 MiB/s 00:01 [###############################] 100%
 mingw-w64-x86_64-sqlite3-3...     2.3 MiB  4.55 MiB/s 00:01 [###############################] 100%
 mingw-w64-x86_64-tk-8.6.16...     2.0 MiB  4.29 MiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-ncurses-6...  1747.4 KiB  3.53 MiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-isl-0.27-...  1456.4 KiB  2.96 MiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-gcc-libs-...  1044.6 KiB  2.11 MiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-libiconv-...   726.4 KiB  1897 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-glew-2.2....   635.3 KiB  1390 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-zstd-1.5....   642.7 KiB  1060 KiB/s 00:01 [###############################] 100%
 mingw-w64-x86_64-gmp-6.3.0...   577.8 KiB  1201 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-mpfr-4.2....   542.5 KiB  1203 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-xz-5.8.1-...   474.4 KiB   892 KiB/s 00:01 [###############################] 100%
 mingw-w64-x86_64-readline-...   411.7 KiB   907 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-gettext-r...   335.2 KiB   685 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-tools-git...   323.2 KiB   710 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-tzdata-20...   221.2 KiB   643 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-glfw-3.4-...   177.0 KiB   501 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-mpdecimal...   155.8 KiB   449 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-expat-2.7...   165.9 KiB   384 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-xxhash-0....   119.2 KiB   341 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-make-4.4....   138.5 KiB   287 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-mpc-1.3.1...   128.7 KiB   245 KiB/s 00:01 [###############################] 100%
 mingw-w64-x86_64-zlib-1.3....   104.4 KiB   236 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-pkgconf-1...   100.1 KiB   212 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-bzip2-1.0...    90.9 KiB   188 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-libffi-3....    43.2 KiB   119 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-libtre-0....    79.5 KiB   165 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-winpthrea...    41.9 KiB   119 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-libwinpth...    30.2 KiB  69.5 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-termcap-1...    27.3 KiB  71.6 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-winstorec...    25.0 KiB  71.4 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-libmangle...    22.8 KiB  57.4 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-libsystre...     9.7 KiB  27.3 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-windows-d...     3.1 KiB  5.74 KiB/s 00:01 [###############################] 100%
 Total (43/43)                   126.3 MiB  16.3 MiB/s 00:08 [###############################] 100%
(43/43) checking keys in keyring                             [###############################] 100%
(43/43) checking package integrity                           [###############################] 100%
(43/43) loading package files                                [###############################] 100%
(43/43) checking for file conflicts                          [###############################] 100%
(43/43) checking available disk space                        [###############################] 100%
:: Processing package changes...
( 1/43) installing mingw-w64-x86_64-libwinpthread            [###############################] 100%
( 2/43) installing mingw-w64-x86_64-gcc-libs                 [###############################] 100%
( 3/43) installing mingw-w64-x86_64-libiconv                 [###############################] 100%
( 4/43) installing mingw-w64-x86_64-gettext-runtime          [###############################] 100%
( 5/43) installing mingw-w64-x86_64-zlib                     [###############################] 100%
( 6/43) installing mingw-w64-x86_64-zstd                     [###############################] 100%
( 7/43) installing mingw-w64-x86_64-binutils                 [###############################] 100%
( 8/43) installing mingw-w64-x86_64-headers-git              [###############################] 100%
( 9/43) installing mingw-w64-x86_64-crt-git                  [###############################] 100%
(10/43) installing mingw-w64-x86_64-gmp                      [###############################] 100%
(11/43) installing mingw-w64-x86_64-isl                      [###############################] 100%
(12/43) installing mingw-w64-x86_64-mpfr                     [###############################] 100%
(13/43) installing mingw-w64-x86_64-mpc                      [###############################] 100%
(14/43) installing mingw-w64-x86_64-windows-default-manifest [###############################] 100%
(15/43) installing mingw-w64-x86_64-winpthreads              [###############################] 100%
(16/43) installing mingw-w64-x86_64-gcc                      [###############################] 100%
(17/43) installing mingw-w64-x86_64-expat                    [###############################] 100%
(18/43) installing mingw-w64-x86_64-libtre                   [###############################] 100%
(19/43) installing mingw-w64-x86_64-libsystre                [###############################] 100%
(20/43) installing mingw-w64-x86_64-ncurses                  [###############################] 100%
(21/43) installing mingw-w64-x86_64-bzip2                    [###############################] 100%
(22/43) installing mingw-w64-x86_64-libffi                   [###############################] 100%
(23/43) installing mingw-w64-x86_64-mpdecimal                [###############################] 100%
(24/43) installing mingw-w64-x86_64-openssl                  [###############################] 100%
Optional dependencies for mingw-w64-x86_64-openssl
    mingw-w64-x86_64-ca-certificates
(25/43) installing mingw-w64-x86_64-termcap                  [###############################] 100%
(26/43) installing mingw-w64-x86_64-readline                 [###############################] 100%
(27/43) installing mingw-w64-x86_64-sqlite3                  [###############################] 100%
Optional dependencies for mingw-w64-x86_64-sqlite3
    mingw-w64-x86_64-tcl: for sqlite3_analyzer [pending]
(28/43) installing mingw-w64-x86_64-tcl                      [###############################] 100%
(29/43) installing mingw-w64-x86_64-tk                       [###############################] 100%
(30/43) installing mingw-w64-x86_64-xz                       [###############################] 100%
(31/43) installing mingw-w64-x86_64-tzdata                   [###############################] 100%
(32/43) installing mingw-w64-x86_64-python                   [###############################] 100%
(33/43) installing mingw-w64-x86_64-xxhash                   [###############################] 100%
(34/43) installing mingw-w64-x86_64-gdb                      [###############################] 100%
Optional dependencies for mingw-w64-x86_64-gdb
    mingw-w64-x86_64-python-pygments: for syntax highlighting
(35/43) installing mingw-w64-x86_64-gdb-multiarch            [###############################] 100%
Optional dependencies for mingw-w64-x86_64-gdb-multiarch
    mingw-w64-x86_64-python-pygments: for syntax highlighting
(36/43) installing mingw-w64-x86_64-libmangle-git            [###############################] 100%
(37/43) installing mingw-w64-x86_64-make                     [###############################] 100%
(38/43) installing mingw-w64-x86_64-pkgconf                  [###############################] 100%
(39/43) installing mingw-w64-x86_64-tools-git                [###############################] 100%
(40/43) installing mingw-w64-x86_64-winstorecompat-git       [###############################] 100%
(41/43) installing mingw-w64-x86_64-glfw                     [###############################] 100%
(42/43) installing mingw-w64-x86_64-glew                     [###############################] 100%
(43/43) installing mingw-w64-x86_64-glm                      [###############################] 100%

furcr@furcraea_built MINGW64 ~
$

完了したら GLSL 含む OpenGL プログラムのビルドが可能に

プロジェクト構成

glsl_sample/
├── CMakeLists.txt
├── main.c
├── shader.vert
└── shader.frag

🔧 main.c(OpenGLでGLSL読み込んで三角形描画)

#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>

// ファイル読み込みヘルパー
char* load_shader_source(const char* filepath) {
    FILE* file = fopen(filepath, "rb");
    if (!file) {
        fprintf(stderr, "Failed to open %s\n", filepath);
        exit(1);
    }
    fseek(file, 0, SEEK_END);
    long len = ftell(file);
    rewind(file);
    char* buffer = (char*)malloc(len + 1);
    fread(buffer, 1, len, file);
    buffer[len] = '\0';
    fclose(file);
    return buffer;
}

GLuint compile_shader(GLenum type, const char* source) {
    GLuint shader = glCreateShader(type);
    glShaderSource(shader, 1, &source, NULL);
    glCompileShader(shader);
    GLint success;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
    if (!success) {
        char infoLog[512];
        glGetShaderInfoLog(shader, 512, NULL, infoLog);
        fprintf(stderr, "Shader compile error: %s\n", infoLog);
        exit(1);
    }
    return shader;
}

int main() {
    if (!glfwInit()) {
        fprintf(stderr, "GLFW init failed\n");
        return -1;
    }

    GLFWwindow* window = glfwCreateWindow(800, 600, "GLSL Sample", NULL, NULL);
    if (!window) {
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    glewInit();

    char* vertexSource = load_shader_source("../shader.vert");
    char* fragmentSource = load_shader_source("../shader.frag");

    GLuint vertexShader = compile_shader(GL_VERTEX_SHADER, vertexSource);
    GLuint fragmentShader = compile_shader(GL_FRAGMENT_SHADER, fragmentSource);

    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    glUseProgram(shaderProgram);

    float vertices[] = {
        -0.5f, -0.5f, 0.0f,
         0.5f, -0.5f, 0.0f,
         0.0f,  0.5f, 0.0f
    };
    GLuint VBO, VAO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    while (!glfwWindowShouldClose(window)) {
        glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        glUseProgram(shaderProgram);
        glBindVertexArray(VAO);
        glDrawArrays(GL_TRIANGLES, 0, 3);

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    glfwTerminate();
    return 0;
}

🧬 shader.vert(頂点シェーダー)

#version 330 core
layout(location = 0) in vec3 aPos;
void main() {
    gl_Position = vec4(aPos, 1.0);
}

🎨 shader.frag(フラグメントシェーダー)

#version 330 core
out vec4 FragColor;
void main() {
    FragColor = vec4(1.0, 0.2, 0.2, 1.0); // 赤
}

🛠 CMakeLists.txt(ビルド設定)

cmake_minimum_required(VERSION 3.5)
project(glsl_sample)

set(CMAKE_C_STANDARD 99)

add_executable(glsl_sample main.c)

find_package(OpenGL REQUIRED)
include_directories(${OPENGL_INCLUDE_DIRS})

# MSYS2パス用のヒント(MINGW64環境)
include_directories("C:/msys64/mingw64/include")
link_directories("C:/msys64/mingw64/lib")

target_link_libraries(glsl_sample glfw3 glew32 opengl32 gdi32)

🔧 ビルド手順(MSYS2 MINGW64 シェル)

cd /path/to/glsl_sample
mkdir build
cd build
cmake ..
make
./glsl_sample.exe

📌 備考

  • 画面に赤い三角形が表示されれば成功です。
  • GLSLシェーダーは外部ファイルから読み込んで動的にコンパイルしています。
  • shader.vertshader.frag を編集すればリアルタイムに変更反映できます。

-bash: cmake: command not found

ChatGPT said:

それは cmake がインストールされていないエラーです。
MSYS2のMINGW64環境では、以下のコマンドで cmake をインストールできます。


✅ cmake のインストール(MSYS2 MINGW64)

pacman -S mingw-w64-x86_64-cmake

必ず MSYS2の「MINGW64」シェル で実行してください(/mingw64/bin がPATHに入っている状態)

furcr@furcraea_built MINGW64 ~
$ pacman -S mingw-w64-x86_64-cmake
resolving dependencies...
looking for conflicting packages...

Packages (24) mingw-w64-x86_64-brotli-1.1.0-5  mingw-w64-x86_64-c-ares-1.34.5-1
              mingw-w64-x86_64-ca-certificates-20241223-1  mingw-w64-x86_64-cppdap-1.65-1
              mingw-w64-x86_64-curl-8.14.1-1  mingw-w64-x86_64-gnutls-3.8.9-4
              mingw-w64-x86_64-jsoncpp-1.9.6-3  mingw-w64-x86_64-libarchive-3.8.1-2
              mingw-w64-x86_64-libb2-0.98.1-2  mingw-w64-x86_64-libidn2-2.3.8-2
              mingw-w64-x86_64-libpsl-0.21.5-3  mingw-w64-x86_64-libssh2-1.11.1-1
              mingw-w64-x86_64-libtasn1-4.20.0-1  mingw-w64-x86_64-libunistring-1.3-1
              mingw-w64-x86_64-libuv-1.51.0-1  mingw-w64-x86_64-lz4-1.10.0-1
              mingw-w64-x86_64-nettle-3.10.2-1  mingw-w64-x86_64-nghttp2-1.66.0-1
              mingw-w64-x86_64-nghttp3-1.10.1-1  mingw-w64-x86_64-ngtcp2-1.13.0-2
              mingw-w64-x86_64-ninja-1.13.0-1  mingw-w64-x86_64-p11-kit-0.25.5-1
              mingw-w64-x86_64-rhash-1.4.5-1  mingw-w64-x86_64-cmake-4.0.3-1

Total Download Size:    19.46 MiB
Total Installed Size:  106.07 MiB

:: Proceed with installation? [Y/n] Enter

:: Retrieving packages...
 mingw-w64-x86_64-gnutls-3....     2.2 MiB  1013 KiB/s 00:02 [###############################] 100%
 mingw-w64-x86_64-curl-8.14...  1552.7 KiB   666 KiB/s 00:02 [###############################] 100%
 mingw-w64-x86_64-libarchiv...   876.9 KiB   374 KiB/s 00:02 [###############################] 100%
 mingw-w64-x86_64-libunistr...   832.7 KiB   349 KiB/s 00:02 [###############################] 100%
 mingw-w64-x86_64-cmake-4.0...     9.2 MiB  3.44 MiB/s 00:03 [###############################] 100%
 mingw-w64-x86_64-cppdap-1....   491.9 KiB  1152 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-nettle-3....   563.7 KiB  1112 KiB/s 00:01 [###############################] 100%
 mingw-w64-x86_64-brotli-1....   420.5 KiB   947 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-ca-certif...   395.0 KiB   884 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-c-ares-1....   309.2 KiB   671 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-libssh2-1...   309.0 KiB   719 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-ngtcp2-1....   269.4 KiB   622 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-libuv-1.5...   221.5 KiB   480 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-libtasn1-...   196.3 KiB   458 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-nghttp2-1...   194.9 KiB   435 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-p11-kit-0...   422.7 KiB   245 KiB/s 00:02 [###############################] 100%
 mingw-w64-x86_64-rhash-1.4...   219.0 KiB   301 KiB/s 00:01 [###############################] 100%
 mingw-w64-x86_64-ninja-1.1...   186.3 KiB   350 KiB/s 00:01 [###############################] 100%
 mingw-w64-x86_64-jsoncpp-1...   176.1 KiB   387 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-libidn2-2...   170.6 KiB   377 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-lz4-1.10....   166.9 KiB   328 KiB/s 00:01 [###############################] 100%
 mingw-w64-x86_64-nghttp3-1...   124.7 KiB   295 KiB/s 00:00 [###############################] 100%
 mingw-w64-x86_64-libpsl-0....    94.4 KiB   181 KiB/s 00:01 [###############################] 100%
 mingw-w64-x86_64-libb2-0.9...    23.7 KiB  53.5 KiB/s 00:00 [###############################] 100%
 Total (24/24)                    19.5 MiB  3.73 MiB/s 00:05 [###############################] 100%
(24/24) checking keys in keyring                             [###############################] 100%
(24/24) checking package integrity                           [###############################] 100%
(24/24) loading package files                                [###############################] 100%
(24/24) checking for file conflicts                          [###############################] 100%
(24/24) checking available disk space                        [###############################] 100%
:: Processing package changes...
( 1/24) installing mingw-w64-x86_64-cppdap                   [###############################] 100%
( 2/24) installing mingw-w64-x86_64-c-ares                   [###############################] 100%
( 3/24) installing mingw-w64-x86_64-brotli                   [###############################] 100%
( 4/24) installing mingw-w64-x86_64-libunistring             [###############################] 100%
( 5/24) installing mingw-w64-x86_64-libidn2                  [###############################] 100%
( 6/24) installing mingw-w64-x86_64-libpsl                   [###############################] 100%
( 7/24) installing mingw-w64-x86_64-libtasn1                 [###############################] 100%
( 8/24) installing mingw-w64-x86_64-p11-kit                  [###############################] 100%
( 9/24) installing mingw-w64-x86_64-ca-certificates          [###############################] 100%
(10/24) installing mingw-w64-x86_64-libssh2                  [###############################] 100%
(11/24) installing mingw-w64-x86_64-nghttp2                  [###############################] 100%
(12/24) installing mingw-w64-x86_64-nettle                   [###############################] 100%
(13/24) installing mingw-w64-x86_64-gnutls                   [###############################] 100%
(14/24) installing mingw-w64-x86_64-ngtcp2                   [###############################] 100%
(15/24) installing mingw-w64-x86_64-nghttp3                  [###############################] 100%
(16/24) installing mingw-w64-x86_64-curl                     [###############################] 100%
(17/24) installing mingw-w64-x86_64-jsoncpp                  [###############################] 100%
(18/24) installing mingw-w64-x86_64-libb2                    [###############################] 100%
(19/24) installing mingw-w64-x86_64-lz4                      [###############################] 100%
(20/24) installing mingw-w64-x86_64-libarchive               [###############################] 100%
(21/24) installing mingw-w64-x86_64-libuv                    [###############################] 100%
(22/24) installing mingw-w64-x86_64-ninja                    [###############################] 100%
(23/24) installing mingw-w64-x86_64-rhash                    [###############################] 100%
(24/24) installing mingw-w64-x86_64-cmake                    [###############################] 100%
Optional dependencies for mingw-w64-x86_64-cmake
    mingw-w64-x86_64-emacs: for cmake emacs mode

furcr@furcraea_built MINGW64 ~
$

✅ インストール確認

which cmake

$ which cmake
/mingw64/bin/cmake

これで /mingw64/bin/cmake と表示されれば OK。あとは前の手順どおり cmake .. && make でビルドできます。


furcr@furcraea_built MINGW64 ~
$ cd C:\glsl_sample

furcr@furcraea_built MINGW64 /c/glsl_sample
$ cd build

furcr@furcraea_built MINGW64 /c/glsl_sample/build
$ cmake ..
CMake Error at CMakeLists.txt:1 (cmake_minimum_required):
  Compatibility with CMake < 3.5 has been removed from CMake.

  Update the VERSION argument <min> value.  Or, use the <min>...<max> syntax
  to tell CMake that the project requires at least <min> but has been updated
  to work with policies introduced by <max> or earlier.

  Or, add -DCMAKE_POLICY_VERSION_MINIMUM=3.5 to try configuring anyway.


-- Configuring incomplete, errors occurred!

furcr@furcraea_built MINGW64 /c/glsl_sample/build
$

完璧です、CMakeはちゃんと動いています
出ているエラーは単に CMakeLists.txt のバージョン指定が古いというだけなので、すぐに修正できます。


✅ 修正方法:CMakeLists.txt の1行目を更新

🔧 変更前:

cmake_minimum_required(VERSION 3.0)

✅ 変更後

cmake_minimum_required(VERSION 3.5)

または、より安全にするならこうしてもOKです:

cmake_minimum_required(VERSION 3.5...3.27)

これは「3.5以上〜3.27以下で対応」と明記する形です(今のMSYS2ではだいたい3.27〜3.29あたりが入ります)。

furcr@furcraea_built MINGW64 /c/glsl_sample/build
$ make
-bash: make: command not found

なので

🧩 補足:make がないとき

pacman -S make
furcr@furcraea_built MINGW64 ~
$ pacman -S make
resolving dependencies...
looking for conflicting packages...

Packages (1) make-4.4.1-2

Total Download Size:   0.50 MiB
Total Installed Size:  1.61 MiB

:: Proceed with installation? [Y/n]
:: Retrieving packages...
 make-4.4.1-2-x86_64             507.6 KiB   320 KiB/s 00:02 [###############################] 100%
(1/1) checking keys in keyring                               [###############################] 100%
(1/1) checking package integrity                             [###############################] 100%
(1/1) loading package files                                  [###############################] 100%
(1/1) checking for file conflicts                            [###############################] 100%
(1/1) checking available disk space                          [###############################] 100%
:: Processing package changes...
(1/1) installing make                                        [###############################] 100%
:: Running post-transaction hooks...
(1/1) Updating the info directory file...

furcr@furcraea_built MINGW64 ~
$

または MINGW版を使うなら:

pacman -S mingw-w64-x86_64-make

furcr@furcraea_built MINGW64 ~
$ pacman -S mingw-w64-x86_64-make
warning: mingw-w64-x86_64-make-4.4.1-3 is up to date -- reinstalling
resolving dependencies...
looking for conflicting packages...

Packages (1) mingw-w64-x86_64-make-4.4.1-3

Total Installed Size:  0.29 MiB
Net Upgrade Size:      0.00 MiB

:: Proceed with installation? [Y/n]
(1/1) checking keys in keyring                               [###############################] 100%
(1/1) checking package integrity                             [###############################] 100%
(1/1) loading package files                                  [###############################] 100%
(1/1) checking for file conflicts                            [###############################] 100%
(1/1) checking available disk space                          [###############################] 100%
:: Processing package changes...
(1/1) reinstalling mingw-w64-x86_64-make                     [###############################] 100%

furcr@furcraea_built MINGW64 ~
$

その場合、呼び出しは mingw32-make になるかもしれません。

対処法:明示的に Makefile を出させる

🔁 ビルドフォルダをクリア

まず、前回のビルドキャッシュを消します:

cd ..
rm -rf build
mkdir build
cd build

✅ CMakeを正しく実行(MSYS Makefiles 指定)

cmake -G "MSYS Makefiles" ..
furcr@furcraea_built MINGW64 /c/glsl_sample/build
$ cmake -G "MSYS Makefiles" ..
CMake Deprecation Warning at CMakeLists.txt:1 (cmake_minimum_required):
  Compatibility with CMake < 3.10 will be removed from a future version of
  CMake.

  Update the VERSION argument <min> value.  Or, use the <min>...<max> syntax
  to tell CMake that the project requires at least <min> but has been updated
  to work with policies introduced by <max> or earlier.


-- The C compiler identification is GNU 15.1.0
-- The CXX compiler identification is GNU 15.1.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/msys64/mingw64/bin/cc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/msys64/mingw64/bin/c++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found OpenGL: opengl32
-- Configuring done (1.2s)
-- Generating done (0.0s)
-- Build files have been written to: C:/glsl_sample/build

これで Makefile がちゃんと生成されるはずです。

📌 補足:-G オプションとは?

CMakeはデフォルトで “NMake” や “Visual Studio” 用のプロジェクトファイルを生成することがあります。
MSYS2で make を使いたい場合は、必ず -G "MSYS Makefiles" を指定しないと Makefile が生成されません。

🔨 再度ビルド

furcr@furcraea_built MINGW64 /c/glsl_sample/build
$ make
[ 50%] Building C object CMakeFiles/glsl_sample.dir/main.c.obj
[100%] Linking C executable glsl_sample.exe
[100%] Built target glsl_sample

furcr@furcraea_built MINGW64 /c/glsl_sample/build
$

🧪 もしそれでもだめなら

最終手段として、以下で手動ビルドできます:

gcc ../main.c -o glsl_sample.exe -lglfw3 -lglew32 -lopengl32 -lgdi32

✅ 次にやること:実行!

cd ..
./glsl_sample.exe

✅ やり直し

furcr@furcraea_built MINGW64 /c/glsl_sample/build
$ cd ..

furcr@furcraea_built MINGW64 /c/glsl_sample
$ rm -rf build

furcr@furcraea_built MINGW64 /c/glsl_sample
$ mkdir build

furcr@furcraea_built MINGW64 /c/glsl_sample
$ cd build

furcr@furcraea_built MINGW64 /c/glsl_sample/build
$ cmake -G "MSYS Makefiles" ..
CMake Deprecation Warning at CMakeLists.txt:1 (cmake_minimum_required):
  Compatibility with CMake < 3.10 will be removed from a future version of
  CMake.

  Update the VERSION argument <min> value.  Or, use the <min>...<max> syntax
  to tell CMake that the project requires at least <min> but has been updated
  to work with policies introduced by <max> or earlier.


-- The C compiler identification is GNU 15.1.0
-- The CXX compiler identification is GNU 15.1.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/msys64/mingw64/bin/cc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/msys64/mingw64/bin/c++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found OpenGL: opengl32
-- Configuring done (1.2s)
-- Generating done (0.0s)
-- Build files have been written to: C:/glsl_sample/build

furcr@furcraea_built MINGW64 /c/glsl_sample/build
$ make
[ 50%] Building C object CMakeFiles/glsl_sample.dir/main.c.obj
[100%] Linking C executable glsl_sample.exe
[100%] Built target glsl_sample

furcr@furcraea_built MINGW64 /c/glsl_sample/build
$ ./glsl_sample.exe
Failed to open shader.vert

furcr@furcraea_built MINGW64 /c/glsl_sample/build
$

できたああああああ