サンプルです。
本文は、こちらです。
#include <memory> #include <fstream> #include <sstream> #include <iostream> #include <string> #include <GL/glew.h> #define NO_SDL_GLEXT #include <SDL2/SDL.h> //OpenGL用の行列変換ライブラリ #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #pragma comment(lib,"SDL2.lib") #pragma comment(lib,"SDL2main.lib") #pragma comment(lib,"opengl32.lib") #pragma comment(lib,"glu32.lib") #pragma comment(lib,"glew32.lib") namespace sample4 { class Cube { public: typedef std::shared_ptr<Cube> Ptr; Cube(GLfloat size) { GLfloat low = -size/2.0f; GLfloat high = size/2.0f; GLfloat vertices[3*8] = { low, low, low, low, high, low, high, high, low, high, low, low, low, low, high, low, high, high, high, high, high, high, low, high }; float colors[3*8] = { 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f }; GLuint indecise[6*6] = { 0, 1, 2, 2, 3, 0, 4, 7, 6, 6, 5, 4, 0, 4, 5, 5, 1, 0, 3, 2, 6, 6, 7, 3, 1, 5, 6, 6, 2, 1, 0, 3, 7, 7, 4, 0 }; //VAO(バッファデータ・設定群)の生成 glGenVertexArrays(1, &vertex_array_object_); //現在のVAOに設定 glBindVertexArray(vertex_array_object_); //VBO(バッファ)の生成 glGenBuffers(1, &vertex_buffer_object_); //現在のバッファに設定 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object_); //現在のバッファにデータを送信 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); //データ型の設定(float * 3) //glVertexPointer(3, GL_FLOAT, 0, 0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr); glEnableVertexAttribArray(0); //インデックスの設定 glGenBuffers(1, &index_buffer_object_); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_object_); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indecise), indecise, GL_STATIC_DRAW); //カラーバッファの生成 glGenBuffers(1, &color_buffer_object_); glBindBuffer(GL_ARRAY_BUFFER, color_buffer_object_); glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, nullptr); glEnableVertexAttribArray(1); //VAO設定を終了する glBindVertexArray(0); } ~Cube() { glDeleteBuffers(1, &index_buffer_object_); glDeleteBuffers(1, &vertex_buffer_object_); glDeleteVertexArrays(1, &vertex_array_object_); } void Draw() { glBindVertexArray(vertex_array_object_); glDrawElements(GL_TRIANGLES, 6*6, GL_UNSIGNED_INT, nullptr); glBindVertexArray(0); } private: GLuint vertex_array_object_; GLuint vertex_buffer_object_; GLuint index_buffer_object_; GLuint color_buffer_object_; }; class Effect { public: typedef std::shared_ptr<Effect> Ptr; Effect(const std::string& vertex_shader_file, const std::string& fragment_shader_file) { Init(vertex_shader_file,fragment_shader_file); } ~Effect() { //各シェーダの利用を終了 glDetachShader(shader_id_, vertex_shader_id_); glDetachShader(shader_id_, fragment_shader_id_); //シェーダの破棄 glDeleteShader(vertex_shader_id_); glDeleteShader(fragment_shader_id_); //シェーダプログラムの削除 glDeleteProgram(shader_id_); } //シェーダの利用を開始する void Begin() { glUseProgram(shader_id_); } //シェーダの利用を終了する void End() { glUseProgram(0); } //プログラムIDの取得 GLuint shader_id()const {return shader_id_;} private: void Init(const std::string& vertex_shader_file, const std::string& fragment_shader_file) { if (vertex_shader_file.empty() || fragment_shader_file.empty()) { return; } //頂点シェーダの生成 vertex_shader_id_ = glCreateShader(GL_VERTEX_SHADER); //フラグメントシェーダの生成 fragment_shader_id_ = glCreateShader(GL_FRAGMENT_SHADER); //ソースコードの読み込み std::string vertex_source = ReadFile(vertex_shader_file); std::string fragment_source = ReadFile(fragment_shader_file); const char* v_source = vertex_source.c_str(); const char* f_source = fragment_source.c_str(); if (vertex_source.empty() || fragment_source.empty()) { return; } //シェーダとソースをバインド glShaderSource(vertex_shader_id_, 1, &v_source, 0); glShaderSource(fragment_shader_id_, 1, &f_source, 0); //シェーダをコンパイル glCompileShader(vertex_shader_id_); glCompileShader(fragment_shader_id_); //シェーダプログラムの生成 shader_id_ = glCreateProgram(); //利用するシェーダを登録 glAttachShader(shader_id_, vertex_shader_id_); glAttachShader(shader_id_, fragment_shader_id_); //シェーダの入力変数のメモリ位置を指定 glBindAttribLocation(shader_id_, 0, "vertex"); //各シェーダの接続 glLinkProgram(shader_id_); } std::string ReadFile(const std::string& filename) { std::ifstream ifs(filename, std::ios::in); if(!ifs)return nullptr; std::istreambuf_iterator<char> ifs_begin(ifs); std::istreambuf_iterator<char> ifs_end; std::string file_string(ifs_begin,ifs_end); return file_string; } GLuint shader_id_; GLuint vertex_shader_id_; GLuint fragment_shader_id_; }; class Sample4 { public: Sample4() { window_ = nullptr; } ~Sample4() { UnInit(); } bool Run() { if (!Init()) return false; if (!InitRenderObjects()) return false; while (PollEvent()) { Render(); } return true; } private: bool Init() { //SDLの初期化 if (SDL_Init(SDL_INIT_VIDEO) < 0) { std::cerr << "Init video failed.\n"; return false; } //利用するOpenGLのバージョンを設定 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); //深度バッファの設定 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); //ダブルバッファの設定 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); //ウィンドウの生成 const int WINDOW_X = 100; const int WINDOW_Y = 100; const int WINDOW_WIDTH = 800; const int WINDOW_HEIGHT = 600; window_ = SDL_CreateWindow( "sample", WINDOW_X, WINDOW_Y, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN); if(window_ == nullptr) { std::cerr << "CreateWindow failed.\n"; return false; } //OpenGLコンテキストの生成 gl_context_ = SDL_GL_CreateContext(window_); //描画を同期 SDL_GL_SetSwapInterval(1); //GLEW(OpenGL拡張)の初期化 if (glewInit() != GLEW_OK) { std::cout << "Init GLEW failed.\n"; return false; } glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); return true; } void UnInit() { SDL_Quit(); } bool PollEvent() { SDL_Event ev; while (SDL_PollEvent(&ev)) { if (ev.type == SDL_QUIT) return false; if (ev.type == SDL_KEYDOWN && ev.key.keysym.sym == SDLK_F4 && (ev.key.keysym.mod & KMOD_ALT) != 0) { return false; } } return true; } bool InitRenderObjects() { shader_ = Effect::Ptr(new Effect("shader.vs","shader.ps")); cube_ = Cube::Ptr(new Cube(1.0f)); //透視投影変換行列を計算 projection_matrix_ = glm::perspective( 60.0f, static_cast<GLfloat>(800)/static_cast<GLfloat>(600), 1.0f, 100.0f); //ビュー行列を計算 view_matrix_ = glm::lookAt( glm::vec3(0.0f, 0.0f, -5.0f), glm::vec3(0.0f), glm::vec3(0.0f, 1.0f, 0.0f)); //glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -5.0f)); //モデル行列を計算 model_matrix_= glm::scale(glm::mat4(1.0f), glm::vec3(0.5f)); //シェーダ変数と関連付けるために //シェーダ変数のメモリ位置を取得する projection_location_ = glGetUniformLocation(shader_->shader_id(), "projection_matrix"); view_location_ = glGetUniformLocation(shader_->shader_id(), "view_matrix"); model_location_ = glGetUniformLocation(shader_->shader_id(), "model_matrix"); return true; } void Render() { //画面のクリア glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //シェーダ開始 shader_->Begin(); view_matrix_ = glm::rotate(view_matrix_, 0.05f, glm::vec3(0.f, 1.f, 0.f)); view_matrix_ = glm::rotate(view_matrix_, 0.05f, glm::vec3(1.f, 0.f, 0.f)); //シェーダへデータを送る glUniformMatrix4fv(projection_location_, 1, GL_FALSE, &projection_matrix_[0][0]); glUniformMatrix4fv(view_location_ , 1, GL_FALSE, &view_matrix_[0][0]); glUniformMatrix4fv(model_location_ , 1, GL_FALSE, &model_matrix_[0][0]); //図形の描画 cube_->Draw(); //シェーダ終了 shader_->End(); //画面を表示 SDL_GL_SwapWindow(window_); } SDL_Window* window_; SDL_GLContext gl_context_; Effect::Ptr shader_; Cube::Ptr cube_; glm::mat4 projection_matrix_; glm::mat4 view_matrix_; glm::mat4 model_matrix_; int projection_location_; int view_location_; int model_location_; }; } int main(int argc, char* argv[]) { sample4::Sample4 sample; sample.Run(); return 0; }