Float encoding gpu side(+ blabla, introduction)

Hello everybody.

To make a long story short, I wrote a very long message yesterday … and forgot to post it.

So, it will be shorter today.
English is not my native language.
Plus it’s very late. I will make even more mistakes.

I have several “objects”. I don’t mean by this term “open gl set of attributes” or anything like that. I mean : a ship, a rock etc.

All of this objects have several parts.
Each part has a material.

However, there is few materials : they are reused over and over again between objects.
(you can look at kenney’s resources if you want an example).
And I can even reduce this number as many materials are only a single color. I can end up with very few render passes.

So, the idea is: have one mesh per material, and store objects as subparts of the mesh.
I can “acquire” and “release” triangles, and I use a virtual addressing so I can relocate the triangles to keep a mesh without holes.
I already have all of this.

However, I need now to give a transformation matrix to each of my objects.
The idea I have is : store an integer on every vertex (or “on every triangle” if possible, but I think there is still no “triangle shaders”, so it will be “on every vertex”).
This integer references a column in a texture.
The texture has a dimension of n*12 (width = n, height = 12)
n is a power of 2, greater than (or equals to) the number of objects I have.

Why “12” ? Well, it’s a 4x4 matrix, but the last line is always “0 0 0 1”. So, there is 4x3 “meaningfull” values = 12

This way, when I want to update the position/rotation of an object, I can just update one column in the texture.
Technically, 6 float would be enough : euler angles + position. Or 7 : quaternion + position. But whatever, it’s not the question.

My questions are:
is this the “good” way of doing it ?
is there a gl function called “glFloatToBytes”, which would convert my IEEE754 float on my cpu to the representation of the float gpu side ? I don’t know how to store floats in a texture. As it is graphic-card dependent, it has to be a gl function.
is it possible to associate an integer to each vertex ? I know I can associate texture coordinates, normals, colors … but a single integer ? I will need this integer in the vertex shader to lookup for the matrix values in the texture.
do you know a library (in C) that already does that ?
(is this forum the good one ? I am not sure it’s a basic or advanced question)

I am not aiming for a particular version of OpenGL. However, my graphic card is pretty old (amd radeon 6570).
And, if possible, it would be better to run on mobile (in theory, as I don’t have any kind of android anyway).
So, OpenGL ES 2 or 3 would be nice.

I am pretty sure I don’t do “opengl >3.1” stuff. However, as I use (basic) shaders and vbo’s the transition should not bo that hard.

I don’t have internet during the day, only during the evening (after midnight and before 4 am). And then I don’t have an environment to program (and I have other things to do anyway).

thanks for reading.
hoping anwsers.

[QUOTE=bubuche;1292155]
is there a gl function called “glFloatToBytes”, which would convert my IEEE754 float on my cpu to the representation of the float gpu side ? I don’t know how to store floats in a texture. As it is graphic-card dependent, it has to be a gl function.[/QUOTE]
Provided that you can rely upon OpenGL 3.0 or the ARB_texture_float extension, you can just use a floating-point texture format (e.g. GL_RGBA32F). There are other options, such as signed normalised and signed integer formats up to 32 bits per component, but those also require 3.0 (or an extension). If you only have 2.1, you’re limited to 16 bit unsigned normalised values. And for OpenGL ES, you aren’t even guaranteed 8 bit normalised values (textures could be limited to 16 bits per pixel = 5 bits per component).

You want to avoid packing a float into several 8-bit components. Even if you can rely upon having the required precision, and can perform the unpacking without introducing errors, it’s going to be inefficient.

Also, with a sufficiently-modern version of OpenGL, you don’t need to use textures for this. You can just use uniform arrays or (for arrays which are too large for the default uniform block) UBOs or SSBOs.

Yes, provided that you have at least OpenGL 3.0. In earlier versions, vertex shader inputs (attributes) are limited to floats. Note that you need to use glVertexAttribIPointer to specify values for an integer attribute. Using glVertexAttribPointer will cause the values to be converted to floats, which won’t work if the GLSL variable is an integer.

Thank you a lot !
Especially for the glVertexAttribIPointer, I got weird results and I was wondering why.
Strangely enough I got the correct result by declaring the type of the buffer as containing floats (in C side), using glVertexAttribPointer ( C side ) and declaring it as int (shader side).

I heard about the texture-of-float thing but I don’t see how to get it, shader side.
I can use the “texture2D” function, but it returns a vec4.

(yep, I made some progress today. It was on of these “on fire” day).

[QUOTE=GClements;1292158]Provided that you can rely upon OpenGL 3.0 or the ARB_texture_float extension, you can just use a floating-point texture format (e.g. GL_RGBA32F). There are other options, such as signed normalised and signed integer formats up to 32 bits per component, but those also require 3.0 (or an extension). If you only have 2.1, you’re limited to 16 bit unsigned normalised values. And for OpenGL ES, you aren’t even guaranteed 8 bit normalised values (textures could be limited to 16 bits per pixel = 5 bits per component).
[/quote]

Ok, well understood. I am going for 3.1 (choice).

You want to avoid packing a float into several 8-bit components. Even if you can rely upon having the required precision, and can perform the unpacking without introducing errors, it’s going to be inefficient.

Received.
However, you can note that I make a lookup in the texture vertex shader.
This texture is only used to contain transformation matrices.

So, it’s not an operator performed in the fragment shader, so I think I can be a bit more heavy.
But I got your advice.

Also, with a sufficiently-modern version of OpenGL, you don’t need to use textures for this. You can just use uniform arrays or (for arrays which are too large for the default uniform block) UBOs or SSBOs.

I heard that it’s in opengl 4.
I am not even sure my graphic card can handle this, and as most models will look like flat untextured stuff, it will be annoying to go for such a high version.
Especially for only one single functionnality.
And even more if I can have roughly the same result with a texture.

Yes, provided that you have at least OpenGL 3.0. In earlier versions, vertex shader inputs (attributes) are limited to floats. Note that you need to use glVertexAttribIPointer to specify values for an integer attribute. Using glVertexAttribPointer will cause the values to be converted to floats, which won’t work if the GLSL variable is an integer.

I already said it, but once again thank you.
I will test that tonight, and answer tomorrow.

Right now I am looking for the shader function to extract a float from a texture. (texture2D is not made for this is seems).

[QUOTE=bubuche;1292207]
Strangely enough I got the correct result by declaring the type of the buffer as containing floats (in C side), using glVertexAttribPointer ( C side ) and declaring it as int (shader side).[/quote]
If you declare it as containing floats, and the variable is assumed to be a float, the data will just be copied without any transformation. But this relies on there being no difference in the treatment of float and integer attributes.

A vec4 is 4 floats. The sampling operation will convert from the texture’s format. E.g. for an 8-bit unsigned normalised texture, sampling will divide by 255.0 to produce values in the range [0.0, 1.0]. For a floating-point texture, there’s no conversion.

The return type of texture() etc depends upon the sampler type. For integer textures, you need to use e.g. isampler2D or usampler2D, which will cause texture() to return ivec4 or uvec4.

Uniform arrays are available in 2.0, but the amount of space for uniforms is quite limited, so early GLSL programs often used textures for arrays which exceeded the available uniform storage. UBOs were added in 3.0. SSBOs were added in 4.3; their main purpose is to provide read-write storage, but they have the added advantage that size is limited only by available video memory.

texture2D() returns a vector of 4 floats, one for each component. Missing components result in 0.0 (for G/B) or 1.0 (for alpha). If you have fewer components, you just extract those components from the result with swizzling.

The main issue is that 8 bits probably isn’t enough. 16 bits might be (accuracy of ~1/200th of a degree), and 2.1 guarantees support for 16-bit formats (e.g. GL_RGB16).

thanks a lot.
It was an other good day and everything is going very well now.

I managed to pass the position (in a single pixel, using rgba32f) and somehow the matrix etc.

Now I can focus on improve that etc. but the basics are here.

Thank you all very much.