2

So my question is exactly like the title states. I'm not looking for a concrete code example, just some thoughts/guidelines on any preferred methods of doing this.

In my 2D game engine, I like to have a grid that represents a certain amount of pixels (e.g 32x32 pixels). I specifically want to be able to define, the width and height of each grid in world space, have a consistent stroke width on all the lines, and be able to adjust the tile size according to camera zoom.

I've tried several different methods in the past to draw this grid:

  1. The first thing I tried was using a custom shader to draw a grid. I found some code online that used some concepts I didn't understand to just draw the grid on a 2D plane. The problems with this approach are that I didn't know how to control the exact size in my game world, and didn't understand how it worked in general.

  2. My second approach was to use my debug drawing facilities. I coded a suite of functions that allows me to add lines of different stroke widths in world space, and I implemented that by just dynamically generating quads for each line every frame. I can then draw a bunch of lines which gives me a grid.

  3. My third approach was to draw a bunch of quads, and use a custom shader to give them an outline. Then I just draw a bunch of white quads with black outlines, giving the appearance of a grid.

Does anybody have a better solution? In all my approaches I have never tried to adjust the grid dynamically according to the camera's zoom level either. So any thoughts on whether these approaches are the typical solutions, or if there is a better one would be much appreciated. Also, if you have any thoughts on how to extend these methods to 3D space that would also be nice, I can't seem to find a good way to get a uniform stroke width on lines drawn in world space.

My engine is currently being coded using Opengl and C++ too, so I'm primarily concerned on how to implement this using modern opengl, not immediate mode.

Here's an image of what I'm trying to achieve: grid example

Edit: I am primarily concerned with rendering techniques. Do you use several quads? One plane and a complex shader? Or do you use a quad for each line? Or something else entirely?

This is one of my attempts, for another reference of the look and feel I'm trying to achieve. I just can't help but think there has to be a better method then the ones I've tried. enter image description here

1 Answers1

0

regardless of the rendering method First you have to compute the grid. I do it like this:

  1. get AABB (x0,y0,x1,y1) of screen in world coordinates

    The best is to have 3x3 matrix with accumulated all the transform converting from world coordinates into GL screen space:

     vec2 world,screen;
     mat3 w2s;
     screen = w2s*world;
    

    To get the AABB we need the opposite transforming screen corners into world:

     mat3 s2w;
     s2w = inverse(w2s);
     world = s2w*screen;
    

    So simply transform all 4 combinations of (+/-1,+/-1) into world and remember the min and max x,y (AABB) lets call them (x0,y0,x1,y1) This matrix is also extra usefull for mouse interaction as it will transform mouse (if converted to screen coordinates) into world coordinates which you can use for editing,selecting...

  2. grid size gx

    compute grid size from AABB. Simply if your grid is of some world unit size base (like 10) then just simply how big the grid squares will be. For simplicity I will do just single axis (either use min of the 2 axises or do both axises separately):

    // let consider x0=-50, x1=+180 
    gx = log10(x1-x0); // bigest power of 10 to fit inside gx = 2.3617278360175928788677771122512
    gx = floor(gx-1); // round down and use 10 times smaller grid
    gx = pow(10,gx);  // your grid size in world coordinates gx=10
    
  3. grid start position

    simply align x0,y0 to gx,gy... again just one axis:

    x0 = floor(x0/gx)-1
    x0*= gx
    
  4. render

    simply loop from x0 to x1 by step gx and render lines ... I usually do also another pass when I step by gx/10 and render just a dot or less bright/thick line prior to the gx step lines.

Spektre
  • 49,595
  • 11
  • 110
  • 380
  • Hi spektre thanks for the answer! I probably should have been a bit more specific in my question, but I'm primarily concerned with how to render the grid. I've never had much trouble calculating where to place the grid lines, when you say just render a dot in your last step, how do you do that? Via one shader that's doing all 4 of these steps? Or are you drawing a bunch of quads or something to represent a dot? –  Jun 18 '20 at 13:33
  • @GabeAmbrosio for basic low level stuff I use old GL api as the new one is not reliable... If you need speed then the best is to have VBO with the set of points and render that as `GL_POINTS` ... using single QUAD covering screen and rendering a lot of primitives from fragment shader is usually much slower – Spektre Jun 18 '20 at 15:14
  • @GabeAmbrosio if you got uniform tile map then yes using shader and texture atlas + map as textures is the best way ... – Spektre Jun 18 '20 at 15:15
  • If you're referring to OpenGL 3 by the old GL api, I use that as well, if you're referring to immediate mode, I'm refraining from using that because I want to use the GPU for all the drawing routines, and immediate mode is not helpful in that regard. If I were to use `GL_POINTS` it would require a lot more calculation CPU side to generate enough points to make a good looking line, I thought drawing quads that represent lines would do a better job at that since it would only require 4 points per 'line'. I'm not currently using a texture, but I've considered doing a tiled texture. –  Jun 18 '20 at 17:55
  • @GabeAmbrosio GL_POINTS for points and GL_LINES for lines ... my grids looks like [this](https://stackoverflow.com/a/30750626/2521214) – Spektre Jun 18 '20 at 19:31
  • Ahh. I kept thinking `GL_LINES` and `GL_POINTS` were only immediate mode, I forgot that you can call `glDrawArrays`, and `glDrawElements` with it as well. My only concern about this approach is flexibility in terms of appearance, however it's nice and simple and seems like a good starting point! I'm going to leave the question as unanswered though, because I'm curious about other developers approaches. Thanks Spektre! –  Jun 18 '20 at 21:47
  • @GabeAmbrosio I am afraid that aspect of your question is `opinion based` without really narrowing down some constraints for specific situation ... like data representation, use , etc ... but even then such questions tent to be closed as of topic – Spektre Jun 19 '20 at 06:32
  • Ok, I think that's fair. I'll make a Reddit post about this to continue the conversation. –  Jun 19 '20 at 17:35