How glTF doubleSided Ensures Two-Sided Visibility
This article explains how the doubleSided property in
the glTF (GL Transmission Format) 2.0 specification enables two-sided
polygon rendering. It details the default behavior of 3D graphics
pipelines regarding backface culling, how setting the
doubleSided boolean alters this behavior, how real-time
rendering engines handle lighting and normal orientation on back-facing
surfaces, and the performance implications of enabling this feature.
The Default Behavior: Backface Culling
In standard real-time 3D rendering (such as WebGL, OpenGL, Vulkan, and DirectX), graphics hardware uses a process called backface culling to optimize performance. Triangles are defined by their vertex winding order—typically counter-clockwise for front-facing polygons. When a triangle faces away from the camera, the hardware automatically discards it before shading.
In glTF, materials default to single-sided rendering where the
doubleSided property is set to false. Under
these conditions, viewing the back side of a polygon results in complete
invisibility, creating transparency where a surface should logically
exist.
The Role of the
doubleSided Property
The glTF specification allows materials to explicitly declare whether
both sides of a surface should be rendered using the
doubleSided boolean inside the material
object:
{
"materials": [
{
"name": "Fabric",
"doubleSided": true
}
]
}When an engine parses a glTF file and encounters
"doubleSided": true, it instructs the graphics API to
disable backface culling for any mesh primitive referencing that
material. As a result, rasterization occurs regardless of whether the
triangle winds clockwise or counter-clockwise relative to the
camera.
Surface Normal Inversion and Lighting
Disabling backface culling is only half of the requirement for correct visibility. In physically based rendering (PBR), surface normals dictate how light interacts with a mesh. If a backface simply used the original geometry's normal, light calculations would compute shading as if the light were striking the opposite side, resulting in incorrect dark patches or inverted specular highlights.
To ensure visual accuracy, the glTF specification mandates that when
doubleSided is true, renderers must negate
(flip) the normal vector for back-facing fragments during shading:
- In GLSL-based pipelines, the shader checks the built-in boolean
gl_FrontFacing. - If
gl_FrontFacingis false, the normal vector (\(N\)) is multiplied by \(-1.0\). - If tangent vectors and normal maps are present, the bitangent and tangent space calculations are similarly mirrored so normal map details render correctly on the reverse side.
This conditional inversion allows both sides of thin geometry—such as leaves, paper, cloth, or chainlink fences—to receive proper diffuse and specular lighting based on their orientation relative to the light sources.
Performance Considerations
While doubleSided is essential for flat geometry that
lacks volume, it carries a performance cost:
- Fragment Shader Load: The GPU must process fragments that would otherwise be discarded during rasterization.
- Shader Branching: Determining whether a face is front- or back-facing introduces minor shader logic overhead.
- Overdraw: If applied carelessly to closed, watertight meshes (such as characters or solid buildings), it wastes GPU cycles rendering hidden interior faces.
Renderers conformant with the glTF 2.0 specification treat
doubleSided strictly as a material-level instruction to
disable face culling and dynamically invert back-facing normals,
providing a standardized way to achieve two-sided visibility across
disparate 3D software and runtime engines.