Closed mrzzzrm closed 9 years ago
As for now, globjects::Program
implements the following functions:
template<typename T>
void setUniform(const std::string & name, const T & value);
template<typename T>
void setUniform(gl::GLint location, const T & value);
template<typename T>
Uniform<T> * getUniform(const std::string & name);
template<typename T>
const Uniform<T> * getUniform(const std::string & name) const;
template<typename T>
Uniform<T> * getUniform(gl::GLint location);
template<typename T>
const Uniform<T> * getUniform(gl::GLint location) const;
and further to fulfil your requirements. Or did I miss anything?
What I want to do is set a uniform from a raw data pointer (and a runtime type (like GL_FLOAT_VEC2
), but that could be queried from the program object). Now I just realised that even the glUniform*v()
functions require you to code the uniform type into the function name. Bummer...
Alright, change my question to: Would you accept the convenience functions setUniform(location, type, ptr)
and setUniform(name, type, ptr)
and respective equivalents for array uniforms in globjects or is that out of the scope of the lib? These functions would really just be massive switch(type)
blocks that would call the appropriate, already available setUniform
function.
This interface would imply, that the provided type behind ptr
has to be converted to the given type from type
.
This is something we hasn't done before and I'm not sure if we ever will.
What is the point of a rendering system to store uniform values in another type as expected in the shader and why would a rendering system doesn't provide the necessary conversion by itself (so that this part has to be taken by globjects)?
What I have looked up (in glbinding) is, that the OpenGL API indeed has enum values for the common uniform types:
GL_FLOAT_VEC2 = 0x8B50,
GL_FLOAT_VEC2_ARB = 0x8B50,
GL_FLOAT_VEC3 = 0x8B51,
GL_FLOAT_VEC3_ARB = 0x8B51,
GL_FLOAT_VEC4 = 0x8B52,
GL_FLOAT_VEC4_ARB = 0x8B52,
GL_INT_VEC2 = 0x8B53,
GL_INT_VEC2_ARB = 0x8B53,
GL_INT_VEC3 = 0x8B54,
GL_INT_VEC3_ARB = 0x8B54,
GL_INT_VEC4 = 0x8B55,
GL_INT_VEC4_ARB = 0x8B55,
GL_BOOL = 0x8B56,
GL_BOOL_ARB = 0x8B56,
GL_BOOL_VEC2 = 0x8B57,
GL_BOOL_VEC2_ARB = 0x8B57,
GL_BOOL_VEC3 = 0x8B58,
GL_BOOL_VEC3_ARB = 0x8B58,
GL_BOOL_VEC4 = 0x8B59,
GL_BOOL_VEC4_ARB = 0x8B59,
GL_FLOAT_MAT2 = 0x8B5A,
GL_FLOAT_MAT2_ARB = 0x8B5A,
GL_FLOAT_MAT3 = 0x8B5B,
GL_FLOAT_MAT3_ARB = 0x8B5B,
GL_FLOAT_MAT4 = 0x8B5C,
GL_FLOAT_MAT4_ARB = 0x8B5C,
GL_SAMPLER_1D = 0x8B5D,
GL_SAMPLER_1D_ARB = 0x8B5D,
GL_SAMPLER_2D = 0x8B5E,
GL_SAMPLER_2D_ARB = 0x8B5E,
GL_SAMPLER_3D = 0x8B5F,
GL_SAMPLER_3D_ARB = 0x8B5F,
GL_SAMPLER_CUBE = 0x8B60,
GL_SAMPLER_CUBE_ARB = 0x8B60,
GL_SAMPLER_1D_SHADOW = 0x8B61,
GL_SAMPLER_1D_SHADOW_ARB = 0x8B61,
GL_SAMPLER_2D_SHADOW = 0x8B62,
GL_SAMPLER_2D_SHADOW_ARB = 0x8B62,
GL_SAMPLER_2D_RECT = 0x8B63,
GL_SAMPLER_2D_RECT_ARB = 0x8B63,
GL_SAMPLER_2D_RECT_SHADOW = 0x8B64,
GL_SAMPLER_2D_RECT_SHADOW_ARB = 0x8B64,
GL_FLOAT_MAT2x3 = 0x8B65,
GL_FLOAT_MAT2x4 = 0x8B66,
GL_FLOAT_MAT3x2 = 0x8B67,
GL_FLOAT_MAT3x4 = 0x8B68,
GL_FLOAT_MAT4x2 = 0x8B69,
GL_FLOAT_MAT4x3 = 0x8B6A,
Nethertheless, your proposed interface would require to rely on C semantics where globjects tries to use semantics-rich (and thus, typed) objects and classes. If you don't want to use those object semantics you are free to call straight glbinding OpenGL calls everywhere in your code. To ease the automatic uniform update upon program relinking, I think we can add the possibility of a callback or observer interface so you get called when non-tracked uniforms has to be updated.
Alternatively, maybe you can explain an explicit use case where we can better understand the intention.
Think of loading arbitrary shaders into an editor that than exposes its uniforms in UI elements generated at runtime (like, single line text edit for float, 4x4 for matrix, ...) and than passing them to the running shader. At some point you're gonna have that massive switch block over the enum you quoted. But if you don't think globjects should be that place, that's okay, feel free to close this ;)
Thank you for your use-case.
If I had to implement such editor, I would parse the shader for the uniforms and their types (e.g., using https://www.opengl.org/wiki/Program_Introspection#Uniforms_and_blocks). The information about the types would then be used to generate an appropriate UI. If the values in the UI gets updated, I would have the information about the type of the uniform to call the correct method on the program object. The information about the type is a must-have somewhere in the code, since either the UI is highly specialized for the uniform values, or the new value has to be parsed, validated, and converted into the target format.
So I would also tend to closing this issue.
If you think in C-terms, then yes, you would use such a switch block. But in C++ this could also be solved in a type-safe manner by using templates. For example, have a GuiElement
You can do fancy, fancy things with this C++, indeed ;) Thanks for your comments, both of you!
As far as I can tell it isn't possible to set the value of a
globjects::Program
's uniform using the globjects API if only the uniform's GLenum type / its memory location/size are available.Imo
globjects::Program
should fully expose https://www.opengl.org/wiki/GLAPI/glProgramUniform / https://www.opengl.org/sdk/docs/man/html/glUniform.xhtml with optional convenience methodssetUniform(location, type, ptr)
andsetUniform(name, type, ptr)
.What do you think? I'd be happy to do the hacking, just wanted to ask for feedback first.