1

I'm learning OpenGL, and I've been experimenting with creating widgets for a GUI. Rendering a monochrome box as (pos, color)[4] seems a little wasteful to me. Is there a way to pack this down to (x, y, w, h, color)?

I'm not going to be drawing enough rects that it's going to matter much, but I'm curious.

Note: I'm representing each vertex/object with a tuple for convenience.

Straivers
  • 349
  • 1
  • 9
  • yes ... geometry shader can emit from your single Vertex 2 triangles filling your rectangle... – Spektre Apr 29 '20 at 08:54
  • You could use that to draw circles, outlines, etc. with the same shader that way too, couldn't you? – Straivers Apr 29 '20 at 18:16
  • Yes ... but in case of circle you would need to emit outscribed shape and in fragment decide if pixel inside or `discard` if not. Something like this: [How can i make gradient sphere on glsl?](https://stackoverflow.com/a/41442375/2521214) Because there is a limit on amount of vertexes that can be emitted from single primitive... also this [Draw Quadratic Curve on GPU](https://stackoverflow.com/a/31423105/2521214) might interest you – Spektre Apr 30 '20 at 06:10
  • Are you familiar with OpenGL instancing? If you make use of that, you can have your normal `(0, 0), (0, 1), (1, 0), (1, 1)` co-ordinates specified just once and then for each instance specify only a colour, x, y, w, h etc – Andrea May 03 '20 at 12:47
  • Only tangentially. However, I'd ideally like to be able to render multiple object types within a single draw call. It may (not) be the most performant, but it's a bit easier for me to work with. – Straivers May 03 '20 at 21:19

2 Answers2

1

Alright, so after some experimenting with the hint given by Spektre, I think I have a solution.

I've taken to representing a shape as:

struct Shape {
  enum Kind : byte {
    LineRect,
    FillRect,
    ...
  }

  float2 position, extent;

  uint color;

  Kind kind;
}

The vertex shader takes that struct, and passes the entire thing along with the projection matrix to the geometry shader to generate the vertices. The geometry shader switches on kind and emits the vertices for the shape, multiplying each vertex by the projection matrix.

This format requires 21 bytes (float + float + float + float + uint + byte) to represent rects, circles, isosceles triangles, and possibly ellipses. I have reason to believe that textured rects is also possible, where color is split into ushort[2] for uv coordinates.

Straivers
  • 349
  • 1
  • 9
0

Well, you can somehow abstract the code to some class that uses these parameters, something like SDL2 has done. There is no OpenGL Class that can help you with these questions. Something Like:

struct Vertex {
    glm::vec3 position;
    glm::vec3 color;
};
class Model {
private:
    std::vector<Vertex> mVertices;
public:
    Model(/* Pass Vertices or Load Model through OBJ */);
};

This is what I used and sorry instead of passing vertices pass unsigned int width, unsigned int height, unsigned int xpos, unsigned int ypos and pass them to a transformation matrix. Hope That Helps!

Steven James
  • 63
  • 1
  • 7