OpenGL (like Direct3D, Metal, etc.) is a graphics API, which provides the interface for specialized hardware on the GPU.
These APIs need a lot of code to optimize hardware utilization and often becomes a performance bottleneck. Need to download updates for drivers often. Also heavily rely on single core performance.
Low-level graphics APIs such as Vulkan shrinks the size of drivers, moving API closer to hardware again
Removes:
glBegin
, glEnd
glRotate
, glFrustum
Shaders handle all rendering: to draw anything you have to write your own shaders.
Shader: a user program loaded and executed in a stage of the rendering pipeline.
Rending application can easily become CPU limited: analyse triangles/sec
CPU bottleneck:
Modern way: Put all the data to pass to the GPU in memory, and a few function calls to pass the data to the GPU.
Shaders replace fixed-function pipeline parts that had hard-coded functionality.
Gets all info of the vertices of primitives to be drawn by GPU.
Per-vertex execution. Produces vertices in clip space.
Replaces in the fixed-function stage:
[Not covered] Breaking primitives into smaller triangles. e.g. Bezier patch -> triangles.
Per-patch vertex (control points) execution. Produces tessellation output patch vertices, i.e. tessellation level factors (level of subdivision), outer and inner.
Per-tessellation level factors execution. Performs tessellation and generates tessellation coordinates.
Per-tessellation coordinate execution. Produces vertex position from tessellation coordinate
[Assume vertex shader -> geometry shader. Another optional stage.]
Per-primitive execution.
Produces either:
Can transform a primitive (e.g. one point $\rightarrow$ triangle(s))
Special hardware to handle these.
If not clipped out, produces a set of fragments (window space pixel location, color, depth attributes)
Can interpolate any type of vertex attributes over primitives.
Per-fragment execution, hence the busiest stage. Produces color of corresponding pixels in framebuffer.
Replaces in the fixed-function stage:
Special hardware operations. Includes:
GLUT: glutMainLoop
initiates an infinite event loop. In each loop, GLUT will:
GLEW: Extension loading library
GLM: OpenGL Mathematics library
GLFW: Alternative to GLUT as a library for
(Note: all “Objects” are identifiers of type GLuint
)
shaderProgramObj
(after making the program, glUseProgram
)VAO
vertex array object (glGenVertexArray
, glBindVertexArray
)
VBO
s vertex buffer objects (glGenBuffers
), glBindBuffers
, glBufferData
)
vertPosBufferObj
, vertColorBufferObj
UniLoc
): The location of the variable in the shader that receives the data from the OpenGL program.UniLoc
s (glGetUniformLocation
)glm::perspective
glm::lookat
UniLoc
sglDrawArrays
glutSwapBuffers
For each shader (vertex and fragment):
glCreateShader
glShaderSource
(get the source text file of the shader)glCompileShader
After creating both:
glCreateProgram
glAttachShader
glLinkProgram
and return the linked program.#version 330 core // openGL version and profile
// input attributes from buffers (per vertex)
layout (location = 0) in vec4 vPos;
layout (location = 1) in vec4 vColor;
// uniform variables from initialization of UniLocs (global)
uniform mat4 ModelViewMatrix;
uniform mat4 ProjectionMatrix;
// output variable to the fragment shader
out vec4 v2fColor;
void main()
{
v2fColor = vColor;
// mandatory: clip space position of the vertex.
gl_Position = ProjectionMatrix * ModelViewMatrix * vPos;
}
#version 330 core
// output attributes from buffers (per fragment)
// location = 0: default color buffer
layout (location = 0) out vec4 fColor;
// input variable from the vertex shader
// must match output name from vertex shader
in vec4 v2fColor;
void main()
{
fColor = v2fColor;
}
GLfloat vertPosColor[numVerts*2][3] = { /* alternate pos and color */ }
// for vPos
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), 0);
// for vColor
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));
// define vertPos[count][3], vertColor[count][3]
GLushort vertIndex[] =
{ 0, 1, 2, 3, 4, 5, 0, 5, 4, 1, 3, 5, 2, 4, 3 };
// create buffer objects for each of vertPos, vertColor, vertIndex
// Index buffer is bound to GL_ELEMENT_ARRAY_BUFFER target binding point.
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertIndexBufferObj);
void MyDisplay(void) {
// ...
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, sizeof(vertIndex)/sizeof(GLushort),
GL_UNSIGNED_SHORT, 0);
glutSwapBuffers();
}