Beginner-Friendly OpenGL Demo: Rendering a Rotating 3D Cube
Overview
This tutorial walks you through creating a simple, beginner-friendly OpenGL demo that renders a rotating 3D cube. You’ll learn how to set up an OpenGL context, compile shaders, create vertex buffers, apply basic transformations, and animate rotation. Assumes basic C/C++ knowledge and a development environment configured for OpenGL.
Requirements
- C or C++ compiler (GCC, Clang, MSVC)
- GLFW for window/context creation
- GLAD or GLEW for loading OpenGL functions
- GLM for math (matrices, vectors)
- Basic familiarity with shader syntax (GLSL)
Project Structure
- src/
- main.cpp
- shader.h
- shaders/
- vertex.glsl
- fragment.glsl
Vertex Shader (vertex.glsl)
Code
#version 330 core layout(location = 0) in vec3 aPos; layout(location = 1) in vec3 aColor;out vec3 vColor;uniform mat4 model; uniform mat4 view; uniform mat4 projection;
void main() {
vColor = aColor; gl_Position = projection * view * model * vec4(aPos, 1.0);}
Fragment Shader (fragment.glsl)
Code
#version 330 core in vec3 vColor; out vec4 FragColor; void main() {FragColor = vec4(vColor, 1.0);}
Key Steps (high level)
- Initialize GLFW and create a window with OpenGL 3.3 core profile.
- Load OpenGL functions with GLAD (or GLEW).
- Configure global OpenGL state (enable depth testing).
- Define cube vertex positions and per-vertex colors, and upload to a VBO with a VAO.
- Create shader program from the GLSL files.
- In the render loop: compute model, view, projection matrices (use GLM), send uniforms, draw the cube, and swap buffers.
- Clean up resources on exit.
Important Code Snippets
main.cpp (essential parts)
Code
#include#include #include #include #include “shader.h” // … initialize GLFW, create window, load GLAD …
glEnable(GL_DEPTH_TEST);
// cube vertices: positions and colors float vertices[] = {
// positions // colors -0.5f,-0.5f,-0.5f, 1.0f,0.0f,0.0f, 0.5f,-0.5f,-0.5f, 0.0f,1.0f,0.0f, 0.5f, 0.5f,-0.5f, 0.0f,0.0f,1.0f, // ... remaining vertices ...};
unsigned int VBO, VAO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1);
// shader Shader shader(“shaders/vertex.glsl”, “shaders/fragment.glsl”);
// render loop while(!glfwWindowShouldClose(window)) {
float time = glfwGetTime(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glm::mat4 model = glm::rotate(glm::mat4(1.0f), time, glm::vec3(0.5f, 1.0f, 0.0f)); glm::mat4 view = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -3.0f)); glm::mat4 proj = glm::perspective(glm::radians(45.0f), 800.0f/600.0f, 0.1f, 100.0f); shader.use(); shader.setMat4("model", model); shader.setMat4("view", view); shader.setMat4("projection", proj); glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES, 0, 36); glfwSwapBuffers(window); glfwPollEvents();}
// cleanup…
Tips and Troubleshooting
- If nothing appears, ensure depth testing is enabled and the clear color isn’t the same as cube colors.
- Check shader compile/link logs when shaders fail.
- Use glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) to debug geometry wireframe.
- For portability, request core profile and check GL version.
Next Steps
- Add keyboard controls to pause/adjust rotation.
- Apply textures and lighting (normals) for realism.
- Port to WebGL via Emscripten or use a higher-level engine.
This demo gives a compact, working foundation for learning OpenGL rendering and transforms.