00001
00002
00003
00004
00005 #include "gtex/gl_extensions.H"
00006 #include "gtex/util.H"
00007 #include "geom/gl_util.H"
00008 #include "mesh/patch.H"
00009 #include "paper_effect.H"
00010 #include "glsl_shader.H"
00011
00012 using namespace mlib;
00013
00014 static bool debug = Config::get_var_bool("DEBUG_GLSL_SHADER", false);
00015
00016
00017
00018 static bool need_arb_ext = false;
00019
00020 GLSLShader::GLSLShader(Patch* p, StripCB* cb) :
00021 BasicTexture(p, cb ? cb : new VertNormStripCB),
00022 _program(0),
00023 _did_init(false)
00024 {
00025 }
00026
00027 GLSLShader::~GLSLShader()
00028 {
00029 delete_program(_program);
00030 }
00031
00032 void
00033 GLSLShader::delete_program(GLuint& prog)
00034 {
00035 if (prog == 0)
00036 return;
00037 if (need_arb_ext) {
00038 glDeleteObjectARB(prog);
00039 } else {
00040 glDeleteProgram(prog);
00041 }
00042 prog = 0;
00043 }
00044
00045 void
00046 GLSLShader::print_shader_source(GLuint shader)
00047 {
00048 GLint src_len = 0;
00049 glGetObjectParameterivARB(shader, GL_OBJECT_SHADER_SOURCE_LENGTH_ARB,
00050 &src_len);
00051 if (src_len < 1) {
00052 cerr << " source length is 0" << endl;
00053 return;
00054 }
00055 GLcharARB* buf = new GLcharARB [ src_len ];
00056 GLint chars_written = 0;
00057 glGetShaderSourceARB(shader, src_len, &chars_written, buf);
00058 cerr << buf << endl;
00059 }
00060
00061 void
00062 GLSLShader::print_info(Cstr_ptr& gtex_name, GLuint obj)
00063 {
00064 cerr << gtex_name << ": print_info: checking object " << obj << endl;
00065 GLint log_len = 0;
00066 GL_VIEW::print_gl_errors(gtex_name + "::print_info:");
00067 glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &log_len);
00068 if (log_len < 1) {
00069 cerr << " print_info: log length is 0" << endl;
00070 return;
00071 }
00072 GLcharARB* buf = new GLcharARB [ log_len ];
00073 GLint chars_written = 0;
00074 glGetInfoLogARB(obj, log_len, &chars_written, buf);
00075 cerr << "info log: " << endl
00076 << buf << endl;
00077 delete buf;
00078 }
00079
00080 bool
00081 GLSLShader::link_program(Cstr_ptr& gtex_name, GLuint prog)
00082 {
00083 GLint status = 0;
00084 if (need_arb_ext) {
00085 glLinkProgramARB(prog);
00086 glGetObjectParameterivARB(prog, GL_OBJECT_LINK_STATUS_ARB, &status);
00087 } else {
00088 glLinkProgram(prog);
00089 glGetProgramiv(prog, GL_LINK_STATUS, &status);
00090 }
00091 if (status != GL_TRUE)
00092 cerr << gtex_name << ": link_program: link failed" << endl;
00093
00094
00095 const GLsizei BUF_SIZE = 4096;
00096 char info_log[BUF_SIZE] = {0};
00097 GLsizei len=0;
00098 if (need_arb_ext) {
00099
00100 } else {
00101 glGetProgramInfoLog(prog, BUF_SIZE, &len, info_log);
00102 }
00103 cerr << gtex_name
00104 << ": ProgramInfoLog: "
00105 << endl
00106 << info_log
00107 << endl;
00108
00109 if (debug && need_arb_ext) {
00110 glValidateProgramARB(prog);
00111 GLint ret = 0;
00112 glGetObjectParameterivARB(prog, GL_OBJECT_VALIDATE_STATUS_ARB, &ret);
00113 cerr << "program " << prog
00114 << " validation status: " << ret << endl;
00115 print_info(gtex_name, prog);
00116 }
00117 return (status == GL_TRUE);
00118 }
00119
00120 bool
00121 GLSLShader::compile_shader(Cstr_ptr& gtex_name, GLuint shader)
00122 {
00123 GLint status = 0;
00124 if (need_arb_ext) {
00125 glCompileShaderARB(shader);
00126 glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &status);
00127 if (debug)
00128 print_info(gtex_name, shader);
00129 } else {
00130 glCompileShader(shader);
00131 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
00132 }
00133 return (status == GL_TRUE);
00134 }
00135
00136 char*
00137 GLSLShader::read_file(
00138 Cstr_ptr& gtex_name,
00139 Cstr_ptr& filename,
00140 GLint& length
00141 )
00142 {
00143
00144 char* buf = 0;
00145 ifstream in(**filename, ifstream::in | ifstream::binary);
00146 if (in.is_open()) {
00147 in.seekg(0, ios::end);
00148 length = in.tellg();
00149 buf = new char[length + 1];
00150 memset(buf, 0, length + 1);
00151 in.seekg(0, ios::beg);
00152 in.read(buf, length);
00153 in.close();
00154 } else {
00155 cerr << gtex_name << "::read_file: could not read file: "
00156 << filename
00157 << endl;
00158 }
00159 return buf;
00160 }
00161
00162 void
00163 GLSLShader::delete_shader(GLuint shader)
00164 {
00165 if (need_arb_ext) {
00166 glDeleteObjectARB(shader);
00167 } else {
00168 glDeleteShader(shader);
00169 }
00170 }
00171
00172 void
00173 GLSLShader::delete_shaders(CARRAY<GLuint>& shaders)
00174 {
00175 for (int i=0; i<shaders.num(); i++)
00176 delete_shader(shaders[i]);
00177 }
00178
00179 GLuint
00180 GLSLShader::load_shader(Cstr_ptr& gtex_name, Cstr_ptr& filename, GLenum type)
00181 {
00182
00183 GLint length = 0;
00184 char* buf = read_file(gtex_name, filename, length);
00185 if (!buf)
00186 return 0;
00187
00188
00189 GLuint shader = 0;
00190 if (need_arb_ext) {
00191 shader = glCreateShaderObjectARB(type);
00192 glShaderSourceARB(shader, 1, (const GLcharARB**)&buf, &length);
00193 } else {
00194 shader = glCreateShader(type);
00195 glShaderSource(shader, 1, (const GLchar**)&buf, &length);
00196 }
00197 delete [] buf;
00198 if (compile_shader(gtex_name, shader)) {
00199 if (debug) {
00200 const GLsizei BUF_SIZE = 4096;
00201 char info_log[BUF_SIZE] = {0};
00202 GLsizei len;
00203 if (need_arb_ext) {
00204 glGetInfoLogARB(shader, BUF_SIZE, &len, info_log);
00205 } else {
00206 glGetShaderInfoLog(shader, BUF_SIZE, &len, info_log);
00207 }
00208 cerr << gtex_name
00209 << "ShaderInfoLog for shader: "
00210 << filename
00211 << endl
00212 << info_log
00213 << endl;
00214 }
00215 return shader;
00216 }
00217
00218
00219 cerr << gtex_name
00220 << "::load_shader: compile failed for file: "
00221 << filename
00222 << endl;
00223
00224
00225 const GLsizei BUF_SIZE = 4096;
00226 char info_log[BUF_SIZE] = {0};
00227 GLsizei len=0;
00228 if (need_arb_ext) {
00229 glGetInfoLogARB(shader, BUF_SIZE, &len, info_log);
00230 } else {
00231 glGetShaderInfoLog(shader, BUF_SIZE, &len, info_log);
00232 }
00233 cerr << gtex_name << ": ShaderInfoLog: "
00234 << endl
00235 << info_log
00236 << endl;
00237
00238 delete_shader(shader);
00239 return 0;
00240 }
00241
00242 bool
00243 GLSLShader::load_shaders(
00244 Cstr_ptr& gtex_name,
00245 Cstr_list& filenames,
00246 ARRAY<GLuint>& shaders,
00247 GLenum type)
00248 {
00249 for (int i=0; i<filenames.num(); i++) {
00250 GLuint shader = load_shader(gtex_name, filenames[i], type);
00251 if (shader == 0) {
00252 cerr << gtex_name
00253 << "::load_shaders: failed to load file: "
00254 << filenames[i]
00255 << endl;
00256
00257 delete_shaders(shaders);
00258 return false;
00259 }
00260 if (debug && need_arb_ext) {
00261 cerr << gtex_name
00262 << ": print_shader_source: checking shader " << shader << endl;
00263
00264 print_shader_source(shader);
00265 }
00266 shaders += shader;
00267 }
00268
00269 return true;
00270 }
00271
00272 bool
00273 GLSLShader::attach_shaders(CARRAY<GLuint>& shaders, GLuint prog)
00274 {
00275 if (need_arb_ext) {
00276 for (int i=0; i<shaders.num(); i++)
00277 glAttachObjectARB(prog, shaders[i]);
00278 } else {
00279 for (int i=0; i<shaders.num(); i++)
00280 glAttachShader(prog, shaders[i]);
00281 }
00282 return true;
00283 }
00284
00285 bool
00286 GLSLShader::init()
00287 {
00288
00289 if (did_init())
00290 return program() != 0;
00291 did_init() = true;
00292
00293 if (GLEW_VERSION_2_0) {
00294
00295 if (debug) cerr << class_name() << "::init: OpenGL 2.0" << endl;
00296 } else if (GLEW_VERSION_1_5) {
00297
00298 need_arb_ext = true;
00299 if (debug) cerr << class_name() << "::init: OpenGL 1.5" << endl;
00300 } else {
00301
00302 if (debug) cerr << class_name()
00303 << "::init: pre-OpenGL 1.5: can't do GLSL" << endl;
00304 return false;
00305 }
00306
00307
00308 if (need_arb_ext) {
00309 program() = glCreateProgramObjectARB();
00310 } else {
00311 GL_VIEW::print_gl_errors("GLSLShader::init");
00312 program() = glCreateProgram();
00313 }
00314
00315 if (!program()) {
00316
00317 cerr << class_name() << "::init: error: glCreateProgram failed" << endl;
00318 return false;
00319 }
00320
00321
00322
00323 ARRAY<GLuint> shaders;
00324 GLenum vp, fp;
00325 if (need_arb_ext) {
00326 vp = GL_VERTEX_SHADER_ARB;
00327 fp = GL_FRAGMENT_SHADER_ARB;
00328 } else {
00329 vp = GL_VERTEX_SHADER;
00330 fp = GL_FRAGMENT_SHADER;
00331 }
00332
00333 if (load_shaders(class_name(), vp_filenames(), shaders, vp) &&
00334 load_shaders(class_name(), fp_filenames(), shaders, fp) &&
00335 attach_shaders(shaders, program()) && bind_attributes(program()) &&
00336 link_program(class_name(), program())) {
00337
00338
00339 activate_program();
00340 if (!get_variable_locs()) {
00341
00342
00343
00344 cerr << class_name()
00345 << "::init: error: can't get variable locations." << endl
00346 << "This error might mean a variable is simply not used " << endl
00347 << "in your program, and otherwise nothing is actually wrong"
00348 << endl;
00349 }
00350 deactivate_program();
00351
00352
00353 if (debug)
00354 cerr << class_name() << "::init: loaded program" << endl;
00355 return true;
00356 }
00357
00358
00359 cerr << class_name() << "::init: could not load program" << endl;
00360 delete_program(program());
00361
00362 return false;
00363 }
00364
00365 void
00366 GLSLShader::use_program(GLuint prog)
00367 {
00368 if (need_arb_ext) {
00369 glUseProgramObjectARB(prog);
00370 } else {
00371 glUseProgram(prog);
00372 }
00373 }
00374
00375 bool
00376 GLSLShader::get_uniform_loc(Cstr_ptr& var_name, GLint& loc)
00377 {
00378
00379
00380 loc = glGetUniformLocation(program(), **var_name);
00381 if (loc < 0) {
00382 cerr << class_name() << "::get_uniform_loc: error: variable "
00383 << "\"" << var_name << "\" not found"
00384 << endl;
00385 return false;
00386 }
00387 return true;
00388 }
00389
00390 bool
00391 GLSLShader::load_texture(TEXTUREglptr& tex)
00392 {
00393
00394
00395
00396
00397
00398
00399
00400 if (!tex) {
00401 return false;
00402 } else if (tex->is_valid()) {
00403 return true;
00404 } else if (tex->load_attempt_failed()) {
00405
00406
00407 return false;
00408 }
00409
00410 return tex->load_texture();
00411 }
00412
00413 bool
00414 GLSLShader::activate_texture(TEXTUREglptr& tex)
00415 {
00416
00417
00418 if (!load_texture(tex))
00419 return false;
00420 tex->apply_texture();
00421
00422 return true;
00423 }
00424
00425 void
00426 GLSLShader::set_gl_state(GLbitfield mask) const
00427 {
00428
00429 glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | mask);
00430
00431 set_face_culling();
00432
00433
00434 if (_patch)
00435 GL_COL(_patch->color(), alpha());
00436 }
00437
00438 void
00439 GLSLShader::restore_gl_state() const
00440 {
00441 glPopAttrib();
00442 }
00443
00444 void
00445 GLSLShader::set_ref_tex_shader()
00446 {
00447 _tex_ref_shader=0;
00448 }
00449
00450
00451 void
00452 GLSLShader::use_ref_tex_shader()
00453 {
00454
00455 }
00456
00457 int
00458 GLSLShader::draw(CVIEWptr& v)
00459 {
00460 GL_VIEW::print_gl_errors(class_name() + "::draw: start");
00461
00462
00463 if (!init())
00464 return 0;
00465 assert(program());
00466
00467
00468
00469
00470
00471
00472
00473
00474 init_textures();
00475 if (debug)
00476 GL_VIEW::print_gl_errors(class_name() + "::draw: init textures");
00477
00478
00479 set_gl_state();
00480 if (debug)
00481 GL_VIEW::print_gl_errors(class_name() + "::draw: push attrib");
00482
00483
00484 activate_textures();
00485 if (debug)
00486 GL_VIEW::print_gl_errors(class_name() + "::draw: activate textures");
00487
00488
00489 activate_program();
00490 if (debug)
00491 GL_VIEW::print_gl_errors(class_name() + "::draw: activate program");
00492
00493
00494 set_uniform_variables();
00495 if (debug)
00496 GL_VIEW::print_gl_errors(class_name() + "::draw: set uniform variables");
00497
00498
00499
00500
00501 if (BasicTexture::dl_valid(v)) {
00502 BasicTexture::draw(v);
00503 } else {
00504
00505 int dl = _dl.get_dl(v, 1, _patch->stamp());
00506 if (dl)
00507 glNewList(dl, GL_COMPILE);
00508
00509
00510 _patch->draw_tri_strips(_cb);
00511
00512
00513 if (_dl.dl(v)) {
00514 _dl.close_dl(v);
00515 BasicTexture::draw(v);
00516 }
00517 }
00518
00519 if (debug)
00520 GL_VIEW::print_gl_errors(class_name() + "::draw: draw triangles");
00521
00522
00523 restore_gl_state();
00524
00525 if (debug)
00526 GL_VIEW::print_gl_errors(class_name() + "::draw: pop attrib");
00527
00528 deactivate_program();
00529
00530 GL_VIEW::print_gl_errors(class_name() + "::draw: end");
00531
00532 return _patch->num_faces();
00533 }
00534
00535
00536
00537
00538
00539
00540 GLuint GLSLLightingShader::_program = 0;
00541 bool GLSLLightingShader::_did_init = false;
00542
00543 GLSLLightingShader::GLSLLightingShader(Patch* p) :
00544 GLSLShader(p)
00545 {
00546 }
00547
00548 int
00549 GLSLLightingShader::draw(CVIEWptr& v)
00550 {
00551
00552 GtexUtil::setup_material(_patch);
00553
00554
00555 return GLSLShader::draw(v);
00556 }
00557
00558