Overview
This project was built for my final year Computer Graphics module. It’s a real-time rendering engine written in C++ using OpenGL, featuring a physically based rendering (PBR) pipeline, advanced lighting, shadowing, procedural content, and dynamic environmental effects. The scene is set on a tropical island, inspired loosely by Pirates of the Caribbean, with a quadcopter drone patrolling the island, for a demonstration of animations.
Core Features
1. Procedural Generation
Two procedurally generated elements were implemented:
- Bubbles: Rising from a starfish, each bubble is procedurally generated using a latitude-longitude sphere mesh. Properties like lifetime, velocity, and scale are randomized for realism.
- Volumetric Clouds: Generated using Marching Cubes on a scalar density field. The density function blends smooth spherical sources with multiple layers of Perlin noise to create natural cloud formations.
Relevant code:
bubbleObject.h
(lines 11–18, 69–118, 123–150)
cloudObject.h
2. 3D Model Import & PBR Materials
Models were imported through a custom OBJ parser that supports full PBR materials: albedo, normal, metallic, roughness, ambient occlusion, and emission maps. Geometry is grouped by material ID for efficient rendering.
Model sources:
- The Black Pearl: rigmodels.com
- Island: rigmodels.com
- Drone: cgtrader.com
3. Animation
The drone autonomously tracks either the player or the pirate ship. It rotates and pitches based on trajectory, with smooth interpolation and added sway. Propellers spin independently using time-based rotation, and the onboard spotlight alternates colors every few seconds.
Code reference: DroneObject.cpp
(lines 42–123)
4. Camera System
Two toggleable camera modes are implemented:
- Fly-through camera: Standard free camera with full translation and mouse pitch/yaw control.
- Drone FPV camera: Attached to the drone body and follows its path and orientation. User-controlled pitch/yaw.
Code:
DroneObject.cpp
(142–147)
MainEngine.cpp
(212–264)
Camera.h
5. Advanced Texturing
The ocean shader dynamically combines reflection and refraction maps, based on view angle, depth, and lighting. All UVs are updated in real-time using gl_FragCoord
. The texture loader supports varying channel counts and auto-generates mipmaps.
Code: ObjectLoader.cpp
(lines 9–63)
6. Lighting System
All lighting is calculated via a custom PBR pipeline:
- Sunlight: Directional light influences all surface normals.
- God rays: Added as a post-process, casting rays through cloud cover.
- Point lights: Glowing rubies in the cave contribute emission lighting to nearby surfaces.
Code:
mainPBR.frag
(lines 293–409)
CloudObject.h
(lines 505–525)
7. Shadow Mapping
Shadow maps are used for both directional sunlight and the drone spotlight. PCF filtering with two samples helps smooth the result. Bubbles cast dual shadows depending on which light is active.
Code:
mainPBR.frag
(111–149)
shadow.vert
, Shadow.cpp
(68–98)
MainEngine.cpp
(930–987)
8. Interactive Elements
The drone shifts behaviour based on the viewer’s proximity. If the player gets too close, it switches from patrol mode to pursuit, chasing and spotlighting the player for 30 seconds before resuming patrol.
Code: DroneObject.cpp
(42–148)
9. Motion Along Curves
The pirate ship follows a smooth, continuous Bézier curve defined by nine control points (three cubic segments). Orientation is calculated by comparing forward samples along the curve.
Code:
ShipObject.h
(24–64)
Castleljau.h
, Point.h
10. Transparency
Transparency is handled via a combination of alpha blending, opacity maps, and material dissolve parameters. Bubbles are rendered with 50% opacity and sorted in real-time based on camera distance. The ocean’s reflective/refractive blend creates depth and realism.
Code:
BubbleObject.h
mainPBR.frag
(lines 307–310)