Material System¶
The Material system in Evoker Engine defines how objects appear when rendered, including textures, shaders, and rendering properties.
Overview (Planned)¶
The material system will include:
- Material: Defines surface appearance
- Shaders: Vertex and fragment programs
- Textures: Albedo, normal, roughness, metallic maps
- Properties: Color, roughness, metallic values
- Rendering Modes: Opaque, transparent, cutout
Material Class (Planned)¶
public class Material
{
public string Name { get; set; }
public Shader Shader { get; set; }
// Textures
public Texture? AlbedoTexture { get; set; }
public Texture? NormalTexture { get; set; }
public Texture? MetallicTexture { get; set; }
public Texture? RoughnessTexture { get; set; }
public Texture? EmissiveTexture { get; set; }
// Properties
public Vector4 AlbedoColor { get; set; } = Vector4.One;
public float Metallic { get; set; } = 0f;
public float Roughness { get; set; } = 0.5f;
public Vector3 Emissive { get; set; } = Vector3.Zero;
// Rendering
public RenderMode RenderMode { get; set; } = RenderMode.Opaque;
public CullMode CullMode { get; set; } = CullMode.Back;
}
public enum RenderMode
{
Opaque, // Standard opaque rendering
Transparent, // Alpha blending
Cutout // Alpha testing
}
public enum CullMode
{
Off, // No culling (two-sided)
Front, // Cull front faces
Back // Cull back faces (default)
}
Creating Materials (Planned)¶
Simple Material¶
var material = new Material
{
Name = "SimpleMaterial",
AlbedoColor = new Vector4(1, 0, 0, 1), // Red
Metallic = 0f,
Roughness = 0.8f
};
Textured Material¶
var material = new Material
{
Name = "TexturedMaterial",
AlbedoTexture = TextureLoader.Load("textures/albedo.png"),
NormalTexture = TextureLoader.Load("textures/normal.png"),
MetallicTexture = TextureLoader.Load("textures/metallic.png"),
RoughnessTexture = TextureLoader.Load("textures/roughness.png"),
AlbedoColor = Vector4.One,
Metallic = 1f,
Roughness = 0.5f
};
Emissive Material¶
var glowMaterial = new Material
{
Name = "GlowMaterial",
AlbedoColor = new Vector4(0.2f, 0.2f, 0.2f, 1),
Emissive = new Vector3(0, 1, 0), // Green glow
EmissiveTexture = TextureLoader.Load("textures/emission.png")
};
PBR Materials (Physically Based Rendering)¶
Metallic-Roughness Workflow¶
public class PBRMaterial : Material
{
// Metallic: 0 = dielectric, 1 = metal
// Roughness: 0 = smooth, 1 = rough
public static PBRMaterial CreateMetal(Vector4 color, float roughness)
{
return new PBRMaterial
{
AlbedoColor = color,
Metallic = 1.0f,
Roughness = roughness
};
}
public static PBRMaterial CreateDielectric(Vector4 color, float roughness)
{
return new PBRMaterial
{
AlbedoColor = color,
Metallic = 0.0f,
Roughness = roughness
};
}
}
// Gold metal
var gold = PBRMaterial.CreateMetal(
new Vector4(1f, 0.766f, 0.336f, 1f),
roughness: 0.3f
);
// Plastic
var plastic = PBRMaterial.CreateDielectric(
new Vector4(0.8f, 0.1f, 0.1f, 1f),
roughness: 0.6f
);
Common Materials¶
Glass¶
var glass = new Material
{
Name = "Glass",
AlbedoColor = new Vector4(1, 1, 1, 0.2f), // Almost transparent
Metallic = 0f,
Roughness = 0.0f, // Very smooth
RenderMode = RenderMode.Transparent
};
Wood¶
var wood = new Material
{
Name = "Wood",
AlbedoTexture = TextureLoader.Load("textures/wood_albedo.png"),
NormalTexture = TextureLoader.Load("textures/wood_normal.png"),
RoughnessTexture = TextureLoader.Load("textures/wood_roughness.png"),
Metallic = 0f,
Roughness = 0.7f
};
Stone¶
var stone = new Material
{
Name = "Stone",
AlbedoTexture = TextureLoader.Load("textures/stone_albedo.png"),
NormalTexture = TextureLoader.Load("textures/stone_normal.png"),
Metallic = 0f,
Roughness = 0.9f
};
Shader System (Planned)¶
Custom Shaders¶
var customShader = new Shader
{
VertexShaderPath = "shaders/custom.vert",
FragmentShaderPath = "shaders/custom.frag"
};
var material = new Material
{
Shader = customShader,
// Custom properties...
};
Shader Properties¶
// Set custom shader properties (planned)
material.SetFloat("_TimeScale", 1.0f);
material.SetVector("_WindDirection", new Vector3(1, 0, 0));
material.SetTexture("_CustomMap", customTexture);
Material Properties¶
Tiling and Offset¶
// Texture tiling (planned)
material.SetTextureScale("_MainTex", new Vector2(2, 2)); // Tile 2x
material.SetTextureOffset("_MainTex", new Vector2(0.5f, 0.5f)); // Offset
Alpha Cutoff¶
// For cutout materials (planned)
var foliage = new Material
{
RenderMode = RenderMode.Cutout,
AlphaClipThreshold = 0.5f, // Discard pixels with alpha < 0.5
AlbedoTexture = TextureLoader.Load("textures/leaves.png")
};
Material Library Example¶
public static class MaterialLibrary
{
private static Dictionary<string, Material> _materials = new();
public static void Initialize()
{
// Metals
Register("gold", CreateGold());
Register("silver", CreateSilver());
Register("copper", CreateCopper());
// Common materials
Register("wood", CreateWood());
Register("stone", CreateStone());
Register("glass", CreateGlass());
Register("plastic", CreatePlastic());
}
public static void Register(string name, Material material)
{
_materials[name] = material;
}
public static Material? Get(string name)
{
return _materials.TryGetValue(name, out var material) ? material : null;
}
private static Material CreateGold()
{
return new Material
{
Name = "Gold",
AlbedoColor = new Vector4(1f, 0.766f, 0.336f, 1f),
Metallic = 1.0f,
Roughness = 0.3f
};
}
private static Material CreateSilver()
{
return new Material
{
Name = "Silver",
AlbedoColor = new Vector4(0.972f, 0.960f, 0.915f, 1f),
Metallic = 1.0f,
Roughness = 0.2f
};
}
private static Material CreateWood()
{
return new Material
{
Name = "Wood",
AlbedoTexture = TextureLoader.Load("textures/wood_albedo.png"),
NormalTexture = TextureLoader.Load("textures/wood_normal.png"),
Metallic = 0f,
Roughness = 0.7f
};
}
private static Material CreateGlass()
{
return new Material
{
Name = "Glass",
AlbedoColor = new Vector4(1, 1, 1, 0.2f),
Metallic = 0f,
Roughness = 0f,
RenderMode = RenderMode.Transparent
};
}
private static Material CreateStone() { /* ... */ return new Material(); }
private static Material CreateCopper() { /* ... */ return new Material(); }
private static Material CreatePlastic() { /* ... */ return new Material(); }
}
// Usage
var goldMaterial = MaterialLibrary.Get("gold");
Applying Materials to Objects¶
var scene = Application.Instance.ActiveScene;
var entity = scene.CreateEntity("Sphere");
// Add mesh renderer
var renderer = scene.Registry.AddComponent<MeshRendererComponent>(entity);
renderer.MeshId = sphereMesh.Id;
renderer.MaterialId = goldMaterial.Id; // Apply gold material
Best Practices¶
✅ Do's¶
- Reuse materials when possible (material instancing)
- Use texture atlases to reduce draw calls
- Set appropriate roughness/metallic values for realism
- Use normal maps for surface detail
- Keep emissive values reasonable
❌ Don'ts¶
- Don't create unique materials for every object
- Don't use extremely high resolution textures (optimize)
- Don't forget to set render mode for transparent materials
- Don't mix units (keep texture scales consistent)
Performance Tips¶
- Material Batching: Group objects with same material
- Texture Atlasing: Combine textures into atlases
- LOD Materials: Use simpler materials for distant objects
- Texture Compression: Use compressed texture formats
See Also¶
- Rendering Pipeline - Rendering system
- Resource Loading - Loading textures
- Vulkan - Graphics API