00001 #include "volprogram.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 std::ifstream in(filename, std::ios::in | std::ios::binary);
00012 in.exceptions(std::ios::failbit | std::ios::badbit);
00013
00014 const long size = in.seekg(0, std::ios::end).tellg();
00015 in.seekg(0, std::ios::beg);
00016
00017 data.clear();
00018 data.resize(size + 1, 0);
00019 in.read(&data[0], size);
00020 }
00021 }
00022
00023 VolProgram::VolProgram(const char *name) :
00024 program_(0), mode_(M_SLICE), recompile_(true), progname_(name)
00025 {
00026 RecompileWhenRequired();
00027 }
00028
00029 GLuint VolProgram::CompileProgram(const char *name, const CompileSettings& settings) const
00030 {
00031 std::vector<char> vs_source;
00032 LoadFile((std::string(name) + ".v_source").c_str(), vs_source);
00033
00034 std::vector<char> fs_source;
00035 LoadFile((std::string(name) + ".f_source").c_str(), fs_source);
00036
00037 std::string defines = "#define RUNTIME_MODE\n";
00038 defines += std::string("#define mode ") + settings.mode + "\n";
00039
00040 const char * dsource = defines.c_str();
00041 const GLchar *vsource[] = { dsource, &vs_source[0] };
00042 const GLchar *fsource[] = { dsource, &fs_source[0] };
00043
00044
00045
00046 struct ShaderResource {
00047 GLuint id;
00048 ShaderResource() :
00049 id(0)
00050 {
00051 }
00052 ~ShaderResource()
00053 {
00054 glDeleteShader(id);
00055 }
00056 };
00057
00058 struct ProgramResource {
00059 GLuint id;
00060 ProgramResource() :
00061 id(0)
00062 {
00063 }
00064 ~ProgramResource()
00065 {
00066 glDeleteProgram(id);
00067 }
00068 };
00069
00070 ShaderResource vs;
00071 vs.id = glCreateShader(GL_VERTEX_SHADER);
00072 if (!vs.id) throw std::runtime_error("glCreateShader failed");
00073 glShaderSource(vs.id, 2, vsource, 0);
00074 glCompileShader(vs.id);
00075 GLint vcompile_status;
00076 glGetShaderiv(vs.id, GL_COMPILE_STATUS, &vcompile_status);
00077
00078 if (vcompile_status != GL_TRUE) throw std::runtime_error("vertex shader compilation failed");
00079
00080 ShaderResource fs;
00081 fs.id = glCreateShader(GL_FRAGMENT_SHADER);
00082 if (!fs.id) throw std::runtime_error("glCreateShader failed");
00083 glShaderSource(fs.id, 2, fsource, 0);
00084 glCompileShader(fs.id);
00085 GLint fcompile_status;
00086 glGetShaderiv(fs.id, GL_COMPILE_STATUS, &fcompile_status);
00087
00088 if (fcompile_status != GL_TRUE) throw std::runtime_error("fragment shader compilation failed");
00089
00090 ProgramResource prog;
00091 prog.id = glCreateProgram();
00092 if (!prog.id) throw std::runtime_error("program creation failed");
00093 glAttachShader(prog.id, vs.id);
00094 glAttachShader(prog.id, fs.id);
00095 glLinkProgram(prog.id);
00096 GLint link_status;
00097 glGetProgramiv(prog.id, GL_LINK_STATUS, &link_status);
00098
00099 if (link_status != GL_TRUE) throw std::runtime_error("program linking failed");
00100
00101 GLuint result = prog.id;
00102
00103
00104 prog.id = 0;
00105
00106 return result;
00107 }
00108
00109 VolProgram::~VolProgram()
00110 {
00111 glDeleteProgram(program_);
00112 }
00113
00114 void VolProgram::SetVolumeTexture(GLuint texture)
00115 {
00116 volume_texture_ = texture;
00117 }
00118
00119 void VolProgram::SetBackAndFrontTextures(GLuint back, GLuint front)
00120 {
00121 back_texture_ = back;
00122 front_texture_ = front;
00123 }
00124
00125 void VolProgram::SetTransferFunctionTexture(GLuint tex)
00126 {
00127 transfer_texture_ = tex;
00128 }
00129
00130 void VolProgram::SetMode(Mode mode)
00131 {
00132 recompile_ = mode_ != mode;
00133 mode_ = mode;
00134 }
00135
00136 void VolProgram::RecompileWhenRequired()
00137 {
00138 if (recompile_) {
00139 recompile_ = false;
00140 CompileSettings settings;
00141
00142 switch (mode_) {
00143 case M_SLICE:
00144 settings.mode = "SLICE_MODE";
00145 break;
00146 case M_3D_COLOR_CUBE:
00147 settings.mode = "COLOR_CUBE_MODE";
00148 break;
00149 case M_3D_RAYCAST:
00150 settings.mode = "RAYCAST_MODE";
00151 break;
00152 }
00153
00154 glDeleteProgram(program_);
00155 program_ = CompileProgram(progname_.c_str(), settings);
00156 }
00157 }
00158
00159 void VolProgram::Use()
00160 {
00161 try {
00162 RecompileWhenRequired();
00163 } catch (...) {
00164 glUseProgram(0);
00165 return;
00166 }
00167
00168 glActiveTexture(GL_TEXTURE3);
00169 glBindTexture(GL_TEXTURE_1D, transfer_texture_);
00170 glActiveTexture(GL_TEXTURE2);
00171 glBindTexture(GL_TEXTURE_2D, back_texture_);
00172 glActiveTexture(GL_TEXTURE1);
00173 glBindTexture(GL_TEXTURE_2D, front_texture_);
00174 glActiveTexture(GL_TEXTURE0);
00175 glBindTexture(GL_TEXTURE_3D, volume_texture_);
00176
00177 glUseProgram(program_);
00178
00179 glUniform1i(glGetUniformLocation(program_, "volume_texture"), 0);
00180 glUniform1i(glGetUniformLocation(program_, "front_texture"), 1);
00181 glUniform1i(glGetUniformLocation(program_, "back_texture"), 2);
00182 glUniform1i(glGetUniformLocation(program_, "transfer_texture"), 3);
00183 }
00184