Open osrf-migration opened 6 years ago
fragmentShaderParams
PopulatingI was digging around the uniform implementation and I noticed that the fragmentShaderParams
(in OgreMaterial.cc) are created on demand.
void OgreMaterial::SetFragmentShader(const std::string &_path)
in OgreMaterial.cc
...
this->ogreMaterial->compile();
this->ogreMaterial->load();
this->fragmentShaderPath = _path;
this->fragmentShaderParams.reset(new ShaderParams);
}
Since OGRE can query all the shader parameters, should we populate fragmentShaderParams
after successfully compiling the shader?
Currently if you try to update a uniform that does not exist it will still be added to the fragmentShaderParams
but OGRE will throw an error when trying to update the non-existent uniform.
Example Code:
ir::ShaderParamsPtr shaderParams = shader->FragmentShaderParams();
(*shaderParams)["thisUniformDoesNotExist"] = 0;
Output:
terminate call after throwing an instance of 'Ogre::InvalidParametersException' what(): OGRE EXCPETION(2:InvalidParametersException): Parameter called thisUniformDoesNotExist does not exist. in GpuProgramParameters::_findNamedConstantDefinition at /home/wlew/work/ogre-1.9/src/ogre-1.9.1/OgreMain/src/OgreGpuProgramParams.cpp (line 1725)
If we have a pre-existing list of all the uniforms, we could handle the error on ign-rendering rather than having OGRE handle it. Populating the fragmentShaderParams
would also let us provide all the available uniforms for a shader program.
I have noticed that OGRE provides the following method which allows setting a uniform buffer of an arbitrary length:
void Ogre::GpuProgramParameters::setNamedConstant(const String& name, const int* val, size_t count, size_t multiple = 4)
I implemented an example on the reference branch that shows updating different uniform buffers with different sizes:
ign-rendering/examples/custom_shaders_uniforms/media/fragment_shader.glsl
uniform float testFloat;
uniform int testInt;
uniform float testFloatBuffer[6];
uniform int testIntBuffer[5];
uniform vec4 testVector4;
uniform mat4 textMatrix4;
void main()
{
gl_FragColor = vec4(textMatrix4[0][0], textMatrix4[3][1], textMatrix4[3][3], 1.0);
}
ign-rendering/examples/custom_shaders_uniforms/GlutWindow.cc
ir::ShaderParamsPtr shaderParams = shader->FragmentShaderParams();
float testMatrix[16] = {
0.1, 0.2, 0.3, 0.4,
0.5, 0.6, 0.7, 0.8,
0.9, 0.1, 0.2, 0.3,
0.4, 0.5, 0.6, 0.7,
};
(*shaderParams)["textMatrix4"].InitializeBuffer(16);
(*shaderParams)["textMatrix4"].UpdateBuffer(testMatrix, 16);
If we were to populate the fragmentShaderParams
after compiling the shader program, the InitializeBuffer
method call could be removed from the user application because OGRE can query the size of a buffer.
If we have a pre-existing list of all the uniforms, we could handle the error on ign-rendering rather than having OGRE handle it.
+1. And I think it may also be a good idea to have a safety catch
in case something shows up that we don't know about, so we don't just crash on the user.
Reference Branch
How about opening a pull request so we can iterate on it?
Original report (archived issue) by Ian Chen (Bitbucket: Ian Chen, GitHub: iche033).
from comment in pull request #55:
While the ShaderParam currently encodes INT and FLOAT, it should probably be expanded to cover other commonly-used types with more than one value (Vector2, Vector3, Vector4, Matrix33, Matrix44)
It may be useful to port the capabilities/features framework from ign-physics to the rendering system to indicate that some renderers don't support raw shaders (eg Optix):
Potentially expand for other shader types: Geometry, Compute, Tesselation