Control Keys

move to next slide (also Enter or Spacebar).
move to previous slide.
 d  enable/disable drawing on slides
 p  toggles between print and presentation view
CTRL  +  zoom in
CTRL  -  zoom out
CTRL  0  reset zoom

Slides can also be advanced by clicking on the left or right border of the slide.

OpenGL

  • Library with about 670 graphic commands
  • All function names begin with "gl"", for example, glClear(), glBegin()
  • Graphics commands are passed to the graphics card (or more exactly to its driver) and are running on the hardware
  • OpenGL thus allows faster display of interactive 3D graphics than pure CPU programming

OpenGL

  • The graphics commands are implemented by the graphics card driver and are therefore independent of
    • the graphics card hardware
    • the operating system
    • the employed window manager
  • Graphics commands are reasonably close to the hardware and sufficient to achieve the core functionality
  • Various libraries are based on OpenGL and allow programming at a higher level of abstraction

OpenGL Versionen

  • Since its introduction (1992) OpenGL has been continuously extended to support new functionality of graphics cards
    • OpenGL 1.0 (1992), OpenGL 1.1 (1997), OpenGL 1.2 (1998), OpenGL 1.3 (2001), OpenGL 1.4 (2002), OpenGL 1.5 (2003)
    • OpenGL 2.0 (2004), OpenGL 2.1 (2006)
    • OpenGL 3.0 (2008), OpenGL 3.1 (2009), OpenGL 3.2 (2009), OpenGL 3.3 (2010)
    • OpenGL 4.0 (2010), OpenGL 4.1 (2010), OpenGL 4.2 (2011), OpenGL 4.3 (2012), OpenGL 4.4 (2013), OpenGL 4.5 (2014), OpenGL 4.6 (2017)
  • In this lecture, OpenGL 2 is used and in later chapters OpenGL version ≥ 3.1 is utilized
  • Since version 3.1 the so-called "fixed-function-pipeline" is no longer supported, which means "shaders" must always be implemented
  • This makes it difficult to get started. Therefore, this lecture uses the "fixed-function-pipeline" (OpenGL 2) up to Chapter 9 "GLSL Shading Language"

OpenGL ES and WebGL

  • OpenGL ES is a version of OpenGL with reduced functionality
  • "ES" stands for "Enbedded Subsystem"", that is, target platforms are embedded systems such as mobile phones, televisions, tablets, etc.
    • OpenGL ES 1.0 (2003): similar to OpenGL 1.3 (fixed-function-pipeline)
    • OpenGL ES 1.1 (2004): similar to OpenGL 1.5 (backwards compatible)
    • OpenGL ES 2.0 (2007): similar to OpenGL 2.0 (but no fixed-function pipeline, always shader, not backwards compatible)
    • OpenGL ES 3.0 (2012): similar to OpenGL 3.3 (no geometry shader)
    • OpenGL ES 3.1 (2014): similar to OpenGL 4.3
    • OpenGL ES 3.2 (2015): similar to OpenGL 4.3
  • OpenGL ES is used for hardware-assisted graphics output on many smart phones (e.g., Apple's iPhone and Android-based devices)
  • WebGL is based on OpenGL ES 2.0 (and WebGL 2.0 on OpenGL ES 3.0) and allows 3D graphics on web pages (meanwhile supported by almost all browsers)

OpenGL Utility Library (GLU)

  • OpenGL Utility Library (GLU) was part of every OpenGL implementation up to version 3.0
  • GLU extends OpenGL by some functions (approx. 50) with a higher level of abstraction
  • Functions for drawing spheres, cylinders, or circles, camera functionality, texture functionality, etc.
  • In the current OpenGL versions GLU is no longer supported
  • The functionality must be either implemented by own code or provided by external libraries (see, e.g., glm library)

C/C++ Include Files

  • OpenGL defines its interfaces using C functions
  • For GL and GLU functions
    #include <GL/gl.h>
    #include <GL/glu.h>
  • Extensions
    #include <GL/glext.h>
  • Only OpenGL 3.1 functions (no fixed-function pipeline)
    #include <GL3/gl3.h>
    #include <GL3/gl3ext.h>

OpenGL Utility Toolkit (GLUT)

  • is a possible window manager for C/C++ programs
  • is not part of a standard installation and must be typically installed separately (freeglut)
  • provides the rendering context for OpenGL in which OpenGL functions can be called
  • handles mouse and keyboard input
  • provides a platform-independent interface
  • is included by
    #include <GL/freeglut.h>
    (Gl/gl.h and GL/glu.h are automatically included)

OpenGL Utility Toolkit (GLUT) as Window Manager

#include <GL/freeglut.h> // we use glut as window manager

class Renderer {
public:
  void init() {...}
  void resize(int w, int h) {...}
  void display() {...}
  void dispose() {...}
};

// static objects and callbacks
static Renderer *renderer;

static void glutResize(int w, int h) 
{ 
  renderer->resize(w, h); 
}

static void glutDisplay() 
{ 
  renderer->display(); 
  glutSwapBuffers(); 
}

static void glutClose()
{ 
  renderer->dispose(); 
}

int main(int argc, char **argv) {
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
  glutInitWindowPosition(100,100);
  glutInitWindowSize(320, 320);
  glutCreateWindow("WindowTitle");
  glutDisplayFunc(glutDisplay);
  glutReshapeFunc(glutResize);
  glutCloseFunc(glutClose);
  renderer = new Renderer;
  renderer->init();
  glutMainLoop();
}

Qt as Window Manager

  • As already discussed in Part 2, Chapter 3, Qt is a widely used class library for cross-platform development of GUIs (Qt website)
  • Qt can also be used in combination with OpenGL
  • To that end, the class QOpenGLWidget must be overwritten
  • Furthermore, the corresponding QMake project file must be extended by the line "QT += widgets opengl openglwidgets"
    QT += widgets opengl openglwidgets
    TARGET = ApplicationName
    SOURCES += main.cpp Widget1.cpp Widget2.cpp
    HEADERS += Widget1.h Widget2.h
    

Qt as Window Manager

#include <QApplication>
#include <QOpenGLWidget>
#include <QOpenGLFunctions_2_0>

class Renderer : protected QOpenGLFunctions_2_0 {
public:
  void init() {
    initializeOpenGLFunctions();
    ...
  }
  void resize(int w, int h) {...}
  void display() {...}
  void dispose() {...}
};

class MyWidget : public QOpenGLWidget {
private:
    Renderer *renderer;
public:
  MyWidget(QWidget *parent = NULL) : QOpenGLWidget(parent) {
    this->setWindowTitle("OpenGL with Qt");
    this->resize(320, 320);
    renderer = new Renderer();
  }
  ~MyWidget() { 
     makeCurrent();
     renderer->dispose();
     doneCurrent();
     delete renderer; 
   }
protected:
  void initializeGL() { renderer->init(); }
  void resizeGL(int w, int h){ renderer->resize(w, h); }
  void paintGL() { renderer->display(); }
};

int main (int argc, char* argv[]) {
  QApplication appl(argc, argv);
  MyWidget widget;  // create a widget
  widget.show(); //show the widget and its children
  return appl.exec(); // execute the application
}

OpenGL and Java

  • Java can also be used in combination with OpenGL
  • For that purpose in this lecture JOGL (Java Binding for the OpenGL API) is used (JOGL website)
  • The OpenGL function calls have the same syntax as in C
  • JOGL needs to be installed in addition to the JDK (Installation instructions)

OpenGL and Java

Compilation: (in a shell)

javac -classpath "jar/gluegen-rt.jar;jar/jogl-all.jar" sourcefile.java

Execution:

java -classpath "jar/gluegen-rt.jar;jar/jogl-all.jar;." sourcefile

The following additional command line parameter is required for the current JDK version (Java 19):

java --add-exports java.desktop/sun.awt=ALL-UNNAMED 
     -classpath "jar/gluegen-rt.jar;jar/jogl-all.jar;." sourcefile

Classpath for Linux:

-classpath "jar/gluegen-rt.jar:jar/jogl-all.jar:."

Java as Window Manager

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import com.jogamp.opengl.*;
import com.jogamp.opengl.awt.GLCanvas;
import com.jogamp.opengl.util.FPSAnimator;
import static com.jogamp.opengl.GL.*;  
import static com.jogamp.opengl.GL2.*;


class Renderer {
  public void init(GLAutoDrawable d) {...}
  public void resize(GLAutoDrawable d, int w, int h) {...}
  public void display(GLAutoDrawable d) {...}
  public void dispose(GLAutoDrawable d) {...}
}

class MyGui extends JFrame implements GLEventListener{
  private Renderer renderer;
 
  public void createGUI() {
    setTitle("JoglFirstTriangle");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   
    GLProfile glp = GLProfile.getDefault();
    GLCapabilities caps = new GLCapabilities(glp);
    GLCanvas canvas = new GLCanvas(caps);
    setSize(320, 320);
    getContentPane().add(canvas);
    final FPSAnimator ani = new FPSAnimator(canvas, 60, true);
    canvas.addGLEventListener(this);
    setVisible(true);
    renderer = new Renderer();
    ani.start();
  }

  @Override
  public void init(GLAutoDrawable d) { 
    renderer.init(d); 
  }

  @Override
  public void reshape(GLAutoDrawable d, int x, int y, 
                      int width, int height) { 
    renderer.resize(d, width, height); 
  }

  @Override
  public void display(GLAutoDrawable d) { 
     renderer.display(d); 
  }

  @Override
  public void dispose(GLAutoDrawable d) { 
    renderer.dispose(d);
  }
}

public class JoglFirstTriangle {
  public static void main(String[] args) {
    System.setProperty("sun.java2d.uiScale", "1.0");
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        MyGui myGUI = new MyGui();
        myGUI.createGUI();
      }
    });
  }
}

The first OpenGL program: Drawing a Triangle

  • Now that the different window managers (GLUT, Qt, Java) were introduced, a triangle will be drawn on the screen with OpenGL
  • In the following, only the functions init(), resize(), display(), and dispose() of the class Renderer are presented, which are completely independent of the employed window manager

The first OpenGL program: Drawing a Triangle

class Renderer {
public:
  void init() {}
  void resize(int w, int h) { glViewport(0, 0, w, h); }
  void display() {
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    glLoadIdentity();
    glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
    glColor3f(1.0f, 1.0f, 1.0f);
    glBegin(GL_TRIANGLES);
    glVertex3f(-0.5f, -0.5f, 0.0f); // vertex on the left
    glVertex3f( 0.5f, -0.5f, 0.0f); // vertex on the right
    glVertex3f( 0.0f,  0.5f, 0.0f); // vertex at the top of the triangle
    glEnd();
  }
  void dispose() {}
};

The first OpenGL program: Drawing a Triangle

opengl_triangle

OpenGL as a State Machine

  • While drawing, OpenGL behaves like a state machine, where the current state influences the output
  • For example, the instruction glColor(...) sets the current drawing color
  • This state remains active until it is changed by another graphics command, e.g, until the next call of glColor(...)

OpenGL as a State Machine

  • OpenGL can push certain combinations of states by glPushAttrib() onto a stack and later re-active them by popping them from the stack with glPopAttrib()
... // draw something here
glPushAttrib(GL_LINE_BIT);    
  glEnable(GL_LINE_SMOOTH);       
  glEnable(GL_LINE_STIPPLE); 
glPushAttrib(GL_COLOR_BUFFER_BIT);
  glEnable(GL_BLEND);
  glDisable(GL_DITHER);
... // drawing something special here
glPopAttrib(); // restore GL_COLOR_BUFFER_BIT
glPopAttrib(); // restore GL_LINE_BIT
... // draw more here

OpenGL-Pipeline

openglpipeline
openglpipeline
openglpipeline
openglpipeline
openglpipeline
openglpipeline
openglpipeline
Source: based on Mark Segal, Kurt Akeley, The OpenGL Graphics System: A Specification Version 2.0, 2004, Figure 2.1. Block diagram of the GL (modified)

OpenGL-Pipeline

  • In the following slides, the individual building blocks of the OpenGL pipeline are explained
  • Currently the aim is only to obtain a rough overview
  • Details will follow in later parts of the lecture

Framebuffer

  • The framebuffer is the "canvas" on which OpenGL draws
  • The framebuffer is a raster graphics, i.e., it has a certain width and height and contains pixels that are arranged on a fixed grid
  • Later, we will learn that OpenGL can draw in multiple attached framebuffers at the same time

Vertex Data

  • A vertex is a coordinate point of graphic object, such as a line, triangle, or polygon
  • With glVertex(...) the vertices are passed individually
    glBegin(GL_TRIANGLES);
    glVertex3f(-0.5f, -0.5f, 0.0f); // vertex on the left
    glVertex3f( 0.5f, -0.5f, 0.0f); // vertex on the right
    glVertex3f( 0.0f,  0.5f, 0.0f); // vertex at the top of the triangle
    glEnd();
  • Later in this lecture, we will get to know techniques that will allow us to pass large memory blocks containing vertex data to the OpenGL pipeline

Per-Vertex Operations

  • In this step, a series of operations is performed for each vertex
  • When using the fixed-function pipeline these comprise, for example,
    • The transformation from the global world-coordinate system in the camera coordinate system and projection in the camera image plane
    • Generation of normals or texture coordinates and their transformation
    • Calculation of a vertex color for a given lighting
  • When using shaders, this step is implemented by means of a so-called vertex shader

Primitive Assembly & Per-Vertex Post-Processing

  • While assembling primitives the vertex data can be used in different ways. This dependents on the argument that is passed to glBegin(...)
prim_types

Primitive Assembly & Per-Vertex Post-Processing

  • Furthermore, in this step, 3D clipping operations are performed. By clipping, additional vertex points can be generated.
  • Then a perspective division is performed, which generates the perspective 2D projection of the objects
  • Hidden primitives can be removed
  • Then the 2D coordinates are scaled and/or shifted according to the selected image resolution and position
  • The generated primitives now know their 2D coordinates (real numbers) in the frame buffer and are transferred to the 2D rasterizer

Pixel Data

  • OpenGL is able to process raster graphics
  • In addition, raster images are often used as textures ("color wallpaper")
  • It is also possible to use the image from the frame buffer as input for a secondary rendering pass

Pixel Operations

  • Pixel data are converted from the main memory of the computer into a particular OpenGL storage format
  • Image manipulations can be performed such as zoom in, zoom out, turn the image, manipulate color values, apply filters, etc.
  • Many of these operations are part of the fixed-function pipeline and are nowadays generally realized by texture and framebuffer objects

Texture Assembly

  • Pixel data can also be used as textures
  • Textures are stored in texture objects, which are equipped with an ID (key) and can be referenced and reused
  • That is, for generation of a texture the pixel data must be transferred only once from the computer's main memory onto the graphics card memory and stays available there
  • The graphics card hardware supports fast access to textures

Rasterizer

  • The rasterizer converts the processed vertex or pixel data in so-called fragments
  • Even on modern graphics hardware (with programmable shader units) the raster conversion is still realized by dedicated hardware
  • Each fragment knows its interpolated color value, depth value, and and possibly other interpolated attributes, such as its texture coordinate or surface normal

Per-Fragment Operations

  • Before the fragment data ends up as pixel values in the framebuffer, a series of operations for each fragment is performed
  • When using the fixed-function pipeline these comprise, for example,
    • Texturing
    • Color generation or manipulation
    • Fog
  • When using shaders, this step can be implemented by means of a so-called fragment shader

Per-Fragment Operations

  • The resulting fragment is then passed through a few more (optional) processing steps until the information reaches the framebuffer:
  1. Scissor-Test
  2. Alpha-Test
  3. Depth-Test
  4. Stencil-Test
  5. Blending
  6. Dithering
  7. Logical operations

Are there any questions?

questions

Please notify me by e-mail if you have questions, suggestions for improvement, or found typos: Contact

More lecture slides

Slides in German (Folien auf Deutsch)