First yes that was my idea. To build multiple copies of the same shader. Here i dont see why this is expensive since after all on every draw call in the renderer i have shader->start and shader->stop before i do vao binding and drawing. I am using a Renderer class and rendering two models for instance looks like: Renderer->(Tree), Renderer->(House).
Should i limit my use of shader->start and shader->stop for shaders that are the same ?
For example start shader then draw all models that use it , stop shader and move on … ?
Next , i am not calling glGetUniformLocation , i have cached the Uniform IDs before the main loop.
I have not tried UBOs
The Scene usually renders for ~approx. 5 ms, so 40% would be somewhere around the line of 2.2 ms
void Model::ShaderLoadUniforms()
{
for (int i = 0; i < ModelData->textureNumber(); i++)
activeShader->loadUniform1i(GL_TEXTURE0 + i, i, ModelData->getTbo()[i]->TBO_Id(), activeShader->getVariableID("texture[" + to_string(i) + "]"));
for (int i = 0; i < ModelData->getMtlProperty().size(); i++)
{
activeShader->loadUniform4fv(&ModelData->getMtlProperty()[i].diffuseColor[0], activeShader->getVariableID("diffColor[" + to_string(i) + "]"));
activeShader->loadUniform4fv(&ModelData->getMtlProperty()[i].specularColor[0], activeShader->getVariableID("specColor[" + to_string(i) + "]"));
activeShader->loadUniform1f(ModelData->getMtlProperty()[i].specularFactor, activeShader->getVariableID("specFactor[" + to_string(i) + "]"));
}
activeShader->loadUniform1f((float)ModelData->isFakeLight(), activeShader->getVariableID("fakeLight"));
}
This is running every frame for the model to upload the uniforms. According to the benchmark - getVariableID function ,is causing most problems ~35% cpu time.
inline GLuint BasicShader::getVariableID(string variable)
{
if (variable == "s_vPosition")
return this->s_vPosition;
else if (variable == "s_vNormal")
return this->s_vNormal;
else if (variable == "s_vTexCoord")
return this->s_vTexCoord;
else if (variable == "mTranslate")
return this->mTranslate;
else if (variable == "mRotate")
return this->mRotate;
else if (variable == "mScale")
return this->mScale;
else if (variable == "mProjection")
return this->mProjection;
else if (variable == "mView")
return this->mView;
else if (variable == "fakeLight")
return this->fakeLight;
else if (variable == "fogColor")
return this->fogColor;
else if (variable == "clipPlane")
return this->clipPlane;
else if (variable.substr(0, variable.find('[')) == "diffColor")
{
int dindex = atoi(variable.substr(variable.find('[') + 1, variable.find(']') - 1).c_str());
return this->diffColor[dindex];
}
//.........
}
Now i find that this function is quite expensive as i look at it. I should find another better more efficient way to do this.
I have used an abstract class which is called StaticShader and every other ModelShader,TerrainShader etc are derived. And there i implement the virtual function getVariableID.
EDIT: I would like to still use the structure *abstrShader = ModelShdr , but still be able to access the ModelShader uniform locations (somehow)
EDIT2: What if instead of string for parameter i use enum + index if the variable is an array