1

When I need to set color of some triangles, I need to define every vertex as follows:

{
    float x;
    float y;
    float z;
    float r;
    float g;
    float b;
    float alpha;
}

But in this case, every vertex will have one color.

A triangle has 3 vertex, so it need 3 colors, and most of the time, every pixel of a single triangle has the same color.

But I need store 3 color for them, that's a waste of RAM, VRAM and GPU bandwidth.

How to storage only one color for each triangle?

Yun
  • 3,056
  • 6
  • 9
  • 28
LiiiiEW
  • 55
  • 6
  • 1
    Are you aware that storing colors as floats is _very_ wasteful? Typically you have single `uint32_t` that packs the colors and alpha channel as `RGBA`. – Botje Oct 28 '22 at 13:23
  • 1
    You might want to look into using [`glVertexAttribDivisor `](https://registry.khronos.org/OpenGL-Refpages/gl4/html/glVertexAttribDivisor.xhtml) for the colour attribute. – G.M. Oct 28 '22 at 13:25
  • That not important.The problem is storage less colors,not shorter color. – LiiiiEW Oct 28 '22 at 13:27
  • I suppose you are using OpenGL pre 2.0? With "recent" OpenGL, you set the number of values you want to the vertex shader, you eventually could send only one color for all triangles. – Adrian Maire Oct 28 '22 at 13:32
  • @LiiiiEW: "*The problem is storage less colors,not shorter color.*" But the only reason to care about "less color" is how much memory it takes. It is way easier to just use bytes for colors than it is to try to use one color per triangle. – Nicol Bolas Oct 28 '22 at 14:42
  • 1
    @LiiiiEW: You currently have 3 * sizeof(float) = 12byte memory per vertex, which means #faces * 3 * 12 bytes. If you only store a single color per face, you will have #faces * 12 bytes. When you do what Nicol suggested (store a single uint32_t for color), you have #face * 3 * 4 bytes which is exactly the same reduction. Optimally, you'd do both, but if you have to choose one, then both are equally fine. – BDL Oct 28 '22 at 14:51
  • It just a example,not important.The main problem is how to reduce the number of a triangle's storaged attributes,in some cases maybe it not a color with alpha(like a grayscale value,just 1 byte). – LiiiiEW Oct 28 '22 at 15:01
  • Can someone please explain how this is a duplicate? The question linked to is basically "How do I render a mesh with indices using any/all graphics APIs?" which is probably not what people will find when asking themselves "How to remove redundant data from my vertex definition when using OpenGL?". The latter also allows for detailed answers specific to OpenGL. – Yun Oct 28 '22 at 15:24
  • @Yun: "*How to remove redundant data from my vertex definition when using OpenGL?*" Removing redundant data means using multiple indices for different attributes. Every one of your suggestions is a way of using multiple indices for different attributes. – Nicol Bolas Oct 28 '22 at 15:36

1 Answers1

0

Yes, this is possible by storing the colors separately from the positions. There are multiple ways of mapping the vertices to colors:

  1. Using an SSBO. For the vertex, store only the x, y, z-coordinates. Store all colors in a Shader Storage Buffer Object and use gl_VertexID as an index into the SSBO: color = ssbo_colors[gl_VertexID / 3];.

    The downside is that colors cannot be reused, e.g., if you want two triangles to be red, then the color red has to be stored twice.

  2. Using an SSBO with an index per vertex. Use the same method as in 1, but also store a color index for each vertex. Then, reusing colors is possible: color = ssbo_colors[color_idx];

  3. Using a texture. It is also possible to store the colors in a 1D texture, store a texture index with each vertex, and use texelFetch to retrieve the corresponding color. Perhaps this isn't exactly advisable, as textures come with limitations (e.g. size, limited number of textures) and you won't be using typical texture lookup features, such as interpolation and mirroring.

Methods 1 and 2 require OpenGL 4.3. Method 3 requires OpenGL 3.3.

Since you are not using interpolation over the faces of the triangles, you may want to determine the color in the vertex shader and pass it to the fragment shader using the flat interpolation qualifier, and use a provoking vertex.

If you further want to reduce the amount of memory used, look into storing colors as normalized integers.

Yun
  • 3,056
  • 6
  • 9
  • 28
  • 4 float for a color,it just a example,don't care about it.The main problem is reduce the number of a triangle's attributes,some times it not only contain color. – LiiiiEW Oct 28 '22 at 14:56
  • @LiiiiEW These methods work for any attribute, not just color. I used color here, because that is what is in the question. – Yun Oct 28 '22 at 14:58
  • 1
    Note that no version of OpenGL requires SSBOs to be available from vertex shaders. ARB_shader_storage_buffer_object only requires SSBOs to be accessible from compute shaders and fragment shaders. See "MAX_VERTEX_SHADER_STORAGE_BLOCKS" under the "New Implementation Dependent State" heading at https://registry.khronos.org/OpenGL/extensions/ARB/ARB_shader_storage_buffer_object.txt . You may be able to use a UBO instead, though they can be prohibitively small on some platforms. You may need a fallback codepath that uses a texture, or duplicates data in your VBO. – Zaaier Jan 20 '23 at 00:04