To map a texture to the triangle we need to tell each vertex of the triangle which part of the texture it corresponds to

Each vertex should thus have a texture coordinate associated with them that specifies what part of the texture image to sample from. Interpolation is used to estimate the middle part

Texture Coordinates

tex_coords.png

float texCoords[] = {
    0.0f, 0.0f,  // lower-left corner  
    1.0f, 0.0f,  // lower-right corner
    0.5f, 1.0f   // top-center corner
};

Generating a Texture

// Textures are created and referenced with an ID
unsigned int texture;
glGenTextures(1, &texture);

// Bind it so any subsequent texture commands will configure the currently bound texture
glBindTexture(GL_TEXTURE_2D, texture);

// Generate a texture using the previously loaded image data
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
// use nearest neighbor filtering when textures are scaled downwards and 
// linear filtering for upscaled textures.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

Screen Shot 2022-06-17 at 3.31.01 PM.png

See this article for some great illustrated examples 🙂 :

Mipmap | Learn OpenGL ES

MipMap