Jump to content
  • Advertisement
Sign in to follow this  
Sean_Seanston

OpenGL Methods for Drawing a Low-Resolution 2D Line Gradually?

This topic is 1292 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hope that title was descriptive enough, but I've prepared a diagram to describe exactly what I'm talking about:

oi62.tinypic.com/11imhr7.jpg

 

As you can see, the image is split into 3 panes. At the top we have two icons that I want to draw a line between. At the bottom there's a complete line between the two as I want it to look when it's finished, and the middle shows a partway progression of the line between the two states.

 

What I'm trying to achieve is basically the ability to draw a line between 2 points in the same style as if you used the pencil tool in Photoshop by clicking somewhere then holding shift and clicking somewhere else to draw a straight line between them. I don't want it to be anti-aliased or hi-res, and I need to be able to control the thickness of the line while retaining the pixellated look so it fits in with the simplistic art style I'm using.

What I want to use it for is graphically representing the path an object is travelling along over time, so it would start off as some kind of dotted line (e.g. only occasional square sections of the line being drawn) and then as the object got closer the line would be drawn in to represent the object's current position, as shown in the middle pane.

 

So... how might I accomplish this? I'm using C++ and OpenGL if it matters.

 

For something that seems so simple, it sure gets complicated when you don't have any experience with this kind of thing and start trying to come up with actual solutions that can be coded.

We start with the 2 points, so we'll need to come up with the equation of the line between them and the slope of that line. The slope tells us how many pixels y will increase by for every pixel that x increases, which is clearly what we need here, but where do we go from there?

My first semi-naive and probably impractical (but maybe someone else knows better) thought was:

1. Create an image file of a square representing the minimum "brush size" of the line.

2. Draw it onto the start position of the line, then draw it for every subsequent step along the line.

Am I right in thinking that would be terribly inefficient? Sounds like it would be. I'm also not sure if I really know how to determine exactly where each "brush" should be drawn.

 

Then I searched around a bit and heard about Bresenham's Line Algorithm. That looks like it would be relevant. The description on Wikipedia states:

"determines the points of an n-dimensional raster that should be selected in order to form a close approximation to a straight line between two points."

 

So that's exactly it. My only concerns would be:

1. Is it a simple matter to replicate a lower-resolution line than the actual resolution of the display? i.e. Make it nice and blocky and easily change this resolution at will.

2. Even if I do use that algorithm to determine what pixels should be coloured in, how should I draw them? Would it be best to use some kind of OpenGL primitives or similar OpenGL function? It would have to be horribly inefficient to use a textured quad for every square "pixel" of the line, but I'm not sure what the obvious alternative is because I haven't done anything like this before.

 

Thoughts?

Share this post


Link to post
Share on other sites
Advertisement

0) Yes, the algorithm is simple enough. Figure out the rise and run, then step along each pixel and draw it.

 

1) You can change the line width the same way, but it requires a bit of math to build properly. Ensure that you have the correct number of parallel pixels involved in the line, or draw the correct number of pixels above/below/beside the pixel you are processing. Determining the correct number depends on the angle of the line.

 

2) You should only do this if you are building your own rasterizer. If you are using OpenGL it already has these primitives built in. Your graphics card and drivers also already have these primitives built in. A thick line might require changing thousands of pixels. For drawing an individual line you can either make thousands of individual calls, potentially requiring thousands of trips across the system bus and across the hardware, or you can make a single call, with a single trip out to the graphics card.  It should be clear that one is several orders of magnitude more efficient.

 

3) Thoughts are that as a learning exercise to understand how the raserizers work it is a good thing to experience on your own. But after you've build your own software rasterizer, throw it away and go back to the hardware accelerated graphics systems.

Share this post


Link to post
Share on other sites
2) You should only do this if you are building your own rasterizer. If you are using OpenGL it already has these primitives built in. Your graphics card and drivers also already have these primitives built in. A thick line might require changing thousands of pixels. For drawing an individual line you can either make thousands of individual calls, potentially requiring thousands of trips across the system bus and across the hardware, or you can make a single call, with a single trip out to the graphics card.  It should be clear that one is several orders of magnitude more efficient.

 

Well for the sake of getting a game/feature completed, I'll take a quick and easy way here if at all possible. It's annoying getting hung up on this little features...

 

So am I right in thinking it's just a matter of using GL_LINES with some vertex data?

 

For a low-res effect would you have to do something with the fragment shader? And would that be quite a simple thing to implement, or somewhat tedious/time-consuming? I just wouldn't be quite sure how/where to begin...

Though I have heard about rendering the whole screen to a texture and then resizing that texture before displaying it on screen as a means of getting a low-res look. Here I just need to change the line itself though, so presumably there are better/quicker ways of achieving that.

Share this post


Link to post
Share on other sites

BTW, on the subject of fixed-function v shader-based OpenGL, is it ever a good idea to actually use FF functions to accomplish things even if you're generally using shaders? i.e. Can it sometimes be more convenient and not really worth the hassle of shaders etc. when you just want to do something quite limited, or should FF always be avoided nowadays?

 

EDIT: Also thinking about it further, I could clearly achieve the desired effect if I was able to use OpenGL to render a 1px-thick line between 2 points and then simply find a way to scale up the pixels by a factor of X and only keep the first 1/X of the line. Does that sound practical? How might you scale up a line like that? Or am I way off in my thinking?

Edited by Sean_Seanston

Share this post


Link to post
Share on other sites
You could render a 1-pixel thick line to a texture and then apply it to a quad of any size. I've never done render to texture, so I cannot help you there, but I've seen several tutorials online.

Share this post


Link to post
Share on other sites

You could render a 1-pixel thick line to a texture and then apply it to a quad of any size.

 

Hmmm... yes that seems like it would make sense. Haven't used render to texture myself either, but it sounds like the kind of thing that would work.

 

Might be a bit fiddly, but presumably it would work out in the end.

 

So unless anyone else has any better ideas, which I would be interested in hearing, I'll probably go with that.

 

Thanks all.

Edited by Sean_Seanston

Share this post


Link to post
Share on other sites

If you're set on drawing the line gradually, I'd do the same thing with RTT, but linear interpolate the position between endpoints and draw quads centered at each point. You'll get some overdraw, but it will be minor since you'll be drawing so little anyway and you'll be able to control the thickness of the line at the same time.

Share this post


Link to post
Share on other sites

If you're set on drawing the line gradually, I'd do the same thing with RTT, but linear interpolate the position between endpoints and draw quads centered at each point.

 

Just to clarify because I'm not 100% sure I understand fully... are you saying to use 2 quads, each centred at an endpoint, one representing the filled/complete section of the line and the other representing the dashed/incomplete section?

Share this post


Link to post
Share on other sites

No, it sounded to me like you want to draw the line gradually over time. I might be misunderstanding. If this is what you mean, what I am saying is to linearly interpolate the line between the two endpoints at each time step. So, the first time step you'd draw the first end point. The next time step, you'd draw the first interpolated point between the two end points, etc. Each time you draw, don't draw a single pixel (unless that is what you want), but a quad of the thickness you desire.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!