2013年6月23日日曜日

サンプルコード1

以前の記事のソースコードです。
一つのファイルでコンパイルできるようになっています。

#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 件のコメント:

コメントを投稿