Coloring indexed veretices, so That one vertices can have more then one color value

So say I want a Square made of two triangles each triangle diffrent color, but I want it optimised so I use vertex indexing like so:

Summary

This text will be hidden

Summary

This text will be hidden

Summary

This text will be hidden

       float testPositions[] = {
		0.0f, 1.0f, 0.0f, 
		1.0f, 1.0f, 0.0f, 
		1.0f, 1.0f, 1.0f,
		0.0f, 1.0f, 1.0f
	};

	unsigned int indices[] = {
		0, 2, 3, 0, 1, 2
	};

And heres my color Buffer:

    float colorData[] = {
		1.0f, 0.0f, 0.0f,
		1.0f, 0.0f, 0.0f,
		1.0f, 0.0f, 0.0f,

		1.0f, 1.0f, 1.0f,
		1.0f, 1.0f, 1.0f,
		1.0f, 1.0f, 1.0f
		};

(I create every buffer like this:

    unsigned int bufferID;
		glGenBuffers(1, &bufferID);
		glBindBuffer(GL_ARRAY_BUFFER, bufferID);
		glBufferData(GL_ARRAY_BUFFER, bufferData.size() * sizeof(float), bufferData, 
                GL_STATIC_DRAW);

		glEnableVertexAttribArray(1);
		glBindBuffer(GL_ARRAY_BUFFER, bufferData);
		glVertexAttribPointer(
			pointerAttrib,                 
			3,                           
			GL_FLOAT,                  
			GL_FALSE,                       
			0,                                
			(void*)0                      
		);

So I wish that my first triangle would be red and second white but the colors get set for indivial vertecies and indexes. Is there any solution to that or I just have to make some vertecies doubled?

Declare the fragment shader input variable for the colour with the flat qualifier. The value for the last vertex of each triangle will be used for all fragments, rather than interpolating between the values. Then you just need to order the vertices so that the last vertex of each triangle isn’t shared.

This lets you have as many triangles as you have vertices. Large connected triangle meshes average twice as many triangles as vertex positions (six triangles sharing each vertex position), so with flat-qualified attributes you need roughly twice as many unique vertices as vertex positions (rather than a six-fold increase if you just duplicate each vertex for each triangle).

Wow, it worked like a charm. Thanks!. Now ill Check if I can do same for more triangles in one mesh.

Well, so You said that I have to organize my vertices that last one in not shared but im not sure how to make it possibly ion my case. So I generate Vertices like that to create a plain:

	// Calculating Vertices for index Drawing
	for (int x = 0; x < m_size + 1; x++)
	{
		for (int z = 0; z < m_size + 1; z++)
		{
			// Calculating Vertex positions
			float xPush = m_startingPos.x + x * m_sqrWidth; 
			float yPush = m_startingPos.y;					
			float zPush = m_startingPos.z + z * m_sqrWidth; 
															
			indVertices.push_back(xPush); 
			indVertices.push_back(yPush); 
			indVertices.push_back(zPush); 


			//Calculating normals ... 
		}
	}

And then I calculate indices like this:

    // Calculating indices
	int skipper = m_size;
	int skipped = 0;

	for (unsigned int i = 0; i < indVertices.size()/3; i++)
	{
		
		if (i == skipper) {
			skipped++; 
			if (skipped == m_size) break;
			else
			{
				skipper += (m_size + 1);
				continue;
			}
		}

		unsigned int TL = i;					//Top left	
		unsigned int TR = i + (m_size + 1);		//Top right		
		unsigned int BL = i + 1;				//Botoom left		
		unsigned int BR = i + (m_size + 2);		//Bottom right	
													

		indices.push_back(TL);
		indices.push_back(TR);
		indices.push_back(BR);

		indices.push_back(TL);
		indices.push_back(BL);
		indices.push_back(BR);
	}

Thats how I set the color:

    // Calculating Color
	for (unsigned int i = 0; i < indices.size() / 6; i++) 
	{
		if (i % 2 == 0)
		{
			colorData.push_back(0.0f); colorData.push_back(1.0f); colorData.push_back(0.0f);
		}
		else 
		{ 
			colorData.push_back(0.0f); colorData.push_back(0.0f); colorData.push_back(1.0f); 
		}
	}

And with such approach I get what Yop can see on one of the photo.

For a rectangular grid (where each triangle can have a distinct colour), the simplest solution is to make each row independent. So for a grid with M×N cells, you have 2M×(N+1) vertices. E.g.

// vertices
for (unsigned int j = 0; j < rows; j++) {
    for (unsigned int i = 0; i <= cols; i++) {
        position.push_back(glm::vec3(x0+i*dx, y0+(j+0)*dy, z0)); // bottom
        position.push_back(glm::vec3(x0+i*dx, y0+(j+1)*dy, z0)); // top
        color.push_back(colors[j][i%cols][0]); // bottom
        color.push_back(colors[j][i%cols][1]); // top
    }
}
// indices
for (unsigned int j = 0; j < rows; j++) {
    for (unsigned int i = 0; i < cols; i++) {
        unsigned int base = j * (cols+1) * 2;
        // bottom-left triangle
        indices.push_back(base+2); // BR
        indices.push_back(base+1); // TL
        indices.push_back(base+0); // BL
        // top-right triangle
        indices.push_back(base+2); // BR
        indices.push_back(base+3); // TR
        indices.push_back(base+1); // TL
    }
}

I bet this is stupid question but I am beginner so plese forgive me. Why is color vector 3 dimensional in your example?

And this code only gets me one column for some reason. I rememberd to set pointer in buffer to &position[0].x and mulitply buffer size times 3 but it doesnt work for some reason

If you have MxN cells and 2 triangles per cell, then M×N×2 triangles so M×N×2 colours.

If you only had one colour per quad, you wouldn’t need to duplicate vertices.

I think this formula is wrong.
unsigned int base = i * 2 + j * (cols+1) * 2;

You’re right. I forgot the i part.

Thanks for all the help. It looks beautyful : )

One last question. How do I calculate normals of this plain?
I tried the following:

//Calculating Vertices
	for (unsigned int z = 0; z < m_size; z++)
	{
		for (unsigned int x = 0; x <= m_size; x++)
		{
			Vertices.push_back(glm::vec3(m_startingPos.x + x * m_sqrWidth, m_startingPos.y, m_startingPos.z + z * m_sqrWidth));
			Vertices.push_back(glm::vec3(m_startingPos.x + x * m_sqrWidth, m_startingPos.y, m_startingPos.z + (z + 1) * m_sqrWidth));

			glm::vec3 TL = glm::vec3(m_startingPos.x + x * m_sqrWidth, m_startingPos.y, m_startingPos.z + z * m_sqrWidth);
			glm::vec3 TR = glm::vec3(m_startingPos.x + (x + 1) * m_sqrWidth, m_startingPos.y, m_startingPos.z + z * m_sqrWidth);
			glm::vec3 BL = glm::vec3(m_startingPos.x + x * m_sqrWidth, m_startingPos.y, m_startingPos.z + (z + 1) * m_sqrWidth);
			glm::vec3 BR = glm::vec3(m_startingPos.x + (x + 1) * m_sqrWidth, m_startingPos.y, m_startingPos.z + (z + 1) * m_sqrWidth);

			Normals.push_back(glm::normalize(glm::cross(TL - BR, BL - BR)));
			Normals.push_back(glm::normalize(glm::cross(TR - BR, TL - BR)));

			colors.push_back(0.0f); colors.push_back(0.0f); colors.push_back(0.5f);
			colors.push_back(0.0f); colors.push_back(0.5f); colors.push_back(0.0f);
		}
	}

And heres my shader code (I assume its okay since it works with other objects):

#shader vertex
#version 330 core

layout(location = 0) in vec3 position;
layout(location = 1) in vec3 color_in;
layout(location = 2) in vec3 normals_in;

uniform mat4 u_MVP;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

out vec3 FragPos;
out vec3 Normal;
out vec3 color_f;

void main()
{
	color_f = color_in;
	FragPos = vec3(model * vec4(position, 1.0));
	Normal = mat3(transpose(inverse(model))) * normals_in;

	gl_Position = projection * view * vec4(FragPos, 1.0);
};

#shader fragment
#version 330 core
out vec4 color;

in vec3 Normal;
in vec3 FragPos;

in flat vec3 color_f;

uniform vec4 u_Color;

uniform vec3 lightPos;
uniform vec3 viewPos;
uniform vec3 lightColor;


void main()
{
	vec3 objectColor = color_f;

	// ambient
	float ambientStrength = 0.1;
	vec3 ambient = ambientStrength * lightColor;

	// diffuse 
	vec3 norm = normalize(Normal);
	vec3 lightDir = normalize(lightPos - FragPos);
	float diff = max(dot(norm, lightDir), 0.0);
	vec3 diffuse = diff * lightColor;

	// specular
	float specularStrength = 0.5;
	vec3 viewDir = normalize(viewPos - FragPos);
	vec3 reflectDir = reflect(-lightDir, norm);
	float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
	vec3 specular = specularStrength * spec * lightColor;

	vec3 result = (ambient + diffuse + specular) * objectColor;
	color = vec4(result, 1.0);
}

Once again, Huge Thanks for all the help.

That looks correct. Obviously, for a plane you can simplify it somewhat as the normals will all be (0,1,0), but the above should work for an arbitrary mesh.

PS: this is inefficient:

If you need to use a distinct normal matrix (which isn’t necessary if the model-view matrix contains only rotations and translations), calculate it in the application and pass it in as a separate uniform.

And if you’re using per-face normals, you can use the flat qualifier on Normal, and you don’t need to normalise it in the fragment shader.

Hmmm for some reason it doesnt work. I tried to set all normals to 0 1 0 but it still didnt quite work for me. Heres a video of a cube with same shader as plain. The plain clearly should look diffrent. It kinda feels like it is upside down and all diffuse? lighting is gone.

com-video-to-gif