Difference between revisions of "Discussion3S16"

From Immersive Visualization Lab Wiki
Jump to: navigation, search
(Finished faces draft.)
(Finished buffer objects.)
Line 32: Line 32:
 
Again, try drawing a simple centered 2d non-unit rectangle to visualize what this would look like. Do you see the positions fitting in the range [-1,1]?
 
Again, try drawing a simple centered 2d non-unit rectangle to visualize what this would look like. Do you see the positions fitting in the range [-1,1]?
  
==Faces==
+
==Reading Faces==
In project 1, we parsed vertices and normals. What other lines were there in <code>.OBJ</code> files? If you answered lines that started with <code>f</code>, or ''faces'' you're correct! (The section title hopefully gave it away). The face lines are formatted as described in [[Discussion1S16#The OBJ file format|Week 1's discussion]], and that shows how to parse and understand them.
+
In [[Project1S16|project 1]], we parsed vertices and normals. What other lines were there in <code>.OBJ</code> files? If you answered lines that started with <code>f</code>, or ''faces'' you're correct! (The section title hopefully gave it away). The face lines are formatted as described in [[Discussion1S16#The OBJ file format|Week 1's discussion]], and that shows how to parse and understand them.
  
 
In this discussion, we wanted to cover why there are face lines to begin with. Let's see how we might specify 6 triangles to make the following hexagon:
 
In this discussion, we wanted to cover why there are face lines to begin with. Let's see how we might specify 6 triangles to make the following hexagon:
Line 40: Line 40:
  
 
Note how when we don't use faces, and list faces simply by the three vertices that make them, we end up duplicating many vertices and use up more lines. This increases our parsing time polynomially as well as make our file sizes larger. The use of face specifications help reduce this.
 
Note how when we don't use faces, and list faces simply by the three vertices that make them, we end up duplicating many vertices and use up more lines. This increases our parsing time polynomially as well as make our file sizes larger. The use of face specifications help reduce this.
 +
 +
==Modern OpenGL Pipeline==
 +
The demand that applications such as games put on graphics card hardware is unimaginably large. So much so that as the amount of geometry and effects the developers were loading up increased, graphics hardware manufacturers couldn't simply keep adding functions to the architecture. This called for a newer way to organize graphics hardware entirely. First lets review what we've done so far in the old pipeline.
 +
 +
===The Old Ways===
 +
[[File:fixed_function.PNG|800px]]
 +
 +
All of [[Project1S16|Project 1]] was done on the old way of OpenGL in which we utilized calls such as <code>glMatrixMult</code>, <code>gluLookAt</code>, <code>gluPerspective</code>. These functions are implemented in hardware and simply do what they were coded to do, hence the name '''"Fixed-function"'''.
 +
 +
===The New and Improved OpenGL===
 +
[[File:programmable_pipeline.PNG|755px]]
 +
 +
All of [[Project2S16|Project 2]] will be done on the programmable pipeline. Instead of specifying vertices through <code>GL_POINTS</code> one-by-one, we now load them all into a Vertex Array Object through Vertex Buffer Objects. This solves the geometry demand by reducing the time we jump back and forth between CPU and GPU.
 +
 +
Instead of OpenGL providing us with the functions to deal with Model Transformations(<code>toWorld</code> matrix), View Transformations(<code>C_inverse</code> matrix) and Projection Transformations(<code>P</code> matrix), we are given nothing. Instead, we now have near-infinite flexibility and can implement any camera effect or projection effects.
 +
 +
We haven't dealt with lighting yet, but again, instead of relying on the few default lighting configurations OpenGL provides us, we have the flexibility of implementing all kinds of weird lighting effects such as ray tracing on the hardware.
 +
 +
Below is another image to show the visual impact of exactly how much of what OpenGL used to do for us is manual, but also programmable now, in this brave new world.
 +
 +
[[File:pipeline_reduction.PNG|800px]]
  
 
==OpenGL Buffer Objects==
 
==OpenGL Buffer Objects==
 +
So how do we use this new fancy geometry specification?
 +
 +
Well first, lets look at what the terminologies are.
 +
 +
===Some Definitions===
 +
* Vertex Array Object (VAO): The Vertex Array Object ties together all of the information that will be stored in our VBO and EBO. It stores their data as well as information on how they are formatted.
 +
* Vertex Buffer Object (VBO): A Vertex Buffer Object is where all the vertex data is actually stored. The starter code stores the position information in this buffer object.
 +
* Element Buffer Object (EBO): The Element Buffer Object is technically not different from any other buffer object(such as the VBO), but we have a special name for it as it is useful almost all the time. Remember the indices that we parsed in the [[#Reading Faces]] section? The EBO will store those.
 +
 +
This is all good but what are we missing? What else did we parse from our <code>.OBJ</code> files?
 +
 +
That's right! Normals! (and maybe color) How can we pass these into our OpenGL buffer?
 +
 +
===Packing Many Attributes===
 +
A vertex doesn't have just a position. It has normals! It has colors! It may even have texture coordinates! How do we pass all of these into the graphics card efficiently? We'll dive into a little bit of the art of memory management and packing for this.
 +
 +
[[File:vertex_attribute_interleaved.png]]
 +
 +
In the figure above, see how each vertex is a nicely packed set of 8 attributes&mdash;<code>X, Y, Z, R, G, B, S, T</code>(The <code>S</code> and <code>T</code> are texture coordinates. You don't have to worry about them yet)? This lets us pass along each vertex in one nice swoop, and byte-aligned to boot! You can construct a C++ struct to format your vertices this way, and pass it along to OpenGL as a VBO much like how we do it in <code>Cube.cpp</code>'s <code>Cube::Cube</code> constructor.
 +
 +
More information on how to do this can be found on the [http://learnopengl.com/#!Model-Loading/Mesh Learn OpenGL] site.
  
 
==GLSL Structure==
 
==GLSL Structure==
 +
 +
 +
==Some Code Tips==
 +
 +
===Update Your Drivers===
 +
 +
===Segmentation Faults? Check Your Object Initializations!===

Revision as of 23:33, 11 April 2016

Contents

Overview

Week 3 discussion recap (04/11/16)

Slides: download here

Object Centering

We can't expect our objects to be centered when we first parse our .OBJ files. The bear obj we parsed for Project1 are good examples. What can we do if we want to center our objects? How may we go about this?

Well the first job would be to find the center of our object right? Let's go through how we might accomplish that.

The Koan of Finding Your Center

This is going to be a slight modification to our parsing code so that we can find where the minimum point and the maximum point lie in our .OBJ file.

  • Loop and parse every vertex in the .OBJ file.
  • Loop through the vertices to find the minX, minY, minZ and maxX, maxY, maxZ.
    • Hint: You would want to use infinity and negative infinity in some way.
  • Find the average: avgX, avgY, avgZ
  • Loop through all vertices and subtract avgX, avgY, avgZ from all coordinates.

Try and draw a simple non-centered 2d rectangle to visualize what this would look like. Do you see how this would center our object?

Here we looped through the list of vertices three times to center our object. Can we do better and reduce the number of iterations?

The Zen of Filling The Room

Once we've centered our object, we can scale our object. Our goal is to fit the object into a standard cube(a 2x2x2 cube, with all vertices in the range [-1,1]) so that all objects start from the same size.

Here's an idea of how we might go about this.

  • Find the longest dimension between the axes x, y, or z.
  • Loop through every vertex and scale them(divide) by the longest axis.

Again, try drawing a simple centered 2d non-unit rectangle to visualize what this would look like. Do you see the positions fitting in the range [-1,1]?

Reading Faces

In project 1, we parsed vertices and normals. What other lines were there in .OBJ files? If you answered lines that started with f, or faces you're correct! (The section title hopefully gave it away). The face lines are formatted as described in Week 1's discussion, and that shows how to parse and understand them.

In this discussion, we wanted to cover why there are face lines to begin with. Let's see how we might specify 6 triangles to make the following hexagon:

Face objs.PNG

Note how when we don't use faces, and list faces simply by the three vertices that make them, we end up duplicating many vertices and use up more lines. This increases our parsing time polynomially as well as make our file sizes larger. The use of face specifications help reduce this.

Modern OpenGL Pipeline

The demand that applications such as games put on graphics card hardware is unimaginably large. So much so that as the amount of geometry and effects the developers were loading up increased, graphics hardware manufacturers couldn't simply keep adding functions to the architecture. This called for a newer way to organize graphics hardware entirely. First lets review what we've done so far in the old pipeline.

The Old Ways

Fixed function.PNG

All of Project 1 was done on the old way of OpenGL in which we utilized calls such as glMatrixMult, gluLookAt, gluPerspective. These functions are implemented in hardware and simply do what they were coded to do, hence the name "Fixed-function".

The New and Improved OpenGL

Programmable pipeline.PNG

All of Project 2 will be done on the programmable pipeline. Instead of specifying vertices through GL_POINTS one-by-one, we now load them all into a Vertex Array Object through Vertex Buffer Objects. This solves the geometry demand by reducing the time we jump back and forth between CPU and GPU.

Instead of OpenGL providing us with the functions to deal with Model Transformations(toWorld matrix), View Transformations(C_inverse matrix) and Projection Transformations(P matrix), we are given nothing. Instead, we now have near-infinite flexibility and can implement any camera effect or projection effects.

We haven't dealt with lighting yet, but again, instead of relying on the few default lighting configurations OpenGL provides us, we have the flexibility of implementing all kinds of weird lighting effects such as ray tracing on the hardware.

Below is another image to show the visual impact of exactly how much of what OpenGL used to do for us is manual, but also programmable now, in this brave new world.

Pipeline reduction.PNG

OpenGL Buffer Objects

So how do we use this new fancy geometry specification?

Well first, lets look at what the terminologies are.

Some Definitions

  • Vertex Array Object (VAO): The Vertex Array Object ties together all of the information that will be stored in our VBO and EBO. It stores their data as well as information on how they are formatted.
  • Vertex Buffer Object (VBO): A Vertex Buffer Object is where all the vertex data is actually stored. The starter code stores the position information in this buffer object.
  • Element Buffer Object (EBO): The Element Buffer Object is technically not different from any other buffer object(such as the VBO), but we have a special name for it as it is useful almost all the time. Remember the indices that we parsed in the #Reading Faces section? The EBO will store those.

This is all good but what are we missing? What else did we parse from our .OBJ files?

That's right! Normals! (and maybe color) How can we pass these into our OpenGL buffer?

Packing Many Attributes

A vertex doesn't have just a position. It has normals! It has colors! It may even have texture coordinates! How do we pass all of these into the graphics card efficiently? We'll dive into a little bit of the art of memory management and packing for this.

Vertex attribute interleaved.png

In the figure above, see how each vertex is a nicely packed set of 8 attributes—X, Y, Z, R, G, B, S, T(The S and T are texture coordinates. You don't have to worry about them yet)? This lets us pass along each vertex in one nice swoop, and byte-aligned to boot! You can construct a C++ struct to format your vertices this way, and pass it along to OpenGL as a VBO much like how we do it in Cube.cpp's Cube::Cube constructor.

More information on how to do this can be found on the Learn OpenGL site.

GLSL Structure

Some Code Tips

Update Your Drivers

Segmentation Faults? Check Your Object Initializations!