Hello Carsten,

On 09.02.2014 14:22, Carsten Neumann wrote:

>> How could that be implemented in OpenSG?
>
> Hmm, one thing that distinguishes buffer objects used to back uniform
> blocks from other uses (in OpenSG), is that they do not contain a
> large amount of data of *the same type* - i.e. for VBOs you usually
> have large chunks of say vec3/4 for positions/normals etc. while for a
> uniform block you'll get much more varied types depending on what kind
> of information needs to be passed to your shader. The same type case
> maps nicely to MField<T> so we can represent such buffers as arrays of
> some type T. I don't immediately have an idea what would be a good way
> to represent the mixed type case (and the alignment issues it brings
> with it [1]), suggestions would be welcome.
>
Let me brainstorming a little bit...

I use the following example taken from the superbible 6

layout(std 140) uniform TransformBlock
{
     float scale;
     vec3 translation;
     float rotation[3];
     mat4 proj_matrix;
} transform;

I would define that the host application does not has to know about the 
structure member names! The semantic interpretation would be the 
responsibility of the shader and the application does only provide the 
uniform buffer object. This does imply, if I understand it correctly, 
that we would be forced to std140, but I'm fine with that.

Next let me describe a coarse interface of an OpenSG object that would 
represent such a uniform buffer object. It would consists of 3 parts:

Part 1: Provide name for binding
--------------------------------
        setName(const std::string& name)  -> "TransformBlock"
        
Part 2: Assemble structure
--------------------------
The assembling of the TransformBlock structure would be conducted by 
consecutive calls to addXXX methods. Each methods defines the type and 
returns a handle to operate with that 'slot'. The array dimensionality 
is provided as an integer argument, which is preset to 1.
The following types would be supported: int, uint, bool, float, double, 
vec2, vec3, vec4, ivec2, ivec3, ivec4, uivec2, uivec3, uivec4.

        int addFloat(int idx = 1)
        int addVec4(int idx = 1)
        int addMat3(int idx = 1)
        ...
        
for the example
        int h1 = addFloat();
        int h2 = addVec3();
        int h3 = addFloat(3);
        int h4 = addMat4();

Part 3: Fill structure with values
----------------------------------
The object provides an interface for filling each slot with a value.
        void setValue(int handle, float value)
        void setValue(int handle, const Vecf4& value)
        void setValue(int handle, const Vecf4* values)
Maybe these methods must be named for each type and maybe the array case 
must be more explicitly rendered here.

anyway for the example
        setValue(h1, 2.5f);
        setValue(h2, Vec3f(1.f,0.f,0.f));
        float rot[3] = {1.f,1.f,1.f}
        setValue(h3, rot);
        setValue(h4, Mat4f());

Next a sketchy implementation. All information has to be laid down by 
Field<T> and MField<T> types, where T could be any of the simple types, 
i.e. bool, int, uint, float and double.
The task is to provide a layout which allows the assembling of the 
uniform buffer object at any time later after the structure definition.

At first I would provide two enumerators for the following information:
1)the subtypes, i.e. the atomic type
        enum sub_type { FLOAT_T, DOUBLE_T, INT_T, UINT_T, BOOL_T };
2) the main types
        enum main_type {SIMPLE, VEC2, VEC3, VEC4, IVEC2,...,MAT2, MAT3,...}

Know, the object carries 4 synchronized MField<unsigned int>:
        MField<uint> _subType;
        MField<uint> _mainType;
        MField<uint> _Dimensionality;
        MField<uint> _index;

At each call to any of the addXXX methods a new entry is generated in 
these four containers. The handle returned by the methods would be the
current position into these four containers.

Additionally, the object has MFields for each of the sub_types, i.e. the 
following value containers.
        MField<float>   _floats;
        MField<double>  _doubles;
        MField<int>     _ints;
        MField<uint>    _uints;
        MField<bool>    _bools;

The addXXX methods would also enlarge the respective value container and 
would store the start position into the _index container.

Now, the setValue methods can take the information about sub type, main 
type array dimensionality and the value container index position from 
the 4 synchronized containers and set the value in the respective value 
container.

At some time the uniform buffer object must be created and filled. Then 
the 4 information multi fields are iterated synchronously and all 
information should be at hand with the set of rules for the std140 
layout for building the buffer content.


What do you think? Could that be working?
What I do not have considered is how to represent arrays of these 
blocks. But first step first.

What I really love about UBO is that they can be installed independently 
of the running shader program and that they therefor allow to define 
different levels of states.

Best,
Johannes



------------------------------------------------------------------------------
Managing the Performance of Cloud-Based Applications
Take advantage of what the Cloud has to offer - Avoid Common Pitfalls.
Read the Whitepaper.
http://pubads.g.doubleclick.net/gampad/clk?id=121051231&iu=/4140/ostg.clktrk
_______________________________________________
Opensg-users mailing list
Opensg-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensg-users

Reply via email to