Arrays can not be passed to GLSL 1.3.

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
Andrey01
Posts: 62
Joined: Mon Jul 27, 2020 9:08 pm

Arrays can not be passed to GLSL 1.3.

Post by Andrey01 »

Before I always passed only non-array uniforms, i.e. just vectors, matrices, floats. However, when I tried to pass arrays of vectors and floats, they are just filled by nulls as if nothing got passed from CPU side.

For example (code from my Irrlicht project):

Code: Select all

s32 lights_count = 2;
services->setPixelShaderConstant("mLightsCount", &lights_count, 1);
services->setPixelShaderConstant("mLightsPositions", reinterpret_cast<f32*>(&lights_positions), 3 * lights_count);
services->setPixelShaderConstant("mLightsColors", reinterpret_cast<f32*>(&lights_colors), 4 * lights_count);
services->setPixelShaderConstant("mLightsIntensities", lights_intensities.data(), lights_count);
In GLSL fragment shader:

Code: Select all

#version 130

#define MAX_LIGHTS_COUNT 10

uniform int mLightsCount;
uniform vec3 mLightsPositions[MAX_LIGHTS_COUNT];
uniform vec4 mLightsColors[MAX_LIGHTS_COUNT];
uniform float mLightsIntensities[MAX_LIGHTS_COUNT];
Here the arrays are std::arrays which are afterwards converted to the standard static ones:

Code: Select all

std::array<core::vector3df, MAX_LIGHTS_COUNT> lights_positions;
std::array<video::SColorf, MAX_LIGHTS_COUNT> lights_colors;
std::array<f32, MAX_LIGHTS_COUNT> lights_intensities;

for (int i = 0; i < lights_count; i++)
{
    lights_positions[i] = lights[i]->pos;
    lights_colors[i] = lights[i]->color;
    lights_intensities[i] = lights[i]->intensity;
}
In that fragment shader below I get access only to the first two elements from each array (since lights_count = 2):

Code: Select all

for (int i = 0; i < mLightsCount; i++)
        // Note that function below works properly independing on the current code, it calculates a PBR color based on the reflection equation
        r += calcReflectCapability(mapNormal, mLightsPositions[i], viewDir, mRoughness, f0, vec3(mLightsColors[i]), mLightsIntensities[i]);
   .......................................................
 
// 'color' is somewhy always actually equal to vec3(0.0, 0.0, 0.0), so outputing a black color
gl_FragColor = vec4(color, 1.0);
I use Irrlicht 1.9 from master branch with the latest commit: https://github.com/zaki/irrlicht . What can I do wrong here?
CuteAlien
Admin
Posts: 9679
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Arrays can not be passed to GLSL 1.3.

Post by CuteAlien »

You should use data() (like lights_positions.data()) to access the address of an std::array object. Like you already do for lights_intensities. Not sure what using address operator directly gives you (probably same, or depends on implementation, I never tried...).

But the more important thing is, I think in setPixelShaderConstant you have to use "mLightsPositions[0]" instead of "mLightsPositions" (and similar for the others).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Andrey01
Posts: 62
Joined: Mon Jul 27, 2020 9:08 pm

Re: Arrays can not be passed to GLSL 1.3.

Post by Andrey01 »

Like no. I tried various ways: reinterpret_cast<f32*>(lights_positions.data()), just lights_positions and then &lights_positions[0] in setPixelShaderConstant(). None of them fixes the issue. I even replaced std::array to the direct static array like f32 lights_positions[3*MAX_LIGHTS_COUNT] and eventually even wrote down explicitly: f32 lights_positions[6]. That doesn't help too.

How the current code looks like now:

Code: Select all

f32 lights_positions[6];
f32 lights_colors[8];
 f32 lights_intensities[2];

for (int i = 0; i < lights_count; i++)
{
	lights_positions[i*3] = lights[i]->pos.X;
	lights_positions[i*3+1] = lights[i]->pos.Y;
	lights_positions[i*3+2] = lights[i]->pos.Z;
	
	lights_colors[i*4] = lights[i]->color.getRed();
	lights_colors[i*4+1] = lights[i]->color.getGreen();
	lights_colors[i*4+2] = lights[i]->color.getBlue();
	lights_colors[i*4+3] = lights[i]->color.getAlpha();

	lights_intensities[i] = lights[i]->intensity;
}

services->setPixelShaderConstant("mLightsPositions", &(lights_positions[0]), 6);
services->setPixelShaderConstant("mLightsColors", &(lights_colors[0]), 8);
services->setPixelShaderConstant("mLightsIntensities", &(lights_intensities[0]), 2);

------------------------------------------------------------
//GLSL fragment shader:
uniform float mLightsPositions[6];
uniform float mLightsColors[8];
uniform float mLightsIntensities[2];
------------------------------------------------------------
// That outputs only the black color below
gl_FragColor = vec4(mLightsPositions[0], mLightsPositions[1], mLightsPositions[2], 1.0);
I can attach the link to my source code:
https://drive.google.com/file/d/1xaXvZ2 ... sp=sharing
CuteAlien
Admin
Posts: 9679
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Arrays can not be passed to GLSL 1.3.

Post by CuteAlien »

Your read my message wrong. Not lights_positions[0] - the shader variable (the one in the string) itself "mLightsPositions[0]".
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Andrey01
Posts: 62
Joined: Mon Jul 27, 2020 9:08 pm

Re: Arrays can not be passed to GLSL 1.3.

Post by Andrey01 »

Yes, that really solved the issue to my wonder. Thanks!
Post Reply