Teaching Computer Graphics with Modern OpenGL

Post on 14-Feb-2016

91 views 1 download

description

Teaching Computer Graphics with Modern OpenGL. Ed Angel University of New Mexico. Overview. Starting teaching a top-down approach using OpenGL about 20 years ago Co-author of Interactive Computer Graphics Sixth edition switched to a fully shader-based approach Successful but …. - PowerPoint PPT Presentation

transcript

Teaching Computer Graphics with Modern OpenGL

Ed AngelUniversity of New Mexico

Starting teaching a top-down approach using OpenGL about 20 years ago

Co-author of Interactive Computer Graphics Sixth edition switched to a fully shader-based

approach Successful but …..

Overview

OpenGL 1.0 was released on July 1st, 1994

Its pipeline was entirely fixed-function

the only operations available were fixed by the implementation

The pipeline evolved, but remained fixed-function through OpenGL versions 1.1 through 2.0 (Sept. 2004)

In the Beginning …

PrimitiveSetup and

Rasterization

Fragment Coloring and

TexturingBlending

VertexData

PixelData

Vertex Transform and

Lighting

TextureStore

Sierpinski Gasket

First Program (old style)

#include <GL/glut.h>

void myinit() { glClearColor(1.0, 1.0, 1.0, 1.0); /* white background */ glColor3f(1.0, 0.0, 0.0); /* draw in red */

glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, 50.0, 0.0, 50.0); glMatrixMode(GL_MODELVIEW);}

void display( void ){

GLfloat vertices[3][2]={{0.0,0.0},{25.0,50.0},{50.0,0.0}}; /* A triangle */

int j, k; int rand(); /* standard random number generator */ GLfloat p[2] ={7.5,5.0}; /* An arbitrary initial point inside traingle */

glClear(GL_COLOR_BUFFER_BIT); /*clear the window */

/* compute and plots 5000 new points */

glBegin(GL_POINTS);

for( k=0; k<5000; k++) { j=rand()%3; /* pick a vertex at random */

/* Compute point halfway between selected vertex and old point */

p[0] = (p[0]+vertices[j][0])/2.0; p[1] = (p[1]+vertices[j][1])/2.0; /* plot new point */

glVertex2fv(p); }

glEnd(); glFlush(); /* clear buffers */ }

void main(int argc, char** argv){

/* Standard GLUT initialization */

glutInit(&argc,argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); /* default, not needed */ glutInitWindowSize(500,500); /* 500 x 500 pixel window */ glutInitWindowPosition(0,0); /* place window top left on display */ glutCreateWindow("Sierpinski Gasket"); /* window title */ glutDisplayFunc(display); /* display callback invoked when window opened */

myinit(); /* set attributes */

glutMainLoop(); /* enter event loop */}

void display( void ) { GLfloat vertices[3][2]={{0.0,0.0},{25.0,50.0}, {50.0,0.0}}; / int j, k; int rand(); /* standard random number generator */ GLfloat p[2] ={7.5,5.0}; /*point inside triangle */

glClear(GL_COLOR_BUFFER_BIT); /*clear the window */

/* compute and plots 5000 new points */

glBegin(GL_POINTS);

for( k=0; k<5000; k++) { j=rand()%3; /* pick a vertex at random */

/* Compute point halfway between selected vertex and old point */

p[0] = (p[0]+vertices[j][0])/2.0; p[1] = (p[1]+vertices[j][1])/2.0; /* plot new point */

glVertex2fv(p); }

glEnd(); glFlush(); /* clear buffers */ }

void main(int argc, char** argv){

/* Standard GLUT initialization */

glutInit(&argc,argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); /* default, not needed */ glutInitWindowSize(500,500); /* 500 x 500 pixel window */ glutInitWindowPosition(0,0); /* place window top left on display */ glutCreateWindow("Sierpinski Gasket"); /* window title */ glutDisplayFunc(display); /* display callback invoked when window opened */

myinit(); /* set attributes */

glutMainLoop(); /* enter event loop */}

glBegin(GL_POINTS); for( k=0; k<5000; k++) { j=rand()%3; /* pick a vertex at random */ p[0] = (p[0]+vertices[j][0])/2.0; p[1] = (p[1]+vertices[j][1])/2.0; glVertex2fv(p); }

glEnd(); glFlush(); /* clear buffers */ }

void main(int argc, char** argv){

/* Standard GLUT initialization */

glutInit(&argc,argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); /* default, not needed */ glutInitWindowSize(500,500); /* 500 x 500 pixel window */ glutInitWindowPosition(0,0); /* place window top left on display */ glutCreateWindow("Sierpinski Gasket"); /* window title */ glutDisplayFunc(display); /* display callback invoked when window opened */

myinit(); /* set attributes */

glutMainLoop(); /* enter event loop */}

void main(int argc, char** argv) { glutInit(&argc,argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(500,500); glutInitWindowPosition(0,0); glutCreateWindow("Sierpinski Gasket"); glutDisplayFunc(display);

myinit();

glutMainLoop(); /* enter event loop */}

OpenGL 2.0 (officially) added programmable shaders vertex shading augmented the fixed-function transform and

lighting stage

fragment shading augmented the fragment coloring stage

However, the fixed-function pipeline was still available

The Start of the Programmable Pipeline

PrimitiveSetup and

Rasterization

Fragment Coloring and

TexturingBlending

VertexData

PixelData

Vertex Transform and

Lighting

TextureStore

OpenGL 3.0 introduced the deprecation model the method used to remove features from OpenGL

The pipeline remained the same until OpenGL 3.1 (released March 24th, 2009)

Introduced a change in how OpenGL contexts are used

An Evolutionary Change

Context Type Description

Full Includes all features (including those marked deprecated) available in the current version of OpenGL

Forward Compatible Includes all non-deprecated features (i.e., creates a context that would be similar to the next version of OpenGL)

OpenGL 3.1 removed the fixed-function pipeline programs were required to use only shaders

Additionally, almost all data is GPU-resident all vertex data sent using buffer objects

The Exclusively Programmable Pipeline

PrimitiveSetup and

Rasterization

FragmentShader Blending

VertexData

PixelData

VertexShader

TextureStore

OpenGL 3.2 also introduced context profiles profiles control which features are exposed

it’s like GL_ARB_compatibility, only not insane currently two types of profiles: core and compatible

More Evolution – Context Profiles

Context Type Profile Description

Fullcore All features of the current release

compatible All features ever in OpenGL

Forward Compatiblecore All non-deprecated features

compatible Not supported

First Program (old style)

#include <GL/glut.h>

void myinit() { glClearColor(1.0, 1.0, 1.0, 1.0); /* white background */ glColor3f(1.0, 0.0, 0.0); /* draw in red */

glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, 50.0, 0.0, 50.0); glMatrixMode(GL_MODELVIEW);}

void display( void ) { GLfloat vertices[3][2]={{0.0,0.0},{25.0,50.0}, {50.0,0.0}}; / int j, k; int rand(); /* standard random number generator */ GLfloat p[2] ={7.5,5.0}; /*point inside triangle */

glClear(GL_COLOR_BUFFER_BIT); /*clear the window */

/* compute and plots 5000 new points */

glBegin(GL_POINTS); for( k=0; k<5000; k++) { j=rand()%3; /* pick a vertex at random */ p[0] = (p[0]+vertices[j][0])/2.0; p[1] = (p[1]+vertices[j][1])/2.0; glVertex2fv(p); }

glEnd(); glFlush(); /* clear buffers */ }

void main(int argc, char** argv) { glutInit(&argc,argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(500,500); glutInitWindowPosition(0,0); glutCreateWindow("Sierpinski Gasket"); glutDisplayFunc(display);

myinit();

glutMainLoop(); /* enter event loop */}

Let’s look at same example Contend not significantly harder

But model is different: retained mode

Still use GLUT (or freeglut) C++ better

Provide mat.h and vec.h to match GLSL

Fully Shader-Based Version

example.cpp

#include "Angel.h”const int NumPoints = 5000;

void init( void ) { vec2 points[NumPoints]; vec2 vertices[3] = {vec2(-1.0, -1.0), vec2(0.0, 1.0), vec2(1.0, -1.0 )}; points[0] = vec2( 0.25, 0.50 );

for ( int i = 1; i < NumPoints; ++i ) { int j = rand() % 3; points[i] = ( points[i - 1] + vertices[j] ) / 2.0; }

example.cpp GLuint vao[1]; glGenVertexArrays ( 1, vao ); glBindVertexArray ( vao[0] ); GLuint buffer; glGenBuffers( 1, &buffer ); glBindBuffer( GL_ARRAY_BUFFER, buffer ); glBufferData( GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW );

GLuint program = InitShader( "vshader21.glsl”, "fshader21.glsl" ); glUseProgram( program );

example.cpp

GLuint loc = glGetAttribLocation( program, "vPosition" ); glEnableVertexAttribArray( loc ); glVertexAttribPointer( loc, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );

glClearColor( 1.0, 1.0, 1.0, 1.0 ); // white background}

example.cpp

void display( ){ glClear( GL_COLOR_BUFFER_BIT ); // clear the window glDrawArrays( GL_POINTS, 0, NumPoints ); // draw the points glFlush();}

example.cpp

int main( int argc, char **argv ){ glutInit( &argc, argv ); glutInitDisplayMode( GLUT_RGBA ); glutInitWindowSize( 512, 512 ); glutCreateWindow( "Sierpinski Gasket" ); init(); glutDisplayFunc( display ); glutMainLoop(); return 0;}

shaders

out vec4 FragColor;void main(){ gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );}

in vec4 vPosition;void main(){ gl_Position = vPosition;}

Not hard to get students started Present situation has some problems

No GLU

What to do about GLUT

Interactivity more difficult

System dependencies

Web is what is happening

Issues

We are teaching Computer Graphics We are not teaching OpenGL as anything but a tool to help

No negative feedback from instructors

Top-down programming approach is still best

Must keep up with advances in hardware

Interactivity a problem

Will WebGL replace desktop OpenGL for teaching?

Observations

WebGL versionvar canvas;var gl;var NumPoints = 5000;

window.onload = init;

function init() { canvas = document.getElementById( "gl-canvas" ); gl = WebGLUtils.setupWebGL( canvas ); if ( !gl ) { alert( "WebGL isn't available" ); } gl.viewport( 0, 0, canvas.width, canvas.height ); gl.clearColor( 1.0, 1.0, 1.0, 1.0 );

var vertices2 = new Array(3);

vertices2[0] = point2.create([-1, -1]); vertices2[1] = point2.create([0, 1]); vertices2[2] = point2.create([1, -1]);

// Load shaders and initialize attribute buffers var program = initShaders( gl, "vertex-shader", "fragment-shader" ); gl.useProgram( program );

var pointsArray = new Array(NumPoints); pointsArray[0] = vec2.create([0.25,0.50]);

for (i = 1; i < NumPoints; i++) { j = Math.floor(Math.random() * 3); pointsArray[i] = point2.create(); point2.add(pointsArray[i-1], vertices2[j], pointsArray[i]); point2.scale(pointsArray[i], 0.5); }

var bufferId = gl.createBuffer(); gl.bindBuffer( gl.ARRAY_BUFFER, bufferId ); gl.bufferData( gl.ARRAY_BUFFER, flatten(pointsArray), gl.STATIC_DRAW );

var vPos = gl.getAttribLocation( program, "vPosition" ); gl.vertexAttribPointer( vPos, 2, gl.FLOAT, false, 0, 0 ); gl.enableVertexAttribArray( vPos );

render();}

function render() { gl.clear( gl.COLOR_BUFFER_BIT ); gl.drawArrays( gl.POINTS, 0, NumPoints );

// window.requestAnimFrame( render, canvas );

}

example.html<html><script id="vertex-shader" type="x-shader/x-vertex">

attribute vec4 vPosition;void main() { gl_Position = vPosition;}</script>

<script id="fragment-shader" type="x-shader/x-fragment">

void main() { gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );}</script>

example.html

<script type="text/javascript" src="../Common/webgl-utils.js”></script><script type="text/javascript" src="../Common/initShaders.js”></script><script type="text/javascript" src="chap2ex1.js"></script><script type="text/javascript" src="../Common/glMatrixEA.js”></script>

<body><canvas id="gl-canvas" width="512” height="512”Oops ... your browser doesn't support the HTML5 canvas element</canvas></body></html>

Examples in all forms on my website:

www.cs.unm.edu/~angel

under book support

Fifth edition for old examples

Sixth edition for shader-based in C++ and WebGL