/** * Finds the shader locations of all uniforms and textures from a given material. * The input material descriptor has all the possible textures and uniforms * that can be used by this shader. (Any material used with this shader * will have the same descriptor.) * * This function uses the descriptor of the input material to find and save * the GL shader locations of each texture and uniform. The locations are * saved into vectors - mTextureLocs and mUniformLocs. Each vector has an * entry for all of the uniforms/textures in the input material * (not just the ones used by this shader). If the shader does not * reference a particular uniform or texture, that location will be -1. * This function must be called after the GL shader program has * been selected as the current program. * @param material can be any Material which uses this shader * @see #getUniformLoc */ void GLShader::findUniforms(const Light& light, int locationOffset) { const UniformBlock& lightBlock = light.uniforms().uniforms(); const GLLight* glLight = static_cast<const GLLight*>(&light); lightBlock.forEachEntry([this, glLight, locationOffset](const DataDescriptor::DataEntry& entry) mutable { if (entry.NotUsed) { return; } std::string name = glLight->getLightName(); name += '.'; name += entry.Name; int loc = glGetUniformLocation(getProgramId(), name.c_str()); if (loc >= 0) { mShaderLocs[LIGHT_UBO_INDEX][entry.Index + locationOffset] = loc; #ifdef DEBUG_SHADER LOGV("SHADER: program %d uniform %s loc %d", getProgramId(), entry.Name, loc); #endif } else { #ifdef DEBUG_SHADER LOGV("SHADER: uniform %s has no location in shader %d", entry.Name, getProgramId()); #endif } }); checkGLError("GLShader::findUniforms"); }
/** * Finds the shader locations of all textures used by this shader. * The shader's texture descriptor has all the possible textures * that can be used by this shader. * * This function uses the texture descriptor to find and save * the GL shader locations of each texture used by the shader. * The locations are saved into mTextureLocs which has an * entry for each texture in the descriptor * (not just the ones used by this shader). If the shader does not * reference a particular texture, that location will be -1. * This function must be called after the GL shader program has * been selected as the current program. * @see #getTextureLoc */ void GLShader::findTextures() { mTextureLocs.resize(mTextureDesc.getNumEntries(), -1); mTextureDesc.forEachEntry([this](const DataDescriptor::DataEntry& entry) mutable { if (entry.NotUsed) { return; } int loc = glGetUniformLocation(getProgramId(), entry.Name); if (loc >= 0) { mTextureLocs[entry.Index] = loc; #ifdef DEBUG_SHADER LOGV("SHADER: program %d texture %s loc %d", getProgramId(), entry.Name, loc); #endif } else { #ifdef DEBUG_SHADER LOGV("SHADER: texture %s has no location in shader %d", entry.Name, getProgramId()); #endif } }); checkGLError("GLShader::findTextures"); }
/** * Finds the shader locations of all uniforms and textures from a given material. * The input material descriptor has all the possible textures and uniforms * that can be used by this shader. (Any material used with this shader * will have the same descriptor.) * * This function uses the descriptor of the input material to find and save * the GL shader locations of each texture and uniform. The locations are * saved into vectors - mTextureLocs and mUniformLocs. Each vector has an * entry for all of the uniforms/textures in the input material * (not just the ones used by this shader). If the shader does not * reference a particular uniform or texture, that location will be -1. * This function must be called after the GL shader program has * been selected as the current program. * @param material can be any Material which uses this shader * @see #getUniformLoc */ void GLShader::findUniforms(const DataDescriptor& desc, int bindingPoint) { std::vector<int>& uniformLocs = mShaderLocs[bindingPoint]; if (uniformLocs.size() > 0) { return; } uniformLocs.resize(desc.getNumEntries(), -1); desc.forEachEntry([&](const DataDescriptor::DataEntry& entry) mutable { if (entry.NotUsed) { return; } int loc = glGetUniformLocation(getProgramId(), entry.Name); if (loc >= 0) { uniformLocs[entry.Index] = loc; #ifdef DEBUG_SHADER LOGV("SHADER: program %d uniform %s loc %d", getProgramId(), entry.Name, loc); #endif } else { #ifdef DEBUG_SHADER LOGV("SHADER: uniform %s has no location in shader %d", entry.Name, getProgramId()); #endif } }); checkGLError("GLShader::findUniforms"); }
AttributeList Program::getActiveAttributes() const { AttributeList al; // Get the number of active attributes GLint num_attributes; getProgram(Program::ActiveAttributes, &num_attributes); // The the maximum size of the attribe names GLsizei max_name_length; getProgram(Program::ActiveAttributeMaxLength, &max_name_length); GLsizei length; std::vector<GLchar> name(max_name_length); for(int index = 0; index < num_attributes; index++) { AttributeInfo ai; // Retrive atribute data and store it in the info struct ai.index = index; glGetActiveAttrib(getProgramId(), index, name.size(), &length, &ai.size, &ai.type, &name[0]); ai.name = std::string(&name[0], length); al.push_back(ai); } return al; }
bool GLShader::useShader(bool is_multiview) { if (nullptr == mProgram) { initialize(is_multiview); } GLint programID = getProgramId(); if (programID <= 0) { LOGE("SHADER: shader could not be generated %s", mSignature.c_str()); return false; } #ifdef DEBUG_SHADER LOGV("SHADER: rendering with program %d", programID); #endif glUseProgram(programID); if(!mTextureLocs.size()) findTextures(); if (!useMaterialGPUBuffer()) { findUniforms(mUniformDesc, MATERIAL_UBO_INDEX); } return true; }
UniformInfo Program::getUniformInfo(const GLint index) const { UniformInfo ui; ui.index = index; if(index < 0) { WARNING("Tried to get info on shader with bad index."); ui.name = ""; ui.size = 0; ui.type = 0; return ui; } // The the maximum size of the attribe name GLsizei max_name_length; getProgram(Program::ActiveUniformMaxLength, &max_name_length); GLsizei length; std::vector<GLchar> name(max_name_length); // Retrive atribute data and store it in the info struct glGetActiveUniform(getProgramId(), index, name.size(), &length, &ui.size, &ui.type, &name[0]); ui.name = std::string(&name[0], length); return ui; }
int* Shader::getUniformiv(std::string name, int size) { if(name.empty() || size <= 0) { std::cerr << "ERROR: getUniform -> Invalid parameter(s)" << std::endl; return NULL; } int* params = new int[size]; GLint loc = getUniformLocation(name); glGetUniformiv(getProgramId(), loc, params); return params; }
UniformBlockList Program::getActiveUniformBlocks() const { UniformBlockList ul; // Get the number of active attributes GLint num_uniform_blocks; getProgram(Program::ActiveUniformBlocks, &num_uniform_blocks); // GL: 3.1 // The the maximum size of the attribe name GLsizei max_name_length; getProgram(Program::ActiveUniformBlockMaxNameLength, &max_name_length); DEBUG_M("Num unifrom blocks %d", num_uniform_blocks); for(int ubo_index = 0; ubo_index < num_uniform_blocks; ubo_index++) { UniformBlockInfo ubi; getActiveUniformBlock( ubo_index, Program::UniformBlockActiveUniforms, &ubi.num_active_uniforms); GLsizei name_length; getActiveUniformBlock( ubo_index, Program::UniformBlockNameLength, &name_length); GLsizei written_name_length; std::vector<GLchar> block_name(name_length); glGetActiveUniformBlockName( getProgramId(), ubo_index, block_name.size(), &written_name_length, &block_name[0] ); ubi.name = std::string(&block_name[0], written_name_length); getActiveUniformBlock( ubo_index, Program::UniformBlockBinding, &ubi.binding); std::vector<GLint> active_uniforms(ubi.num_active_uniforms); getActiveUniformBlock( ubo_index, Program::UniformBlockActiveUniformIndices, &active_uniforms[0]); ul.push_back(ubi); } return ul; }
void Shader::bindFragDataLoc(std::string name, int layLoc) { glBindFragDataLocation(getProgramId(), layLoc, name.c_str()); }
void Shader::bind() { glUseProgram(getProgramId()); }
void Shader::setUniformfv(std::string name, float m[], int size) { GLint loc = getUniformLocation(name.c_str()); if(loc == -1) { std::cerr << "ERROR: The variable name " << name << " was not set because its location was not found on the shader program " << getProgramId() << std::endl; std::cerr << "In files-> Vertex shader: " << m_sVertPath << " Fragment shader: " << m_sFragPath << " Geometry shader: " << m_sGeomPath << " Tesselation control shader: " << m_sTessControlPath << " Tesselation evaluation shader: " << m_sTessEvalPath << std::endl; return; } switch(size) { case 4: glUniform4f(loc, m[0], m[1], m[2], m[3]); break; case 3: glUniform3f(loc, m[0], m[1], m[2]); break; case 2: glUniform2f(loc, m[0], m[1]); break; case 1: glUniform1f(loc, m[0]); break; } }
GLuint Shader::getUniformLocation(const String &name) { return glGetUniformLocation(getProgramId(), name); }
void ScreenShader::beforeLink() { GLRUN(glBindAttribLocation(getProgramId(), 0, "position")); GLRUN(glBindAttribLocation(getProgramId(), 2, "texCoords")); }
void LightShader::beforeLink() { GLRUN(glBindAttribLocation(getProgramId(), 0, "position")); }
GLint Shader::getUniformLocation(std::string s) { GLint loc = glGetUniformLocation(getProgramId(), s.c_str()); return loc; }
void Shader::setUniform4fv(std::string name, glm::vec4 v) { GLint loc = getUniformLocation(name.c_str()); if(loc == -1) { std::cerr << "ERROR: The variable name " << name << " was not set because its location was not found on the shader program " << getProgramId() << std::endl; std::cerr << "In files-> Vertex shader: " << m_sVertPath << " Fragment shader: " << m_sFragPath << " Geometry shader: " << m_sGeomPath << " Tesselation control shader: " << m_sTessControlPath << " Tesselation evaluation shader: " << m_sTessEvalPath << std::endl; return; } glUniform4fv(loc, 1, glm::value_ptr(v)); }
void Shader::setUniformLocation(const String &name, const GLuint &location) { GLuint glLocation = glGetUniformLocation(getProgramId(), name); glUniform1i(glLocation, location); }