00001 #include "flowvis_program.h"
00002 #include <vector>
00003 #include <fstream>
00004 #include <stdexcept>
00005 #include <string>
00006
00007 namespace
00008 {
00009 void LoadFile(const char *filename, std::vector<char> &data)
00010 {
00011 try
00012 {
00013 std::ifstream in((std::string("shader/") + std::string(filename)).c_str(), std::ios::in | std::ios::binary);
00014 in.exceptions(std::ios::failbit | std::ios::badbit);
00015
00016 const long size = in.seekg(0, std::ios::end).tellg();
00017 in.seekg(0, std::ios::beg);
00018
00019 data.clear();
00020 data.resize(size + 1, 0);
00021 in.read(&data[0], size);
00022 }catch(...)
00023 {
00024 throw std::runtime_error((std::string("File loading failed for: ") + std::string(filename)).c_str());
00025 }
00026 }
00027 }
00028
00029 FlowVisProgram::FlowVisProgram(const char *name)
00030 : program_(0)
00031 , recompile_(true)
00032 , progname_(name)
00033 , m_mode(M_BG_INTER)
00034 {
00035 RecompileWhenRequired();
00036 }
00037
00038 GLuint FlowVisProgram::CompileProgram(const char *name) const
00039 {
00040 std::vector<char> vs_source;
00041 LoadFile((std::string(name) + ".v_source").c_str(), vs_source);
00042
00043 std::vector<char> fs_source;
00044 LoadFile((std::string(name) + ".f_source").c_str(), fs_source);
00045
00046 std::string defines = "#define RUNTIME_MODE\n";
00047
00048 switch (m_mode)
00049 {
00050 case M_BG_INTER:
00051 defines += std::string("#define mode M_BG_INTER\n");
00052 break;
00053 case M_TEXTURE_ROTATION:
00054 defines += std::string("#define mode M_TEXROT\n");
00055 break;
00056 default:
00057 defines += std::string("#define mode M_TEXTURE_ROTATION\n");
00058 break;
00059 }
00060
00061
00062 const char * dsource = defines.c_str();
00063 const GLchar *vsource[] = { dsource, &vs_source[0] };
00064 const GLchar *fsource[] = { dsource, &fs_source[0] };
00065
00066
00067
00068 struct ShaderResource {
00069 GLuint id;
00070 ShaderResource() :
00071 id(0)
00072 {
00073 }
00074 ~ShaderResource()
00075 {
00076 glDeleteShader(id);
00077 }
00078 };
00079
00080 struct ProgramResource {
00081 GLuint id;
00082 ProgramResource() :
00083 id(0)
00084 {
00085 }
00086 ~ProgramResource()
00087 {
00088 glDeleteProgram(id);
00089 }
00090 };
00091
00092 ShaderResource vs;
00093 vs.id = glCreateShader(GL_VERTEX_SHADER);
00094 if (!vs.id) throw std::runtime_error("Shader creation failed for vertex shader!");
00095 glShaderSource(vs.id, 2, vsource, 0);
00096 glCompileShader(vs.id);
00097 GLint vcompile_status;
00098 glGetShaderiv(vs.id, GL_COMPILE_STATUS, &vcompile_status);
00099
00100 if (vcompile_status != GL_TRUE) throw std::runtime_error("Vertex shader compilation failed!");
00101
00102 ShaderResource fs;
00103 fs.id = glCreateShader(GL_FRAGMENT_SHADER);
00104 if (!fs.id) throw std::runtime_error("Shader creation failed for fragment shader!");
00105 glShaderSource(fs.id, 2, fsource, 0);
00106 glCompileShader(fs.id);
00107 GLint fcompile_status;
00108 glGetShaderiv(fs.id, GL_COMPILE_STATUS, &fcompile_status);
00109
00110 if (fcompile_status != GL_TRUE) throw std::runtime_error("Fragment shader compilation failed!");
00111
00112 ProgramResource prog;
00113 prog.id = glCreateProgram();
00114 if (!prog.id) throw std::runtime_error("Shader program creation failed!");
00115 glAttachShader(prog.id, vs.id);
00116 glAttachShader(prog.id, fs.id);
00117 glLinkProgram(prog.id);
00118 GLint link_status;
00119 glGetProgramiv(prog.id, GL_LINK_STATUS, &link_status);
00120
00121 if (link_status != GL_TRUE) throw std::runtime_error("Shader program linking failed!");
00122
00123 GLuint result = prog.id;
00124
00125
00126 prog.id = 0;
00127
00128 return result;
00129 }
00130
00131 FlowVisProgram::~FlowVisProgram()
00132 {
00133 glDeleteProgram(program_);
00134 }
00135
00136 void FlowVisProgram::RecompileWhenRequired()
00137 {
00138 if (recompile_) {
00139 recompile_ = false;
00140
00141 if(program_) glDeleteProgram(program_);
00142 program_ = CompileProgram(progname_.c_str());
00143 }
00144 }
00145
00146 void FlowVisProgram::Use()
00147 {
00148 Prepare();
00149 Start();
00150 }
00151
00152 void FlowVisProgram::Prepare()
00153 {
00154 try {
00155 RecompileWhenRequired();
00156 } catch (...) {
00157 glUseProgram(0);
00158 return;
00159 }
00160
00161 glActiveTexture(GL_TEXTURE2);
00162 glBindTexture(GL_TEXTURE_2D, m_glyph_texture_);
00163 glActiveTexture(GL_TEXTURE1);
00164 glBindTexture(GL_TEXTURE_1D, m_transfer_texture_);
00165 glActiveTexture(GL_TEXTURE0);
00166 glBindTexture(GL_TEXTURE_2D, m_bgdata_texture_);
00167 }
00168
00169 void FlowVisProgram::Start()
00170 {
00171 glUseProgram(program_);
00172
00173 glUniform1i(glGetUniformLocation(program_, "bgdata_texture"), 0);
00174 glUniform1i(glGetUniformLocation(program_, "transfer_texture"), 1);
00175 glUniform1i(glGetUniformLocation(program_, "glyph_texture"), 2);
00176 }
00177
00178 void FlowVisProgram::Stop()
00179 {
00180 glUseProgram(0);
00181 }
00182
00183 void FlowVisProgram::SetBGDataTexture(GLuint tex)
00184 {
00185 m_bgdata_texture_ = tex;
00186 }
00187
00188 void FlowVisProgram::SetVelocityTexture(GLuint tex)
00189 {
00190 m_velocity_texture_ = tex;
00191 }
00192
00193 void FlowVisProgram::SetTransferFunctionTexture(GLuint tex)
00194 {
00195 m_transfer_texture_ = tex;
00196 }
00197
00198 void FlowVisProgram::SetMode(Mode new_mode)
00199 {
00200 recompile_ = m_mode != new_mode;
00201 m_mode = new_mode;
00202 }
00203
00204 void FlowVisProgram::SetArrowTexture(GLuint tex)
00205 {
00206 m_arrow_texture_ = tex;
00207 }
00208
00209 void FlowVisProgram::SetGlyphTexture(GLuint tex)
00210 {
00211 m_glyph_texture_ = tex;
00212 }