Materials
Atlas uses a Physically-Based Rendering (PBR) material system based on metallic-roughness workflow.
Material Structure
The Material struct defines surface properties:
struct Material {
Color albedo = {1.0, 1.0, 1.0, 1.0}; // Base color
float metallic = 0.0f; // Metallic factor
float roughness = 0.5f; // Roughness factor
float ao = 1.0f; // Ambient occlusion
};
albedo
Color
default:"{1.0, 1.0, 1.0, 1.0}"
Base color contribution of the surface (RGB + Alpha)
Metallic factor (0.0 = dielectric, 1.0 = metallic)
Roughness factor influencing specular highlight spread (0.0 = smooth, 1.0 = rough)
Ambient occlusion term to darken creases and cavities
Setting Material Properties
// Create a box
CoreObject cube = createBox({1.0, 1.0, 1.0});
// Configure PBR material
cube.material.albedo = Color(0.8f, 0.1f, 0.1f, 1.0f); // Red
cube.material.metallic = 0.0f; // Non-metallic
cube.material.roughness = 0.6f; // Slightly rough
cube.material.ao = 1.0f; // Full ambient
window.addObject(&cube);
Common Material Presets
cube.material.albedo = Color::blue();
cube.material.metallic = 0.0f;
cube.material.roughness = 0.8f;
cube.material.ao = 1.0f;
Textures
Loading Textures from Resources
First, register resources with the workspace:
#include "atlas/texture.h"
#include "atlas/workspace.h"
// Set root path for resources
Workspace::get().setRootPath("assets/");
// Create resource
Resource brickResource = Workspace::get().createResource(
"textures/brick.png",
"BrickTexture",
ResourceType::Image
);
// Create texture from resource
Texture brickTexture = Texture::fromResource(
brickResource,
TextureType::Color
);
// Or load by name directly
Texture diffuseMap = Texture::fromResourceName(
"BrickTexture",
TextureType::Color
);
Texture Types
Normal map for surface detail
Specular map (Phong/Blinn-Phong)
Height map for parallax mapping
Texture Parameters
Configure texture wrapping and filtering:
TextureParameters params;
params.wrappingModeS = TextureWrappingMode::Repeat;
params.wrappingModeT = TextureWrappingMode::Repeat;
params.minifyingFilter = TextureFilteringMode::Linear;
params.magnifyingFilter = TextureFilteringMode::Linear;
Texture texture = Texture::fromResource(
resource,
TextureType::Color,
params
);
Wrapping Modes
Repeat - Repeats the texture infinitely
MirroredRepeat - Alternates direction on every repeat
ClampToEdge - Stretches edge pixels
ClampToBorder - Uses constant border color
Filtering Modes
Nearest - Picks closest texel (pixelated look)
Linear - Linearly interpolates texels (smoother)
Attaching Textures to Objects
CoreObject model = createBox({1.0, 1.0, 1.0});
// Attach albedo texture
Texture albedoMap = Texture::fromResourceName("WoodAlbedo", TextureType::Color);
model.attachTexture(albedoMap);
// Attach normal map
Texture normalMap = Texture::fromResourceName("WoodNormal", TextureType::Normal);
model.attachTexture(normalMap);
// Attach metallic map
Texture metallicMap = Texture::fromResourceName("WoodMetallic", TextureType::Metallic);
model.attachTexture(metallicMap);
// Attach roughness map
Texture roughnessMap = Texture::fromResourceName("WoodRoughness", TextureType::Roughness);
model.attachTexture(roughnessMap);
Procedural Textures
Checkerboard Texture
Texture checkerboard = Texture::createCheckerboard(
512, 512, // Width, height
32, // Check size
Color::white(), // Color 1
Color::black() // Color 2
);
Double Checkerboard
Texture doubleChecker = Texture::createDoubleCheckerboard(
512, 512, // Width, height
64, // Big check size
16, // Small check size
Color::red(), // Color 1
Color::green(), // Color 2
Color::blue() // Color 3
);
Tiled Checkerboard
std::vector<CheckerTile> tiles = {
{Color::red(), Color::black(), 64},
{Color::green(), Color::black(), 32},
{Color::blue(), Color::black(), 16}
};
Texture tiledTexture = Texture::createTiledCheckerboard(
512, 512,
tiles
);
Rain Streak Texture
For particle effects:
Texture rainStreak = Texture::createRainStreak(64, 256);
Cubemaps
Cubemaps are used for skyboxes and environment mapping:
// Create resources for each face
Resource right = Workspace::get().createResource(
"skybox/px.png", "RightSkybox", ResourceType::Image
);
Resource left = Workspace::get().createResource(
"skybox/nx.png", "LeftSkybox", ResourceType::Image
);
Resource top = Workspace::get().createResource(
"skybox/py.png", "TopSkybox", ResourceType::Image
);
Resource bottom = Workspace::get().createResource(
"skybox/ny.png", "BottomSkybox", ResourceType::Image
);
Resource front = Workspace::get().createResource(
"skybox/pz.png", "FrontSkybox", ResourceType::Image
);
Resource back = Workspace::get().createResource(
"skybox/nz.png", "BackSkybox", ResourceType::Image
);
// Create resource group
ResourceGroup group = Workspace::get().createResourceGroup(
"Skybox",
{right, left, top, bottom, front, back}
);
// Create cubemap
Cubemap skyboxCubemap = Cubemap::fromResourceGroup(group);
Solid Color Cubemap
std::array<Color, 6> colors = {
Color::red(), // +X
Color::green(), // -X
Color::blue(), // +Y
Color::yellow(), // -Y
Color::cyan(), // +Z
Color::magenta() // -Z
};
Cubemap colorCubemap = Cubemap::fromColors(colors, 512);
Advanced Texture Usage
Water with DUDV and Normal Maps
From the test suite:
Texture waterDUDV = Texture::fromResource(
Workspace::get().createResource(
"water_dudv.png", "WaterDUDV", ResourceType::Image
)
);
Texture waterNormal = Texture::fromResource(
Workspace::get().createResource(
"water_normal.png", "WaterNormal", ResourceType::Image
)
);
Fluid water = Fluid();
water.create({0.9, 0.9}, Color::blue());
water.setPosition({0.0f, 0.10f, 0.5f});
water.movementTexture = waterDUDV;
water.normalTexture = waterNormal;
water.initialize();
Border Color for Clamped Textures
Texture texture = Texture::fromResource(
resource,
TextureType::Color,
params,
Color(0.0f, 0.0f, 0.0f, 1.0f) // Black border
);
Texture Coordinates
Vertex texture coordinates are defined in the CoreVertex struct:
struct CoreVertex {
Position3d position;
Color color;
TextureCoordinate textureCoordinate; // {u, v}
Normal3d normal;
Normal3d tangent;
Normal3d bitangent;
};
Texture coordinates typically range from [0, 0] to [1, 1]:
CoreVertex vertex(
{1.0f, 1.0f, 0.0f}, // Position
Color::white(), // Color
{1.0f, 1.0f}, // Top-right UV
{0.0f, 0.0f, 1.0f} // Normal (Z+)
);
Best Practices
Use power-of-two resolutions (256, 512, 1024, 2048) for better GPU compatibility and mipmap generation.
Enable mipmaps for textures viewed at varying distances to improve performance and reduce aliasing.
Combine multiple small textures into a single atlas to reduce draw calls.
Use compressed texture formats (DXT, ASTC) for production builds to save memory.
Keep metallic at 0.0 or 1.0 for physically accurate materials. Use roughness to control specular highlights.
See Also