You are on page 1of 39

OpenGL Graphics

L06-PERFORMANCE
Mohammad Shaker
mohammadshaker.com
@ZGTRShaker
2015
Performance
How can you up your OpenGL app performance?
• Different Techniques:
– Vertex buffer and vertex arrays
– Display Lists
– Frustum culling
– Other methods
Vertex Buffer Object (VBO)
Vertex Array Object (VAO)
Vertex and Array Buffers
• Look at this,
Vertex and Array Buffers

Good oder Bad?


Vertex and Array Buffers

Good oder Bad?


Vertex and Array Buffers
Vertex and Array Buffers
Vertex and Array Buffers

huge performance benefit!


VBO and VAO
Example: Creating Cube Using VBO and VAO
Initializing the Cube’s Data
• We’ll build each cube face from individual triangles
• We need to determine how much storage is required:
– (6 faces)(2 triangles/face)(3 vertices/triangle)
const int NumVertices = 36;
• To simplify communicating with GLSL, we’ll use a vec4 class (implemented in
C++) similar to GLSL’s vec4 type
– We’ll also typedef it to add logical meaning:
typedef vec4 point4;
typedef vec4 color4;
Initializing the Cube’s Data
• Our cube has two attributes per vertex:
– position
– color
• We create two arrays to hold the VBO data:
point4 points[NumVertices];
color4 colors[NumVertices];
Initializing the Cube’s Data
// Vertices of a unit cube centered at origin, sides aligned with axes
point4 vertex_positions[8] = {
point4(-0.5, -0.5, 0.5, 1.0 ),
point4(-0.5, 0.5, 0.5, 1.0 ),
point4( 0.5, 0.5, 0.5, 1.0 ),
point4( 0.5, -0.5, 0.5, 1.0 ),
point4(-0.5, -0.5, -0.5, 1.0 ),
point4(-0.5, 0.5, -0.5, 1.0 ),
point4( 0.5, 0.5, -0.5, 1.0 ),
point4( 0.5, -0.5, -0.5, 1.0 )
};

// RGBA colors
color4 vertex_colors[8] = {
color4(0.0, 0.0, 0.0, 1.0 ), // black
color4(1.0, 0.0, 0.0, 1.0 ), // red
color4(1.0, 1.0, 0.0, 1.0 ), // yellow
color4(0.0, 1.0, 0.0, 1.0 ), // green
color4(0.0, 0.0, 1.0, 1.0 ), // blue
color4(1.0, 0.0, 1.0, 1.0 ), // magenta
color4(1.0, 1.0, 1.0, 1.0 ), // white
color4(0.0, 1.0, 1.0, 1.0 ) // cyan
};
Initializing the Cube’s Data
// quad() generates two triangles for each face and assigns colors to the vertices
int Index = 0; // global variable indexing into VBO arrays

void quad(int a, int b, int c, int d )


{
colors[Index] = vertex_colors[a]; points[Index] = vertex_positions[a]; Index++;
colors[Index] = vertex_colors[b]; points[Index] = vertex_positions[b]; Index++;
colors[Index] = vertex_colors[c]; points[Index] = vertex_positions[c]; Index++;
colors[Index] = vertex_colors[a]; points[Index] = vertex_positions[a]; Index++;
colors[Index] = vertex_colors[c]; points[Index] = vertex_positions[c]; Index++;
colors[Index] = vertex_colors[d]; points[Index] = vertex_positions[d]; Index++;
}

// generate 12 triangles: 36 vertices and 36 colors


Void colorcube()
{
quad(1, 0, 3, 2);
quad(2, 3, 7, 6);
quad(3, 0, 4, 7);
quad(6, 5, 1, 2);
quad(4, 5, 6, 7);
quad(5, 4, 0, 1);
}
Creating the VAO
• VAOs store the data of a geometric object
• Steps for using a VAO
1. Generate VAO names by calling glgenvertexarrays()
2. Bind a specific VAO for initialization by calling glbindvertexarray()
3. Update VBOs associated with this VAO
4. Bind VAO for use in rendering
• This approach allows a single function call to specify all the data for an objects
– previously, you might have needed to make many calls to make all the data current

GLuint vao; // Create a vertex array object


glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
Creating the VBO
• Vertex data must be stored in a VBO, and associated with a VAO
• The code-flow is similar to configuring a VAO:
– generate VBO names by calling
glGenBuffers()
– bind a specific VBO for initialization by calling
glBindBuffer(GL_ARRAY_BUFFER, …)
– load data into VBO using
glBufferData(GL_ARRAY_BUFFER, …)
– bind VAO for use in rendering
glBindVertexArray()
GLuint buffer; // Create and initialize a buffer object
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(points) + sizeof(colors), NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(points), points);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(points), sizeof(colors), colors);
Creating the VBO
• Vertex data must be stored in a VBO, and associated with a VAO
• The code-flow is similar to configuring a VAO:
– generate VBO names by calling
glGenBuffers()
– bind a specific VBO for initialization by calling
glBindBuffer(GL_ARRAY_BUFFER, …)
– load data into VBO using
glBufferData(GL_ARRAY_BUFFER, …)
– bind VAO for use in rendering
glBindVertexArray()
GLuint buffer; // Create and initialize a buffer object
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(points) + sizeof(colors), NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(points), points);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(points), sizeof(colors), colors);
Display List
Display lists allow you to define the geometry and execute them multiple times.
If you plan to redraw the same geometry multiple times, this is a great way to
save performance!
Immediate Mode versus Display Listed Rendering
• Immediate Mode Graphics
– Primitives are sent to pipeline and display right away
– No memory of graphical entities
• Display Listed Graphics
– Primitives placed in display lists
– Display lists kept on graphics server
– Can be redisplayed with different state
– Can be shared among OpenGL graphics contexts
OpenGL Architecture

Per Vertex
Polynomial Operations &
Evaluator Primitive
Assembly

Display Per Fragment Frame


CPU List
Rasterization
Operations Buffer

Texture
Memory
Pixel
Operations
OpenGL Architecture

Per Vertex
Polynomial Operations &
Evaluator Primitive
Assembly

Display Per Fragment Frame


CPU List
Rasterization
Operations Buffer

Texture
Memory
Pixel
Operations
OpenGL Architecture

Per Vertex
Polynomial Operations &
Evaluator Primitive
Assembly

Display Per Fragment Frame


CPU List
Rasterization
Operations Buffer

Texture
Memory
Pixel
Operations
Display Lists
• Not all OpenGL routines can be stored in display lists
• State changes persist, even after a display list is finished
• Display lists can call other display lists
• Display lists are not editable, but you can fake it
– make a list (A) which calls other lists (B, C, and D)
– delete and replace B, C, and D, as needed
Display Lists and Hierarchy
• Consider model of a car
– Create display list for chassis
– Create display list for wheel

glNewList(CAR, GL_COMPILE);
glCallList(CHASSIS);
glTranslatef(…);
glCallList(WHEEL);
glTranslatef(…);
glCallList(WHEEL);

glEndList();
Display List Example
for Terrain Drawing
DisplayList Code
Global scope:

GLvoid init()
//Set camera and projection

GLvoid DrawGLScene()
DisplayList Code
Global scope:

GLuint terrainListId;

GLvoid init()
//Set camera and projection
terrainListId = glGenLists(1);

GLvoid DrawGLScene()
DisplayList Code
Global scope:

GLuint terrainListId;

GLvoid init()
//Set camera and projection
terrainListId = glGenLists(1);
DrawTerrain();

GLvoid DrawGLScene()

glCallList(terrainListId);
DisplayList Code
Global scope:

GLuint terrainListId;

GLvoid init()
//Set camera and projection
terrainListId = glGenLists(1);
DrawTerrain();

GLvoid DrawGLScene()

glCallList(terrainListId);
DisplayList Code
Global scope:

GLuint terrainListId;

GLvoid init()
//Set camera and projection
terrainListId = glGenLists(1);
DrawTerrain();

GLvoid DrawGLScene()

glCallList(terrainListId);

DrawTerrain()

glNewList(terrainListId, GL_COMPILE);
//Terrain Code
glEndList();
Culling and Clipping
Frustum Culling
• Create a clipping plane
– float plane [] = {A, b, C, D};
• Create a clipping plane with it
– glClipPlane(GL_CLIP_PLANE0, plane);
• Enable the clipping plane
– glEnable(GL_CLIP_PLANE0);
Scissor Box
• Additional Clipping Test
glScissor(x, y, w, h )
• any fragments outside of box are clipped
• useful for updating a small section of a viewport
– affects glClear() operations
General Memory Management
http://docs.unity3d.com/Manual/UnderstandingAutomaticMemoryManagement.html
General Memory Management
• Avoid memory allocation in a loops
function ConcatExample(intArray: int[]) {
var line = intArray[0].ToString();

for (i = 1; i < intArray.Length; i++) {


line += ", " + intArray[i].ToString();
}

return line;
}
General Memory Management
• Avoid memory allocation in a loops
var scoreBoard: GUIText;
var score: int;

function Update() {
var scoreText: String = "Score: " + score.ToString();
scoreBoard.text = scoreText;
}

var scoreBoard: GUIText;


var scoreText: String;
var score: int;
var oldScore: int;

function Update() {
if (score != oldScore) {
scoreText = "Score: " + score.ToString();
scoreBoard.text = scoreText;
oldScore = score;
}
}
General Memory Management
• Avoid memory allocation in a loops
– Assign random variables to an array.

function RandomList(numElements: int) {


var result = new float[numElements];

for (i = 0; i < numElements; i++) {


result[i] = Random.value;
}

return result;
}

function RandomList(arrayToFill: float[]) {


for (i = 0; i < arrayToFill.Length; i++) {
arrayToFill[i] = Random.value;
}
}
General Memory Management
• Free Memory in C++ and C# (for example: arrays, images, complex objects, ..etc.)
– C++: delete keyword
– C#: enforce garbage collection cleanup

You might also like