5

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.

genpfault
  • 51,148
  • 11
  • 85
  • 139
  • Perhaps a solution would be to create a texture atlas. The only issue would be to get the correct texture coordinates, but that can be done client side by classes and XML. Then you do not have to worry about switching textures. –  Aug 08 '11 at 03:50
  • You're mistreating vertex arrays. The idea of a vertex array is, that you're batching a large set of triangles in a single glDrawElements call, not switch the vertex array pointer for each triangle and have glDrawElements call exactly one triangle. Also there's no requirement to pad your vertex structure to a multiple of 32 (whatever?). – datenwolf Aug 08 '11 at 07:57
  • @datenwolf But in his case it seems neccessary, as he wants each polygon with a different texture (although there are other approaches for this). – Christian Rau Aug 08 '11 at 13:31
  • @Christian Rau: He could use texture arrays for this http://www.opengl.org/wiki/Array_Texture , but I agree a texture atlas probably was the sane solution. – datenwolf Aug 08 '11 at 13:34
  • @Moniker: If you persist with your original approach, try to sort the triangles per texture first, to swap textures as few times as possible during rendering. This is, and has always been, a Good Idea (tm). – Macke Aug 08 '11 at 13:49

2 Answers2

4

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.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • So my plan is what? When I render each region, render groups of each polygons with matching texture indices. How would you recommend doing it? – Moniker Grantis Aug 08 '11 at 03:05
  • @Moniker: Recommend doing what? You haven't said what it is that you're actually rendering. All you've said is that you have some triangles, and you want to associate some number of textures with them. Is this a particle system? Is this some kind of tilemap? Is this a mesh you exported from a modeller? What are you rendering? – Nicol Bolas Aug 08 '11 at 03:32
  • This is a zone from an old game. It has various regions which are linked to meshes. Those meshes contain x amount of polygons and y amount of vertices. I have a PVS which is a potentially visible section so if I am standing in area 3, it generates a list of regions that I can see from my current position. I then, sort those potentially visible regions through a frustum to determine which is visible. Those regions contains polygons which point to vertices in the huge vertex list. The polygons each have an index into the texture list as well. For example, polygon 6 has of region 5... – Moniker Grantis Aug 08 '11 at 07:03
  • ...has reference to vertices 1234, 1263, and 1253. It also has a texture reference. So I want to render all polygons from a specific region. Problem is every polygon has an associated texture. Any ideas. I can draw a UML diagram and I am willing to pay for any help in this area. Seriously... pay money for help in this respect. Thank you. – Moniker Grantis Aug 08 '11 at 07:04
  • @Nicol But with his current code it is definitely possible, although not the fastest/smartest approach. – Christian Rau Aug 08 '11 at 13:43
  • I am in a fairly similar set of circumstances (although I got a bit lost with the generating a list of regions bit) I am rendering a heightmap (i.e. terrain) where "regions" are visible based on your position, a tiled terrain basically, where each "tile" is rendered as you get within a certain distance from it. I am now hitting myself in the head as this approach to rendering only allows me to apply one texture per draw as mentioned by others in this post. It looks like I have to refactor the tile rendering portion to select groups of vertices with different textures. – eggmatters Apr 23 '13 at 16:25
1

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.

Christian Rau
  • 45,360
  • 10
  • 108
  • 185