bool ShaderProgram::setTextureSampler(const std::string& name, const Texture2D& texture) { // Look up sampler location: GLint location = static_cast<GLint>(findUniform(name)); if (location == -1) { m_error = "Could not set sampler " + name + ". No uniform with that name."; return false; } // Check if the texture is already bound: GLint textureUnitId = 0; typedef std::map<const Texture2D*, int>::const_iterator TMapIter; TMapIter result = m_textureUnitBindings.find(&texture); if (result == m_textureUnitBindings.end()) { // Not bound. Attempt to bind the texture to an available texture unit. // We'll leave GL_TEXTURE0 unbound, as it is used for manipulating // textures. std::vector<bool>::iterator begin = m_boundTextureUnits.begin() + 1; std::vector<bool>::iterator end = m_boundTextureUnits.end(); std::vector<bool>::iterator available = std::find(begin, end, false); if (available == end) { m_error = "Could not set sampler " + name + ". No remaining texture " "units available."; return false; } textureUnitId = static_cast<GLint>(available - begin); GLenum textureUnit = lookupTextureUnit(textureUnitId); if (textureUnit == 0) { m_error = "Could not set sampler " + name + ". Texture unit lookup failed."; return false; } glActiveTexture(textureUnit); if (!texture.bind()) { m_error = "Could not set sampler " + name + ": Error while binding " "texture: '" + texture.error() + "'."; glActiveTexture(GL_TEXTURE0); return false; } glActiveTexture(GL_TEXTURE0); // Mark texture unit as in-use. m_textureUnitBindings.insert(std::make_pair(&texture, textureUnitId)); *available = true; } else { // Texture is already bound. textureUnitId = result->second; } // Set the texture unit uniform glUniform1i(location, textureUnitId); return true; }
bool ShaderProgram::setUniformValue(const std::string& name, const Vector2i& v) { GLint location = static_cast<GLint>(findUniform(name)); if (location == -1) { m_error = "Could not set uniform " + name + ". No such uniform."; return false; } glUniform2iv(location, 1, v.data()); return true; }
void Shader::setUniform(const string &name, float* val) { unsigned int pos = findUniform(name, 0, Uniforms.size()); if (pos >= Uniforms.size()) return; if (Uniforms[pos] == name) Uniforms[pos].set(val); }
bool ShaderProgram::setUniformValue(const std::string& name, float f) { GLint location = static_cast<GLint>(findUniform(name)); if (location == -1) { m_error = "Could not set uniform " + name + ". No such uniform."; return false; } glUniform1f(location, static_cast<GLfloat>(f)); return true; }
bool ShaderProgram::setUniformValue(const std::string& name, const Vector3ub& v) { GLint location = static_cast<GLint>(findUniform(name)); if (location == -1) { m_error = "Could not set uniform " + name + ". No such uniform."; return false; } Vector3f colorf(v.cast<float>() * (1.0f / 255.0f)); glUniform3fv(location, 1, colorf.data()); return true; }
void opengl::ShaderUniforms::setUniformMatrix4fv(const SCP_string &name, const int count, const matrix4 *val) { Assertion(GL_state.IsCurrentProgram(_program->getShaderHandle()), "The program must be current before setting uniforms!"); size_t uniform_index = findUniform(name); bool resident = false; if (uniform_index != (size_t)-1) { Assert((size_t)uniform_index < _uniforms.size()); uniform_bind *bind_info = &_uniforms[uniform_index]; if (bind_info->type == uniform_bind::MATRIX4 && bind_info->count == count) { bool equal = true; // if the values are close enough, pass. for (int i = 0; i < count; ++i) { if (!vm_matrix_equal(val[i], _uniform_data_matrix4[bind_info->index + i])) { equal = false; break; } } if (equal) { return; } resident = true; for (int i = 0; i < count; ++i) { _uniform_data_matrix4[bind_info->index + i] = val[i]; } } } if (!resident) { // uniform doesn't exist in our previous uniform block so queue this new value for (int i = 0; i < count; ++i) { _uniform_data_matrix4.push_back(val[i]); } uniform_bind new_bind; new_bind.count = count; new_bind.index = _uniform_data_matrix4.size() - count; // new_bind.index = num_matrix_uniforms - count; new_bind.type = uniform_bind::MATRIX4; new_bind.name = name; _uniforms.push_back(new_bind); _uniform_lookup[name] = _uniforms.size() - 1; } glUniformMatrix4fv(findUniformLocation(name.c_str()), count, GL_FALSE, (const GLfloat*)val); }
bool ShaderProgram::setUniformValue(const std::string& name, const Eigen::Matrix4f& matrix) { GLint location = static_cast<GLint>(findUniform(name)); if (location == -1) { m_error = "Could not set uniform " + name + ". No such uniform."; return false; } glUniformMatrix4fv(location, 1, GL_FALSE, static_cast<const GLfloat*>(matrix.data())); return true; }
void opengl_uniform_state::setUniformMatrix4fv(const SCP_string &name, const int count, const matrix4 *val) { size_t uniform_index = findUniform(name); bool resident = false; if ( uniform_index != (size_t)-1) { Assert( (size_t)uniform_index < uniforms.size() ); uniform_bind *bind_info = &uniforms[uniform_index]; if ( bind_info->type == uniform_bind::MATRIX4 && bind_info->count == count ) { bool equal = true; // if the values are close enough, pass. for ( int i = 0; i < count; ++i ) { if ( !vm_matrix_equal(val[i], uniform_data_matrix4[bind_info->index+i]) ) { equal = false; break; } } if ( equal ) { return; } resident = true; for ( int i = 0; i < count; ++i ) { uniform_data_matrix4[bind_info->index+i] = val[i]; } } } if ( !resident ) { // uniform doesn't exist in our previous uniform block so queue this new value for ( int i = 0; i < count; ++i ) { uniform_data_matrix4.push_back(val[i]); } uniform_bind new_bind; new_bind.count = count; new_bind.index = uniform_data_matrix4.size() - count; // new_bind.index = num_matrix_uniforms - count; new_bind.type = uniform_bind::MATRIX4; new_bind.name = name; uniforms.push_back(new_bind); uniform_lookup[name] = uniforms.size()-1; } glUniformMatrix4fv(opengl_shader_get_uniform(name.c_str()), count, GL_FALSE, (const GLfloat*)val); }
void Shader::updateVec3Array(const char* name, const vec3* arr, int size) { GLint x = findUniform(name); if (x != -1) { float* floats = new float[3*size]; for (int i = 0; i < size; i++) { floats[i*3] = arr[i].x; floats[i*3+1] = arr[i].y; floats[i*3+2] = arr[i].z; } glUniform3fv(x, size, floats); } }
float* Shader::getUniformMemPos(string name) { unsigned int pos = findUniform(name, 0, Uniforms.size()); if (pos >= Uniforms.size()) return nullptr; if (Uniforms[pos] == name) { Uniforms[pos].enable(); return Uniforms[pos].getPtr(); } return nullptr; }
int Shader::findUniform(const Uniform& u, int min, int max) { if (min > max) { return min; } else if (Uniforms.size() == 0) return 0; else { unsigned int mid = (min + max) / 2; if (mid >= Uniforms.size()) return Uniforms.size(); if (Uniforms[mid] == u) { return mid; } else if (Uniforms[mid] < u) { return findUniform(u, mid + 1, max); } else { return findUniform(u, min, mid - 1); } } }
int Shader::findUniform(const string& name, int min, int max) { if (min > max) { return min; } else if (Uniforms.size() == 0) return 0; else { unsigned int mid = (min + max) / 2; if (mid >= Uniforms.size()) return Uniforms.size(); if (Uniforms[mid] == name) { return mid; } else if (Uniforms[mid] < name) { return findUniform( name, mid + 1, max); } else { return findUniform( name, min, mid - 1); } } }
PushUniformSPtr ShaderObject::createUniform( UniformType type , String const & name , int nbOccurences ) { PushUniformSPtr result = findUniform( type, name ); if ( !result ) { result = doCreateUniform( type, nbOccurences ); result->getBaseUniform().setName( name ); doAddUniform( result ); } return result; }
void opengl::ShaderUniforms::setUniformMatrix4f(const SCP_string &name, const matrix4 &val) { Assertion(GL_state.IsCurrentProgram(_program->getShaderHandle()), "The program must be current before setting uniforms!"); size_t uniform_index = findUniform(name); bool resident = false; if (uniform_index != (size_t)-1) { Assert((size_t)uniform_index < _uniforms.size()); uniform_bind *bind_info = &_uniforms[uniform_index]; if (bind_info->type == uniform_bind::MATRIX4 && bind_info->count == 1) { if (vm_matrix_equal(_uniform_data_matrix4[bind_info->index], val)) { return; } _uniform_data_matrix4[bind_info->index] = val; resident = true; } } if (!resident) { // uniform doesn't exist in our previous uniform block so queue this new value //matrix_uniform_data[num_matrix_uniforms] = val; //memcpy(&(matrix_uniform_data[num_matrix_uniforms]), &val, sizeof(matrix4)); _uniform_data_matrix4.push_back(val); // num_matrix_uniforms += 1; uniform_bind new_bind; new_bind.count = 1; new_bind.index = _uniform_data_matrix4.size() - 1; // new_bind.index = num_matrix_uniforms - 1; new_bind.type = uniform_bind::MATRIX4; new_bind.name = name; _uniforms.push_back(new_bind); _uniform_lookup[name] = _uniforms.size() - 1; } glUniformMatrix4fv(findUniformLocation(name.c_str()), 1, GL_FALSE, (const GLfloat*)&val); }
void opengl_uniform_state::setUniformMatrix4f(const SCP_string &name, const matrix4 &val) { size_t uniform_index = findUniform(name); bool resident = false; if ( uniform_index != (size_t)-1) { Assert( (size_t)uniform_index < uniforms.size() ); uniform_bind *bind_info = &uniforms[uniform_index]; if ( bind_info->type == uniform_bind::MATRIX4 && bind_info->count == 1 ) { if ( vm_matrix_equal(uniform_data_matrix4[bind_info->index], val) ) { return; } uniform_data_matrix4[bind_info->index] = val; resident = true; } } if ( !resident ) { // uniform doesn't exist in our previous uniform block so queue this new value //matrix_uniform_data[num_matrix_uniforms] = val; //memcpy(&(matrix_uniform_data[num_matrix_uniforms]), &val, sizeof(matrix4)); uniform_data_matrix4.push_back(val); // num_matrix_uniforms += 1; uniform_bind new_bind; new_bind.count = 1; new_bind.index = uniform_data_matrix4.size() - 1; // new_bind.index = num_matrix_uniforms - 1; new_bind.type = uniform_bind::MATRIX4; new_bind.name = name; uniforms.push_back(new_bind); uniform_lookup[name] = uniforms.size()-1; } glUniformMatrix4fv(opengl_shader_get_uniform(name.c_str()), 1, GL_FALSE, (const GLfloat*)&val); }
void opengl::ShaderUniforms::setUniform4f(const SCP_string &name, const vec4 &val) { Assertion(GL_state.IsCurrentProgram(_program->getShaderHandle()), "The program must be current before setting uniforms!"); size_t uniform_index = findUniform(name); bool resident = false; if (uniform_index != (size_t)-1) { Assert((size_t)uniform_index < _uniforms.size()); uniform_bind *bind_info = &_uniforms[uniform_index]; if (bind_info->type == uniform_bind::VEC4) { if (vm_vec_equal(_uniform_data_vec4[bind_info->index], val)) { // if the values are close enough, pass. return; } _uniform_data_vec4[bind_info->index] = val; resident = true; } } if (!resident) { // uniform doesn't exist in our previous uniform block so queue this new value _uniform_data_vec4.push_back(val); uniform_bind new_bind; new_bind.count = 1; new_bind.index = _uniform_data_vec4.size() - 1; new_bind.type = uniform_bind::VEC4; new_bind.name = name; _uniforms.push_back(new_bind); _uniform_lookup[name] = _uniforms.size() - 1; } glUniform4f(findUniformLocation(name.c_str()), val.a1d[0], val.a1d[1], val.a1d[2], val.a1d[3]); }
void opengl::ShaderUniforms::setUniformi(const SCP_string &name, const int val) { Assertion(GL_state.IsCurrentProgram(_program->getShaderHandle()), "The program must be current before setting uniforms!"); size_t uniform_index = findUniform(name); bool resident = false; if (uniform_index != (size_t)-1) { Assert(uniform_index < _uniforms.size()); uniform_bind *bind_info = &_uniforms[uniform_index]; if (bind_info->type == uniform_bind::INT) { if (_uniform_data_ints[bind_info->index] == val) { return; } _uniform_data_ints[bind_info->index] = val; resident = true; } } if (!resident) { // uniform doesn't exist in our previous uniform block so queue this new value _uniform_data_ints.push_back(val); uniform_bind new_bind; new_bind.count = 1; new_bind.index = _uniform_data_ints.size() - 1; new_bind.type = uniform_bind::INT; new_bind.name = name; _uniforms.push_back(new_bind); _uniform_lookup[name] = _uniforms.size() - 1; } glUniform1i(findUniformLocation(name.c_str()), val); }
void opengl_uniform_state::setUniform4f(const SCP_string &name, const vec4 &val) { size_t uniform_index = findUniform(name); bool resident = false; if (uniform_index != (size_t)-1) { Assert( (size_t)uniform_index < uniforms.size() ); uniform_bind *bind_info = &uniforms[uniform_index]; if ( bind_info->type == uniform_bind::VEC4 ) { if ( vm_vec_equal(uniform_data_vec4[bind_info->index], val) ) { // if the values are close enough, pass. return; } uniform_data_vec4[bind_info->index] = val; resident = true; } } if ( !resident ) { // uniform doesn't exist in our previous uniform block so queue this new value uniform_data_vec4.push_back(val); uniform_bind new_bind; new_bind.count = 1; new_bind.index = uniform_data_vec4.size() - 1; new_bind.type = uniform_bind::VEC4; new_bind.name = name; uniforms.push_back(new_bind); uniform_lookup[name] = uniforms.size()-1; } glUniform4f(opengl_shader_get_uniform(name.c_str()), val.a1d[0], val.a1d[1], val.a1d[2], val.a1d[3]); }
void opengl_uniform_state::setUniformf(const SCP_string &name, const float val) { size_t uniform_index = findUniform(name); bool resident = false; if ( uniform_index != (size_t) -1) { Assert( (size_t)uniform_index < uniforms.size() ); uniform_bind *bind_info = &uniforms[uniform_index]; if ( bind_info->type == uniform_bind::FLOAT ) { if ( fl_equal(uniform_data_floats[bind_info->index], val) ) { return; } uniform_data_floats[bind_info->index] = val; resident = true; } } if ( !resident ) { // uniform doesn't exist in our previous uniform block so queue this new value uniform_data_floats.push_back(val); uniform_bind new_bind; new_bind.count = 1; new_bind.index = uniform_data_floats.size() - 1; new_bind.type = uniform_bind::FLOAT; new_bind.name = name; uniforms.push_back(new_bind); uniform_lookup[name] = uniforms.size()-1; } glUniform1f(opengl_shader_get_uniform(name.c_str()), val); }
void Shader::updateMat4(const char* name, mat4 v) { GLint x = findUniform(name); if (x != -1) glUniformMatrix4fv(x, 1, GL_FALSE, value_ptr(v)); }
void Shader::updateInt(const char* name, int v) { GLint x = findUniform(name); if (x != -1) glUniform1i(x,v); }
void Shader::updateVec4(const char* name, vec4 v) { GLint x = findUniform(name); if (x != -1) glUniform4fv(x, 1, value_ptr(v)); }
virtual void postLink() { uTEX = uniforms.add(findUniform("tex"), 0); }
void Shader::build() { if (Code.size() == reqArr.size()) { for (size_t i = 0; i < Code.size(); i++) { Code[i] = *((ShaderCode*)reqArr[i].get()); Code[i].makeShader(); vector<Uniform>& t = Code[i].getUniforms(); for (Uniform& temp : t) Uniforms.insert(Uniforms.begin() + findUniform(temp.getName(), 0, Uniforms.size()), temp); } } if (!program.get() || !glIsProgram(*program)) *program = glCreateProgram(); //no Program existent creating int attached = 0; glGetProgramiv(*program, GL_ATTACHED_SHADERS, &attached); if (attached) //in case old Shaders are attached { vector<GLuint> shaders = vector<GLuint>(); for (char i = 0; i < 16; i++) //write invaid numbers to seperate them shaders.push_back(-1); glGetAttachedShaders(*program, 16, NULL, &shaders[0]); //get all Shaders attached to Program for (GLuint shader : shaders) if (shader != -1) //check if it is a valid shader glDetachShader(*program, shader); //detaches Shader, DOES NO DELETE attached = 0; //resets counter } for (ShaderCode& shader : Code) { //should check Shader values glAttachShader(*program, shader.getPos()); int ShaderCount = 0; glGetProgramiv( *program, GL_ATTACHED_SHADERS, &ShaderCount); //might turn out t be slow since it querries operations and wait for them if (ShaderCount > attached) //used for Error catching attached++; } if (attached > 0) glLinkProgram(*program); else LOG << "OpenGL Program " << "NO SHADERS ATTACHED." << "\n"; int isLinked = 0; glGetProgramiv(*program, GL_LINK_STATUS, &isLinked); if (!isLinked) { GLint maxLength = 0; glGetProgramiv(*program, GL_INFO_LOG_LENGTH, &maxLength); if (maxLength > 1) { //The maxLength includes the NULL character vector<GLchar> infoLog = vector<GLchar>(maxLength); glGetProgramInfoLog(*program, maxLength, NULL, &infoLog[0]); LOG << "OpenGL Program " << infoLog.data() << "\n"; } } //Uniform Phase setUniforms(); }
void Shader::updateFloat(const char* name, float v) { GLint x = findUniform(name); if (x != -1) glUniform1f(x, v); }