CEN 515-New
CEN 515-New
COMPUTER
GRAPHICS
Understanding OpenGL
and Computer Graphics
A Comprehensive
Introduction
• What is OpenGL?
• Open Graphics Library (OpenGL)
is a cross-platform API for
rendering 2D and 3D graphics
• Developed by Silicon Graphics Inc.
in 1992
• Industry standard for graphics
programming
• Used in: video games, CAD
software, scientific visualization,
VR applications
Understanding
Computer Graphics:
The Basics
• 2D Graphics
• Like drawing on paper
• Flat images made of pixels
• Examples: icons, buttons, 2D games
• 3D Graphics
• Like sculpting in virtual space
• Objects with depth and volume
• Must be converted to 2D for display
How Screens
Display Graphics
• The Reality of Screens
• Screens are flat surfaces made of
pixels
• Each pixel shows one color at a time
• Arranged in a grid pattern
• Creating the 3D Illusion
1.Perspective (smaller = farther)
2.Shading and shadows
3.Overlapping objects
4.Color and contrast variations
OpenGL
Programming
Devices
• Key Components
1.Graphics Processing Unit (GPU)
1. Specialized processor for graphics
calculations
2. Parallel processing capabilities
3. Optimized for matrix and vector
operations
2.Frame Buffer
1. Temporary storage for rendered
images
2. Like a digital canvas
3. Holds pixel data before display
3.Display Device
1. Monitor or screen
2. Converts digital data to visible pixels
Understanding
Vertex Buffers
What is a Vertex?
• A point in 3D space
• Contains position information
• May include other data (color, texture coordinates)
• Vertex Buffer Example
// Create and bind buffer
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
// Define triangle coordinates
float vertices[] = {
-0.5f, -0.5f, 0.0f, // Bottom left
0.5f, -0.5f, 0.0f, // Bottom right
0.0f, 0.5f, 0.0f // Top
};
Core OpenGL
Concepts
• Vertex Arrays and VBOs
• Efficient storage of geometric data
• Reduces data transfer time
• Optimizes memory usage
• Vertex Array Objects (VAOs)
• Encapsulates vertex array
configuration
• Stores attribute settings
• Simplifies state management
User Interaction
in OpenGL
Mouse Programming
Viewports
Multiple Windows
• Frequently-used
OpenGL programming
devices
1. Vertex Arrays and Drawing
Commands
• Understanding Vertex Arrays
• A vertex array is a contiguous
block of memory containing
vertex data
• More efficient than immediate
mode rendering
• Reduces function call overhead
• Key Benefits
• Reduced API calls
• Better performance
• More organized code structure
• Implementation Example
// Define vertex data
GLfloat vertices[] = {
// x, y, z coordinates for a triangle
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
// Draw triangle
glDrawArrays(GL_TRIANGLES, 0, 3);
• Performance Considerations
• Use GL_STATIC_DRAW for unchanging
data
• GL_DYNAMIC_DRAW for frequently
updated data
• Creating and Using VBOs
// Generate and bind a VBO
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
• Understanding VAOs
• Stores vertex attribute configurations
• Reduces state changes
• Simplifies rendering code
• Implementation
// Create and bind VAO
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Later, to draw:
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 3);
4. Display Lists
glEndList();
if (button == GLUT_LEFT_BUTTON) {
if (state == GLUT_DOWN) {
if (state == GLUT_DOWN) {
if (dir > 0) {
// Scroll up
} else {
// Scroll down
// Register callbacks
glutMouseFunc(mouseButton);
glutMotionFunc(mouseMotion);
glutMouseWheelFunc(mouseWheel);
7. Programming Non-
ASCII Keys
// Register callback
glutSpecialFunc(specialKeys);
8. Programming Pop-up Menus
• Built-in Shapes
• Geometric primitives
• Complex objects
• Utility functions
• Using FreeGLUT
Objects
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glutSwapBuffers();
}
11. Clipping Planes
• Implementation
// Define clipping plane
GLdouble equation[] = {1.0, 0.0, 0.0, 0.0}; // x = 0
plane
• Implementation
void reshape(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
}
Viewing
Frustum
Visualization
• Key elements shown:
• Camera position at
apex
• Near and far clipping
planes
• Field of View (FOV)
angle
• Objects within viewing
volume
13. Viewports
• Multiple Views
• Split screen effects
• Custom view regions
• Mini-maps
• Implementation
void display() {
glClear(GL_COLOR_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT);
glutSwapBuffers();
}
Understanding
Viewports and
Windows
The diagram illustrates:
• Main viewport for
primary rendering
• Mini-map viewport in
corner
• Coordinate system
orientation
• Relative positioning of
viewports
14. Multiple Windows
• Implementation
int window1, window2;
void display1() {
glutSetWindow(window1);
// Draw in window 1
}
void display2() {
glutSetWindow(window2);
// Draw in window 2
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutMainLoop();
Exercises
• Exercise 1: Basic Triangle Rendering
• Create a program that displays a
colored triangle in the center of the
window. The triangle should rotate
continuously.
• Requirements:
• Use modern OpenGL (3.3+)
• Implement vertex and fragment
shaders
• Use VBOs and VAOs
• Implement rotation using
Solution (Setting up our shaders)
• // Vertex Shader
• const char* vertexShaderSource = R"(
• #version 330 core
• layout (location = 0) in vec3 aPos; // Position attribute
• layout (location = 1) in vec3 aColor; // Color attribute
• out vec3 vertexColor; // Output to fragment shader
• uniform mat4 transform; // Transformation matrix
•
• void main() {
• gl_Position = transform * vec4(aPos, 1.0);
• vertexColor = aColor;
• }
• )";
• // Fragment Shader
• const char* fragmentShaderSource = R"(
• #version 330 core
• in vec3 vertexColor;
• out vec4 FragColor;
•
• void main() {
• FragColor = vec4(vertexColor, 1.0);
• }
• )";
Main Program
• class RotatingTriangle {
private:
GLuint VBO, VAO;
GLuint shaderProgram;
float rotationAngle = 0.0f;
public:
void init() {
// Define vertex data with positions and colors
float vertices[] = {
// Positions // Colors
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // Bottom left - Red
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // Bottom right - Green
0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f // Top - Blue
};
// Create and bind Vertex Array Object
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
Main Program – Contd
// Create and bind Vertex Buffer Object
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices,GL_STATIC_DRAW);
// Update rotation
rotationAngle += 0.01f;
// Create rotation matrix
glm::mat4 transform = glm::mat4(1.0f);
transform = glm::rotate(transform, rotationAngle, glm::vec3(0.0f, 0.0f, 1.0f));
struct Shape {
std::vector<float> vertices;
GLenum drawMode;
int vertexCount;
};
public:
void init() {
// Initialize shapes
createShapes();
// Create and set up shaders (similar to Exercise 1)
shaderProgram = createShaderProgram(vertexShaderSource, fragmentShaderSource);
// Create buffers
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
void render() {
glUseProgram(shaderProgram);
• Requirements:
• Load and apply a texture to
cube faces
• Implement perspective
projection
• Add mouse-controlled
rotation
• Include depth testing
Solution
class TexturedCube {
private:
GLuint VBO, VAO, EBO;
GLuint texture;
GLuint shaderProgram;
glm::mat4 projection;
float rotation = 0.0f;
void main() {
gl_Position = projection * view * model * vec4(aPos, 1.0);
TexCoord = aTexCoord;
}
)";
// Fragment shader source
const char* fragmentShaderSource = R"(
#version 330 core
out vec4 FragColor;
in vec2 TexCoord;
uniform sampler2D ourTexture;
void main() {
FragColor = texture(ourTexture, TexCoord);
}
)";
public:
void init() {
// Set up vertex data for a cube with texture coordinates
float vertices[] = {
// positions // texture coords
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
// ... (remaining vertices for all six faces)
};
unsigned int indices[] = {
0, 1, 2, // first triangle
2, 3, 0, // second triangle
// ... (remaining indices for all faces)
};
// Create and bind VAO
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
stbi_image_free(data);
}
void render() {
glEnable(GL_DEPTH_TEST);
glUseProgram(shaderProgram);
// Create transformations
glm::mat4 model = glm::mat4(1.0f);
model = glm::rotate(model, rotation, glm::vec3(0.5f, 1.0f, 0.0f));
rotation += 0.01f;
glm::mat4 view = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -3.0f));
// Bind texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
// Render cube
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
}
};
• Exercise 4: Multiple Viewport
Scene
• Requirements:
• Main viewport: Perspective view
• Top-right viewport: Top-down
view
• Bottom-right viewport: Side view
• Allow switching active viewport
Solution
class MultiViewportScene {
private:
GLuint VBO, VAO;
GLuint shaderProgram;
std::vector<glm::mat4> viewMatrices;
glm::mat4 projection;
struct ViewportSetup {
int x, y, width, height;
glm::mat4 view;
glm::mat4 projection;
};
std::vector<ViewportSetup> viewports;
public:
void init(int windowWidth, int windowHeight) {
// Initialize viewports
setupViewports(windowWidth, windowHeight);
// Set matrices
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "view"),
1, GL_FALSE, glm::value_ptr(viewport.view));
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"),
1, GL_FALSE, glm::value_ptr(viewport.projection));
// Draw scene
renderScene();
}
}
private:
void renderScene() {
// Draw background grid for orientation
drawGrid();
void drawGrid() {
// Set grid color
glUniform3f(glGetUniformLocation(shaderProgram, "objectColor"), 0.5f, 0.5f, 0.5f);
// Draw horizontal and vertical grid lines
glBegin(GL_LINES);
glEnd();
}
void drawObjects() {
// Draw a cube at the origin
drawCube(glm::vec3(0.0f, 0.5f, 0.0f), glm::vec3(1.0f, 0.0f, 0.0f));
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"),
1, GL_FALSE, glm::value_ptr(model));
glUniform3fv(glGetUniformLocation(shaderProgram, "objectColor"),
1, glm::value_ptr(color));
// Bind cube VAO and draw
glBindVertexArray(cubeVAO);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT,
0);
}
glUniformMatrix4fv(glGetUniformLocation(shaderProgram,
"model"),
1, GL_FALSE, glm::value_ptr(model));
// Use GLUT to draw a sphere
glutSolidSphere(0.5, 32, 32);
}
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"),
1, GL_FALSE, glm::value_ptr(model));
glUniform3fv(glGetUniformLocation(shaderProgram, "objectColor"),
1, glm::value_ptr(color));
• Requirements:
• Implement a hierarchical transformation
system
• Show planets orbiting the sun
• Show moons orbiting planets
• Allow camera movement through the scene
Solution
// First, let's define our Scene Node class which forms the foundation of our scene graph
class SceneNode {
private:
std::string name; // Node identifier
glm::mat4 localTransform; // Local transformation matrix
glm::mat4 worldTransform; // Cached world transformation
SceneNode* parent; // Parent node
std::vector<std::shared_ptr<SceneNode>> children; // Child nodes
std::shared_ptr<Mesh> mesh; // Geometry data
bool transformDirty; // Flag for transform updates
public:
SceneNode(const std::string& nodeName)
: name(nodeName),
localTransform(1.0f),
worldTransform(1.0f),
parent(nullptr),
transformDirty(true) {
}
// Add a child node to this node
void addChild(std::shared_ptr<SceneNode> child) {
children.push_back(child);
child->parent = this;
child->markTransformDirty();
}
if(mesh) {
// Set the world transform uniform
GLuint worldMatrixLoc = glGetUniformLocation(shaderProgram, "worldMatrix");
glUniformMatrix4fv(worldMatrixLoc, 1, GL_FALSE, glm::value_ptr(worldTransform));
GLuint shaderProgram;
std::shared_ptr<Mesh> sphereMesh;
void setupSceneGraph() {
// Create all nodes
rootNode = std::make_shared<SceneNode>("root");
sunNode = std::make_shared<SceneNode>("sun");
earthOrbitNode = std::make_shared<SceneNode>("earthOrbit");
earthNode = std::make_shared<SceneNode>("earth");
moonOrbitNode = std::make_shared<SceneNode>("moonOrbit");
moonNode = std::make_shared<SceneNode>("moon");
// Set up hierarchy
rootNode->addChild(sunNode);
sunNode->addChild(earthOrbitNode);
earthOrbitNode->addChild(earthNode);
earthNode->addChild(moonOrbitNode);
moonOrbitNode->addChild(moonNode);
earthNode->setLocalTransform(
glm::translate(glm::mat4(1.0f), glm::vec3(10.0f, 0.0f, 0.0f)) * // Earth is 10
units from sun
glm::scale(glm::mat4(1.0f), glm::vec3(1.0f)) // Earth is 1 unit in
diameter
);
moonNode->setLocalTransform(
glm::translate(glm::mat4(1.0f), glm::vec3(2.0f, 0.0f, 0.0f)) * // Moon is 2 units
from earth
// Assign meshes
sunNode->setMesh(sphereMesh);
earthNode->setMesh(sphereMesh);
moonNode->setMesh(sphereMesh);
}