WRL File Documentation


Summary

A .wrl file is a 3D scene written in VRML (Virtual Reality Modeling Language), an early open standard for describing 3D models and interactive “worlds”. It is plain UTF-8 text: a scene graph of shapes, transforms, materials, lights and viewpoints. Its MIME type is model/vrml. To view one, open it in MeshLab or Blender, or a browser-based VRML viewer. VRML’s successor is X3D, so converting .wrl to OBJ, STL or glTF is common when you need it in modern tools.

Technical details

FeatureValue
Full nameVRML World (Virtual Reality Modeling Language)
File extension.wrl (gzip-compressed: .wrz)
MIME typemodel/vrml (also x-world/x-vrml)
Format typePlain-text 3D scene description (scene graph)
DeveloperWeb3D Consortium (ISO/IEC standard)
Introduced1995 (VRML 1.0); VRML97 in 1997
StandardVRML97 = ISO/IEC 14772-1:1997
Open standardYes — published ISO/IEC specification
EncodingASCII (VRML 1.0) / UTF-8 (VRML97)
Header line#VRML V1.0 ascii or #VRML V2.0 utf8
Geometry nodesIndexedFaceSet, Box, Sphere, Cylinder, Cone
GroupingTransform, Group, Shape
AppearanceMaterial, ImageTexture (per-vertex/per-face colour)
InteractivitySensors, Script, ROUTE events (VRML97)
SuccessorX3D (XML-based, same Web3D Consortium)
Related extensions.x3d, .x3dv, .wrz, .obj, .dae, .stl
Specificationweb3d.org/documents/specifications/14772/
Syntax at a glance

A WRL file is plain text with no binary signature. It is identified by its first line, a header comment: #VRML V1.0 ascii for VRML 1.0 or #VRML V2.0 utf8 for VRML97. What follows is a scene graph — a nesting of nodes such as Transform, Group and Shape, each written as NodeName { field value }. Geometry lives in nodes like Box, Sphere and IndexedFaceSet; appearance in Appearance and Material. Because it is text, any editor can read it, and a gzip-compressed VRML file uses the .wrz extension.

What is a WRL file?

A .wrl file (the extension is short for “world”) is a 3D scene written in VRML, the Virtual Reality Modeling Language. VRML was one of the first standards for describing interactive 3D content, created in 1995 for the early web; its second revision, VRML97, became the international standard ISO/IEC 14772-1:1997, published by what is now the Web3D Consortium. A WRL file is not a mesh dump or a binary blob. It is a human-readable text document describing a scene graph: a hierarchy of nodes for shapes, transforms, materials, textures, lights, cameras and, in VRML97, scripted behaviour.

Because it is text, you can open any .wrl in an editor and read the scene directly. VRML was designed to be viewed in a browser through plugins such as Cortona3D and Cosmo Player, but those plugins are long dead, so WRL files today are opened in desktop 3D tools (Blender, MeshLab) or converted to a current format. The rest of this article is about how the language actually encodes a scene: the header, the node syntax, the coordinate system, and the geometry nodes that carry the real mesh data.

The header line and file versions

A VRML file is identified not by magic bytes but by its first line, a header comment that names the version and character encoding:

#VRML V1.0 ascii     ← VRML 1.0 (1995), ASCII
#VRML V2.0 utf8      ← VRML97 / ISO 14772, UTF-8

The two versions are genuinely different languages. VRML 1.0 borrowed its object model from SGI’s Open Inventor and used a state-based rendering model. VRML97 (the V2.0 header) redesigned the language around an event-driven scene graph with routes, sensors and scripting, and is what almost every surviving WRL file uses. A parser must read this line first, because it selects which node set and semantics apply. A # anywhere on a line begins a comment that runs to end of line, so the header is itself a comment that also carries the version declaration.

Node syntax: fields, DEF and USE

Everything in a WRL is a node, written as a type name followed by a brace-delimited body of fields:

Shape {
  appearance Appearance {
    material Material {
      diffuseColor 0.8 0.2 0.2
      transparency 0.0
    }
  }
  geometry Box { size 2 1 3 }
}

Each field has a name and a typed value: single or multiple floats, integers, colours (RGB triples in the 0–1 range), booleans (TRUE/FALSE), strings, or nested nodes. Fields whose names start with a capital and hold nodes (like appearance and geometry above) build the tree by containment. VRML has no commas between values; whitespace and newlines separate tokens, which is why the format tolerates almost any indentation.

Two keywords give the graph its efficiency. DEF name Node { ... } names a node so it can be referenced later, and USE name inserts that same node again by reference rather than copying it. A scene with a hundred identical bolts defines the bolt once with DEF and places it ninety-nine more times with USE, so the shared geometry is stored a single time. This is the VRML equivalent of instancing, and it is also how animations reference the node they drive.

Transform hierarchy and the coordinate system

A VRML scene is a tree of grouping nodes, chiefly Group and Transform. A Transform applies translation, rotation and scale to all of its children, and transforms nest, so child coordinates are expressed relative to the parent’s frame. This is what lets a model be built from sub-assemblies that are positioned as units.

Transform {
  translation 0 1 0
  rotation 0 1 0 1.5708     # axis x y z, angle in RADIANS
  scale 1 1 1
  children [
    Shape { ... }
    Transform { ... }        # nested, relative to parent
  ]
}

VRML uses a right-handed coordinate system: +X right, +Y up, +Z toward the viewer, with distances in metres by convention. Rotations are given as an axis (three numbers) plus an angle in radians, not degrees, which is a frequent surprise when reading a file by hand. Colours are floating-point RGB in the range 0 to 1 rather than 0 to 255. These conventions are worth knowing because they explain why a naive import into a Y-down or degrees-based tool can flip or over-rotate a model.

IndexedFaceSet: how the mesh is actually stored

Primitive nodes (Box, Sphere, Cylinder, Cone) cover simple shapes, but real models are polygon meshes stored in an IndexedFaceSet. It separates the list of unique vertices from the list of faces that reference them by index:

Shape {
  geometry IndexedFaceSet {
    coord Coordinate {
      point [ 0 0 0, 1 0 0, 1 1 0, 0 1 0 ]   # vertex list
    }
    coordIndex [ 0 1 2 3 -1 ]                 # one quad; -1 ends a face
    color Color { color [ 1 0 0, 0 1 0 ] }
    colorPerVertex TRUE
  }
}

The coord field holds a Coordinate node whose point array lists every unique vertex once. The coordIndex array then defines faces as sequences of indices into that array, with -1 as the terminator that ends each face, so faces can have any number of sides. Sharing vertices by index means a shared corner is stored once, and a mesh’s topology is fully described by the two arrays. Optional companion fields carry normal vectors, texCoord texture coordinates, and color data. The colorPerVertex flag decides whether the colour list is applied per vertex (smooth gradients) or per face (flat panels).

That per-vertex and per-face colour is why WRL is a common carrier for full-colour 3D printing: it stores colour that plain STL cannot. Converting such a model to STL for printing silently drops the colour, so a colour-capable target (OBJ+MTL, PLY, glTF or 3MF) is the right choice when the WRL was made for colour output.

Appearance, textures, viewpoints and lights

A Shape’s look comes from its appearance field, an Appearance node holding a Material and optionally an ImageTexture. The Material node carries diffuseColor, specularColor, emissiveColor, shininess and transparency, the classic parameters of the fixed-function lighting model VRML predates modern PBR by two decades. An ImageTexture references an external image file by URL, which means a WRL with textures depends on those side files being present.

Scenes also carry navigation and lighting nodes. A Viewpoint defines a named camera position and orientation, so a file can ship with several preset views. DirectionalLight, PointLight and SpotLight illuminate the scene, and a Background node sets sky and ground colours or a panorama. None of these hold mesh data; they describe how the geometry is lit and framed when a viewer opens the world.

Sensors, scripts and where WRL goes next

VRML97’s ambition was interactivity, and it encodes behaviour with three ingredients: sensors that detect events (a TouchSensor for clicks, a TimeSensor that emits a clock), interpolators that turn a fraction into a value (a PositionInterpolator or OrientationInterpolator keyframes an animation), and ROUTE statements that wire an event from one node’s output to another’s input. A ROUTE Timer.fraction_changed TO Mover.set_fraction is how a clock drives an interpolator that moves an object. A Script node can run ECMAScript or Java to compute behaviour that routes alone cannot express. These behaviours only come alive in a full VRML browser; a mesh viewer such as Blender or MeshLab imports the geometry and ignores the scripting, which is also the safe way to open an untrusted file, since Script and EXTERNPROTO nodes can pull in external resources.

VRML’s direct successor is X3D, the same scene model re-expressed in XML by the same Web3D Consortium; conversion between WRL and X3D is close to 1:1. For modern real-time and web 3D, glTF has taken over the role VRML once aimed at. In practice a WRL is imported into Blender or MeshLab and re-exported to OBJ, glTF or STL for use in current pipelines, while the original file remains a readable, self-describing record of the scene.

References