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_viewershader.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 Allinclude/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 AllKHR/khrplatform.h
https://glad.dav1d.de/ でとってくる
Language/Generator: C/C++
Specification: gl
APIs: gl=3.3
Profile: core
Extensions:Add Allexternal/glad/src/glad.c
https://glad.dav1d.de/ でとってくる
Language/Generator: C/C++
Specification: gl
APIs: gl=3.3
Profile: core
Extensions:Add Allexternal/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

















