What is Opal?
Opal is Atlas Engine’s low-level rendering abstraction layer that provides a unified API across OpenGL, Vulkan, and Metal backends. It handles context creation, device management, command buffers, and GPU resources.
This is an alpha API and may change in future releases.
Multi-Backend Architecture
Opal automatically selects the appropriate backend based on compile-time flags:
OpenGL : Cross-platform fallback (4.1+ Core)
Vulkan : Modern low-overhead API for Windows/Linux
Metal : Native high-performance rendering on macOS/iOS
Core Components
Context Creation
The Context manages the GLFW window and backend initialization:
#include "opal/opal.h"
using namespace opal ;
// Configure the rendering context
ContextConfiguration config;
config . useOpenGL = true ;
config . majorVersion = 4 ;
config . minorVersion = 1 ;
config . profile = OpenGLProfile ::Core;
config . applicationName = "My Atlas App" ;
// Create context
auto context = Context :: create (config);
context -> makeWindow ( 1600 , 1200 , "My Window" );
context -> makeCurrent ();
Use OpenGL backend (set to false for Vulkan/Metal)
OpenGL major version number
OpenGL minor version number
Enable validation layers for debugging (Vulkan)
Device Acquisition
The Device represents the GPU and manages rendering resources:
// Acquire device from context
auto device = Device :: acquire (context);
// Get device information
DeviceInfo info = device -> getDeviceInfo ();
std ::cout << "GPU: " << info . deviceName << std ::endl;
std ::cout << "Vendor: " << info . vendorName << std ::endl;
std ::cout << "Driver: " << info . driverVersion << std ::endl;
std ::cout << "Rendering API: " << info . renderingVersion << std ::endl;
Command Buffers
Command buffers record and submit GPU commands:
// Acquire command buffer for rendering
auto commandBuffer = device -> acquireCommandBuffer ();
// Start recording
commandBuffer -> start ();
// Begin render pass
auto renderPass = RenderPass :: create ();
renderPass -> setFramebuffer (framebuffer);
commandBuffer -> beginPass (renderPass);
// Clear screen
commandBuffer -> clear ( 0.1 f , 0.1 f , 0.15 f , 1.0 f , 1.0 f );
// Bind pipeline and draw
commandBuffer -> bindPipeline (pipeline);
commandBuffer -> bindDrawingState (drawingState);
commandBuffer -> drawIndexed (indexCount, 1 );
// End pass and submit
commandBuffer -> endPass ();
commandBuffer -> commit ();
device -> submitCommandBuffer (commandBuffer);
Textures
Opal supports multiple texture types and formats:
// Create a 2D RGBA texture
auto texture = Texture :: create (
TextureType ::Texture2D,
TextureFormat ::Rgba8,
1024 , 1024 ,
TextureDataFormat ::Rgba,
pixelData
);
// Create a multisampled texture for MSAA
auto msTexture = Texture :: createMultisampled (
TextureFormat ::Rgba16F,
1920 , 1080 ,
4 // 4x MSAA
);
// Create a depth cubemap for omnidirectional shadows
auto shadowCubemap = Texture :: createDepthCubemap (
TextureFormat ::Depth32F,
2048 // Resolution per face
);
// Configure texture sampling
texture -> setParameters (
TextureWrapMode ::Repeat,
TextureWrapMode ::Repeat,
TextureFilterMode ::LinearMipmapLinear,
TextureFilterMode ::Linear
);
// Generate mipmaps
texture -> automaticallyGenerateMipmaps ();
Texture2D | TextureCubeMap | Texture3D | Texture2DArray | Texture2DMultisample
Rgba8 | sRgba8 | Rgba16F | Depth24Stencil8 | Depth32F | and more
Buffers
Manage vertex, index, and uniform buffers:
// Create vertex buffer
auto vertexBuffer = Buffer :: create (
BufferUsage ::VertexBuffer,
vertices . size () * sizeof (Vertex),
vertices . data (),
MemoryUsageType ::GPUOnly
);
// Create index buffer
auto indexBuffer = Buffer :: create (
BufferUsage ::IndexArray,
indices . size () * sizeof ( uint32_t ),
indices . data (),
MemoryUsageType ::GPUOnly
);
// Update buffer data
vertexBuffer -> updateData ( 0 , newData . size () * sizeof (Vertex), newData . data ());
Framebuffers
Render to textures using framebuffer objects:
// Create framebuffer
auto framebuffer = Framebuffer :: create ( 1920 , 1080 );
// Attach color texture
framebuffer -> attachTexture (colorTexture, 0 );
// Attach depth-stencil buffer
auto depthBuffer = DepthStencilBuffer :: create (
1920 , 1080 ,
TextureFormat ::Depth24Stencil8
);
framebuffer -> attachDepthStencilBuffer (depthBuffer);
// Bind and render
framebuffer -> bind ();
// ... rendering commands ...
framebuffer -> unbind ();
Shaders and Pipelines
Compile shaders and configure the graphics pipeline:
// Create shaders from source
auto vertShader = Shader :: createFromSource (vertexSource, ShaderType ::Vertex);
auto fragShader = Shader :: createFromSource (fragmentSource, ShaderType ::Fragment);
vertShader -> compile ();
fragShader -> compile ();
// Create shader program
auto shaderProgram = ShaderProgram :: create ();
shaderProgram -> attachShader (vertShader);
shaderProgram -> attachShader (fragShader);
shaderProgram -> link ();
// Create and configure pipeline
auto pipeline = Pipeline :: create ();
pipeline -> setShaderProgram (shaderProgram);
pipeline -> setPrimitiveStyle ( PrimitiveStyle ::Triangles);
pipeline -> enableDepthTest ( true );
pipeline -> setDepthCompareOp ( CompareOp ::Less);
pipeline -> setCullMode ( CullMode ::Back);
pipeline -> enableBlending ( true );
pipeline -> setBlendFunc ( BlendFunc ::SrcAlpha, BlendFunc ::OneMinusSrcAlpha);
pipeline -> build ();
Backend-Specific Features
Vulkan
When compiled with VULKAN defined:
Uses VkDevice, VkCommandBuffer, and VkPipeline
Supports descriptor sets for efficient resource binding
Includes push constants for small uniform data
Provides swapchain management
When compiled with METAL defined:
Uses Metal API on macOS/iOS
Optimized for Apple Silicon
Efficient memory management
OpenGL
Default fallback implementation:
Uses VAOs, VBOs, and FBOs
Compatible with OpenGL 4.1 Core and above
Widely supported across platforms
Best Practices
Batch draw calls with the same pipeline to reduce overhead.
Render multiple copies of objects with drawIndexed(count, instanceCount).
Always generate mipmaps for textures to improve performance and quality.
Use Texture::createMultisampled() for high-quality anti-aliasing.
See Also