GLSL 330 multi texturing per vertex.

I’m back again finally after learning more about glsl 3.3/opengl 3.3 and I’ve been trying to get my multi texturing to work with little success so far.

This just draws a quad with a single texture, I loaded 2 textures and if I change the fragSampler uniform I can change textures but I want to make this change per vertex…

glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);

	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(float), (void*)0);
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 6*sizeof(float), (void*)(3*sizeof(float)));
	glEnableVertexAttribArray(2);
	glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, 6*sizeof(float), (void*)(5*sizeof(float)));

	glActiveTexture(GL_TEXTURE0 + 1);
	glBindTexture(GL_TEXTURE_2D, grass.getTexture());
	glActiveTexture(GL_TEXTURE0 + 2);
	glBindTexture(GL_TEXTURE_2D, rock.getTexture());

	glUniform1i(fragSamplerLoc, 2);
	glDrawElements(GL_QUADS, (sizeof(index) / sizeof(unsigned int)), GL_UNSIGNED_INT, (void*)0);

	glDisableVertexAttribArray(0);
	glDisableVertexAttribArray(1);
	glDisableVertexAttribArray(2);
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

edit: in my frag shader fragSampler is just a uniform sampler2D.

I figured I could just add the texture unit at the end of each of my vertices data… like this…
first 3 are vertex, next 2 are texture cords and finally the texture unit.

float data[] = {
	-0.2, -0.2, 0.0,		0.0, 0.0,	1,
	0.2, -0.2, 0.0,			1.0, 0.0,	2, 
	0.2, 0.2, 0.0,			1.0, 1.0,	2,
	-0.2, 0.2, 0.0,			0.0, 1.0,	2

};

If I just use…

layout (location = 2) int textUnit;

and pass the unit to the frag shader per vertex I thought it would work but it was drawing random colors instead of the textures. I also tried making the int textUnit into a sampler2D textUnit since that’s how my current code works it just sets the samplers to the current texture unit… no luck with this either. I also tried…

layout (location = 2) int textUnit;

in vec2 textCoord;

sampler2D textSampler

out outpurColor;

void main()
{
    outputColor = texture(textSampler + textUnit, textCoord);
}

This didn’t work at all. I’m sure I’m missing something simple here but it’s been bugging me for 2 days so here I am again.

PS: If you notice some small syntax error like a misspelled variable it’s cause I wrote this code out as I’ve been testing stuff all day and don’t have most of the old stuff in my program anymore. It’s likely not the cause of my issues.

I am not sure what are doing in above code.

Are you passing attributes to fragment shader? AFIK we can’t pass attribute to frag shader, you need to use uniform variable instead. Even if you are planning to pass texture unit in attribute data and hence to vertex shader, it will interpolate those values when passing to fragment shader so you can’t pass by interpolation.
You can use conditional rendering in fragment shader.

So I’d need a sampler for each active texture and pass the attribute from vertex to the frag shader… Just do if attrib equals 1 use sample1 … Is this what you mean? Seems like a weird solution. Surely there is a way I can pass data to the frag shader on a per vertex bases (from a vbo).

From the OpenGL wiki:

Samplers do not have a value. They can not be set by expressions and the only expression they can be used in is as the direct argument to a function call which takes an in​ sampler of that type.

Instead you could use a 2D array texture for this. You’d use a sampler2Darray instead of sampler2D and include an extra term in your texture coordinate which indicates the layer to use. See Array Texture - OpenGL Wiki.

Of-Course you can pass data from vertex to fragment shader. What i meant to say is that due to interpolation you cannot have selection criteria based on data coming from vertex shader.

The fragment shader deals with fragments, not vertices. The outputs from the vertex shader are interpolated to produce the inputs to the fragment shader. Interpolation can be “flat” (and for integer attributes, it must be flat), meaning that the value from one of the vertices (either the first or the last, see glProvokingVertex()) is used for all fragments forming the primitive.

However, samplers cannot be used for shader inputs or outputs, only uniforms and function parameters. In 4.x, you can have an array of samplers, and select one with a dynamically-uniform expression, i.e. something which is constant across a primitive (IIRC, in 3.x it had to be uniform, i.e. constant for an entire draw call). Or you can use an array texture, but that requires all layers to have the same dimensions, and the filter/wrap modes are common to all layers. In any case, the general solution is to pass values which are used to select which samplers to use, rather than trying to pass samplers around as if they were values.