2

I am developing an application in C++ in QT QML 3D. I need to pass tens of float values (or vectors of float numbers) to fragment shader. These values are positions and colors of lights, so I need values more then range from 0.0 to 1.0. However, there is no support to pass an array of floats or integers to a shader in QML. My idea is to save floats to a texture, pass the texture to a shader and get the values from that.

I tried something like this:

float array [4] = {100.5, 60.05, 63.013, 0.0};
uchar data [sizeof array * sizeof(float)];
memcpy(data, &array, sizeof array * sizeof(float));
QImage img(data, 4, 1, QImage::Format_ARGB32);

and pass this QImage to a fragment shader as sampler2D. But is there there a method like memcpy to get values from texture in GLSL? texelFetch method only returns me vec4 with float numbers range 0.0 to 1.0. So how can I get the original value from the texture in a shader? I prefer to use sampler2D type, however, is there any other type supporting direct memory access in GLSL?

genpfault
  • 51,148
  • 11
  • 85
  • 139
david
  • 31
  • 1
  • 4
  • This doesn't solve my problem. I don't have any problem to create the QImage with correct float values. I have a problem to access these values in a shader (in GLSL). – david Jul 21 '17 at 14:45

2 Answers2

3

This will create a float texture from a float array.

glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, width, height, 0, GL_RED, GL_FLOAT, &array);

You can access float values from your fragment shader like this:

uniform sampler2D float_texture;

...

float float_texel = float( texture2D(float_texture, tex_coords.xy) );

"OpenGL float texture" is a well documented subject. What exactly is a floating point texture?

Octo
  • 543
  • 1
  • 5
  • 16
  • Hi, could you please expand your answer on *how to access the values from the fragment shader*? To me it seems this might be applicable to my problem described here: https://stackoverflow.com/questions/45301962/passing-qml-array-to-shadereffect – derM - not here for BOT dreams Jul 26 '17 at 08:47
  • When I use glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, width, height, 0, GL_RED, GL_FLOAT, &array); I must pass the created texture to shader like this: GLuint texture_sampler_loc = glGetUniformLocation(shaderprogram, "texture"); glUniform1f(texture_sampler_loc, 1); But in the QML I can not get pointer to shader program. Or is there any other way how to pass the texture to shader? – david Jul 26 '17 at 13:46
2

The texture accessing functions do directly read from the texture. The problem is that Format_ARGB32 is not 32-bits per channel; it's 32-bits per pixel. From this documentation page, it seems clear that QImage cannot create floating-point images; it only deals in normalized formats. QImage itself seems to be a class intended for dealing with GUI matters, not for loading OpenGL images.

You'll have to ditch Qt image shortcuts and actually use OpenGL directly.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • When I created the QImage like above, the values are saved there, but not organized per pixel. So that is why I need some function like memcpy in GLSL, which doesn't access the texture per pixel or texel, but just copy the bytes to any array. Is there some function like this? – david Jul 21 '17 at 15:14
  • 2
    @david: The *are* organized per-pixel. It's just that Qt is interpreting those pixels as 8-bit-per-channel normalized integers, instead of 32-bit-per-channel floats. OpenGL can do exactly what you need; just use it *correctly*. – Nicol Bolas Jul 21 '17 at 15:15