🚀 Pi3D - OpenGL ES 2.0 3D Model Viewer
Pi3D - 3D Viewer for Raspberry Pi and Linux Systems
Pi3D is an OpenGL/GLES viewer originally designed to make it possible to view 3D models on a Raspberry Pi
and other GLES/OpenGL Linux systems using the Open Asset Import Library (Assimp). This web version demonstrates
the same technology running in your browser through Emscripten and WebGL!
🎯 Project Goals:
- Enable 3D model viewing on resource-constrained devices like Raspberry Pi
- Support multiple 3D file formats through Open Asset Import Library
- Provide efficient OpenGL ES 2.0 rendering for embedded systems
- Cross-platform compatibility - from Raspberry Pi to web browsers
Welcome! This interactive tutorial demonstrates the WebGL version of Pi3D, compiled from C++ using Emscripten.
Learn about the OpenGL ES 2.0 pipeline, shader programming, and how this viewer renders 3D aircraft models in your browser -
the same code that runs on Raspberry Pi hardware!
📚 Table of Contents
🥧 About Pi3D Project
Pi3D is a 3D viewer specifically designed for Raspberry Pi and other GLES/OpenGL Linux systems.
The project's primary goal is to enable 3D model visualization on resource-constrained embedded devices,
particularly the Raspberry Pi, which has limited GPU capabilities compared to desktop systems.
Raspberry Pi / Linux
→
OpenGL ES 2.0
→
Pi3D Viewer
→
3D Models
Key Features of Pi3D:
Feature |
Description |
Benefit |
Embedded Optimization |
Designed for low-power ARM processors |
Runs smoothly on Raspberry Pi's limited hardware |
OpenGL ES 2.0 |
Uses embedded systems graphics standard |
Hardware acceleration on mobile GPUs |
Assimp Integration |
Open Asset Import Library support |
Loads 40+ 3D file formats |
Cross-Platform |
C++ codebase with multiple targets |
Runs on Pi, Linux, and now web browsers |
Platform Compatibility:
- Native: Raspberry Pi (all models), Linux with OpenGL ES support
- Web: This version via Emscripten/WebGL in modern browsers
- Required: OpenGL ES 2.0 compatible GPU
🎨 Introduction to OpenGL ES 2.0
OpenGL ES (OpenGL for Embedded Systems) 2.0 is a subset of OpenGL designed for embedded devices like smartphones, tablets, and in our case, web browsers through WebGL. This program demonstrates core concepts of 3D graphics rendering.
Key Features of OpenGL ES 2.0:
- Programmable pipeline with vertex and fragment shaders
- Hardware-accelerated 3D rendering
- Cross-platform compatibility through WebGL
- Efficient rendering for complex 3D models
❓ Is OpenGL Working Entirely in the GPU?
Not quite! Only hard image processing and a few other intensive operations run on the GPU.
OpenGL provides features to store images, data, and information in optimized formats.
These optimized data structures are then processed directly by the GPU for maximum performance.
Is OpenGL Hardware Dependent?
Unfortunately, yes! If the hardware (Graphics Card) doesn't support OpenGL, we can't use it.
Newer OpenGL versions often require newer GPU features. However, don't worry - in practice,
all Graphics Card chips today have an implementation of OpenGL. You can use OpenGL in many
languages and devices, even in Microsoft Windows!
🧠 OpenGL's Core Logic
OpenGL is a graphics library that's very concise and focused. What you see in professional 3D software
is super complex work built on top of OpenGL. At its core, OpenGL's logic revolves around just
three fundamental concepts:
1. Primitives
2. Buffers
3. Rasterization
Just these 3 concepts? Believe it - OpenGL works entirely around these fundamentals. Let's explore each
concept and see how they combine to create the most advanced 3D graphics (OpenGL also handles 2D graphics -
to OpenGL, 2D is just 3D with all Z-depth at 0!).
📍 1. Primitives
OpenGL's primitives are limited to 3 basic types of objects:
Primitive Type |
Description |
Usage in Our Viewer |
3D Point |
A single point in space (x, y, z) Can be used as a particle |
Vertex positions in the aircraft model |
3D Line |
Composed of two 3D points Used as vectors or edges |
Wireframe mode, debug visualization |
3D Triangle |
Composed of three 3D points The fundamental surface primitive |
All aircraft surfaces are triangle meshes |
Note: Some OpenGL versions support quads (4-sided polygons), but OpenGL ES omits them
for maximum performance. Everything in our aircraft model is rendered as triangles!
💾 2. Buffers
Buffers are temporary optimized storage areas. OpenGL works with three types of buffers:
1. Frame Buffers
- Most abstract buffer type
- Stores the final rendered image
- Can output to screen or another buffer for post-processing
- Our viewer renders to the default framebuffer (your screen)
2. Render Buffers
- Optimized for rendering operations
- Often used for depth and stencil testing
- Stores per-pixel information during rendering
3. Buffer Objects (VBOs, IBOs)
- Vertex Buffer Objects store vertex data (positions, normals, textures)
- Index Buffer Objects store triangle connectivity
- Our program uses these extensively for the aircraft geometry
In our viewer, the aircraft model's vertices are stored in VBOs, uploaded once to the GPU,
and reused every frame for efficient rendering.
🖼️ 3. Rasterization
Rasterization is the process of converting vector graphics (our triangles) into pixels on the screen.
This is where the magic happens - the GPU takes our 3D triangles and determines which pixels they cover,
at what depth, and what color they should be.
Triangle Vertices
→
Rasterizer
→
Pixels/Fragments
→
Screen
How These 3 Concepts Work Together in Our Viewer:
- Primitives: Aircraft model is decomposed into thousands of triangles
- Buffers: Triangle data stored in GPU memory via VBOs
- Rasterization: GPU converts triangles to pixels every frame
This happens 60 times per second to create smooth animation!
⚙️ The Graphics Pipeline
Now that we understand the three core concepts (Primitives, Buffers, Rasterization), let's see how
our 3D viewer processes geometry through the complete OpenGL ES 2.0 pipeline:
Vertex Data
→
Vertex Shader
→
Primitive Assembly
→
Rasterization
→
Fragment Shader
→
Frame Buffer
Pipeline Stages Explained:
Stage |
Description |
In Our Program |
Vertex Data |
3D model vertices, normals, and texture coordinates |
Loaded from .mdl or .pkg aircraft model files |
Vertex Shader |
Transforms vertices from 3D to screen space |
Applies model, view, and projection matrices |
Primitive Assembly |
Groups vertices into triangles |
Creates aircraft surface from triangle mesh |
Rasterization |
Converts triangles to pixels |
Hardware-accelerated by WebGL |
Fragment Shader |
Colors each pixel |
Applies textures and lighting to aircraft |
🔧 Understanding Shaders in This Program
Vertex Shader
Our vertex shader transforms each vertex of the 3D model:
attribute vec3 position; // Vertex position in model space
attribute vec3 normal; // Vertex normal for lighting
attribute vec2 vtex; // Texture coordinates
uniform mat4 model; // Model transformation matrix
uniform mat4 view; // Camera view matrix
uniform mat4 projection; // Perspective projection matrix
varying vec2 texcoord; // Pass texture coords to fragment shader
void main() {
// Transform vertex position through MVP matrices
gl_Position = projection * view * model * vec4(position, 1.0);
// Flip Y coordinate for texture (common for image formats)
texcoord = vec2(vtex.x, 1.0 - vtex.y);
}
Matrix Transformations:
- Model Matrix: Rotates and positions the aircraft in world space
- View Matrix: Simulates camera position and orientation
- Projection Matrix: Creates 3D perspective effect
Fragment Shader
The fragment shader determines the color of each pixel:
precision highp float;
varying vec2 texcoord; // Interpolated texture coordinates
uniform sampler2D tex; // Texture sampler
uniform vec4 colour; // Optional color tint
void main() {
// Sample texture at interpolated coordinates
vec2 coord = clamp(texcoord, 0.0, 1.0);
gl_FragColor = texture2D(tex, coord);
// Optionally apply color tint
// gl_FragColor = texture2D(tex, coord) * colour;
}
🏗️ Program Architecture
Key Components:
1. Main Rendering Loop (do_frame)
- Polls input events
- Updates camera position
- Sets transformation matrices
- Binds textures and vertex data
- Draws the model
2. Model Loading System
- Loads .mdl and .pkg aircraft files
- Parses vertex, normal, and texture data
- Creates Vertex Buffer Objects (VBOs)
3. Camera System
- FPS-style camera controls
- Mouse look and WASD movement
- Zoom with scroll wheel
4. Texture Management
- SOIL library for image loading
- WebGL texture binding
- Automatic mipmap generation
Data Flow
Load Model File
→
Parse Geometry
→
Create VBOs
→
Load Textures
→
Render Frame
🎮 Interactive Controls
Control |
Action |
W, A, S, D |
Move camera forward, left, backward, right |
Mouse Move |
Rotate view (look around) |
Mouse Scroll |
Zoom in/out |
ESC |
Exit fullscreen / Release pointer lock |
Performance Tips:
- The viewer uses hardware acceleration - ensure WebGL is enabled in your browser
- Complex models may take time to load initially
- Use Chrome, Firefox, or Edge for best performance
📊 Technical Specifications
Supported File Formats:
- .mdl - Single model files
- .pkg - Package files containing multiple models
- Textures: PNG, JPG (loaded via SOIL library)
OpenGL ES 2.0 Features Used:
- Vertex Buffer Objects (VBOs) for efficient geometry storage
- Index Buffer Objects for optimized triangle rendering
- Texture mapping with bilinear filtering
- Matrix transformations (GLM library)
- Depth testing for proper 3D occlusion
- Alpha blending for transparency
🎯 Live Demo - A320 Aircraft Model
Interactive 3D Viewer
The viewer below is running the compiled C++ OpenGL ES code in your browser via Emscripten/WebGL!
Downloading...