Drawing only one quad (what to use?)

Hello,

This question is bothering me over a long time, so im deciding to seek your advise.
Currently im creating a game where im drawing all terrain to a single texture, where i only need to draw one quad each chunk.
Even translations are done in the shader, so its really the same quad all the time.

What would be the best method to draw only one quad (multiple times a frame), that never changes.
Since its just 2 rectangles, im puzzled about the most performant method, since vertexbuffers got some overhead, its making it slow with just one quad.
Now im thinking about using displaylists, but im afraid these are depricated.

So what would be the fastest way to draw one quad (with textcoords)?
The SAME quad is used 10 - 30 times each frame.

Use static VBOs for vertex data that doesn’t change often (e.g. position, color) and a dynamic VBO for anything you need to send to the shader per frame (e.g. texcoords). Put all 10-30 quads into the same VBO to improve batching.

The overhead is negligible for such a small amount of vertices. You don’t need to do anything fancy like transform feedback, geom shaders, or instanced rendering.

I’m curious how you plan to render all your terrain with a single quad? Can you show an image of what you mean?

The point is, i have only one quad wich i draw 10-30 times.

Currently im using this code to draw an chunk:


    public void Draw(){
        if(isempty){ return; }

        terrainshader.Enable();
        terrainshader.activeTexture("terrain", 0, terrain);
        terrainshader.activeTexture("mask", 1, mask);
        terrainshader.setVar("clampscreen", Panel.getRect());
        terrainshader.setVar("directoutput", Debugger.ShadeTerrain() ? 1 : 0);
        terrainshader.setVar("screenoffset", new Vector2f(Panel.getX()+parent.getX(), Panel.getY() + parent.getY()));
        
        glBegin(GL_QUADS);
            glTexCoord2f(0, 0);
            glVertex2f(0, 0);
            glTexCoord2f(0, 1);
            glVertex2f(0, Chunk.SIZE);
            glTexCoord2f(1, 1);
            glVertex2f(Chunk.SIZE, Chunk.SIZE);
            glTexCoord2f(1, 0);
            glVertex2f(Chunk.SIZE, 0);
        glEnd();
    }

This is just test code, so i need to convert this “glBegin(GL_QUADS); … glEnd();” to some real rendering code now.
As you can see only one quad is used for all chunks.

Read up on sprite batching. LibGDX has one which you can get inspired by, or see lwjgl-basics:

There is some info on sprite batching here:

These pages might also be relevant, since a sprite batcher pulls together many aspects of OpenGL and graphics programming (shaders, textures, VBOs, etc).




Basically the point is to minimize the number of times you are changing states, and batch as many vertices as you can into the same GL draw call. This means you should sort all of your quads so they aren’t causing a lot of texture switches, or use sprite sheets where possible. Also, you should try using vertex attributes instead of uniforms (i.e. “setVar” it looks like) where possible, if the data is changing per-quad.

At the end of the day, if you are only rendering 30 quads it doesn’t matter. You could stick with immediate mode and still get decent performance.

Thank you, but sprite batching does a lot of other stuff im not looking for.
I have one texture every chunk, so each draw call needs another texture to be bound to the shader.

Ill try to explain my loop:

for(int i = 0; i < 10; i++){
 - Bind Texture
 - Draw quad
}

If i can draw these with only one batch (bind an texture to every quad), please tell me.

About perfomance, im having this issue with multiple objects (like with drawing framebuffers), when im profiling the application, glBegin is way to high in that list :).

Why does each chunk need its own texture? What’s wrong with texture atlases? Most desktops support at least 4k textures these days.

If you are targeting new desktops you can use GL_TEXTURE_2D_ARRAY.

Because each chunk has textures of 512x512 px.
These textures are actually TBO’s to buffer terrain data (Using GL_RG8).
Packing multiple textures tougether, would create a slowdown at the updates (updates currently requires to reupload the buffer data).

Thanks for GL_TEXTURE_2D_ARRAY, maybe i could use this one.

An image for clarification (raster is drawn using gl_lines, therefore the ms each frame is very high):

Red layer is used for masking, green layer for texture index (because texture index is < 15, almost no green is visible).
The raster is the quadtree used for colissions.
The coordinates are at the left top of each chunk.