14
COMPUTER GRAPHICS CS 482 – FALL 2014 AUGUST 20, 2014 GRAPHICS IN OPENGL • OPENGL OVERVIEW • OPENGL 2D EXAMPLES • OPENGL 3D EXAMPLES

COMPUTER GRAPHICS CS 482 – FALL 2014 AUGUST 20, 2014 GRAPHICS IN OPENGL OPENGL OVERVIEW OPENGL 2D EXAMPLES OPENGL 3D EXAMPLES

Embed Size (px)

Citation preview

Page 1: COMPUTER GRAPHICS CS 482 – FALL 2014 AUGUST 20, 2014 GRAPHICS IN OPENGL OPENGL OVERVIEW OPENGL 2D EXAMPLES OPENGL 3D EXAMPLES

COMPUTER GRAPHICS

CS 482 – FALL 2014

AUGUST 20, 2014GRAPHICS IN OPENGL

• OPENGL OVERVIEW• OPENGL 2D EXAMPLES• OPENGL 3D EXAMPLES

Page 2: COMPUTER GRAPHICS CS 482 – FALL 2014 AUGUST 20, 2014 GRAPHICS IN OPENGL OPENGL OVERVIEW OPENGL 2D EXAMPLES OPENGL 3D EXAMPLES

OPENGL OVERVIEW

CS 482 – FALL 2014

BROAD STROKES

AUGUST 20, 2014: GRAPHICS IN OPENGL PAGE 2

SILICON GRAPHICS (SGI) DEVELOPED OPENGL, A LOW-LEVEL GRAPHICS API WITH FINE-GRAINED CONTROL.

APPLICATIONS SUPPLY GEOMETRY INFORMATION FOR EACH PRIMITIVE OBJECT (VERTEX, SEGMENT, TRIANGLE), AS WELL AS THE EFFECTS TO BE APPLIED TO THE PRIMITIVES (COLOR,

TRANSPARENCY, FOG, ETC.).OPENGL PROVIDES A GREATER LEVEL OF CONTROL FOR

DEVELOPERS AND IS RELIABLE ACROSS DIFFERENT HARDWARE PLATFORMS.

APIPRIMITIVE

PROCESSING

TRANSFORM &

LIGHTING

PRIMITIVE ASSEMBLY

RASTERIZER

TEXTURE ENVIRONMEN

T

COLOR SUM

FOG

ALPHA TEST

DEPTH/STENCIL

COLOR BUFFER BLEND

FRAME BUFFER

VERTICES

TRIANGLES/LINES/POINTS

Page 3: COMPUTER GRAPHICS CS 482 – FALL 2014 AUGUST 20, 2014 GRAPHICS IN OPENGL OPENGL OVERVIEW OPENGL 2D EXAMPLES OPENGL 3D EXAMPLES

OPENGL OVERVIEW

CS 482 – FALL 2014

OPENGL PIPELINE

AUGUST 20, 2014: GRAPHICS IN OPENGL PAGE 3

AN APPLICATION’S

OPENGL FUNCTION CALLS ARE

PLACED IN THE OPENGL

COMMAND BUFFER.

THESE FUNCTIONS CREATE AND MANIPULATE

PRIMITIVE GRAPHICAL

OBJECTS (VERTICES, SEGMENTS, POLYGONS,

CURVES, PIXELS)

THE COMMAND BUFFER IS

PERIODICALLY FLUSHED

(POSSIBLY BY EXPLICIT

PROGRAMMED

COMMANDS)

THE GEOMETRY

OF THE OBJECTS BEING

DISPLAYED IS USED TO CALCULATE VISIBILITY,

ORIENTATION, AND

LIGHTING

THE IMAGE IS

GENERATED FROM

THE DATA ASSOCIATE

D WITH THE

OBJECTS’ GEOMETRY, MATERIAL PROPERTIE

S, AND TEXTURE

THE IMAGE IS PLACED IN THE FRAME BUFFER OF THE

GRAPHICS

DISPLAY DEVICE

Page 4: COMPUTER GRAPHICS CS 482 – FALL 2014 AUGUST 20, 2014 GRAPHICS IN OPENGL OPENGL OVERVIEW OPENGL 2D EXAMPLES OPENGL 3D EXAMPLES

OPENGL OVERVIEW

CS 482 – FALL 2014

TRADITIONAL GRAPHICS PIPELINE

AUGUST 20, 2014: GRAPHICS IN OPENGL PAGE 4

THE TRADITIONAL GRAPHICS

PROCESSING PIPELINE BEGINS

WITH OBJECT-SPACE VERTICES, TO

WHICH LIGHTING, COLOR, AND

TEXTURE ARE APPLIED.

INFORMATION CONCERNING THE VERTICES IS USED TO GENERATE GEOMETRIC PRIMITIVES, SUCH AS LINE SEGMENTS, TRIANGLES, TRIANGLE STRIPS, ETC.THE PRIMITIVES ARE THEN PROCESSED (CLIPPING, PROJECTIONS, ETC.) TO PRODUCE FRAGMENTS, EACH OF WHICH IS ESSENTIALLY THE DATA NEEDED TO GENERATE A SINGLE PIXEL.BEFORE THE DEVELOPMENT OF PROGRAMMABLE SHADERS, THE ONLY WAY TO ACHIEVE HARDWARE SPEED-UPS IN GRAPHICS WAS TO HARDWIRE THE GRAPHICS CARD TO PERFORM VERY SPECIFIC, “FIXED-FUNCTION” GRAPHICS ALGORITHMS.

EACH FRAGMENT’S INFORMATION IS

USED TO GENERATE A PIXEL FOR THE

FRAME BUFFER (I.E., RASTER POSITION,

DEPTH, COLOR, TEXTURE

COORDINATES, AND

TRANSPARENCY).

Page 5: COMPUTER GRAPHICS CS 482 – FALL 2014 AUGUST 20, 2014 GRAPHICS IN OPENGL OPENGL OVERVIEW OPENGL 2D EXAMPLES OPENGL 3D EXAMPLES

OPENGL OVERVIEW

CS 482 – FALL 2014

OPENGL 4.4

AUGUST 20, 2014: GRAPHICS IN OPENGL PAGE 5

Page 6: COMPUTER GRAPHICS CS 482 – FALL 2014 AUGUST 20, 2014 GRAPHICS IN OPENGL OPENGL OVERVIEW OPENGL 2D EXAMPLES OPENGL 3D EXAMPLES

OPENGL 2D EXAMPLES

CS 482 – FALL 2014

FERN ITERATED FUNCTION SYSTEM

AUGUST 20, 2014: GRAPHICS IN OPENGL PAGE 6

IN THIS EXAMPLE, USERS PRODUCE A FRACTAL IMAGE GENERATED VIA MATHEMATICAL CHAOS THEORY.

NOTEWORTHY FEATURES:

• THE MATHEMATICAL FIELD OF CHAOS THEORY INCLUDES THE STUDY OF CONTRACTIVE, AFFINE TRANSFORMATIONS THAT YIELD “STRANGE ATTRACTORS”, I.E., SETS OF POINTS WHICH, WHEN GRAPHICALLY RENDERED, PRODUCE SELF-SIMILAR FRACTAL IMAGES THAT ARE REMINISCENT OF NATURAL PHENOMENA.

Page 7: COMPUTER GRAPHICS CS 482 – FALL 2014 AUGUST 20, 2014 GRAPHICS IN OPENGL OPENGL OVERVIEW OPENGL 2D EXAMPLES OPENGL 3D EXAMPLES

OPENGL 2D EXAMPLES

CS 482 – FALL 2014

FERN ITERATED FUNCTION SYSTEM

AUGUST 20, 2014: GRAPHICS IN OPENGL PAGE 7

Starting with the point (0,0), generate a random number in [0,1].

• If that number is in [0,p1], then apply the affine transformation W1(x,y) = (a1x+b1y+e1,c1x+d1y+f1);

• if the number’s in (p1,p2], apply W2(x,y)= (a2x+b2y+e2,c2x+d2y+f2);

• if the number’s in (p2,p3], apply W3(x,y)= (a3x+b3y+e3,c3x+d3y+f3);

• if the number’s in (p3,p4], apply W4(x,y)= (a4x+b4y+e4,c4x+d4y+f4).

Then generate another random number and apply the appropriate transformation to the previously generated point, and so on.

THIS LIST OF COEFFICIENTS PRODUCES THE FERN PATTERN:

i ai bi ci di ei fi pi

1 0.00 0.00 0.00 0.16 0.00 0.00 0.01

2 0.85 0.04 -0.04

0.85 0.00 1.60 0.86

3 0.20 -0.26

0.23 0.22 0.00 1.60 0.93

4 -0.15

0.28 0.26 0.24 0.00 0.44 1.00

Page 8: COMPUTER GRAPHICS CS 482 – FALL 2014 AUGUST 20, 2014 GRAPHICS IN OPENGL OPENGL OVERVIEW OPENGL 2D EXAMPLES OPENGL 3D EXAMPLES

/* Window-reshaping routine, to adjust the fern *//* size to fit the window, scaling the image so *//* it will be entirely visible whether the *//* window is short and wide, or tall and thin. */void ResizeWindow(GLsizei w, GLsizei h){ glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) glOrtho(-2.0f, 2.0f, -2.0f * (GLfloat)h / (GLfloat)w, 2.0f * (GLfloat)h / (GLfloat)w, -10.0f, 10.0f); else glOrtho(-2.0f * (GLfloat)w / (GLfloat)h, 2.0f * (GLfloat)w / (GLfloat)h, -2.0f, 2.0f, -10.0f, 10.0f); glMatrixMode(GL_MODELVIEW);}

// Generate next iterated point. // newVert[0] = A[coeffIndex] * vert[0] + B[coeffIndex] * vert[1] + E[coeffIndex]; newVert[1] = C[coeffIndex] * vert[0] + D[coeffIndex] * vert[1] + F[coeffIndex]; vert[0] = newVert[0]; vert[1] = newVert[1];

// Scale and translate point into display window. // displayVert[0] = IMAGE_SCALE_FACTOR[0] * vert[0] + IMAGE_DISPLACEMENT[0]; displayVert[1] = IMAGE_SCALE_FACTOR[1] * vert[1] + IMAGE_DISPLACEMENT[1];

// Display colored point. // glBegin(GL_POINTS); glColor3fv(clr); glVertex2fv(displayVert); glEnd();

// Draw all points periodically. // if (n % FLUSH_ITER_INCREMENT == 0) glFlush(); }}

/* Principal display routine: clears the frame buffer *//* and the depth buffer, and then draws the fern. */void Display(){ glClear(GL_COLOR_BUFFER_BIT); DrawFern();}

OPENGL 2D EXAMPLES

CS 482 – FALL 2014

FERN ITERATED FUNCTION SYSTEM

AUGUST 20, 2014: GRAPHICS IN OPENGL PAGE 8

/* Function to draw the fern, one point at a time. */void DrawFern(){ GLfloat vert[2] = {0.0f, 0.0f}; GLfloat newVert[2]; GLfloat displayVert[2]; GLfloat clr[3]; int clrIndex; int coeffIndex; float r;

// Iterate the point generation and display. // for (int n = 1; n <= NBR_ITERATIONS; n++) { // Alternate color selection. // clrIndex = n % NBR_COLORS; clr[0] = COLOR[clrIndex][0]; clr[1] = COLOR[clrIndex][1]; clr[2] = COLOR[clrIndex][2];

// Select function coefficients using random // // numbers and weighted probabilities. // r = float(rand()) / RAND_MAX; if (r < PROB[0]) coeffIndex = 0; else if (r < PROB[1]) coeffIndex = 1; else if (r < PROB[2]) coeffIndex = 2; else coeffIndex = 3;

/* The main function: uses the OpenGL Utility Toolkit to set *//* the window up to display the iterated function system. */void main(int argc, char **argv){ /* Set up the display window. */ gltSetWorkingDirectory(argv[0]); glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA); glutInitWindowPosition( INIT_WINDOW_POS[0], INIT_WINDOW_POS[1] ); glutInitWindowSize( INIT_WINDOW_SIZE[0], INIT_WINDOW_SIZE[1] ); glutCreateWindow( "Fern Iterated Function System" );

// Ensure proper OpenGL availability, with generic shader. GLenum err = glewInit(); if (GLEW_OK != err) { fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err)); return; } shaderManager.InitializeStockShaders();

/* Specify the resizing and refreshing routines. */ glutReshapeFunc( ResizeWindow ); glutDisplayFunc( Display ); glutMainLoop();}

const int INIT_WINDOW_POS[2] = { 50, 50 };const int INIT_WINDOW_SIZE[2] = { 1000, 1000 };

const int NBR_ITERATIONS = 1000000;const int FLUSH_ITER_INCREMENT = 100;

const float IMAGE_SCALE_FACTOR[2] = { 0.50f, 0.35f };const float IMAGE_DISPLACEMENT[2] = { 0.0f, -1.8f };

//////////////////////// Global Variables ////////////////////////GLShaderManager shaderManager; // Manager of GLTools stock shaders.

/////////////////////////// Function Prototypes ///////////////////////////void DrawFern();void Display();void ResizeWindow(GLsizei w, GLsizei h);

Noteworthy: /*********************************************************************//* Filename: Fern.cpp *//* Produces an iterated function system in the shape of a fern leaf. *//*********************************************************************/

#include <GLTools.h> // OpenGL toolkit#include <GLShaderManager.h> // Shader Manager Class

#ifdef __APPLE__#include <glut/glut.h> // OS X version of GLUT library#else#define FREEGLUT_STATIC#include <GL/glut.h> // Windows FreeGlut equivalent#endif

//////////////////////// Global Constants ////////////////////////const int NBR_COLORS = 5;const GLfloat COLOR[NBR_COLORS][3] = { 0.1f, 0.8f, 0.1f, // Bright green // 0.1f, 0.4f, 0.1f, // Dark green // 0.8f, 0.1f, 0.1f, // Bright red // 0.4f, 0.8f, 0.1f, // Medium brown // 0.8f, 0.8f, 0.1f }; // Bright yellow //

const GLfloat A[4] = {0.00f, 0.85f, 0.20f, -0.15f};const GLfloat B[4] = {0.00f, 0.04f, -0.26f, 0.28f};const GLfloat C[4] = {0.00f, -0.04f, 0.23f, 0.26f};const GLfloat D[4] = {0.16f, 0.85f, 0.22f, 0.24f};const GLfloat E[4] = {0.00f, 0.00f, 0.00f, 0.00f};const GLfloat F[4] = {0.00f, 1.60f, 1.60f, 0.44f};const GLfloat PROB[4] = {0.01f, 0.86f, 0.93f, 1.00f};

• Apple OS X & Windows• No hard-coded numerics• Generic shader setup• Single-buffered (no

animation)• Title bar• Reshape function

specification• Display function

specification

• Iterated function system implementation

• Points primitive• Periodic image flushing• Window resizing

Page 9: COMPUTER GRAPHICS CS 482 – FALL 2014 AUGUST 20, 2014 GRAPHICS IN OPENGL OPENGL OVERVIEW OPENGL 2D EXAMPLES OPENGL 3D EXAMPLES

OPENGL 2D EXAMPLES

CS 482 – FALL 2014

INTERACTIVE POLYGON DRAWING

AUGUST 20, 2014: GRAPHICS IN OPENGL PAGE 9

IN THIS EXAMPLE, USERS EMPLOY THE MOUSE TO LINK VERTICES TO FORM A POLYGON.

NOTEWORTHY FEATURES:

• THE POLYGON IS “CLOSED” VIA THE ‘C’ KEY; ONCE CLOSED, THE POLYGON MAY NOT BE REOPENED (I.E., NO MORE VERTICES MAY BE ADDED).

• AFTER CLOSURE, SELECTED VERTICES MAY BE DELETED VIA THE ‘D’ KEY; WHEN DELETED, A VERTEX’S PREDECESSOR AND SUCCESSOR BECOME JOINED BY AN EDGE.

Page 10: COMPUTER GRAPHICS CS 482 – FALL 2014 AUGUST 20, 2014 GRAPHICS IN OPENGL OPENGL OVERVIEW OPENGL 2D EXAMPLES OPENGL 3D EXAMPLES

/* Window-reshaping routine, to scale the rendered polygon according *//* to the window dimensions, setting the global variables so the *//* mouse operations will correspond to mouse pointer positions. */void ResizeWindow(GLsizei w, GLsizei h){ glViewport(0, 0, w, h); currWindowSize[0] = w; currWindowSize[1] = h; glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) { windowWidth = 2.0f; windowHeight = 2.0f * (GLfloat)h / (GLfloat)w; glOrtho(-1.0, 1.0, -1.0 * (GLfloat)h / (GLfloat)w, (GLfloat)h / (GLfloat)w, -10.0, 10.0); } else { windowWidth = 2.0f * (GLfloat)w / (GLfloat)h; windowHeight = 2.0f; glOrtho(-1.0 * (GLfloat)w / (GLfloat)h, (GLfloat)w / (GLfloat)h, -1.0, 1.0, -10.0, 10.0); } glMatrixMode(GL_MODELVIEW);}

// Highlight the selected vertex (if any). // if (selectMode) { glColor3fv(HIGHLIGHT_COLOR); currPoint = pointList.getHeadValue(); glBegin(GL_TRIANGLE_FAN); glVertex2f(currPoint.x, currPoint.y); for (int j = 0; j < NBR_SLICES; j++) { theta = 360 * j * PI_OVER_180 / NBR_SLICES; glVertex2f(currPoint.x + POINT_RADIUS * cos(theta), currPoint.y + POINT_RADIUS * sin(theta)); theta = 360 * (j + 1) * PI_OVER_180 / NBR_SLICES; glVertex2f(currPoint.x + POINT_RADIUS * cos(theta), currPoint.y + POINT_RADIUS * sin(theta)); } glEnd(); }

glFlush();}

// Draw the polygon vertices. // glColor3fv(POINT_COLOR); for (i = 1; i <= pointList.getSize(); i++) { currPoint = pointList.getHeadValue(); glBegin(GL_TRIANGLE_FAN); glVertex2f(currPoint.x, currPoint.y); for (int j = 0; j < NBR_SLICES; j++) { theta = 360 * j * PI_OVER_180 / NBR_SLICES; glVertex2f(currPoint.x + POINT_RADIUS * cos(theta), currPoint.y + POINT_RADIUS*sin(theta)); theta = 360 * (j + 1) * PI_OVER_180 / NBR_SLICES; glVertex2f(currPoint.x + POINT_RADIUS * cos(theta), currPoint.y + POINT_RADIUS * sin(theta)); } glEnd(); ++pointList;}

/* Principal display routine: clears the frame *//* buffer and draws the polygon in the window. */void Display(){ int i; GLfloatPoint currPoint; float theta;

glClear(GL_COLOR_BUFFER_BIT);

// Draw the polygon's (2-pixel thick) line segments. // glLineWidth(2.0f); glColor3fv(LINE_COLOR); glBegin(GL_LINE_STRIP); for (i = 1; i <= pointList.getSize(); i++) { currPoint = pointList.getHeadValue(); glVertex2f(currPoint.x, currPoint.y); ++pointList; } if ((!createMode) && (pointList.getSize() > 0)) { currPoint = pointList.getHeadValue(); glVertex2f(currPoint.x, currPoint.y); } glEnd(); glLineWidth(1.0f);

OPENGL 2D EXAMPLES

CS 482 – FALL 2014

INTERACTIVE POLYGON DRAWING

AUGUST 20, 2014: GRAPHICS IN OPENGL PAGE 10

/* Function to react to the pressing of keyboard keys by the *//* user, either by completing the polygon creation (by "closing" *//* the polygon) or by deleting the selected polygon vertex. */void KeyboardPress(unsigned char pressedKey, int mouseXPosition, int mouseYPosition){ switch(pressedKey) { case 'c': case 'C': { createMode = false; Display(); break; } case 'd': case 'D': { if (selectMode) { pointList.removeHead(); selectMode = false; Display(); } break; } }}

/* Function to move the position of the selected polygon *//* vertex to the current mouse pointer position if the *//* mouse button is pressed and the pointer is in motion. */void MouseDrag(int mouseXPosition, int mouseYPosition){ GLfloatPoint currPoint; GLfloat x = windowWidth * mouseXPosition / currWindowSize[0] - 0.5f * windowWidth; GLfloat y = 0.5f * windowHeight - (windowHeight * mouseYPosition / currWindowSize[1]); if (selectMode) { currPoint = pointList.getHeadValue(); currPoint.x = x; currPoint.y = y; pointList.removeHead(); pointList.insert(currPoint); Display(); } glFlush();}

/* Function to react to mouse clicks by adding an additional vertex *//* to the polygon being built, or by determining whether the mouse *//* pointer is close enough to an existing vertex to select it. */void MouseClick(int mouseButton, int mouseState, int mouseXPosition, int mouseYPosition){ GLfloatPoint currPoint; GLfloat x = windowWidth * mouseXPosition / currWindowSize[0] - 0.5f * windowWidth; GLfloat y = 0.5f * windowHeight - (windowHeight * mouseYPosition / currWindowSize[1]);

if ( (createMode) && (mouseState == GLUT_DOWN) ) { GLfloatPoint newPoint; newPoint.x = x; newPoint.y = y; pointList.insert(newPoint); } else if ( mouseState == GLUT_DOWN ) { selectMode = false; for (int i = 1; i <= pointList.getSize(); i++) { currPoint = pointList.getHeadValue(); if ( sqrt(pow(x - currPoint.x, 2) + pow(y - currPoint.y, 2)) < POINT_RADIUS ) { selectMode = true; break; } ++pointList; } } Display();}

/* The main function: uses the OpenGL Utility Toolkit to set *//* the window up to display the window and its contents. */void main(int argc, char **argv){ /* Set up the display window. */ currWindowSize[0] = INIT_WINDOW_SIZE[0]; currWindowSize[1] = INIT_WINDOW_SIZE[1]; gltSetWorkingDirectory(argv[0]); glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA); glutInitWindowPosition( INIT_WINDOW_POSITION[0], INIT_WINDOW_POSITION[1] ); glutInitWindowSize( currWindowSize[0], currWindowSize[1] ); glutCreateWindow( "POLYGON DRAW (C: Close Polygon; D: Delete Vertex)" );

// Ensure proper OpenGL availability, with generic shader. GLenum err = glewInit(); if (GLEW_OK != err) { fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err)); return; } shaderManager.InitializeStockShaders();

/* Specify the resizing and refreshing routines. */ glutReshapeFunc( ResizeWindow ); glutDisplayFunc( Display ); glutMouseFunc( MouseClick ); glutMotionFunc( MouseDrag ); glutKeyboardFunc( KeyboardPress ); glutMainLoop();}

// RGB color of line segments and point vertices (regular and highlighted).const GLfloat LINE_COLOR[3] = { 1.0f, 0.8f, 0.1f };const GLfloat POINT_COLOR[3] = { 1.0f, 0.3f, 0.1f };const GLfloat HIGHLIGHT_COLOR[3] = { 0.1f, 0.3f, 1.0f };

// Radius of circular point vertices.const GLfloat POINT_RADIUS = 0.02f;

// # of segments comprising "circular" vertex.const int NBR_SLICES = 12;

// One degree (in radians).const GLfloat PI_OVER_180 = 0.0174532925f;

//////////////////////// Global Variables ////////////////////////GLShaderManager shaderManager; // Manager of GLTools stock shaders.GLint currWindowSize[2]; // Window size in pixels.GLfloat windowWidth = 2.0; // Resized window width.GLfloat windowHeight = 2.0; // Resized window height.bool selectMode = false; // Flag indicating selected vertex.bool createMode = true; // Flag indicating polygon creation.LinkedList<GLfloatPoint> pointList; // Circular list of polygon vertices.

/////////////////////////// Function Prototypes ///////////////////////////void MouseClick(int mouseButton, int mouseState, int mouseXPosition, int mouseYPosition);void MouseDrag(int mouseXPosition, int mouseYPosition);void KeyboardPress(unsigned char pressedKey, int mouseXPosition, int mouseYPosition);void Display();void ResizeWindow(GLsizei w, GLsizei h);

Noteworthy: /******************************************************//* Filename: PolygonDraw.cpp *//* Uses the mouse to permit the user to interactively *//* create and draw a polygon within a display window, *//* and keyboard callbacks to change editing modes. *//******************************************************/

#include <GLTools.h> // OpenGL toolkit#include <GLShaderManager.h> // Shader Manager Class#include <cmath> // Header File For Math Library#include "LinkedList.h" // Header File For Linked List Class

#ifdef __APPLE__#include <glut/glut.h> // OS X version of GLUT library#else#define FREEGLUT_STATIC#include <GL/glut.h> // Windows FreeGlut equivalent#endif

///////////////////////////////////////// 2D point class (for convenience). /////////////////////////////////////////class GLfloatPoint{ public: GLfloat x, y;};

//////////////////////// Global Constants ////////////////////////// Pixel position of upper left-hand corner of display window.const GLint INIT_WINDOW_POSITION[2] = { 100, 100 };const GLint INIT_WINDOW_SIZE[2] = { 800, 800 };

• 2D point class• Global constants &

variables• Mouse click

function• Mouse drag

function• Keyboard press

function• Mouse click

implementation• Mouse drag

implementation• Keyboard press

implementation• Line strip primitive• Lines drawn first• Triangle fan

primitive• Vertices drawn

second• Selected vertex

drawn last• Window resizing

implementation

Page 11: COMPUTER GRAPHICS CS 482 – FALL 2014 AUGUST 20, 2014 GRAPHICS IN OPENGL OPENGL OVERVIEW OPENGL 2D EXAMPLES OPENGL 3D EXAMPLES

OPENGL 2D EXAMPLES

CS 482 – FALL 2014

ANIMATED POLYGONS

AUGUST 20, 2014: GRAPHICS IN OPENGL PAGE 11

IN THIS EXAMPLE, USERS UTILIZE THE KEYBOARD TO CREATE SPINNING 2D POLYGONS.

NOTEWORTHY FEATURES:

• NUMERICAL KEYS ‘3’ THROUGH ‘9’ GENERATE POLYGONS WITH A CORRESPONDING NUMBER OF SIDES, RANDOM RADIUS AND SPIN, AND RGBYMC COLORS.• A POP-UP MENU ALSO PROVIDES A POLYGON SELECTION CAPABILITY.

• EACH POLYGON “BOUNCES” OFF THE SIDES OF THE WINDOW, BUT IGNORES THE OTHER POLYGONS.

Page 12: COMPUTER GRAPHICS CS 482 – FALL 2014 AUGUST 20, 2014 GRAPHICS IN OPENGL OPENGL OVERVIEW OPENGL 2D EXAMPLES OPENGL 3D EXAMPLES

/* Render the polygon with its latest position and orientation. */ void draw() { GLfloat theta; glColor3fv(polyColor); glBegin(GL_TRIANGLE_FAN); glVertex2f(x, y); for (int j = 0; j < nbrVerts; j++) { theta = spin + 360 * j * PI_OVER_180 / nbrVerts; glVertex2f(x + radius * cos(theta), y + radius * sin(theta)); theta = spin + 360 * (j + 1) * PI_OVER_180 / nbrVerts; glVertex2f(x + radius * cos(theta), y + radius * sin(theta)); } glEnd(); }

/* Generate a random floating-point value between the two parameterized values. */ float GenerateRandomNumber(float lowerBound, float upperBound) { static bool firstTime = true; static time_t randomNumberSeed;

if (firstTime) { time(&randomNumberSeed); firstTime = false; srand((unsigned int)randomNumberSeed); } return (lowerBound + ((upperBound - lowerBound) * (float(rand()) / RAND_MAX))); } };

#define GLFLOAT_POLYGON_H#endif

// Adjust position & direction if window bounds exceeded. // if (tooRight > 0.0f) { x -= tooRight; xInc *= -1.0f; } else if (tooLeft > 0.0f) { x += tooLeft; xInc *= -1.0f; } if (tooHigh) { y -= tooHigh; yInc *= -1.0f; } else if (tooLow) { y += tooLow; yInc *= -1.0f; } }

// Determine whether polygon exceeds window boundaries. // for (int i = 0; i < nbrVerts; i++) { theta = spin + 360 * i * PI_OVER_180 / nbrVerts; xvalue = x + radius * cos(theta); yvalue = y + radius * sin(theta); if (xvalue - 0.5f * windowWidth > tooRight) tooRight = xvalue - 0.5f * windowWidth; else if (-0.5f * windowWidth - xvalue > tooLeft) tooLeft = -0.5f * windowWidth - xvalue; if (yvalue - 0.5f * windowHeight > tooHigh) tooHigh = yvalue - 0.5f * windowHeight; else if (-0.5f * windowHeight - yvalue > tooLow) tooLow = -0.5f * windowHeight - yvalue; }

OPENGL 2D EXAMPLES

CS 482 – FALL 2014

ANIMATED POLYGONS

AUGUST 20, 2014: GRAPHICS IN OPENGL PAGE 12

/* Default constructor. */ GLfloatPolygon::GLfloatPolygon() { for (int i = 0; i <= 2; i++) polyColor[i] = DEFAULT_COLOR[i]; nbrVerts = DEFAULT_NBR_VERTS; radius = GenerateRandomNumber(RADIUS_RANGE[0], RADIUS_RANGE[1]); x = y = spin = 0.0f; spinInc = GenerateRandomNumber(SPIN_INC_RANGE[0], SPIN_INC_RANGE[1]); xInc = GenerateRandomNumber(X_INC_RANGE[0], X_INC_RANGE[1]); yInc = GenerateRandomNumber(Y_INC_RANGE[0], Y_INC_RANGE[1]); }

/* Update the position and orientation of the polygon with each clock tick. */ void update(GLfloat windowWidth, GLfloat windowHeight) { GLfloat tooHigh; GLfloat tooLow; GLfloat tooLeft; GLfloat tooRight; GLfloat theta, xvalue, yvalue;

tooHigh = tooLow = tooLeft = tooRight = 0.0f;

// Update polygon position and orientation. // x += xInc; y += yInc; spin += spinInc; if (spin > 360 * PI_OVER_180) spin -= 360 * PI_OVER_180;

/////////////////////////////////////////// 2D polygon class (for convenience). ///////////////////////////////////////////#include <GLTools.h> // OpenGL toolkit#include <cmath> // Header File For Math Library#include <ctime> // Header File For Accessing System Time

#ifndef GLFLOAT_POLYGON_H

//////////////////////// Global Constants ////////////////////////const GLfloat PI_OVER_180 = 0.0174532925f; // One Degree. //const GLfloat DEFAULT_COLOR[3] = { 0.5f, 0.5f, 0.5f };const GLint DEFAULT_NBR_VERTS = 3;const GLfloat RADIUS_RANGE[2] = { 0.15f, 0.45f };const GLfloat SPIN_INC_RANGE[2] = { 0.1f, 0.2f };const GLfloat X_INC_RANGE[2] = { 0.02f, 0.05f };const GLfloat Y_INC_RANGE[2] = { 0.02f, 0.05f };

class GLfloatPolygon{ public: GLfloat polyColor[3]; GLint nbrVerts; GLfloat radius; GLfloat x; GLfloat y; GLfloat xInc; GLfloat yInc; GLfloat spin; GLfloat spinInc;

/* Window-reshaping routine, to scale the rendered scene according *//* to the window dimensions, setting the global variables so the *//* mouse operations will correspond to mouse pointer positions. */void ResizeWindow(GLsizei w, GLsizei h){ glViewport(0, 0, w, h); currWindowSize[0] = w; currWindowSize[1] = h; glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) { windowWidth = WINDOW_WIDTH ; windowHeight = WINDOW_HEIGHT * (GLfloat)h / (GLfloat)w; glOrtho(-0.5f * WINDOW_WIDTH, 0.5f * WINDOW_WIDTH, -0.5f * WINDOW_HEIGHT * (GLfloat)h / (GLfloat)w, 0.5f * WINDOW_HEIGHT * (GLfloat)h / (GLfloat)w, ORTHO_NEAR, ORTHO_FAR); } else { windowWidth = WINDOW_WIDTH * (GLfloat)w / (GLfloat)h; windowHeight = WINDOW_HEIGHT; glOrtho(-0.5f * WINDOW_WIDTH * (GLfloat)w / (GLfloat)h, 0.5f * WINDOW_WIDTH * (GLfloat)w / (GLfloat)h, -0.5f * WINDOW_HEIGHT, 0.5f * WINDOW_HEIGHT, ORTHO_NEAR, ORTHO_FAR ); } glMatrixMode(GL_MODELVIEW);}

/* Principal display routine: clears the frame buffer *//* and draws the polygons within the window. */void Display(){ int i; GLfloatPolygon currPoly;

glClear(GL_COLOR_BUFFER_BIT);

// Display each polygon, applying its spin as needed. // for (i = 1; i <= polyList.getSize(); i++) { currPoly = polyList.getHeadValue(); currPoly.draw(); ++polyList; }

glutSwapBuffers(); glFlush();}

/* Function to update each polygon's position by "bouncing" *//* it off the boundaries of the display window. */void TimerFunction(int value){ GLfloatPolygon currPoly;

// Loop through the list of polygons. // for (int i = 1; i <= polyList.getSize(); i++) { currPoly = polyList.getHeadValue(); polyList.removeHead(); currPoly.update(windowWidth, windowHeight); polyList.insert(currPoly); ++polyList; }

// Force a redraw after 50 milliseconds. // glutPostRedisplay(); glutTimerFunc(CALLBACK_TIME, TimerFunction, 1);}

/* Function to react to selection from the pop-up menu, *//* by generating a polygon of the user-selected type. */void MenuSelect(int menuID){ switch(menuID) { case 3: { KeyboardPress( '3', 0, 0 ); break; } case 4: { KeyboardPress( '4', 0, 0 ); break; } case 5: { KeyboardPress( '5', 0, 0 ); break; } case 6: { KeyboardPress( '6', 0, 0 ); break; } case 7: { KeyboardPress( '7', 0, 0 ); break; } case 8: { KeyboardPress( '8', 0, 0 ); break; } case 9: { KeyboardPress( '9', 0, 0 ); break; } default: { break; } }

// After processing the menu action, redraw the image without the menu. glutPostRedisplay();}

/* Function to react to the pressing of keyboard keys by the user, *//* by creating a new polygon with the same number of vertices as the *//* pressed numerical value, with the next consecutive RGBYMC color. */void KeyboardPress(unsigned char pressedKey, int mouseXPosition, int mouseYPosition){ GLfloatPolygon poly; static int i = 0; switch(pressedKey) { case '3': { poly.nbrVerts = 3; break; } case '4': { poly.nbrVerts = 4; break; } case '5': { poly.nbrVerts = 5; break; } case '6': { poly.nbrVerts = 6; break; } case '7': { poly.nbrVerts = 7; break; } case '8': { poly.nbrVerts = 8; break; } case '9': { poly.nbrVerts = 9; break; } default: { return; } } poly.polyColor[0] = ((i == 0) || (i == 3) || (i == 4)) ? HIGH_SHADE : LOW_SHADE; poly.polyColor[1] = ((i == 1) || (i == 3) || (i == 5)) ? HIGH_SHADE : LOW_SHADE; poly.polyColor[2] = ((i == 2) || (i == 4) || (i == 5)) ? HIGH_SHADE : LOW_SHADE; i = (i + 1) % NBR_COLORS; polyList.insert(poly);}

for (int i = 0; i <= 1; i++) currWindowSize[i] = INIT_WINDOW_SIZE[i]; glutInitWindowSize( currWindowSize[0], currWindowSize[1] ); glutCreateWindow( "BOUNCING POLYGONS" );

// Ensure proper OpenGL availability, with generic shader. GLenum err = glewInit(); if (GLEW_OK != err) { fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err)); return; } shaderManager.InitializeStockShaders();

/* Set up the pop-up menu. */ glutCreateMenu( MenuSelect ); glutAddMenuEntry( "Triangle", 3 ); glutAddMenuEntry( "Square", 4 ); glutAddMenuEntry( "Pentagon", 5 ); glutAddMenuEntry( "Hexagon", 6 ); glutAddMenuEntry( "Heptagon", 7 ); glutAddMenuEntry( "Octagon", 8 ); glutAddMenuEntry( "Nonagon", 9 ); glutAttachMenu(GLUT_RIGHT_BUTTON);

/* Specify the resizing, refreshing, and interactive routines. */ glutReshapeFunc( ResizeWindow ); glutDisplayFunc( Display ); glutKeyboardFunc( KeyboardPress ); glutTimerFunc(CALLBACK_TIME, TimerFunction, 1); glutMainLoop();}

//////////////////////// Global Constants ////////////////////////const GLint INIT_WINDOW_POSITION[2] = { 100, 100 }; // Window Offset. //const GLint INIT_WINDOW_SIZE[2] = { 500, 500 }; // Window dimensions. //const GLfloat WINDOW_WIDTH = 2.0f; // Screen coordinates. //const GLfloat WINDOW_HEIGHT = 2.0f; // Screen coordinates. //const GLfloat ORTHO_FAR = 10.0f; // Far plane z-value. //const GLfloat ORTHO_NEAR = -10.0f; // Near plane z-value. //const unsigned int CALLBACK_TIME = 50; // Timer in msecs. //const int NBR_COLORS = 6; // # different colors. //const GLfloat HIGH_SHADE = 0.9f; // High RGB value. //const GLfloat LOW_SHADE = 0.1f; // Low RGB value. //

//////////////////////// Global Variables ////////////////////////GLShaderManager shaderManager; // Manager of stock shaders. //GLint currWindowSize[2]; // Window size in pixels. //GLfloat windowWidth = WINDOW_WIDTH; // Resized window width. //GLfloat windowHeight = WINDOW_HEIGHT; // Resized window height. //LinkedList<GLfloatPolygon> polyList; // Current polygon list. //

/* The main function: uses the OpenGL Utility Toolkit to set *//* the window up to display the window and its contents. */void main(int argc, char **argv){ /* Set up the display window. */ gltSetWorkingDirectory(argv[0]); glutInit(&argc, argv); glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA ); glutInitWindowPosition( INIT_WINDOW_POSITION[0], INIT_WINDOW_POSITION[1] );

Noteworthy: /**************************************************************//* Filename: BouncingPolygons.cpp *//* Uses the keyboard to permit the user to interactively add *//* rotating polygons to a list of shapes bouncing within a *//* display window. When "lower" and "upper" polygons overlap, *//* no clipping takes place and the lower ones are obscured. *//**************************************************************/

#include <GLTools.h> // OpenGL toolkit#include <GLShaderManager.h> // Shader Manager Class#include <cmath> // Header File For Math Library#include <ctime> // Header File For Accessing System Time#include "LinkedList.h" // Header File For Linked List Class#include "GLfloatPolygon.h" // Header File For 2D Polygon Class

#ifdef __APPLE__#include <glut/glut.h> // OS X version of GLUT library#else#define FREEGLUT_STATIC#include <GL/glut.h> // Windows FreeGlut equivalent#endif

/////////////////////////// Function Prototypes ///////////////////////////void KeyboardPress(unsigned char pressedKey, int mouseXPosition, int mouseYPosition);void MenuSelect(int menuID);void TimerFunction(int value);void Display();void ResizeWindow(GLsizei w, GLsizei h);float GenerateRandomNumber(float lowerBound, float upperBound);

• Timer function indicates animation• Polygon data will be stored in linked list

• Double buffering for animation• Context menu setup

• Timer function for updating polygon positions/orientations

• Numerical keys generate polygons

• Context menu merely activates keyboard code

• Timer function doesn’t render – it just updates the polygons• Display function renders polygons

• 2D polygon class

Page 13: COMPUTER GRAPHICS CS 482 – FALL 2014 AUGUST 20, 2014 GRAPHICS IN OPENGL OPENGL OVERVIEW OPENGL 2D EXAMPLES OPENGL 3D EXAMPLES

OPENGL 3D EXAMPLES

CS 482 – FALL 2014

QUADRIC SURFACES

AUGUST 20, 2014: GRAPHICS IN OPENGL PAGE 13

IN THIS EXAMPLE, USERS INTERACT WITH A 3D SNOWMAN BY TOSSING 3D SNOWBALLS.

NOTEWORTHY FEATURES:

• THE SCENE IS COMPOSED OF VARIOUS QUADRIC SURFACES (SPHERES, CYLINDERS, DISKS, CONES, ETC.) THAT MAY BE DISPLAYED AS SOLID OR WIREFRAME OBJECTS.

Noteworthy:• Graphical object classes• Global constant header file• Non-ASCII character control• Wireframe & solid

implementation• Material & lighting properties• Quadric surfaces

Page 14: COMPUTER GRAPHICS CS 482 – FALL 2014 AUGUST 20, 2014 GRAPHICS IN OPENGL OPENGL OVERVIEW OPENGL 2D EXAMPLES OPENGL 3D EXAMPLES

OPENGL 3D EXAMPLES

CS 482 – FALL 2014

QUADRIC SURFACES

AUGUST 20, 2014: GRAPHICS IN OPENGL PAGE 14

IN THIS EXAMPLE, USERS EMPLOY MOUSE OPERATIONS TO TARGET AND EXPLODE 3D ASTEROID CLUSTERS.

NOTEWORTHY FEATURES:

• INSTEAD OF USING THE QUADRIC SURFACES FROM THE GLU LIBRARY, THIS PROGRAM MAKES USE OF THE SPHERE RENDERING CAPABILITIES OF THE GLUT LIBRARY.

Noteworthy:• Mouse-motion reticle control• Ray casting to implement

firing• Color morphing• Lifetime-based particle

regeneration• User orientation via gluLookAt