Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Texturing each polygon in vertex array - OpenGL

I am trying to get my render function to work. I am using vertex arrays. Here is the my vertex structure.

struct Vertex 
{
    float x, y, z;              // The x, y and z floating point values     
    float u, v;                 // The u - v texture coordinates
    float padding[3];   // needs to be multiple of 32
};

Here is my render code:

// Render the mesh
void WLD::render(GLuint* textures, long curRegion, CFrustum cfrustum)
{

    int num = 0;

    // Set up my indices
    GLuint indicies[3];

    // Cycle through the PVS
    while(num < regions[curRegion].visibility.size())
    {
        int i = regions[curRegion].visibility[num];

        if(!regions[i].dead && regions[i].meshptr != NULL)
        {
            if(cfrustum.BoxInFrustum(regions[i].meshptr->min[0], regions[i].meshptr->min[2], regions[i].meshptr->min[1], regions[i].meshptr->max[0], regions[i].meshptr->max[2], regions[i].meshptr->max[1]))
            {
                // Cycle through every polygon in the mesh and render it
                for(int j = 0; j < regions[i].meshptr->polygonCount; j++)
                {   
                    // Assign the index for the polygon to the index in the huge vertex array
                    indicies[0] = regions[i].meshptr->poly[j].vertIndex[0];
                    indicies[1] = regions[i].meshptr->poly[j].vertIndex[1];
                    indicies[2] = regions[i].meshptr->poly[j].vertIndex[2];

                    glEnableClientState(GL_VERTEX_ARRAY);
                    glVertexPointer(3, GL_FLOAT, sizeof(Vertex), &verticies[0].x);

                    // Texture index
                    int tex = regions[i].meshptr->poly[j].tex;
                    // Need to bind this to the polygon I render.

                    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
                    glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &verticies[0].u);
                    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, indicies);

                    glDisableClientState(GL_VERTEX_ARRAY);
                    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
                }
            }
        }
    num++;
    }
}

One of the arguments, GLuint* textures contains all the loaded textures. So the value returned by line int tex = regions[i].meshptr->poly[j].tex; is the index in the textures for this specific polygon. How do I bind that to each polygon when I render it? Let me know if you have any questions.

I know I need to use glClientActiveTexture() but one, it says it's undefined and I can't find the correct header, and two, I have no idea how it is used. I couldn't find any good examples. So how do I, if say the polygon references texture index 4, bind it to the polygon as I render with glClientActiveTexture.

like image 559
Moniker Grantis Avatar asked Oct 11 '22 07:10

Moniker Grantis


2 Answers

What you are trying to do is not generally possible. You usually do not attempt to render a single stream of triangles (a glDraw* call) with multiple textures. Well, not the way you mean, at any rate.

Each triangle within a single draw call must pull from the same set of textures as every other triangle within that draw call.

The general solution is to combine the images into a single texture. This is commonly called a "texture atlas". In this case, the texture coordinates on the vertices describe where in the texture atlas (which is a single texture) to pull image data from.

If you are using GL 4.0-capable hardware (D3D11) and GLSL, then there are tricks you can play to dynamically select between 16 textures based on arbitrary computations. And for earlier hardware, you could use shaders to pick between textures. But both cases would be slower than just massaging the data properly.

like image 56
Nicol Bolas Avatar answered Oct 20 '22 00:10

Nicol Bolas


You can do this with your currect approach. You don't need glClientActiveTexture. This function is for multitexturing and I suppose every polygon has only a single texture applied. So just bind the neccessary texture using glBindTexture(GL_TEXTURE_2D, textures[tex]) and don't forget to glEnable(GL_TEXTURE_2D) (if not using shaders) before drawing the polygon.

But although it works, this is obviously not the best way to do it. Vertex arrays are there to render multiple primitives (triangles) in one go (one call to glDrawElements) and you missuse them to render single triangles. The first and easiest idea would be to at least sort your polygons by texture index and then render all triangles with the same texture in one call to glDrawElements. Look at Nicol's answer for more advanced approaches.

like image 43
Christian Rau Avatar answered Oct 20 '22 00:10

Christian Rau