[solved] Passing a lookup table (10 value array) to GLSL

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
GrafZahl
Posts: 37
Joined: Mon Oct 20, 2014 6:24 pm

[solved] Passing a lookup table (10 value array) to GLSL

Post by GrafZahl »

Hi everyone

I think this is an extremely basic question, but I was not able to find the answer so far. Maybe I did not search with the right words?

I want to create a one index lookup table with 10 values (uint8_t or float, I don't care) and this table I want to pass to my pixel shader in GLSL.
In the pixel shader I use a sampler1D variable for that, I think here is everything fine.

However I was not able to pass my 10 value array to the shader with Irrlicht. I think I need to create a texture out of it, right? Then I can use "setMaterialTexture" to bind to texture to the texture layer of the material. And in the ShaderCallback I just need to give the texture index to the shader. So this is clear to me.
But how to create a ITexture object out of the array?

The only way I found so far is to paint my table in a PNG file (1x10 pixel), store this and create an byte array out of the file.
This byte array I can have in my source code (I don't want to use a png-file for that) and then I can use "createMemoryReadFile" to create a IReadFile object out of the array.
This object I can use for the "getTexture" function to load and bind this PNG to my texture...

Even when this works, it seems to be a lot of overhead for 10 simple values. Furthermore: When I want to calculate the values dynamically, I also have to create the PNG file with all CRC and header bytes dynamically... so for me this is not a good solution.

Is there another more simple solution to pass a 10 value array to my GLSL shader as sampler1D?
Last edited by GrafZahl on Sun Nov 16, 2014 5:29 pm, edited 1 time in total.
Irrlicht related projects:
Looking for a cool and easy to use GUI? Try the IrrIMGUI bindings for IMGUI: https://github.com/ZahlGraf/IrrIMGUI
Try out my Irrlicht CMake build system: https://github.com/ZahlGraf/IrrlichtCMake
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: Passing a lookup table (10 value array) to GLSL shader

Post by mongoose7 »

If you pass an array to a shader, it can't be sampler1D. Therefore, you need a texture. So, either
a) Pass ten values to the shader as uniforms, though you should be able to pass an array as the function takes a point and not an int/float, but I've never done it. You can also pass the 10 values in a 4x4 matrix. Or
b) Create a texture and put everything you need into it.

You mention creating values dynamically. Can't you do this in the shader?
GrafZahl
Posts: 37
Joined: Mon Oct 20, 2014 6:24 pm

Re: Passing a lookup table (10 value array) to GLSL shader

Post by GrafZahl »

Thanks for your answer.

Why I can't pass a sampler1D to the shader? Due to Irrlicht limitations?
However it would also be ok for me to pass a sampler2D to the shader instead and just use one row there.

Yes passing this array as uniform to the shader is some kind of workaround for that, I think.
I mean in this case I have just 10 values, nevertheless for other shader I might have very complex lookup tables and I think here the texture solution might be better.

Your solution b is basically exactly what I tried to do: Creating a texture out of it. However, so far I was not able to find any method in Irrlicht to do this.
The only way I found is to create an array where the bytes corresponds to the PNG file format and then I can use "createMemoryReadFile" and "getTexture" to get my ITexture object. But a PNG file has a lot of overhead in calculation and memory consumption (Header, CRC, Compression, Filter).
And since textures as look-up tables for shaders (sampler1D, sampler2D and sampler3D) seems to be a very common concept in shader programming, I assume there is also a good and simple solution for that in Irrlicht.
Irrlicht related projects:
Looking for a cool and easy to use GUI? Try the IrrIMGUI bindings for IMGUI: https://github.com/ZahlGraf/IrrIMGUI
Try out my Irrlicht CMake build system: https://github.com/ZahlGraf/IrrlichtCMake
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: Passing a lookup table (10 value array) to GLSL shader

Post by mongoose7 »

I'm not saying you can't pass a sampler1D. I'm saying *if* you want to pass an array, it can't be a sampler1D.

Although it is usual to use a 1-D texture as a lookup array, it is never a dynamic array. So all cases of this procedure use a texture that has been created outside the program.

I guess what you need to do is create your 1-D texture of size 1x10 (though 1x16 might be better). I don't know if Irrlicht can create a texture without data (anybody?) but OpenGL can. Then you lock the texture (as it is in the GPU) and copy the data. Hence, you can update it at any time.
GrafZahl
Posts: 37
Joined: Mon Oct 20, 2014 6:24 pm

Re: Passing a lookup table (10 value array) to GLSL shader

Post by GrafZahl »

Hi

Maybe my wording was wrong: With one index array, I basically mean a one dimensional array, like a texture, that has only x values but no y values.

Anyway, creating such a texture you mentions in your last sentence is what I want to do. Do you have any entry point for me how I can archive this in OpenGL (just a function name, I will search for it)?

Thanks,
Graf Zahl
Irrlicht related projects:
Looking for a cool and easy to use GUI? Try the IrrIMGUI bindings for IMGUI: https://github.com/ZahlGraf/IrrIMGUI
Try out my Irrlicht CMake build system: https://github.com/ZahlGraf/IrrlichtCMake
GrafZahl
Posts: 37
Joined: Mon Oct 20, 2014 6:24 pm

Re: Passing a lookup table (10 value array) to GLSL shader

Post by GrafZahl »

Hey mongoose7 your wording ("create empty texture") gave me some input and I searched for it:
Actually I found that "addTexture" can create an empty texture.

From the API doc:
virtual ITexture * addTexture (const core::dimension2d< u32 > &size, const io::path &name, ECOLOR_FORMAT format=ECF_A8R8G8B8)=0
=> Creates an empty texture of specified size.

Now I only need to find a way to fill the pixel of this texture...
Irrlicht related projects:
Looking for a cool and easy to use GUI? Try the IrrIMGUI bindings for IMGUI: https://github.com/ZahlGraf/IrrIMGUI
Try out my Irrlicht CMake build system: https://github.com/ZahlGraf/IrrlichtCMake
GrafZahl
Posts: 37
Joined: Mon Oct 20, 2014 6:24 pm

Re: Passing a lookup table (10 value array) to GLSL shader

Post by GrafZahl »

In the end the solution was very easy (as usual, when you found the answer ;-) ).

First I need to create an empty image object with "createImage".
Then I can set the color of all pixel, here in my example I just have some values assigned to the red-channel.
For debug purpose I can also write the image to a png file and look at it in paint. That's also why I assigned 255 to the alpha channel (however, the alpha channel can also be used as independent value for the lookup-table).
Afterwards I just need to add this image to the texture database (together with a name).

As an alternative to the setpixel-function, it is also possible to use "createImageFromData" where you can create an IImage object directly from an array. For big lookup-tables this is faster, but then you need to take care about the array layout (that the right values are assigned to the right pixel and colour channels).
So for small array the solution below seems to be more safety for me.

Code: Select all

 
  IrrVideo::IImage * pLookUpImage = pSceneManager->getVideoDriver()->createImage(IrrVideo::ECF_A8R8G8B8, IrrCore::dimension2d<Irr::u32>(10, 1));
 
  //                                             alpha, red, green, blue - channel
  pLookUpImage->setPixel( 0, 0, IrrVideo::SColor(255, 255, 0, 0));
  pLookUpImage->setPixel( 1, 0, IrrVideo::SColor(255, 250, 0, 0));
  pLookUpImage->setPixel( 2, 0, IrrVideo::SColor(255, 240, 0, 0));
  pLookUpImage->setPixel( 3, 0, IrrVideo::SColor(255, 220, 0, 0));
  pLookUpImage->setPixel( 4, 0, IrrVideo::SColor(255, 175, 0, 0));
  pLookUpImage->setPixel( 5, 0, IrrVideo::SColor(255, 125, 0, 0));
  pLookUpImage->setPixel( 6, 0, IrrVideo::SColor(255,  75, 0, 0));
  pLookUpImage->setPixel( 7, 0, IrrVideo::SColor(255,  25, 0, 0));
  pLookUpImage->setPixel( 8, 0, IrrVideo::SColor(255,  10, 0, 0));
  pLookUpImage->setPixel( 9, 0, IrrVideo::SColor(255,   0, 0, 0));
  this->setMaterialTexture(0, pSceneManager->getVideoDriver()->addTexture("lookup.png", pLookUpImage));
  
  // debug output of the "image"
  //pSceneManager->getVideoDriver()->writeImageToFile(pLookUpImage, "lookup.png");
 
(keep in mind, that the pLookUpImage object must be drooped after usage).

Thanks mongoose7 for pushing my thought into the right direction, so I was able to find the right functions in the API documentation :)
Irrlicht related projects:
Looking for a cool and easy to use GUI? Try the IrrIMGUI bindings for IMGUI: https://github.com/ZahlGraf/IrrIMGUI
Try out my Irrlicht CMake build system: https://github.com/ZahlGraf/IrrlichtCMake
Post Reply