一つのファイルでコンパイルできるようになっています。
#include <memory>
#include <fstream>
#include <sstream>
#include <iostream>
#include <GL/glew.h>
#define NO_SDL_GLEXT
#include <SDL2/SDL.h>
#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 sample1 {
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_);
//各シェーダの接続
glLinkProgram(shader_id_);
}
std::string ReadFile(const std::string& filename) {
std::ifstream ifs(filename);
if(ifs.is_open())return nullptr;
std::istreambuf_iterator ifs_begin(ifs);
std::istreambuf_iterator 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 Sample1 {
public:
Sample1() {
window_ = nullptr;
}
~Sample1() {
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;
}
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"));
return true;
}
void Render() {
//画面の消去
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//シェーダの利用を開始する
glUseProgram(shader_id_);
//ここに描画処理
//シェーダの利用を終了する
glUseProgram(0);
//画面に描画する
SDL_GL_SwapWindow(window_);
}
SDL_Window* window_;
SDL_GLContext gl_context_;
Effect::Ptr shader_;
};
}
int main(int argc, char* argv[]) {
sample1::Sample1 sample;
sample.Run();
return 0;
}
0 件のコメント:
コメントを投稿