Rendering Components

Visual rendering, lighting, cameras, materials, and LOD components powered by Three.js.

Rendering components control how entities appear visually in your game. Web Engine uses Three.js for rendering, supporting meshes, lights, cameras, materials, shadows, and advanced features like LOD and render layers.

MeshRenderer#

The MeshRenderer component defines what mesh an entity renders. It supports both built-in primitives (box, sphere, plane) and loaded 3D models (GLTF, FBX).

Properties#

PropertyTypeDefaultDescription
primitiveTypeui800=use assetId, 1=Box, 2=Sphere, 3=Plane, 4=Cylinder, 5=Capsule, 6=Cone, 7=Torus
assetIdui320Asset ID for loaded models (when primitiveType=0)
castShadowui80Whether mesh casts shadows (0=no, 1=yes)
receiveShadowui81Whether mesh receives shadows (0=no, 1=yes)

Usage#

import { addComponent, MeshRenderer, PrimitiveType } from '@web-engine/core';
// Create box primitive
const box = world.addEntity();
addComponent(world, MeshRenderer, box);
MeshRenderer.primitiveType[box] = PrimitiveType.Box;
MeshRenderer.castShadow[box] = 1;
MeshRenderer.receiveShadow[box] = 1;
// Create entity with loaded model
const character = world.addEntity();
addComponent(world, MeshRenderer, character);
MeshRenderer.primitiveType[character] = PrimitiveType.None;
MeshRenderer.assetId[character] = loadedModelAssetId;

Primitive Types

Built-in primitives: Box (1x1x1), Sphere (r=0.5), Plane (1x1), Cylinder (r=0.5, h=1), Capsule (r=0.35, h=1.2), Cone (r=0.5, h=1), Torus (R=0.5, r=0.2)

MaterialRef#

The MaterialRef component assigns materials to meshes with support for material overrides, UV tiling/offset, color tinting, and material variants.

Properties#

PropertyTypeDefaultDescription
assetIdui320Material asset ID (0=use default/mesh material)
tiling[f32, 2][1, 1]UV tiling multiplier [x, y]
offset[f32, 2][0, 0]UV offset [x, y]
colorOverride[f32, 3][1, 1, 1]RGB color multiplier [r, g, b]
alphaOverridef321.0Alpha multiplier (0-1)
variantHashui320Hash of active variant name
slotCountui80Number of material slots (multi-material)

Usage#

import { addComponent, MaterialRef } from '@web-engine/core';
// Assign material with color tint
const entity = world.addEntity();
addComponent(world, MaterialRef, entity);
MaterialRef.assetId[entity] = materialAssetId;
MaterialRef.colorOverride[entity][0] = 1.0; // Red
MaterialRef.colorOverride[entity][1] = 0.5; // Green
MaterialRef.colorOverride[entity][2] = 0.5; // Blue
// UV tiling for repeating textures
MaterialRef.tiling[entity][0] = 2.0; // Tile 2x horizontally
MaterialRef.tiling[entity][1] = 2.0; // Tile 2x vertically
// Material transparency
MaterialRef.alphaOverride[entity] = 0.5; // 50% transparent

Material Overrides

MaterialRef overrides multiply with the base material properties. This allows runtime tinting and transparency without creating new material instances.

MeshColor#

The MeshColor component applies a color tint to a mesh, similar to MaterialRef.colorOverride but as a separate component.

Properties#

PropertyTypeDefaultDescription
rf321.0Red channel (0-1)
gf321.0Green channel (0-1)
bf321.0Blue channel (0-1)
af321.0Alpha channel (0-1)

Light#

The Light component creates light sources in the scene. Supports point lights, directional lights (sun), and spot lights.

Properties#

PropertyTypeDefaultDescription
typeui800=Point, 1=Directional, 2=Spot
color[f32, 3][1, 1, 1]Light color [r, g, b]
intensityf321.0Light intensity multiplier
rangef3210.0Light range in meters (point/spot only)
anglef320.5Spot light cone angle in radians
castShadowui80Whether light casts shadows (0=no, 1=yes)

Usage#

import { addComponent, Light } from '@web-engine/core';
// Create directional light (sun)
const sun = world.addEntity();
addComponent(world, Transform, sun);
addComponent(world, Light, sun);
Light.type[sun] = 1; // Directional
Light.intensity[sun] = 1.0;
Light.color[sun][0] = 1.0; // White
Light.color[sun][1] = 1.0;
Light.color[sun][2] = 1.0;
Light.castShadow[sun] = 1;
Transform.rotation[sun][0] = -Math.PI / 4; // Angle down
// Create point light (lamp)
const lamp = world.addEntity();
addComponent(world, Transform, lamp);
addComponent(world, Light, lamp);
Light.type[lamp] = 0; // Point
Light.intensity[lamp] = 2.0;
Light.range[lamp] = 15.0;
Light.color[lamp][0] = 1.0; // Orange
Light.color[lamp][1] = 0.7;
Light.color[lamp][2] = 0.3;
// Create spot light (flashlight)
const flashlight = world.addEntity();
addComponent(world, Transform, flashlight);
addComponent(world, Light, flashlight);
Light.type[flashlight] = 2; // Spot
Light.intensity[flashlight] = 3.0;
Light.range[flashlight] = 20.0;
Light.angle[flashlight] = Math.PI / 6; // 30 degree cone

Camera#

The Camera component defines camera projection properties. Paired with CameraTag to mark the active camera.

Properties#

PropertyTypeDefaultDescription
fovf3260.0Field of view in degrees (45-90 typical)
nearf320.1Near clipping plane distance (meters)
farf321000.0Far clipping plane distance (meters)
aspectf321.77Aspect ratio (width/height), set automatically
focusf3210.0Focus distance for depth of field (meters)

Usage#

import { addComponent, Camera, CameraTag } from '@web-engine/core';
// Create main camera
const camera = world.addEntity();
addComponent(world, Transform, camera);
addComponent(world, Camera, camera);
addComponent(world, CameraTag, camera); // Mark as active
Camera.fov[camera] = 75.0; // Wide FOV for FPS
Camera.near[camera] = 0.1;
Camera.far[camera] = 500.0;
// Position camera
Transform.position[camera][1] = 1.7; // Eye height
Transform.position[camera][2] = 5.0; // Back from origin

Active Camera

Only one camera should have CameraTag at a time. The rendering system uses this to determine which camera renders the scene.

Renderable#

The Renderable tag component marks entities that should be rendered. Used for frustum culling and occlusion queries.

import { addComponent, Renderable } from '@web-engine/core';
// Mark entity as renderable
addComponent(world, Renderable, entity);

RenderLayers#

The RenderLayers component controls which cameras can see an entity using bitmask-based layer membership.

Properties#

PropertyTypeDefaultDescription
maskui320xFFFFFFFF32-bit bitmask of layer membership

Usage#

import { addComponent, RenderLayers, RenderLayerBit } from '@web-engine/core';
// Create UI element on UI layer
const uiElement = world.addEntity();
addComponent(world, RenderLayers, uiElement);
RenderLayers.mask[uiElement] = RenderLayerBit.UI;
// Create object visible on multiple layers
const multiLayerObject = world.addEntity();
addComponent(world, RenderLayers, multiLayerObject);
RenderLayers.mask[multiLayerObject] =
RenderLayerBit.Default | RenderLayerBit.Shadows;

Layer Bits

Available layers: Default, UI, Gizmos, Shadows, Transparent, PostProcess, Reflections, Custom1-4. Combine using bitwise OR (|).

CullingMask#

The CullingMask component on cameras determines which RenderLayers the camera can see.

Properties#

PropertyTypeDefaultDescription
maskui320xFFFFFFFF32-bit bitmask of visible layers
import { addComponent, CullingMask, RenderLayerBit } from '@web-engine/core';
// Main camera sees default and shadows only
addComponent(world, CullingMask, mainCamera);
CullingMask.mask[mainCamera] =
RenderLayerBit.Default | RenderLayerBit.Shadows;
// UI camera sees UI only
addComponent(world, CullingMask, uiCamera);
CullingMask.mask[uiCamera] = RenderLayerBit.UI;

BoundingBox#

The BoundingBox component stores precomputed axis-aligned bounding boxes for frustum culling and spatial queries.

Properties#

PropertyTypeDefaultDescription
min[f32, 3][0, 0, 0]Minimum corner [x, y, z]
max[f32, 3][0, 0, 0]Maximum corner [x, y, z]
center[f32, 3][0, 0, 0]Center point [x, y, z]
radiusf320.0Bounding sphere radius

Automatic Computation

BoundingBox is automatically computed by RenderSystem from mesh geometry. Mark entities with BoundingBoxDirty to trigger recalculation.

LODGroup#

The LODGroup component manages Level of Detail switching based on camera distance, reducing rendering cost for distant objects.

Properties#

PropertyTypeDefaultDescription
distances[f32, 3][10, 50, 100]Distance thresholds for LOD levels [LOD0→1, LOD1→2, LOD2→cull]
assetIds[ui32, 3][0, 0, 0]Asset IDs for each LOD level [LOD0, LOD1, LOD2]
currentLODui80Current active LOD (0=highest, 3=culled)
hysteresisui825Hysteresis percentage (0-255 mapped to 0-100%)
lastChangeTimef320.0Time of last LOD change (seconds)
cooldownMsui8100Cooldown between changes (0-255 = 0-2550ms)

Usage#

import { addComponent, LODGroup } from '@web-engine/core';
// Setup LOD for tree
const tree = world.addEntity();
addComponent(world, LODGroup, tree);
// LOD0: Full detail (0-20m)
LODGroup.assetIds[tree][0] = highDetailTreeAssetId;
LODGroup.distances[tree][0] = 20.0;
// LOD1: Medium detail (20-50m)
LODGroup.assetIds[tree][1] = mediumDetailTreeAssetId;
LODGroup.distances[tree][1] = 50.0;
// LOD2: Low detail (50-100m)
LODGroup.assetIds[tree][2] = lowDetailTreeAssetId;
LODGroup.distances[tree][2] = 100.0;
// Beyond 100m: Culled (not rendered)
// Optional: Adjust hysteresis to prevent flickering
LODGroup.hysteresis[tree] = 26; // 10% hysteresis (26/255 ≈ 0.1)

LOD Hysteresis

Hysteresis prevents visual popping when objects are near threshold boundaries. With 10% hysteresis at 50m: switch to higher LOD at 45m, switch to lower LOD at 55m.

Environment#

The Environment component controls global environmental settings like skybox, fog, ambient light, and sun position.

Properties#

PropertyTypeDefaultDescription
presetui800=None, 1=Sunset, 2=Dawn, 3=Night, 4=Warehouse, etc.
backgroundui81Show skybox as background (0=no, 1=yes)
blurf320.0Skybox blur amount (0-1)
sunPosition[f32, 3][0, 1, 0]Sun direction [x, y, z]
ambientIntensityf321.0Ambient light intensity
fogColor[f32, 3][0.5, 0.5, 0.5]Fog color [r, g, b]
fogDensityf320.0Fog density (0=no fog)

PostProcessing#

The PostProcessing component configures global post-processing effects like bloom, vignette, chromatic aberration, and tone mapping.

Properties#

PropertyTypeDefaultDescription
enabledui80Enable post-processing (0=no, 1=yes)
bloomIntensityf320.5Bloom glow intensity
bloomThresholdf320.9Brightness threshold for bloom
bloomSmoothingf320.5Bloom smoothness
vignetteDarknessf320.5Vignette edge darkness
vignetteOffsetf321.0Vignette offset from edges
chromaticAberrationf320.0Chromatic aberration offset
toneMappingExposuref321.0Tone mapping exposure
ssaoIntensityf320.5Screen-space ambient occlusion intensity

Best Practices#

  • Use LODGroup for distant objects to improve performance
  • Enable castShadow only on important objects (shadows are expensive)
  • Use RenderLayers to separate UI, world, and effects rendering
  • Keep light count low (1 directional + 2-3 point lights max for realtime shadows)
  • Use MaterialRef.colorOverride for runtime tinting instead of material clones
  • Set appropriate camera.near/far planes to minimize z-fighting
  • Use BoundingBox for custom culling and spatial queries
Components | Web Engine Docs | Web Engine Docs