Forge Language
Forge is object-like and incremental.
var sphere = Sphere {
radius: 1.0
};
sphere.pos.y = 0.4;
let mat = Metal {
color: #ebc757,
roughness: 0.18
};
sphere.material = mat;
let scene = sphere;
Current Scope
Current supported pieces include:
letandvar- top-level
fn name(...) { ... } - top-level
import "..." ; - top-level
export { ... }; - nested property assignment like
pos.xandrot.z - object literals
- scalar and
vec3arithmetic - hex color literals like
#ff0000and#f00 - built-ins such as
mix,clamp,step,smoothstep,dot,length,normalize,sin,cos - material definitions with local bindings and functions
- environment definitions with local bindings and functions
- custom SDF definitions with
sdf Name { fn distance(p) { ... } }
Functions
Material functions can now also drive shading-normal perturbation with fn normal(ctx) { ... }, which is useful for procedural bump-style detail without changing the underlying SDF geometry.
Top-level helper functions can be reused across a module and may take multiple arguments:
fn accent() {
return #ebc757;
}
fn tint(base, amount) {
return mix(base, vec3(1.0), amount);
}
fn make_gold() {
return Metal {
color: tint(accent(), 0.12),
roughness: 0.18
};
}
Imported helpers also work through aliases:
import "Gold" as metals;
fn make_highlight() {
return metals.Gold {};
}
Imports
Imports are resolved before evaluation:
import "./shared/materials.ft";
import "Gold" as gold;
import "SoftBlob" as blob;
Import rules:
./...and../...import from disk relative to the current filematerials/...,objects/..., andscenes/...import from the built-in embedded library- bare built-in names like
Glass,SoftBlob, andStudioalso resolve from the embedded library as namenamespaces the imported top-level symbols undername.- imports are loaded once even if multiple files reference them
- cyclic imports are rejected
Files can also declare an explicit public surface:
let private_color = #ebc757;
material Gold {
model: Metal;
color = private_color;
roughness = 0.18;
};
export { Gold };
If a file contains export { ... };, imports treat that list as the intended public entry points.
Environments
Procedural environments use the same block-style function model:
environment Sky {
let zenith = #4d74c7;
let horizon = #d8e7ff;
fn color(dir) {
let t = clamp(dir.y * 0.5 + 0.5, 0.0, 1.0);
return mix(horizon, zenith, t);
}
};
color(dir) is called on ray misses in render, ray, and path.
Status
The language is intentionally still small. Semantics are being stabilized before a VM/JIT layer is added.