差分
このページの2つのバージョン間の差分を表示します。
| 両方とも前のリビジョン前のリビジョン次のリビジョン | 前のリビジョン | ||
| youtube:opengl-training-005 [2025/12/06 05:02] – Add a link to YouTube freemikan | youtube:opengl-training-005 [2025/12/07 00:55] (現在) – Fix worng boost include directories freemikan | ||
|---|---|---|---|
| 行 1: | 行 1: | ||
| ====== OpenGLの修行 #5 - 続・三角形を描く (1) ====== | ====== OpenGLの修行 #5 - 続・三角形を描く (1) ====== | ||
| - | |||
| {{ https:// | {{ https:// | ||
| + | ===== ソースコード ===== | ||
| {{ : | {{ : | ||
| + | |||
| + | |||
| + | ==== プロジェクトレイアウト ==== | ||
| + | |||
| + | HelloTriangle-simpleshader | ||
| + | ├── .clang-format | ||
| + | ├── CMakeLists.txt | ||
| + | ├── glad | ||
| + | │ ├── CMakeLists.txt | ||
| + | │ ├── include | ||
| + | │ │ ├── KHR | ||
| + | │ │ │ └── khrplatform.h | ||
| + | │ │ └── glad | ||
| + | │ │ | ||
| + | │ └── src | ||
| + | │ | ||
| + | ├── shaders | ||
| + | │ ├── hello_triangle.frag | ||
| + | │ └── hello_triangle.vert | ||
| + | └── src | ||
| + | ├── main.cpp | ||
| + | ├── simpleshader.cpp | ||
| + | └── simpleshader.h | ||
| + | |||
| + | |||
| + | ==== .clang-format ==== | ||
| + | < | ||
| + | BasedOnStyle: | ||
| + | IndentWidth: | ||
| + | PointerAlignment: | ||
| + | AccessModifierOffset: | ||
| + | ConstructorInitializerIndentWidth: | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== CMakeLists.txt ==== | ||
| + | <file cmake> | ||
| + | cmake_minimum_required(VERSION 3.13 FATAL_ERROR) | ||
| + | |||
| + | project(HelloTriangle VERSION 0.1.0 LANGUAGES CXX) | ||
| + | |||
| + | set(CMAKE_CXX_STANDARD 20) | ||
| + | set(CMAKE_CXX_STANDARD_REQUIRED TRUE) | ||
| + | |||
| + | find_package(Boost REQUIRED CONFIG) | ||
| + | |||
| + | include_directories(${Boost_INCLUDE_DIRS}) | ||
| + | |||
| + | find_package(glfw3 REQUIRED) | ||
| + | |||
| + | add_subdirectory(glad) | ||
| + | |||
| + | add_executable( | ||
| + | HelloTriangle | ||
| + | src/ | ||
| + | src/ | ||
| + | ) | ||
| + | |||
| + | target_link_libraries(HelloTriangle PRIVATE glad glfw) | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== glad/ | ||
| + | <file cmake> | ||
| + | enable_language(C) | ||
| + | |||
| + | add_library(glad OBJECT src/glad.c) | ||
| + | |||
| + | target_include_directories( | ||
| + | glad | ||
| + | PUBLIC | ||
| + | ${CMAKE_CURRENT_SOURCE_DIR}/ | ||
| + | ) | ||
| + | </ | ||
| + | |||
| + | |||
| + | === glad/* ==== | ||
| + | [[https:// | ||
| + | |||
| + | |||
| + | ==== shaders/ | ||
| + | |||
| + | <file glsl> | ||
| + | #version 410 core | ||
| + | |||
| + | in vec4 vert_color; | ||
| + | out vec4 color; | ||
| + | |||
| + | void main(void) { | ||
| + | // color = vec4(1.0, 0.0, 0.0, 1.0); | ||
| + | color = vert_color; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ==== shaders/ | ||
| + | |||
| + | <file glsl> | ||
| + | #version 410 core | ||
| + | |||
| + | out vec4 vert_color; | ||
| + | |||
| + | void main(void) { | ||
| + | const float y = sqrt(3.0) / 2.0 / 2.0; | ||
| + | |||
| + | const vec4 vertices[3] = vec4[3](vec4(-0.5, | ||
| + | vec4( 0.5, -y, 1.0, 1.0), | ||
| + | vec4( 0.0, y, 1.0, 1.0)); | ||
| + | gl_Position = vertices[gl_VertexID]; | ||
| + | |||
| + | const vec4 colors[3] = vec4[3](vec4(1.0, | ||
| + | | ||
| + | | ||
| + | vert_color = colors[gl_VertexID]; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== src/ | ||
| + | <file cpp> | ||
| + | #include < | ||
| + | // glad.h must be included before glfw3.h | ||
| + | #include < | ||
| + | |||
| + | #include " | ||
| + | |||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | namespace fs = std:: | ||
| + | using namespace simpleshader; | ||
| + | |||
| + | std:: | ||
| + | auto const vert_path = " | ||
| + | auto const frag_path = " | ||
| + | |||
| + | auto vert_src = read_to_string(vert_path); | ||
| + | if (!vert_src) { | ||
| + | std::cerr << " | ||
| + | return {}; | ||
| + | } | ||
| + | |||
| + | auto frag_src = read_to_string(frag_path); | ||
| + | if (!frag_src) { | ||
| + | std::cerr << " | ||
| + | return {}; | ||
| + | } | ||
| + | |||
| + | ShaderObject vert{GL_VERTEX_SHADER, | ||
| + | if (!vert.ok()) { | ||
| + | print_compilation_errors(vert, | ||
| + | return {}; | ||
| + | } | ||
| + | |||
| + | ShaderObject frag{GL_FRAGMENT_SHADER, | ||
| + | if (!frag.ok()) { | ||
| + | print_compilation_errors(frag, | ||
| + | return {}; | ||
| + | } | ||
| + | |||
| + | ShaderProgram program{vert, | ||
| + | if (!program.ok()) { | ||
| + | print_link_errors(program); | ||
| + | return {}; | ||
| + | } | ||
| + | |||
| + | return program; | ||
| + | } | ||
| + | |||
| + | int main() { | ||
| + | glfwInit(); | ||
| + | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, | ||
| + | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, | ||
| + | glfwWindowHint(GLFW_OPENGL_PROFILE, | ||
| + | glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, | ||
| + | | ||
| + | GLFWwindow *window = glfwCreateWindow(800, | ||
| + | if (!window) { | ||
| + | std::cerr << " | ||
| + | glfwTerminate(); | ||
| + | std:: | ||
| + | } | ||
| + | | ||
| + | glfwMakeContextCurrent(window); | ||
| + | | ||
| + | if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { | ||
| + | std::cerr << " | ||
| + | glfwTerminate(); | ||
| + | std:: | ||
| + | } | ||
| + | | ||
| + | auto const version = glGetString(GL_VERSION); | ||
| + | std::cout << " | ||
| + | | ||
| + | auto shader_program = setup_shaders(); | ||
| + | if (!shader_program) { | ||
| + | std::cerr << " | ||
| + | glfwTerminate(); | ||
| + | std:: | ||
| + | } | ||
| + | | ||
| + | GLuint VAO; | ||
| + | glGenVertexArrays(1, | ||
| + | glBindVertexArray(VAO); | ||
| + | | ||
| + | while (!glfwWindowShouldClose(window)) { | ||
| + | glClearColor(0.0, | ||
| + | glClear(GL_COLOR_BUFFER_BIT); | ||
| + | | ||
| + | glUseProgram(shader_program-> | ||
| + | glDrawArrays(GL_TRIANGLES, | ||
| + | | ||
| + | glfwSwapBuffers(window); | ||
| + | glfwPollEvents(); | ||
| + | } | ||
| + | |||
| + | shader_program-> | ||
| + | |||
| + | glfwTerminate(); | ||
| + | |||
| + | std::clog << " | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== src/ | ||
| + | <file cpp> | ||
| + | #ifndef SIMPLESHADER_H | ||
| + | #define SIMPLESHADER_H | ||
| + | |||
| + | #include < | ||
| + | |||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | namespace simpleshader { | ||
| + | |||
| + | class ShaderObject : boost:: | ||
| + | public: | ||
| + | ShaderObject(GLenum type, std::string const &src); | ||
| + | ~ShaderObject(); | ||
| + | ShaderObject(ShaderObject && | ||
| + | ShaderObject & | ||
| + | |||
| + | bool ok() const; | ||
| + | GLuint name() const; | ||
| + | |||
| + | private: | ||
| + | GLenum type_; | ||
| + | GLuint name_; | ||
| + | }; | ||
| + | |||
| + | class ShaderProgram : boost:: | ||
| + | public: | ||
| + | ShaderProgram(ShaderObject const &vert, ShaderObject const &frag); | ||
| + | ~ShaderProgram(); | ||
| + | ShaderProgram(ShaderProgram && | ||
| + | ShaderProgram & | ||
| + | |||
| + | bool ok() const; | ||
| + | GLuint name() const; | ||
| + | void clear(); | ||
| + | |||
| + | private: | ||
| + | GLuint name_; | ||
| + | }; | ||
| + | |||
| + | std:: | ||
| + | |||
| + | void print_compilation_errors(ShaderObject const & | ||
| + | |||
| + | void print_link_errors(ShaderProgram const & | ||
| + | |||
| + | } // namespace simpleshader | ||
| + | |||
| + | #endif | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== src/ | ||
| + | <file cpp> | ||
| + | #include " | ||
| + | |||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | namespace fs = std:: | ||
| + | |||
| + | namespace /*anon*/ { | ||
| + | |||
| + | bool compile_shader(GLuint name, GLchar const *src) { | ||
| + | GLchar const *src_arr[] = {src}; | ||
| + | glShaderSource(name, | ||
| + | glCompileShader(name); | ||
| + | |||
| + | GLint success; | ||
| + | glGetShaderiv(name, | ||
| + | return success; | ||
| + | } | ||
| + | |||
| + | bool link_shaders(GLuint program, GLuint vert, GLuint frag) { | ||
| + | glAttachShader(program, | ||
| + | glAttachShader(program, | ||
| + | |||
| + | glLinkProgram(program); | ||
| + | |||
| + | glDetachShader(program, | ||
| + | glDetachShader(program, | ||
| + | |||
| + | GLint success; | ||
| + | glGetProgramiv(program, | ||
| + | return success; | ||
| + | } | ||
| + | |||
| + | } // namespace | ||
| + | |||
| + | namespace simpleshader { | ||
| + | |||
| + | std:: | ||
| + | if (std:: | ||
| + | return std:: | ||
| + | } else { | ||
| + | return std:: | ||
| + | } | ||
| + | } | ||
| + | |||
| + | void print_compilation_errors(ShaderObject const & | ||
| + | fs::path const &path) { | ||
| + | GLint log_length; | ||
| + | glGetShaderiv(shader.name(), | ||
| + | if (log_length > 0) { | ||
| + | std:: | ||
| + | glGetShaderInfoLog(shader.name(), | ||
| + | std::cerr << path.string() << ':' | ||
| + | } | ||
| + | } | ||
| + | |||
| + | void print_link_errors(ShaderProgram const & | ||
| + | GLint log_length; | ||
| + | glGetProgramiv(program.name(), | ||
| + | if (log_length > 0) { | ||
| + | std:: | ||
| + | glGetProgramInfoLog(program.name(), | ||
| + | std::cerr << log.data() << ' | ||
| + | } | ||
| + | } | ||
| + | |||
| + | ShaderObject:: | ||
| + | : type_{type}, | ||
| + | name_ = glCreateShader(type_); | ||
| + | compile_shader(name_, | ||
| + | } | ||
| + | |||
| + | ShaderObject:: | ||
| + | glDeleteShader(name_); | ||
| + | } | ||
| + | |||
| + | ShaderObject:: | ||
| + | : type_{other.type_}, | ||
| + | type_ = 0; // nothing? | ||
| + | name_ = 0; | ||
| + | } | ||
| + | |||
| + | ShaderObject & | ||
| + | using std::swap; | ||
| + | swap(type_, other.type_); | ||
| + | swap(name_, other.name_); | ||
| + | return *this; | ||
| + | } | ||
| + | |||
| + | bool ShaderObject:: | ||
| + | GLint success; | ||
| + | glGetShaderiv(name_, | ||
| + | return success; | ||
| + | } | ||
| + | |||
| + | GLuint ShaderObject:: | ||
| + | return name_; | ||
| + | } | ||
| + | |||
| + | ShaderProgram:: | ||
| + | : name_{} { | ||
| + | name_ = glCreateProgram(); | ||
| + | link_shaders(name_, | ||
| + | } | ||
| + | |||
| + | ShaderProgram:: | ||
| + | glDeleteProgram(name_); | ||
| + | } | ||
| + | |||
| + | ShaderProgram:: | ||
| + | : name_{other.name_} { | ||
| + | other.name_ = 0; | ||
| + | } | ||
| + | |||
| + | ShaderProgram & | ||
| + | using std::swap; | ||
| + | swap(name_, other.name_); | ||
| + | return *this; | ||
| + | } | ||
| + | |||
| + | bool ShaderProgram:: | ||
| + | GLint success; | ||
| + | glGetProgramiv(name_, | ||
| + | return success; | ||
| + | } | ||
| + | |||
| + | GLuint ShaderProgram:: | ||
| + | return name_; | ||
| + | } | ||
| + | |||
| + | void ShaderProgram:: | ||
| + | glDeleteProgram(name_); | ||
| + | name_ = 0; | ||
| + | } | ||
| + | |||
| + | } // namespace simpleshader | ||
| + | </ | ||
