Very Simple: Back To Top
Very Simple: Back To Top
I'm rather unsatisfied with how difficult and scattered good OpenGL tutorials are. I'm going to
document this stuff here so I can find it and so anyone else interested now or in the future can
find it.
Think vehicle HUDs with speedometers, "Objective Hint Displays", maybe even "mini-maps".
We'll see ...
This is going to start very simple and build its way up eventually.
Last edited by Baker on Wed Dec 17, 2008 2:48 am; edited 2 times in total
Back to top
Baker
Code:
// Render Frame
glClear (GL_COLOR_BUFFER_BIT) // Clear it
glColor3f (1,0,0) // RGB = Red
glBegin (GL_LINES) // Draw lines
glVertex2d (128, 256) // x1,y1
glVertex2d (384, 256) // x2,y2
glend ()
Last edited by Baker on Tue Dec 16, 2008 2:40 am; edited 2 times in total
Back to top
Baker
A key difference between this and the above is the use of GL_LINE_LOOP instead of
GL_LINES.
GL_LINE_LOOP closes the sequence so a final line is draw from x4,y4 back to x1,y1. If you use
GL_LINES, it will only draw 2 lines: x1,y1 to x2, y2 and then x3,y3 to x4,y4.
Code:
// Initialization
glClearColor (0, 0, 0, 0) // Clear to black
glMatrixMode (GL_PROJECTION) // Projection view
glOrtho (0, 512, 512, 0) // Define display coordinates (left, bottom, right top)
Code:
// Render Frame
glClear (GL_COLOR_BUFFER_BIT) // Clear it
glColor3f (0,0,1) // RGB = Blue
glBegin (GL_LINE_LOOP) // Draw line loop
glVertex2d (128, 128) // x1 y1
glVertex2d (384, 128) // x2 y2
glVertex2d (384, 384) // x3 y3
glVertex2d (128, 384) // x4 y4
glend ()
Now ...
Code:
// Render Frame
glClear (GL_COLOR_BUFFER_BIT) // Clear it
glColor3f (0,1,0) // RGB = Green
glBegin (GL_POLYGON) // Filled polygon
glVertex2d (128, 128) // x1 y1
glVertex2d (384, 128) // x2 y2
glVertex2d (384, 384) // x3 y3
glVertex2d (128, 384) // x4 y4
glend ()
Unclosed Dashed Line Sequence with Line Width
Modifying the above to use GL_LINE_STRIP, which is a series of connected lines but unlike
GL_LINE_LOOP does not close it.
Also modifying the line width and using glLineStipple to make the lines dashed.
Code:
Note: An RGB color table can be found at this link. RGB = red green blue with values from 0 to
255, OpenGL uses 0.0 to 1.0 to represent these values.
Back to top
Baker
You won't be able to tell from the above resampled image, but this circle is NOT anti-aliased.
Code:
Const PI = 3.141592
Const X = 256
Const Y = 256
Const Radius = 60
glColor3f (1, 0.5, 0) // Orange
glBegin (GL_POLYGON)
For angle = 0 To PI * 2 Step 0.01 // Circumference of circle = 2PI * r
glVertex2f (X + Sin(angle) * Radius, Y + Cos(angle) * Radius)
Next
glEnd ()
Now let's take a close look at this before getting into the anti-aliasing issue. Notice the circle is
NOT smooth.
Back to top
Baker
But first, let's draw a simple outline of a circle. Simply change GL_POLYGON to
GL_LINE_LOOP.
Code:
Const PI = 3.141592
Const X = 256
Const Y = 256
Const Radius = 60
glColor3f (1, 0.5, 0) // Orange
glBegin (GL_LINE_LOOP)
For angle = 0 To PI * 2 Step 0.01 // Circumference of circle = 2PI * r
glVertex2f (X + Sin(angle) * Radius, Y + Cos(angle) * Radius)
Next
glEnd ()
Quote:
Const PI = 3.141592
Const X = 256
Const Y = 256
Const Radius = 60
glEnable (GL_BLEND)
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glEnable (GL_LINE_SMOOTH)
glBegin (GL_LINE_LOOP)
For angle = 0 To PI * 2 Step 0.01 // Circumference of circle = 2PI * r
glVertex2f (X + Sin(angle) * Radius, Y + Cos(angle) * Radius)
Next
glEnd ()
glDisable (GL_BLEND)
Ok, what we did above is turn blending on and then set the blending algorithm function (there
are several). Then we turned line smoothing on and now the circle is anti-aliased.
We needed to do this because we are going to hit some rocks in trying to create an anti-aliased
filled circle while sticking to OpenGL 1.2.
Many Intel display adapters support only OpenGL 1.2 and we don't want to rely on anything that
isn't universally available. They ship as the default "video card" in tons of desktops and laptops
and we're doing simple 2D graphics here and cutting out a large % of computer would be crazy.
Last edited by Baker on Tue Dec 16, 2008 3:42 am; edited 1 time in total
Back to top
Baker
Ok, in the immediately above example we made an anti-aliased circle outline usign
GL_LINE_SMOOTH.
So all we need to do is take the filled circle code from a couple of examples ago and use
GL_POLYGON_SMOOTH.
Quote:
Const PI = 3.141592
Const X = 256
Const Y = 256
Const Radius = 60
We are getting an effect called tessellation where as the pixels are drawn, the anti-alias is
creating this effect.
I know of no easy way to solve this with OpenGL 1.2 and I've found a lot of dead-ends. So let's
do this another way:
(No we aren't going to use OpenGL 2.0, that isn't acceptable .. we want OpenGL 1.2 for broad
compatibility particularly with Intel display adapters .. see above. Nor do we want to use an ARB
extension, we shouldn't be at the mercy of an extension being available.)
Code:
Const PI = 3.141592
Const X = 256
Const Y = 256
Const Radius = 60
glClear (GL_COLOR_BUFFER_BIT)
// Draw the filled circle
glColor3f (1, 0.5, 0) '// Set to orange
glBegin (GL_POLYGON)
For angle = 0 To PI * 2 Step 0.01
glVertex2f (X + Sin(angle) * Radius, Y + Cos(angle) * Radius)
Next
glEnd ()
Ok, we can draw a circle. Can draw lines. A point is just using GL_POINT instead of
GL_LINES.
Let's draw a quicky speedometer and have the needle.
Code:
Static mph = 0
mph = (mph + 1) Mod 160
Const pi = 3.141592
Const X = 256
Const Y = 256
Const Radius = 120
glClear (GL_COLOR_BUFFER_BIT)
// Draw the outline
glColor3f (1, 0.5, 0)
// Draw the filled circle
glLineWidth (1)
glBegin(GL_POLYGON)
For angle = 0 To pi * 2 Step 0.01
// Let's toy with the color a little to make it a gradient
colorgrad = 0.2 - angle * 0.1
glColor3f (colorgrad, colorgrad, colorgrad)
glVertex2f (X + Sin(angle) * Radius, Y + Cos(angle) * Radius)
Next
glEnd ()
// Speed marks
glLineWidth (1)
glColor3f (0.8, 0.8, 0.8) // Mostly whiteish
glEnable (GL_BLEND)
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glEnable (GL_LINE_SMOOTH)
glBegin (GL_LINES)
// This looks a little ugly, I'll explain ...
startangle = 2 * PI * 0.125 // We are starting the marks at 12.5% left of bottom
center
endangle = 2 * PI - startangle // We are ending the marks at 12.5% right of bottom
center
usableRange = 2 * PI * 0.75 // Our usable range is 75% of the diameter
For angle = startangle to endangle Step usableRange / 10 // We want 11 marks so
we divide by 10
glVertex2f (X + Sin(angle) * Radius * 0.8, Y + Cos(angle) * Radius * 0.8) // We
start the line inside a little
glVertex2f (X + Sin(angle) * Radius, Y + Cos(angle) * Radius) // To the end
point at the edge
Next
glEnd ()
glDisable (GL_BLEND)
// Outline
glColor3f (0.4, 0.4, 0.4) // Grayish
glLineWidth (5)
glEnable (GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glEnable (GL_LINE_SMOOTH)
glBegin (GL_LINE_LOOP)
For angle = 0 To pi * 2 Step 0.01
glVertex2f (X + Sin(angle) * Radius, Y + Cos(angle) * Radius)
Next
glDisable (GL_BLEND)
glEnd ()
Not going to cover texture loading (see post #1). It is a lot of fumbling around with the bytes and
then working within the framework of the "the texture size must be a power of 2" fun.
Code:
Static mph = 0
mph = (mph + 1) Mod 100
Const PI = 3.141592
Const X = 256
Const Y = 256
Const Radius = 90
glClear GL_COLOR_BUFFER_BIT
// Some texture constants
Const glsl = 0
Const gltl = 0
Const glsh = 1
Const glth = 1
Const Halfpicwidth = 128
Const Halfpicheight = 128
// Draw our speedometer texture
glColor4f (1, 1, 1, 1)
glEnable (GL_TEXTURE_2D) // Enable 2d texture
glBindTexture (GL_TEXTURE_2D, SpeedometerTexture) // Select texture
// Coordinates
glBegin (GL_QUADS)
glTexCoord2f (glsl, gltl)
glVertex2f (X - Halfpicwidth , Y - Halfpicheight )
glTexCoord2f (glsh, gltl)
glVertex2f (X + Halfpicwidth , Y - Halfpicheight )
glTexCoord2f (glsh, glth)
glVertex2f (X + Halfpicwidth , Y + Halfpicheight )
glTexCoord2f (glsl, glth)
glVertex2f (X - Halfpicwidth , Y + Halfpicheight )
glEnd ()
glDisable (GL_TEXTURE_2D)
// Needle
glColor3f (0.9, 0.7, 0.2) // Yellowish orange
glLineWidth (2)
glEnable (GL_BLEND)
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glEnable (GL_LINE_SMOOTH)
glBegin (GL_LINES)
// Like last time, this is just translating the MPH to the range we get to use
angle = (1 - ((mph * 1.2 + 40) / 200)) * 2 * pi
glVertex2f (X + Sin(angle) * Radius * -0.03, Y + Cos(angle) * Radius * -0.03)
glVertex2f (X + Sin(angle) * Radius * 0.9, Y + Cos(angle) * Radius * 0.9)
glDisable (GL_BLEND)
glEnd ()
Back to top
Willem
Hey, thanks for the info on stippling. I had no idea OpenGL could do that! I've added it to a few
places in my editor code now.
_________________
www.wantonhubris.com