3D Rendering in OpenGL
David Blumenthal
David Murray
Anthony Magro
20 February 2006
Goals for this Tutorial
• Show you a simple 3D application
o Discuss the basic elements of an OpenGL program
o Give you enough familiarity with OpenGL that you can
go learn the details on your own
• Hows and Whys
o Concepts behind how OpenGL works
o Things you might not get from reading the code
• Practical Tips
o Code and data organization
o Performance
Outline
• Look at some drawing code
• Coordinate Spaces and Transformations
• Program And Data Structure
• Performance
• OpenGL in SolidWorks
• Q&A and Open Discussion
Looking at the Code
• Setup OpenGL State
• Geometry precomputation
• Frame Loop
• Drawing Code
Draw Buffers
• The Front Buffer is what you see on screen – everything
else is off-screen
• Draw to the back buffer, then call SwapBuffersTexture 1
Accumulation Buffer
Stencil Buffer
Depth Buffer Texture 2
Back Buffer
Window decoration
Front Buffer
Texture 3
Why Flush?
• Commands in a graphics pipeline get buffered
o Lowers the cost of sending data to the graphics card
o No guarantee the buffer ever gets sent
o glFlush ensures the commands will eventually
complete
o Generally a SwapBuffer implies a glFlush
...
glVertex DMA Buffer
glVertex
glVertex
glVertex
…
Why Finish?
• glFinish = glFlush + wait for completion
o This can slow down the frame rate, but…
o It increases responsiveness!
Drawing as fast as possible: Long latency from input to response,
and it gets worse!
Dra Render
w Dra Render
w Dra Render
w Dra Render
w Dra Render
w Dra Render
w Dra Render
w Dra Render
Using glFinish: w
Dra Render Faster, consistent response
w Dra Render
w Dra Render
w Dra Render
w Dra Render
Questions
• Any questions about the code so far?
Coordinate Spaces
• Think of space in terms of an origin and axes
o From inside the space:
The origin is (0, 0, 0), the X axis is (1, 0, 0), etc…
Right Hand Rule!
• A space can be positioned inside another space
o A transformation describes how to move from the
“child” space to the “parent” space
o Translate, rotate, scale, skew, invert, and project
• Use whatever spaces are useful to you
o My personal space • this room • the building • Madison
• the world • the solar system • the galaxy • the
Universe • ???
OpenGL Coordinate Spaces
• Model vertices become window coordinates via a
series of spaces and transformations
Window Space
Clipping Space
Eye Space
World Space
Model Space Model Space
Model Space Model Space Model Space
Modeling Transformations
• Use any transformations you want to place model
geometry in the “World” space.
• GL_MODELVIEW matrix Window Space
• Define Objects and Lights
• Hierarchical Modeling by nesting
transforms Clipping Space
o glPushMatrix
o glPopMatrix
• Most common GL calls: Eye Space
o glTranslate
o glRotate
World Space
Model Space Model Space
Model Space Model Space Model Space
Order is Important
• glLoadIdentity() • glLoadIdentity()
• glRotated(45, 0, 0, 1) • glTranslated(5, 0, 0)
• glTranslated(5, 0, 0) • glRotated(45, 0, 0, 1)
OpenGL commands successively define new “local” coordinate
spaces in terms of the “current” or previous local space.
Viewing Transformation
• OpenGL doesn’t care about “World” space, it does
all lighting, culling, etc. calculations in Eye Space.
• GL_MODELVIEW matrix Window Space
• Position the world in front of the
camera.
• Define Objects and Lights which Clipping Space
are relative to the viewpoint
o Headlights
o First Person objects Eye Space
gluLookAt
World Space
Model Space Model Space
Model Space Model Space Model Space
Positioning the View
• Don’t position the camera in the world…
o Position the world in front of the camera!
• Transform the world into “Eye Space”
o The camera is at the origin
o Looking down the negative Z axis
o X points right, Y points up
• gluLookAt
o Converts a world space camera into the correct
Camera in world space
rotation and translation
• Or, invert a camera position matrix World in eye space
Projection Transformation
• Transform the region to be displayed into the
region of the Clipping Cube.
• The Clipping Cube: Window Space
o -1 to 1 in X
o -1 to 1 in Y
o -1 to 1 in Z Clipping Space glOrtho,
• Everything outside that volume is glPerspective
clipped out. gluPerspective
• Use the GL_PROJECTION matrix Eye Space
World Space
Model Space Model Space
Model Space Model Space Model Space
Perspective Projection
• The GL_PROJECTION matrix maps a region of
eye space to the clipping space cube.
• glFrustum creates a non-linear mapping, yielding
a perspective effect.
Items far from the
camera get squished
Eye space Items close to the Clip Space
camera get stretched
Viewport Transformation
• The Clipping Cube is mapped to the viewport
bounds.
• [-1,1] in X is mapped to the left to Window Space
right viewport range.
glViewport and
• [-1,1] in Y is mapped to the bottom
glDepthRange
to top viewport range. Clipping Space
• [-1,1] in Z is mapped to the near
and far limits of the depth buffer
range. Eye Space
World Space
Model Space Model Space
Model Space Model Space Model Space
Questions
• Any questions about coordinate spaces or
transformations?
Program Structure
• Do everything that you can in the Setup function
o All file I/O: model, texture, and shader loading
o Setup OpenGL state, anything that doesn’t change
o Prepare display lists, vertex and pixel buffer objects
o Setup program logic, animation controls, etc.
• Keep the Frame Loop fast
o Advance time, update program and animation state
o Minimize OpenGL state changes and draw calls
o Performance and Pretty Pictures!
OpenGL Setup
• Create a Window and a GL Context (glut, SDL)
• Load Models, Textures, and Shaders
o Load from files, or generate at runtime
o Put static geometry into display lists or Vertex Buffer Objects
o Put textures onto the card or in Pixel Buffer Objects
• Setup Lighting
o Light positions may change, but light colors, ambient lighting, and
other lighting parameters often don’t
• Setup any other static OpenGL state
o Enable depth testing, antialiasing, backface culling
• Initialize the program and animation state
Animation Logic
• Update at the start of every frame
• Try to use elapsed realtime as much as possible
o Avoid fixed increments per frame
o Throttle the increment in case of chronic or transient
bad performance
• Create an Event Queue and a Behavior Manager
o Ability to schedule tasks for the future
o Ability to wrap AIs and repetitive actions inside an
easy-to-maintain structure
o Add new events and behaviors based on program
logic
Scene Graphs
• Organize all your models into a structure
o Update the structure for animation
o Iterate over the nodes to draw
• Create a base SG Node class
o Manage tree structure (parent, children pointers)
o Manage transforms and bounding boxes
• Subclass for different types of objects
o Primitives which can generate their own geometry
o Generic Mesh class for loaded geometry
• Lights and Cameras are special nodes
o Need to be handled outside the normal traversal
Scene Graphs (continued)
• Keep the actual geometry in a separate class
o Contain the logic for managing display lists/VBOs
o Allows reuse of geometry for multiple objects
o Special logic for drawing at a reduced level of detail
• Keep the appearance in a separate class
o Material parameters, texture and shader IDs
o Be able to iterate over appearances, and find all the
objects which use the same appearance
o Special logic for drawing transparent surfaces
• Keep the behavior in a separate class
o Behaviors often belong to an object, but are updated
by a separate behavior manager
Don’t Reinvent the Wheel
• Freely available math libraries:
o Wild Magic (http://www.geometrictools.com/)
• Freely available image libraries:
o libjpg
o libpng
• Model formats and loading libraries:
o Plenty of them out there if you search
Questions
• Any questions about code and data organization?
Performance
• Use the best vertex mechanism you can
o Vertex Buffer Objects are the best because the data is
in memory which the hardware can access
o Vertex arrays are good – several extensions make
them better
o glVertex3fv is better than glVertex3f
• Don’t use glScale if you’re using lighting
o Requires GL_NORMALIZE to be enabled
• Don’t use GL_POLYGON
o It’s the same thing as GL_TRIANGLE_FAN, but may
not be as well optimized
Performance 2
• Display Lists are making a comeback
o They used to be for getting data across an XWindows
socket.
o Now, OpenGL drivers are taking advantage of them to
optimize the way the hardware is used.
• Minimize draw calls
o Group together objects which use the same textures,
shaders, other material properties
o Use a Unified Shader Model – write one shader which
can produce several different visual effects
o Group objects which are always drawn together into a
display list
Performance 3
• Cull out objects which aren’t visible
o Quick test: if the bounding box is behind the camera…
o Better tests will take into account field of view,
distance, occlusion (can’t see that room if you’re in this
room), etc.
• Precompute lighting for static lights and models
• Avoid round trips, like glReadBuffer
o Completely stalls the graphics hardware
o New GL extensions help you avoid them
Render directly to a texture
Asynchronous reads using pixel buffer objects
Performance 4
• Use texture formats supported by the hardware
o GL_BGRA
• Use pixel buffer objects to load textures quickly
o If possible, keep all your textures on the card
o If not, use PBOs so the card can directly read the
texture data
• Measure! Measure! Measure!
o You never know what change you’re going to make
which will kick you off the fast path, or even worse,
require software rendering…
Learning More
• The Red Book: The OpenGL Programming Guide
o A good tutorial and guide to OpenGL
• www.opengl.org
o The OpenGL Specification
o GL Extensions
• www.nvidia.org
o Lots of papers about how to draw pretty pictures
quickly
• UPL GameSIG
o Come meet other students and join projects
• Email me:
[email protected] o I’m always available to answer questions