サンプルです。
本文は、こちらです。
#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;
}
0 件のコメント:
コメントを投稿