From Pixels to Shapes

From Pixels to Shapes




Any use of computers to make/create
images.
Areas?
Applications?
So, where does it all start?




Any use of computers to make/create images.
Areas? Modeling / Rendering / Animation /
User Interaction / Virtual Reality / Visualization
/ Image Processing / 3D Scanning
Applications? Video Games / Cartoons / Film
Special Effects / CAD and CAM / Simulation /
Medical Imaging / Information Visualization /
Scientific Visualization / Charts (Business)
So, where does it all start? Pixels!




Fundamental Building Block
Dots of Light
Colors
Resolution




Wide variety
Resolution
Monitor Intensities and Gamma
Frame Buffers


RGB Color
Alpha Channel
Color
Red
Green
Blue
Yellow
1
1
0
White
1
1
1
Black
0
0
0
Cyan
0
1
1
Magenta
1
0
1



Where to we place the pixels?
Clipping
OpenGL and GLUT



As you noticed yesterday, we don’t have machines yet
– they are coming! (Picture Dr. Smith and I jumping
up and down in excitement – the actual picture was
too disturbing to place in the notes.)
Currently, we will go over the code in the book and
you may feel free to install versions on your own
machines (as I mentioned yesterday). Hopefully, next
week, we will quickly go back through the examples
together and begin altering them and creating some
of our own.
(See Appendix A for instructions.)
//Example1_1.cpp : a simple example to open a window
#include <windows.h> //the windows include file, required by all windows applications
#include <gl\glut.h> //the glut file for windows operations - it also includes gl.h and glu.h for the openGL library calls
void Display(void) {
glClear(GL_COLOR_BUFFER_BIT); //clear all pixels with the specified clear color
glFlush(); //dont wait, start flushing opengl calls to display buffer
}
void init(void) {
glClearColor(1.0,0.0,0.0,1.0); //set the clear color to be red
glViewport(0,0,320,240); // set the viewport to be 320 by 240, the initial size of the window
gluOrtho2D(0.0, 160.0, 0.0, 120.0); // set the 2D clipping area
}
void main(int argc, char* argv[]) {
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (320, 240);
glutCreateWindow("My First OpenGL Window");
init();
glutDisplayFunc(Display);
glutMainLoop();
}
//the windows include file, required by all windows applications
#include <windows.h>
//the glut file for windows operations - it also includes gl.h and glu.h for the openGL library calls
#include <gl\glut.h>
void main(int argc, char* argv[]) {
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (320, 240);
glutCreateWindow("My First OpenGL Window");
init();
glutDisplayFunc(Display);
glutMainLoop();
}
void init(void) {
glClearColor(1.0,0.0,0.0,1.0); //set the clear color to be red
glViewport(0,0,320,240); // set the viewport to be 320 by 240, the initial size of the window
gluOrtho2D(0.0, 160.0, 0.0, 120.0); // set the 2D clipping area
}
void Display(void) {
glClear(GL_COLOR_BUFFER_BIT); //clear all pixels with the specified clear color
glFlush(); //dont wait, start flushing opengl calls to display buffer
}

Objects and scenes consist of combinations
of shapes





Points
Lines
Circles
Rectangles
Other graphics primitives




Primitives in OpenGL are drawn as a point (one
or more) which is represented as a “vertex”
glVertex2f(1.0,2.0); refers to a vertex point at
(1.0,2.0)
Vertices are bracketed between calls to
glBegin() and glEnd().
The type of primitive being drawn is passed in
as a parameter to glBegin (in this case,
GL_POINTS)
//Example1_2.cpp : let the drawing begin
#include <windows.h> //the windows include file, required by all windows applications
#include <gl\glut.h> //the glut file for windows operations - it also includes gl.h and glu.h for the openGL library calls
void Display(void) {
glClear(GL_COLOR_BUFFER_BIT); //clear all pixels with the specified clear color
glBegin(GL_POINTS);
glColor3f(0.0, 1.0, 0.0);
glVertex2f(10.,10.);
glColor3f(1.0, 1.0, 0.0);
glVertex2f(10.,110.);
glColor3f(0.0, 0.0, 1.0);
glVertex2f(150.,110.);
glColor3f(1.0, 1.0, 1.0);
glVertex2f(150.,10.);
glEnd();
/* green */
/* yellow */
/* blue */
/* white */
glFlush(); //dont wait, start flushing opengl calls to display buffer
}
void reshape (int w, int h) {
glViewport (0, 0, (GLsizei) w, (GLsizei) h); // on reshape and on startup, keep the viewport to be the entire size of the window
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluOrtho2D(0.0, 160.0, 0.0, 120.0); // keep our logical coordinate system constant
}
void init(void) {
glClearColor(1.0,0.0,0.0,1.0); //set the clear color to be red
glPointSize(5.0); // set the point size to be 3.0 pixels
}
void main(int argc, char* argv[]) {
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (320, 240);
glutCreateWindow("My First OpenGL Window");
init();
glutDisplayFunc(Display);
glutReshapeFunc(reshape);
glutMainLoop();
}
void main(int argc, char* argv[]) {
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (320, 240);
glutCreateWindow("My First OpenGL Window");
init();
glutDisplayFunc(Display);
glutReshapeFunc(reshape);
glutMainLoop();
}
void init(void) {
glClearColor(1.0,0.0,0.0,1.0); //set the clear
color to be red
glPointSize(5.0); // set the point size to be
5.0 pixels
}
void Display(void) {
glClear(GL_COLOR_BUFFER_BIT); //clear all pixels with the specified clear color
glBegin(GL_POINTS);
glColor3f(0.0, 1.0, 0.0);
glVertex2f(10.,10.);
glColor3f(1.0, 1.0, 0.0);
glVertex2f(10.,110.);
glColor3f(0.0, 0.0, 1.0);
glVertex2f(150.,110.);
glColor3f(1.0, 1.0, 1.0);
glVertex2f(150.,10.);
glEnd();
/* green */
/* yellow */
/* blue */
/* white */
glFlush(); //dont wait, start flushing opengl calls to display buffer
}
void reshape (int w, int h) {
glViewport (0, 0, (GLsizei) w, (GLsizei) h); // on
reshape and on startup, keep the viewport to
be the entire size of the window
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluOrtho2D(0.0, 160.0, 0.0, 120.0); // keep our
logical coordinate system constant
}

We know how to draw a line, circle, or other
shape – how do we get a computer to do it?

Find the right pixels to turn on – aka scan
conversion or rasterizing

Popular line drawing algorithm: midpointline algorithm


Idea: Give the x,y coordinates of the endpoints
Algorithm then calculates all the x,y coordinates
between them.



First, calculates physical pixels for each endpoint
Ideal line drawn between them, used as a reference
to determine which pixels to light up along the way.
Pixels less than .5 units from the line are turned on



Triangles and Polygons – drawn as series of
lines (vertices connected by lines)
To specify shapes, we use a call to glVertex
surrounded by calls to glBegin() and glEnd()
Arguments for glBegin are:
Primitive Definition
Meaning
GL_POINTS
Individual points
GL_LINES
Pair of vertices defining a line
GL_LINE_STRIP
Series of connected lines
GL_TRIANGLES
Strip of linked triangles
GL_POLYGON
Vertices define a simple
convex polygon


Curved shapes can also be created with
algorithms or by drawing a large number of
short, straight lines
Remember your trigonometry? Any point on a
circle’s radius (and centered at the origin) has
an x,y coordinate pair that can be represented
as a function of the angle theta the point
makes with the axes (see fig 1.14, p. 21)
P(theta)=((rcos(theta)),(rsin(theta)))
GLint circle_points = 100;
void MyCircle2f(GLfloat centerx, GLfloat centery, GLfloat radius) {
GLint i;
GLdouble theta;
glBegin(GL_POLYGON);
for (i = 0; i < circle_points; i++) {
theta = 2*PI*i/circle_points;
glVertex2f(centerx+radius*cos(theta), centery+radius*sin(theta));
}
glEnd();
}

Now, we can make a simple drawing – let’s
look at the code for a stick figure (seen in
your text as figure 1.15)
//Example1_3 : A stick figure
#include <windows.h> //the windows include file, required by all windows applications
#include <math.h> // included for the cos and sin functions
#include <gl\glut.h> //the glut file for windows operations - it also includes gl.h and glu.h for the openGL library calls
// routine to draw a circle approximated by line segments
#define PI 3.1415926535898 // recall that cos and sin functions require angles in radians so 2PI radians = 360 degrees, a full circle
GLint circle_points = 100;
void MyCircle2f(GLfloat centerx, GLfloat centery, GLfloat radius) {
GLint i;
GLdouble theta;
glBegin(GL_POLYGON);
for (i = 0; i < circle_points; i++) {
theta = 2*PI*i/circle_points;
glVertex2f(centerx+radius*cos(theta), centery+radius*sin(theta));
}
glEnd();
}
void Display(void) {
//clear all pixels with the specified clear color
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0,0.8,0.1);
MyCircle2f(80.,85., 10.);
// the eyes are black points
// set the point size to be 3.0 pixels
glBegin(GL_POINTS);
glColor3f(0.0, 0.0, 0.0);
glVertex2f(77.,88.);
glVertex2f(83.,88.);
glEnd();
// polygonal body
glColor3f(0.8,0.0,0.9);
glBegin(GL_POLYGON);
glVertex2f(75.,75.);
glVertex2f(85.,75.);
glVertex2f(100.,30.);
glVertex2f(60.,30.);
glEnd();
//rectangular legs
glColor3f(1.0,0.8,0.1);
glRectf(70.,5.,75.,30.);
glRectf(85.,5.,90.,30.);
// but lines for hands!
glBegin(GL_LINES);
glVertex2f (74.,70.); glVertex2f (50.,50.);
glEnd();
glBegin(GL_LINES);
glVertex2f (86.,70.); glVertex2f (110.,50.);
glEnd();
//dont wait, start flushing opengl calls to display buffer
glFlush();
}
void reshape (int w, int h) {
glViewport (0, 0, (GLsizei) w, (GLsizei) h); // on reshape and on startup, keep the viewport to be the entire size of the window
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
// keep our logical coordinate system constant
gluOrtho2D(0.0, 160.0, 0.0, 120.0);
}
void init(void){
//set the clear color to be white
glClearColor(1.0,1.,1.0,1.0);
// set the point size of points drawn to be 5.0 pixels
glPointSize(5.0);
// set the line width to be 5.0 pixels
glLineWidth(5.0);
// polygons drawn should be filled
glPolygonMode(GL_FRONT, GL_FILL);
}
void main(int argc, char* argv[])
{
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (320, 240);
glutCreateWindow("My First OpenGL Window");
init();
glutDisplayFunc(Display);
glutReshapeFunc(reshape);
glutMainLoop();
}




Most scan conversion code creates jagged
edges (known as “jaggies”)
High resolution monitors – no big deal
Low resolution monitors – harsh!
Solution? Anti-Aliasing!



Pixels set to different intensities and properly
manipulated based on their position relative to
one another can be manipulated so that they
blend to form a smooth image. (We’re tricking
our eyes!)
For a line, this means turning on pixels with
varying intensities instead of just on or off (like
a dimmer on a light switch)
Makes image look more continuous, though
sometimes blurry.

Two steps:


Turn on antialiasing with glEnable(), passing in
GL_POINT_SMOOTH or GL_LINE_SMOOTH as
appropriate
Enable blending by using a blending factor.
Probably want to use GL_SRC_ALPHA (source)
and GL_ONE_MINUS_SRC_ALPHA (destination)

Commands – in the init() function:
void init(void){
glEnable (GL_LINE_SMOOTH);
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glHint (GL_LINE_SMOOTH_HINT | GL_POLYGON_SMOOTH_HINT, GL_DONT_CARE);
//set the clear color to be white
glClearColor(0.0,0.8,0.0,1.0);
// set the point size of points drawn to be 5.0 pixels
glPointSize(5.0);
// set the line width to be 5.0 pixels
glLineWidth(5.0);
// polygons drawn should be filled
glPolygonMode(GL_FRONT, GL_FILL);
}
//Example1_4.cpp : An anti-aliased stick figure
#include <windows.h> //the windows include file, required by all windows applications
#include <math.h> // included for the cos and sin functions
#include <gl\glut.h> //the glut file for windows operations
// it also includes gl.h and glu.h for the openGL library calls
// routine to draw a circle approximated by line segments
#define PI 3.1415926535898
GLint circle_points = 100;
void MyCircle2f(GLfloat centerx, GLfloat centery, GLfloat radius){
GLint i;
GLdouble angle;
glBegin(GL_POLYGON);
for (i = 0; i < circle_points; i++) {
angle = 2*PI*i/circle_points;
glVertex2f(centerx+radius*cos(angle), centery+radius*sin(angle));
}
glEnd();
}
void Display(void)
{
//clear all pixels with the specified clear color
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0,0.8,0.1);
MyCircle2f(80.,85., 10.);
// the eyes are black points
// set the point size to be 3.0 pixels
glBegin(GL_POINTS);
glColor3f(0.0, 0.0, 0.0);
glVertex2f(77.,88.);
glVertex2f(83.,88.);
glEnd();
// polygonal body
glColor3f(0.8,0.0,0.9);
glBegin(GL_POLYGON);
glVertex2f(75.,75.);
glVertex2f(85.,75.);
glVertex2f(100.,30.);
glVertex2f(60.,30.);
glEnd();
//rectangular legs
glColor3f(1.0,0.8,0.1);
glRectf(70.,5.,75.,30.);
glRectf(85.,5.,90.,30.);
// but lines for hands!
glBegin(GL_LINES);
glVertex2f (74.,70.); glVertex2f (50.,50.);
glEnd();
glBegin(GL_LINES);
glVertex2f (86.,70.); glVertex2f (110.,50.);
glEnd();
//dont wait, start flushing opengl calls to display buffer
glFlush();
}
void reshape (int w, int h)
{
// on reshape and on startup, keep the viewport to be the entire size of the window
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
// keep our logical coordinate system constant
gluOrtho2D(0.0, 160.0, 0.0, 120.0);
}
void init(void){
glEnable (GL_LINE_SMOOTH);
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glHint (GL_LINE_SMOOTH_HINT | GL_POLYGON_SMOOTH_HINT, GL_DONT_CARE);
//set the clear color to be white
glClearColor(0.0,0.8,0.0,1.0);
// set the point size of points drawn to be 5.0 pixels
glPointSize(5.0);
// set the line width to be 5.0 pixels
glLineWidth(5.0);
// polygons drawn should be filled
glPolygonMode(GL_FRONT, GL_FILL);
}
void main(int argc, char* argv[])
{
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (320, 240);
glutCreateWindow("Anti-Aliased Stick Figure");
init();
glutDisplayFunc(Display);
glutReshapeFunc(reshape);
glutMainLoop();
}