00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <GLSL/GLSLProgram.h>
00022 #include <GLEXT/GLStateExtension.h>
00023 #include <common/Logger.h>
00024 #include <common/Defines.h>
00025
00026 const GLSLProgram* GLSLProgram::used_program_(0);
00027
00028 GLSLProgram::GLSLProgram() :
00029 id_(0), linked_(false)
00030 {
00031 DIALOG_ASSERT(GLStateExtension::hasShaders());
00032
00033 id_ = glCreateProgram();
00034
00035 DIALOG_ASSERT(id_);
00036 }
00037
00038 GLSLProgram::~GLSLProgram()
00039 {
00040 if (used_program_ == this)
00041 {
00042
00043 Logger::log("warning: deleting bound glsl program!");
00044 use_fixed();
00045 }
00046
00047 std::list<GLSLShader*>::iterator it;
00048 for (it = attached_shaders_.begin();
00049 it != attached_shaders_.end();
00050 it++)
00051 {
00052 glDetachShader(id_, (*it)->getId());
00053 }
00054
00055 glDeleteProgram(id_);
00056 }
00057
00058 void GLSLProgram::attach(GLSLShader &s)
00059 {
00060 glAttachShader(id_, s.getId());
00061 attached_shaders_.push_front(&s);
00062 linked_ = false;
00063 }
00064
00065 void GLSLProgram::detach(GLSLShader &s)
00066 {
00067 glDetachShader(id_, s.getId());
00068
00069 std::list<GLSLShader*>::iterator it;
00070 for (it = attached_shaders_.begin();
00071 it != attached_shaders_.end(); )
00072 {
00073 if (*it == &s)
00074 {
00075 glDetachShader(id_, (*it)->getId());
00076 it = attached_shaders_.erase(it);
00077 } else
00078 {
00079 it++;
00080 }
00081 }
00082 linked_ = false;
00083 }
00084
00085 void GLSLProgram::link()
00086 {
00087 glLinkProgram(id_);
00088 GLint waslinked = GL_FALSE;
00089 glGetProgramiv(id_, GL_LINK_STATUS, &waslinked);
00090
00091 if (!waslinked)
00092 {
00093 GLint maxlength = 0;
00094 glGetProgramiv(id_, GL_INFO_LOG_LENGTH, &maxlength);
00095 std::string log(maxlength+1, ' ');
00096 GLsizei length = 0;
00097 glGetProgramInfoLog(id_, maxlength, &length, &log[0]);
00098 S3D::dialogExit("GLSLProgram",
00099 S3D::formatStringBuffer("linking of program failed : %s", log.c_str()));
00100 }
00101
00102 linked_ = true;
00103 }
00104
00105 void GLSLProgram::use() const
00106 {
00107 DIALOG_ASSERT(linked_);
00108 glUseProgram(id_);
00109 used_program_ = this;
00110 }
00111
00112 void GLSLProgram::set_gl_texture(GLTexture &tex, const char *texname, unsigned texunit) const
00113 {
00114 DIALOG_ASSERT(used_program_ == this);
00115
00116 GLint uniloc = glGetUniformLocation(id_, texname);
00117 glActiveTexture(GL_TEXTURE0 + texunit);
00118 tex.draw(true);
00119 glUniform1i(uniloc, texunit);
00120 }
00121
00122 void GLSLProgram::set_gl_texture(GLShadowFrameBuffer &tex, const char *texname, unsigned texunit) const
00123 {
00124 DIALOG_ASSERT(used_program_ == this);
00125
00126 GLint uniloc = glGetUniformLocation(id_, texname);
00127 glActiveTexture(GL_TEXTURE0 + texunit);
00128 tex.bindDepthTexture();
00129 glUniform1i(uniloc, texunit);
00130 }
00131
00132 void GLSLProgram::set_gl_texture_unit(const char *texname, unsigned texunit) const
00133 {
00134 DIALOG_ASSERT(used_program_ == this);
00135
00136 GLint uniloc = glGetUniformLocation(id_, texname);
00137 glActiveTexture(GL_TEXTURE0 + texunit);
00138 glUniform1i(uniloc, texunit);
00139 }
00140
00141 void GLSLProgram::set_uniform(const char *name, const Vector& value) const
00142 {
00143 DIALOG_ASSERT(used_program_ == this);
00144
00145 GLint loc = glGetUniformLocation(id_, name);
00146 glUniform3f(loc, value[0], value[1], value[2]);
00147 }
00148
00149 void GLSLProgram::set_uniform(const char *name, const float value) const
00150 {
00151 DIALOG_ASSERT(used_program_ == this);
00152
00153 GLint loc = glGetUniformLocation(id_, name);
00154 glUniform1f(loc, value);
00155 }
00156
00157 unsigned GLSLProgram::get_vertex_attrib_index(const char *name) const
00158 {
00159 DIALOG_ASSERT(used_program_ == this);
00160
00161 return glGetAttribLocation(id_, name);
00162 }
00163
00164 void GLSLProgram::use_fixed()
00165 {
00166 glUseProgram(0);
00167 used_program_ = 0;
00168 }