Batch rendering with multiple textures question

Hello!
My last topic was about solving a texture rendering problem using batch rendering, that was solved indexing the sampler2d array with a flat int input. But, looking at the GLSL specification, i can’t do it, or at least, i shouldn’t.

Shader code

// Vertex Shader
#version 450 core
			
layout(location = 0) in vec3 a_position;
layout(location = 1) in vec4 a_color;
layout(location = 2) in vec2 a_textureCoord;
layout(location = 3) in int a_textureIndex;
layout(location = 4) in float a_tilingFactor;

uniform mat4 u_viewProjection;

out vec2 v_textureCoord;
out vec4 v_color;
flat out int v_textureIndex;
out float v_tilingFactor;

void main()
{
	v_textureCoord = a_textureCoord;
	v_color = a_color;
	v_textureIndex = a_textureIndex;
	v_tilingFactor = a_tilingFactor;
	gl_Position = u_viewProjection * vec4(a_position, 1.0f);	
}
// Fragment Shader
#version 450 core

layout(location = 0) out vec4 color;

uniform sampler2D u_textures[32];

in vec2 v_textureCoord;
in vec4 v_color;
flat in int v_textureIndex; // <- here is the "problem"
in float v_tilingFactor;
         
void main()
{
	color = texture(u_textures[v_textureIndex], v_textureCoord * v_tilingFactor) * v_color;
}

The question is: how could i change my code to don’t use an array of sampler2d and index it with an integer index input, and still use batch rendering with more than one texture?

Or

How could i still use array an array of sampler2d, without using and flat int for indexing the samplers?

Here’s data I’m passing to the vertex buffer (QuadVertexDataBuffer):

      struct QuadVertexData
      {
         Vec3 position = { 0.0f, 0.0f, 0.0f };
         Vec4 color = { 1.0f, 0.0f, 1.0f, 1.0f };
         Vec2 textureCoordinate = { 0.0f, 0.0f };
         Int textureIndex = 0;
         Float tilingFactor = 1.0f;
      };

      struct QuadVextexDataBuffer
      {
         static constexpr UInt maxQuads = 10000;
         static constexpr UInt maxVertices = maxQuads * 4;
         static constexpr UInt maxIndexes = maxQuads * 6;
         static constexpr Vec4 defaultPositions[4] = {
               { -0.5f, -0.5f, 0.0f, 1.0f },
               { 0.5f, -0.5f, 0.0f, 1.0f },
               { 0.5f,  0.5f, 0.0f, 1.0f },
               { -0.5f,  0.5f, 0.0f, 1.0f }
               };

         UInt indexCount = 0;
         std::unique_ptr<QuadVertexData[]> data;
         QuadVertexData* currentPos = nullptr;

         QuadVextexDataBuffer()
            : data(std::make_unique<QuadVertexData[]>(
               QuadVextexDataBuffer::maxVertices))
         {
         }

         void addQuad(const Mat4& transform, const Vec4& color,
            const Vec2* textureCoordinates, Int textureIndex,
            Float tilingFactor)
         {
            for (SizeType i = 0; i < 4; ++i)
            {
               this->currentPos->position = transform * defaultPositions[i];
               this->currentPos->color = color;
               this->currentPos->textureCoordinate = textureCoordinates[i];
               this->currentPos->textureIndex = textureIndex;
               this->currentPos->tilingFactor = tilingFactor;
               this->currentPos++;
            }
            this->indexCount += 6;
         }

         IntLong getDataSize() const
         {
            return (IntLong)((Byte*)(this->currentPos) -
               (Byte*)(this->data.get())
               );
         }

         void reset()
         {
            this->indexCount = 0;
            this->currentPos = this->data.get();
         }
      };

Is there some reason you can’t use an array texture? Also, why are you against “using and flat int for indexing the samplers”? That’s the typical method for getting a per-primitive texture index to the shader.

@Alfonse_Reinheart Looking at the topic: “In a fragment shader, why can’t I use a flat input integer to index a uniform array of sampler2D?” from Stackoverflow (I can’t post links) caused me to “go against” using flat ints for indexing samplers.

As the StackOverflow responses point out, if you need to support OpenGL 3.x then the index must be uniform, not just dynamically uniform.

Array textures are supported since 3.0 and have no requirement for the layer to be uniform or dynamically uniform; it can vary per fragment. However, using an array texture means that all layers have the same dimensions, format and sampling parameters.

If you actually need to use an array of samplers in 3.x, you could use a switch statement.

That has nothing to do with being a “flat int” and everything to do with sampling from an array of sampler2D. That is, you’re transmitting the information correctly, but you can’t use it that way. Hence you should use array textures.

I was thinking that maybe i could use batchs per texture (one or more glDrawElements calls per texture) instead of relly on fixed dimension textures using array textures. But I would need to sort my VBO somehow… or add the textures in order, but i would need to use a linked list instead of a fixed size array. I don’t know if this is viable in terms of computacional cost.