OpenGL – An introduction - elmindreda · OpenGL is a state machine The old way; fixed pipeline...

Post on 18-Jan-2019

229 views 0 download

Transcript of OpenGL – An introduction - elmindreda · OpenGL is a state machine The old way; fixed pipeline...

OpenGL – An introduction

Camilla Berglundelmindreda@stacken.kth.se

Introductory illustration by theodore

This material is under a Creative Commons licensehttp://creativecommons.org/licenses/by-sa/2.5/se/

http://www.elmindreda.org/opengl/

Requirements

● Basic ANSI C● Basic linear algebra and trigonometry● Basic familiarity with common computer

graphics terminology

Before we begin...

● This lecture is not complete– More states, commands, extensions and object types

exist than will be shown here.

● You can get most of it from the Red Book– But this way, you'll know what to look for.

● Examples are intended to be easily readable– Don't confuse them with serious code.

Terminology

This is a pixel

Any questions?

What doesn't OpenGL do?

● Provide a scene graph or “3D-engine”.● Provide any kind of animation support.● Handle input (keyboard, mouse, joystick, time).● Handle windows or display modes.● Import or export external data formats.● Initialise OpenGL (?!)

– However, this is actually an advantage.

So what is OpenGL?

● A standardised, relatively platform independent, networkable API for rendering of two- and three-dimensional graphical primitives, with a structure suitable for hardware acceleration.

● A “portable” interface to your “3D-card”.

Why should you avoid OpenGL?

● It evolves slower than Direct3D does.● It has a lower level of abstraction than Direct3D,

and thus requires more work to write a proper rendering engine for.

● Support for hardware-accelerated OpenGL on Open/Free Unix-systems is still lacking.– However, there is always Mesa.

Why then use OpenGL?

● It is standardised and portable.● It is (probably) available on your platform.● It is easy to get started with.● The API is very stable; old code is still relevant.● New core functionality tends to be future proof.

How does OpenGL evolve?

● ARB – The Architecture Review Board● Extension mechanism (ask your API for details)● Every OEM and API can add their own

extensions as they see fit:– GL_NV_foo_bar

– GL_ARB_baz

– GLX_glork

– WGL_ARB_swizzled_quuxes

OpenGL is a state machine

● The old way; fixed pipeline– A huge (but static) collection of wheels and knobs.

– Easy to get started with, lower demands on hardware, but very limiting for advanced rendering.

● The new way; programmability– Large parts of the fixed pipeline can today be replaced

by various kinds of programs.

– These programs can access all relevant states.

– More work to get started with, but also more flexible.

API naming conventions

● GL_FOO_BAR for constants

● glFooBar for functions and procedures

● GLfoobar for data types

● Suffixes on functions with several variants– n specific number of parameters

– d f i s b specific data type

– v pointer to one or more values

– Example: glVertex3fv

State commands

● Setting boolean states– glEnable, glDisable

● Setting complex states– glLight, glMaterial, glTexEnv, glClearColor, etc...

● Using the state stack– glPushAttrib, glPopAttrib

● Retrieving states– glGetInteger, glGetError, glGetLight, etc...

#include <GL/glfw.h>

int main(void){  if (!glfwInit())    return 1;

  if (glfwOpenWindow(640, 480, 8, 8, 8, 0, 0, 0, GLFW_WINDOW))  {    glClearColor(1.f, 0.f, 0.f, 0.f);        while (glfwGetWindowParam(GLFW_OPENED))    {      glClear(GL_COLOR_BUFFER_BIT);

      glfwSwapBuffers();    }  }

  glfwTerminate();

  return 0;}

Some nomenclature

● Vertex– A position in space, plus associated attributes

– Used to define all supported 3D primitive types.

● Fragment– A value from one part of the pixel pipeline.

– We will only be dealing with color fragments.

● Pixel– The result of combining all relevant fragments.

– This is what gets written into the framebuffer.

Geometric primitives

● Points● Line segments

– Strip, list, loop

● Triangles– Strip, list, fan

● Quads (planar only)– Strip, list

● Single polygon (simple, convex, planar only)

Line primitives

Line list

Line strip

Line loop

Triangle primitives

Triangle fan

Triangle list

Triangle strip

Quad primitives

Quad list

Quad strip

Geometric primitive commands

● Begin rendering– glBegin(GLenum mode) the desired primitive(s)

● Vertex attributes– glColor... for vertex color

– glTexCoord... for texture coordinate

– glNormal... for vertex normal

– glVertex... for finalising a vertex

● End rendering– glEnd()

Basic vertex processing

● Modelview matrix transformation– From object space into camera space

● Projection matrix transformation– From camera space into clipping space

● Clipping to the viewing frustum– Including user-defined clipping planes.

● Perspective divide● Viewport transformation

Matrix commands

● Changing the active stack– glMatrixMode

● Working with the stack– glPushMatrix, glPopMatrix

● Working with the current matrix– glLoadIdentity, glMultMatrix, glLoadMatrix

● Commonly used matrix constructions– glRotate..., glTranslate..., glScale..., glFrustum

– gluLookAt, gluProjection, gluOrtho2D

glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(60.f, WIDTH / (GLdouble) HEIGHT, 0.1f, 100.f);glMatrixMode(GL_MODELVIEW);

while (glfwGetWindowParam(GLFW_OPENED)){  glClear(GL_COLOR_BUFFER_BIT);

  glLoadIdentity();  glTranslatef(0.f, 0.f, ­2.f);  glRotatef(glfwGetTime() * 50.f, 0.f, 1.f, 0.f);

  glBegin(GL_TRIANGLES);  glColor3f(1.f, 0.f, 0.f);  glVertex3f(0.f, 1.f, 0.f);  glColor3f(0.f, 1.f, 0.f);  glVertex3f(1.f, ­1.f, 0.f);  glColor3f(0.f, 0.f, 1.f);  glVertex3f(­1.f, ­1.f, 0.f);  glEnd();

  glfwSwapBuffers();}

Lighting

● Four kinds of light source– Spot-, point-, directional and global ambient lights.

● Fixed number of simultaneous lights– But this is can be worked around.

● Lighting in fixed pipeline is per vertex– Fragment programs allow more complex lighting

models, as well as per-pixel lighting

● Lighting formula is basically Phong's model

Materials

● Defines emission and reflectivity parameters– Ambient, diffuse and specular reflection.

– Emission (which does not affect other primitives).

● Ambient and/or diffuse reflection can be connected to glColor commands

● But usually, you specify materials per primitive– Texture mapping is better for detailed coloring.

Partial lighting formulas

I local=ke∑i=0

n

I ia kakd N⋅L ik s V⋅Ris

I global=k a I ga

Per vertex for fixed pipeline lighting;programmable pipeline allows better models

Note that attenuation isn't shown here

I= I local I global

Lighting commands

● Enabling and disabling lighting– GL_LIGHTING for global control

– GL_LIGHTn for individual lights

● Changing individual light parameters– glLight...

● Changing material properties– glMaterial...

● Changing the lighting model– glLightModel...

GLfloat position[4] = { 0.f, 0.f, 1.f, 0.f };Glfloat color[4] = { 1.f, 0.f, 0.5f, 0.f };

[...]

glEnable(GL_LIGHTING);glEnable(GL_LIGHT0);glLightfv(GL_LIGHT0, GL_POSITION, position);glMaterialfv(GL_FRONT, GL_DIFFUSE, color);

while (...){  [...]

  draw_cube();

  [...]}

Some more nomenclature

● Texel– A fragment originating from a texture map, analogous

to a framebuffer pixel.

● Mipmap– One of several versions of a texture, used to minimise

aliasing errors.

● Texture space– The coordinate system within a texture map, usually

but not always in the range [0, 1].

Texture mapping

● Textures are objects accessed through handles● Textures can be 1D, 2D, 3D or cube maps● Texture coordinates...

– ...are per vertex, unless you use fragment programs.

– ...address texture space, not object space.

– ...have their own transformation matrix stack.

– ...can be specified during rendering.

– ...can be generated with glTexGen.

Texture object commands

● Managing texture objects– glGenTextures, glIsTexture, glDeleteTextures

● Setting the active texture object– glBindTexture

● Setting texture object states– glTexParameter...

● Setting global texture states– glTexEnv...

Texture data commands

● Writing texture data– glTexImage2D, glTexSubImage2D

● Reading texture data– glGetTexImage

● Copying from the color buffer– glCopyTexImage2D, glCopyTexSubImage2D

● All of these exist for 1D (and nowadays 3D)

GLuint textureID;

glEnable(GL_TEXTURE_2D);

glGenTextures(1, &textureID);glBindTexture(GL_TEXTURE_2D, textureID);

generate_texture(64, 64);

glEnable(GL_TEXTURE_GEN_S);glEnable(GL_TEXTURE_GEN_T);glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);

while (...){  [...]

  draw_cube();

  [...]}

void generate_texture(unsigned int width,                      unsigned int height){  GLubyte* data = (GLubyte*) malloc(width * height);

  /* Insert magic here */

  gluBuild2DMipmaps(GL_TEXTURE_2D,                    1,                    width, height,                    GL_LUMINANCE,                    GL_UNSIGNED_BYTE,                    data);

  free(data);}

Culling

● A simple form of hidden surface removal.● Removes filled primitives based on their winding.

– Primitives with a certain winding, as it appears during rendering, will be culled when enabled.

– By default, clockwise winding is culled.

Culling commands

● Global culling control– GL_CULL_FACE to glEnable/glDisable

● Deciding which faces to cull– glCullFace Front, back or both

● Deciding which face is front– glFrontFace CW or CCW

Blending

● When blending, pixels are combined with the color buffer instead of simply written to it.– This enables effects such as simple transparency.

● In fixed pipeline, there is a single, fixed formula for combining pixels– Unless you have GL_ARB_imaging.

s f∗ f sd f∗ f d

Blending commands

● Global blending control– GL_BLEND to glEnable/glDisable

● Setting source and destination factors– glBlendFunc

● Also, if you have GL_ARB_imaging– glBlendColor

– glBlendEquation

glEnable(GL_BLEND);glBlendFunc(GL_ONE, GL_SRC_ALPHA);

while (...){  [...]

  glLoadIdentity();  glTranslatef(0.f, ­1.f, ­4.5f);  glRotatef(glfwGetTime() * 40.f, 1.f, 1.f, 0.f);  draw_cube();

  glLoadIdentity();  glTranslatef(0.6f, 0.f, ­3.f);  glRotatef(glfwGetTime() * 20.f, 1.f, 0.f, ­1.f);  draw_cube();

  glLoadIdentity();  glTranslatef(­0.2f, 0.2f, ­1.5f);  glRotatef(glfwGetTime() * 50.f, 1.f, 1.f, 1.f);  draw_cube();

  [...]}

Fog

● Tinting vertices based on distance● Fixed pipeline fog has a single color● Gives a crude impression of depth

– Useful for simulating certain atmospheric effects.

● Three fog formulas– Linear, exponential and exponential squared.

Fog formulas

f =e−density∗z

f =e−density∗z 2

f =end−zend− start

C= f C i1− f C f

Exponential

Exponential squared

Linear

Final interpolation

Fog commands

● Global fog control– GL_FOG to glEnable/glDisable

● Setting fog parameters– glFog...

● Controlling fog niceness– GL_FOG_HINT to glHint

struct ColorRGBA color = { 0.8f, 0.8f, 0.7f, 0.f };

glClearColor(color.r, color.g, color.b, 0.f);

glEnable(GL_FOG);glFogi(GL_FOG_MODE, GL_LINEAR);glFogf(GL_FOG_START, 0.f);glFogf(GL_FOG_END, 10.f);glFogfv(GL_FOG_COLOR, (GLfloat*) &color);

while (...){  glLoadIdentity();  glTranslatef(1.f, 0.f, ­4.f);

  for (i = 0;  i < 5;  i++)  {    glTranslatef(0.f, 0.f, ­1.5f);    glRotatef(glfwGetTime() * 50.f, 1.f, 1.f, 1.f);

    draw_cube();  }

  [...]}

Buffers

● Color buffer● Depth buffer

– Z axis distance or eye distance values

● Stencil buffer– Scratch values for dynamic masking effects

● Accumulation buffer● Auxillary buffers

Texture / buffer formats

● Color (RGB)● Intensity● Luminance● Alpha● Depth● Normal maps● Combined or compressed variants of the above

Buffer commands

● Setting clearing values– glClearColor, glClearDepth, glClearStencil, etc...

● Clearing buffers– glClear

● Masking buffer writes– glColorMask, glDepthMask, glStencilMask

● Limiting writes to a specific area– glScissor

Display lists

● Display lists are objects accessed through handles● Records and plays back a sequence of commands● A display list may call other display lists● The surrounding state is not saved

– This may radically change the result of your list

● May save both coding and execution time● Pure vertex display lists are often accelerated

– However, there are better ways to achieve this now

Display list commands

● Creating lists– glGenLists

● Recording lists– glNewList, glEndList

● Calling lists– glCallList, glCallLists

● Destroying lists– glDeleteLists

Gluint listID;

[...]

listID = glGenLists(1);

glNewList(listID, GL_COMPILE);

for (x = 0;  x < 2;  x++){  for (y = 0;  y < 2;  y++)  {    for (z = 0;  z < 2;  z++)    {      glPushMatrix();      glTranslatef(x * 2.f ­ 1.f, y * 2.f ­ 1.f, z * 2.f ­ 1.f);      draw_cube();      glPopMatrix();    }  }}

glEndList();

Reading an extension

● Very standardised format– Dependencies

– Overview, Reasoning, Issues

– New Procedures and Functions, New Tokens

– Additions to Chapter n of the OpenGL x.x Specification

– Interactions with extension

– Errors

– New state

Various access methods

● GLUT (original or FreeGLUT)● SDL, GLFW, Prophecy, etc...● Bindings exist for Ada, C#, Java, Ruby, Python,

PHP and most other languages● Most GUI-toolkits provide access to OpenGL● The hard way (GLX, AGL, CGL, WGL,

NSOpenGL, etc...)● Never, ever use GLAUX!

Resources

● The Red Book (programmer's guide)– Version 1.1 is available on the Internet

● The specification is always free● The OpenGL extension registry● NeHe Productions and GameDev.net● KTHB and other libraries● Google is your friend● IRC ( ##opengl on Freenode )

The End

Thank you for your time

Now go make something cool