A texture says what the surface of an object looks like. It is built from three parts: a pigment (the colour, possibly a pattern of colours), a normal (bumps that change the surface normal, see Normals and finishes) and a finish (how light is reflected, also on that page). Textures can be plain (one of each), patterned (several textures chosen by a pattern) or layered (several textures on top of each other). This page covers the texture and pigment statements, colour maps, image maps, the material statement, how transformations apply to a texture, and the warps and turbulence that distort a pattern. The patterns themselves and the generic map grammar are on Patterns and maps.
A scene with no #version directive runs as language version 3.62. Several defaults below depend on that: from language version 3.8 the default pigment is white and the default ambient is 0; before that the default pigment is black and the default ambient is 0.1.
The texture statement
texture {
[texture identifier]
[pigment identifier | normal identifier | finish identifier ...]
[pigment { ... }] [normal { ... }] [finish { ... }]
[transformations] [no_bump_scale]
}
Every item is optional. A texture starts as a copy of the identifier if one is given, otherwise as a copy of the default texture (see below). Pigment, normal and finish identifiers (written without their keyword, for old scenes such as texture { MyPigment }) replace that part. A later pigment { … }, normal { … } or finish { … } modifies that part: it is parsed starting from the copy, so pigment { rgb 1 } after an identifier keeps the pattern modifiers of the identifier unless the new statement replaces the pattern.
| Form | Syntax | Meaning |
|---|---|---|
| plain | texture { pigment { … } normal { … } finish { … } } | one pigment, an optional normal, one finish. The pigment can itself be patterned; the texture is still “plain” |
| patterned | texture { pattern [modifiers] texture_map { … } }texture { checker texture { … } texture { … } } | several textures selected or blended by a pattern, see texture maps. A patterned texture must have a texture_map or a texture list; otherwise the parser stops: “Patterned texture must have texture_map.” |
| layered | texture { … } texture { … } … | two or more textures written one after the other in an object. The first is the bottom layer, the last the top layer |
| identifier | texture { Name [transformations] } | a declared texture (also a patterned or layered one) with optional transformations. For a plain texture it can also be modified with pigment, normal or finish; for a patterned or special one only the transformations (and no_bump_scale) are accepted |
| tiles (obsolete) | texture { tiles texture tile2 texture [transformations] } | a checker of two textures; a missing first texture is the error “First texture missing from tiles”. Use checker instead |
| material_map | texture { material_map { … } } | chooses a texture for each pixel of an image, see material_map |
| Item | What it is applied to |
|---|---|
pigment, normal, finish | replace or modify that part |
translate, rotate, scale, matrix, transform | the pigment and the normal of every layer written so far. The finish is never transformed, because it has no position. A transformation written after only a pigment affects that pigment only; one written after the normal affects both. For a patterned texture it is applied to the pattern and (through the pattern) to the textures of the map |
no_bump_scale | marks the texture so that scaling does not change the depth of its normals |
The pigment, normal and finish statements also work directly inside an object: sphere { 0, 1 pigment { rgb 1 } finish { phong 1 } } builds a texture from the default texture and the given parts. If the object already has a patterned texture, a new layer is started. The object keywords texture, interior_texture, material, interior and cutaway_textures are described on Object modifiers.
Layered textures
In a layered texture all layers except the bottom one should have some transparency (a filter or transmit value in the pigment). The colour of a lower layer shows through where the layers above are transparent. A layer filters the colour of the layers below it, but not the illumination on the way in, so the result is not the same as a stack of transparent surfaces. A layered texture can be declared: #declare Layers = texture { T1 } texture { T2 } texture { T3 }. A pigment, normal or finish written after such an identifier modifies the bottom layer only. A patterned texture cannot be a layer, but a layered texture can be an item of a patterned texture (declare it first). Macros are not allowed inside a layered texture declaration.
Texture maps and block lists
texture {
pattern [pattern modifiers]
texture_map { [ value texture body ] ... }
}
texture { checker | brick | hexagon | square | triangular | cubic | object texture { ... } texture { ... } ... }
With a continuous pattern the map is a texture_map; each entry is what could stand inside texture { … } without the keyword. Where two entries meet, both textures are evaluated completely and their colours mixed, so reflection, refraction and lighting are computed twice. With a block pattern (checker and so on) the textures are listed after the keyword, each in texture { … }; missing items are copies of the default texture. The grammar of maps, their value rules and the list of patterns are on Patterns and maps. In a layered texture, the texture-map form (a patterned texture) cannot be one of the layers.
material_map
texture {
material_map {
[bitmap_type] "file"
[once] [interpolate n] [map_type n]
[repeat <u, v>] [offset <u, v>]
texture { … } texture { … } …
}
[transformations]
}
The image is placed like an image map (see below) on the square <0,0> to <1,1> of the x-y plane. For an image with a palette, the palette index of the pixel selects the texture from the list; for an image without a palette, the 8-bit value of the red component (0 to 255) is the index. If the index is larger than the number of textures it is taken modulo the number. With once, points outside the unit square get the first texture. At least one texture is needed. No pigment, normal or finish may be written outside the textures. No alpha handling is done: the data of the file is used as it is. interpolate interpolates the index before the texture is chosen, which is rarely useful. A material_map cannot be part of a layered texture; declare it and use the identifier. (Not to be confused with the material statement.)
The #default directive
#default { texture { … } }
#default { pigment { … } }
#default { normal { … } }
#default { finish { … } }
#default changes the default texture, the texture that every new texture starts from. Several of the four items may be written in one block. The default texture must be plain: it cannot be layered (“Default texture cannot be layered.”) or a patterned texture, tiles or material_map (“Default texture cannot be material map or tiles.”). The factory defaults are:
| Part | Factory value |
|---|---|
| pigment | rgb <1, 1, 1> from language version 3.8, rgb <0, 0, 0> before |
| normal | none |
| finish | all defaults of the finish statement; ambient is 0 from language version 3.8 and 0.1 before |
If a scene changes the language version after a #default, the version-dependent factory values are not applied (a warning is given). The default camera right vector depends on the version in the same way, see Cameras.
uv_mapping
All textures are three-dimensional. With uv_mapping a texture is instead taken from the surface coordinates u and v of the object: a slice of the 3D texture from the x-y plane (z = 0) is wrapped around the surface. Some textures should be rotated to fit the slice into the x-y plane.
| Form | Meaning |
|---|---|
sphere { … uv_mapping pigment { … } } | object keyword placed before the first texture, pigment, normal or finish of the object. After a texture it is the error “uv_mapping must be specified before texture.” |
pigment { uv_mapping pigment body }, normal { uv_mapping normal body }, texture { uv_mapping texture body } | the same, as a pattern: it turns the statement into one single item that is evaluated in surface coordinates |
Objects with surface coordinates: bicubic_patch (the patch parameters; the default corners are <0,0>, <1,0>, <1,1>, <0,1>, changed with uv_vectors), box, cone, cylinder, lathe, sor, lemon, mesh and mesh2 (a UV pair for each vertex), ovus, parametric, sphere, torus. A pattern does not work with uv_mapping in a pattern function.
The pigment statement
pigment {
[pigment identifier]
[colour | pattern type | image_map { … } | user_defined { … }]
[pattern modifiers]
[color_map { … } | pigment_map { … }] [quick_color colour]
}
An identifier first, if present, supplies the starting pigment; the other items modify it. Without an identifier the items modify a copy of the pigment of the default texture. The pattern type is one of the patterns of Patterns and maps, a plain colour, or an image_map. Pigment modifiers apply only to the pigment, not to the other parts of the texture. A pigment can be declared with #declare Name = pigment { … }; the identifier is then used as pigment { Name } or, with a texture, as texture { Name }.
| Kind | Syntax | Notes |
|---|---|---|
| solid colour | pigment { rgb <1, 0.5, 0> } | the keyword color or colour is optional. All five components (red, green, blue, filter, transmit) are used. Pattern modifiers are accepted but have no effect. A solid colour also sets the quick colour |
| colour pattern | pigment { gradient x color_map { … } } | any continuous pattern with a colour map; without one, the default map of that pattern |
| pigment map | pigment { pattern pigment_map { … } } | a pigment in each map entry. A pattern that cannot be mapped (block patterns, plain colours, image maps) gives “Not with this pigment type” |
| colour list | pigment { checker rgb 1, rgb 0 }, brick, hexagon, square, triangular, cubic, object { … } | a list of colours, or of pigment { … } items, selected by a block pattern |
| image map | pigment { image_map { … } } | see image maps. It cannot have a colour map or pigment map |
| function | pigment { function { expression } color_map { … } } | the number of a function of x, y, z is used as pattern value and goes through the map. Without a map it is mapped from black to white |
| user_defined | pigment { user_defined { function {…}, … } } | up to five functions give red, green, blue, filter, transmit directly. See Patterns and maps |
| average | pigment { average pigment_map { [weight pigment] … } } | a weighted average |
| pigment_pattern, image_pattern, slope, aoi, density_file … | as on Patterns and maps |
Pigment-specific items, in addition to the pattern modifiers:
| Keyword | Value | Default | Meaning |
|---|---|---|---|
color_map, colour_map | map | the default map of the pattern | see colour maps |
pigment_map | map | see Patterns and maps | |
quick_color, quick_colour | colour | invalid (not set) | the solid colour used instead of the pigment at quality settings of 5 or less (+Q5, see INI options), where all pigment patterns are turned off. Without it those renders are grey |
Filter and transmit
A colour has five components: red, green, blue, filter and transmit. rgbf and rgbt set the fourth component, rgbft all five; the keyword form is rgb 1 filter 0.5 transmit 0.2 (also red, green, blue). srgb, srgbf, srgbt, srgbft do the same for sRGB values. The full colour syntax is on Expressions.
- filter is filtered transparency: light passing through the surface is tinted by the colour of the surface (stained glass). The colour is subtracted from the light.
- transmit is non-filtered transparency: light passes unchanged but is reduced in amount (fine mesh, dust). The colour of the object and the transmitted colour together make 100 per cent: with transmit 0.9, 90 per cent of the colour comes from behind and 10 per cent from the object. Values outside 0 to 1 are allowed and act like contrast (transmit 2 doubles the contrast around the object colour, a negative value inverts it).
- Both apply only to the diffuse, ambient and emission components, unless the finish has
use_alpha on; then they also hide the highlights and the specular reflection. - In layered textures filter and transmit decide how much of the layers below shows through. A
finishwithconserve_energyreduces both by the amount that is reflected.
Colour maps
color_map | colour_map {
[blend_mode 0..3] [blend_gamma g]
[ value colour ] ...
}
A colour map turns the value of a pattern (0 to 1 after the wave type) into a colour. Entries are written [ value colour ] in ascending order of value; the brackets belong to the syntax. A value below the first entry gets the first colour, at or above the last entry the last colour, and between two entries the colours are blended linearly. Two entries with the same value ([0.6 Blue] [0.6 Green]) make a sharp edge; a value equal to that number takes the second colour. Entries with the same colour next to each other make a flat band. The colours may use filter and transmit: the map then blends those too. A colour map can be declared (#declare Rainbow = color_map { … }) and used by its identifier (color_map { Rainbow }). It cannot be used with checker, brick, hexagon, object, square, triangular, cubic, average, or image_map: the parser gives “Cannot use color_map with this pattern type.” The map has at least one entry; version 3.8 has no upper limit. Details of the blend modes and the old double entry [0.0 0.1 color Red color Red] are on Patterns and maps.
sphere { 0, 1
pigment {
gradient x
color_map {
blend_mode 1
[0.0 rgb <1, 0, 0>]
[0.3 rgbt <1, 1, 0, 0.5>]
[0.3 rgb <0, 0, 1>]
[1.0 rgbf <0, 1, 0, 0.8>]
}
quick_color rgb 0.5
}
}
+Q5 and lower.Image maps
pigment {
image_map {
[bitmap_type] "file" | function w, h { body }
[gamma g] [premultiplied bool]
[map_type n] [once] [interpolate n]
[filter all f | filter index, f]
[transmit all t | transmit index, t]
[use_colour | use_index]
[repeat <u, v>] [offset <u, v>]
}
}
An image map wraps a picture around the object. By default the image is projected on the x-y plane as if from a slide projector in the −z direction. It exactly fills the square from <0, 0> to <1, 1> of the x-y plane, whatever its size in pixels. Imagine each pixel as a long thin rod along the z axis; the object is carved out of the bundle. Move, scale and rotate the pigment to place the image. The same keywords (without filter and transmit) are accepted by bump_map, image_pattern and material_map. The file is searched in the current directory first, then in the library paths (+L, Library_Path).
The image source
| Form | Meaning |
|---|---|
gif, tga, iff, png, pgm, ppm, jpeg, tiff, bmp, exr, hdr, sys followed by a file name | the file type is given by the keyword (sys is the system format of the platform). pot is accepted only for height fields. Other keywords are the error “File type not supported here.” |
| a file name only | the type is taken from the extension of the name; with no extension, from the output file type of the render (Output_File_Type), so image_map { "Eggs" } reads Eggs.png in a PNG render. A name with an extension that is not an image type is the error “Could not determine valid image file type from extension.” |
function w, h { body } | an image made from a function of x, y over <0,0,0> to <1,1,0>. The body is a plain function (grey), pattern { … } (grey) or a pigment or a function returning five values (colour). 16 bits per component. The size is rounded to whole pixels |
Keywords
| Keyword | Value | Default | Meaning |
|---|---|---|---|
gamma | number, srgb, bt709, bt2020 | depends on the file type and the assumed_gamma setting (Global settings) | overrides the decoding gamma of this file. A number must be positive; values below 1 give a warning that suggest the reciprocal. It must follow the file name immediately (before or after premultiplied). For PGM and PPM files the default is the BT.709 curve in language version 3.8 and later (with a warning that asks to state it); before 3.8 no correction is made |
premultiplied | bool | by file type | says whether the colour data of the file are stored premultiplied by the alpha value. Default: PNG straight, OpenEXR premultiplied, TIFF as the header says, TGA and BMP straight. Without an alpha channel it does nothing |
map_type | 0, 1, 2, 5, 7 | 0 | 0 planar, 1 spherical (y is the pole, the image covers the sphere once, the left edge at +x, west to east), 2 cylindrical (around y, one unit high, repeated at every height unless once), 5 torus (major radius 1 in the x-z plane), 7 angular, for light probes. Other numbers (3, 4, 6, and so on) are the error “Invalid map_type value.” in an image_map; in a bump_map and image_pattern they are not checked. once has no meaning for type 1 |
once | off (the image repeats in every unit square) | only the copy at <0,0> to <1,1> is used. Outside it an image map is fully transparent, a bump map is flat, a material map gets the first texture | |
interpolate | 2, 3, 4 | none | 2 bilinear, 3 bicubic (can over-sharpen at colour borders), 4 normalised distance (the slowest). Writing interpolate 0 or 1 in an image map is the error “Invalid interpolate value.”; leave the keyword out for no interpolation |
filter all | number | 0 | sets the filter value of the whole picture. With an alpha channel it is added scaled by the alpha value (language version 3.8 and later; before, it is added without regard to alpha) |
filter n, f | palette index, number | sets the filter value of colour number n of a palette image (PNG, GIF, IFF). An index outside the palette is the error “FILTER color register value out of range.”; with an image that has no palette: “Not with non color-mapped image” | |
transmit all | number | 0 | as filter all, for transmit |
transmit n, t | palette index, number | as filter n, f | |
use_colour, use_color, use_index | colour | accepted by the parser in an image map as in a bump map: use the colour, or the palette index | |
repeat | 2D vector, both above 0 | <1, 1> | size of the image as a multiple of its original size (a vector with zero or negative components is an error) |
offset | 2D vector | <0, 0> | moves the image, in units of the image size |
The old keyword alpha still means filter (a warning for language versions of 1.55 and later). An image with an alpha channel uses it as transmit automatically; alpha 255 is transmit 0 and alpha 0 is transmit 1. The old syntax with a vector or map type before the file type is ignored with a warning.
sphere { 0, 1
pigment {
image_map {
function 64, 64 { pigment { checker rgb <1, 0, 0>, rgb <0, 0, 1> scale 0.1 } }
map_type 1
interpolate 2
filter all 0.2
}
}
}
plane { -z, -3
pigment {
image_map {
function 8, 8 { pattern { checker } }
once
transmit all 0.5
}
scale 4
translate <-2, -2, 0>
}
}
The material statement
material {
[material identifier]
[texture { … }] [interior_texture { … }] [interior { … }]
[transformations]
}
A material bundles the surface texture with the interior (the volume properties, see Media, interior and atmosphere). It is declared with #declare Name = material { … } and used inside an object: sphere { 0, 1 material { Name } }. Several texture items are layers. interior_texture is the texture of the inside surface of the object. The transformations are applied to the textures and to the interior (its media density). If the object has a texture already, the material adds its layers on top.
#declare Glass = material {
texture {
pigment { rgbf <1, 1, 1, 0.9> }
finish { reflection 0.05 specular 0.8 roughness 0.01 }
}
interior { ior 1.5 }
}
sphere { 0, 1 material { Glass } }
How transformations apply
A pattern is fixed in space: a transformation of an object does not move a texture that was set before it, and a transformation of a texture or pigment moves the pattern, not the surface. A translate, rotate, scale, matrix or transform inside a pigment, normal, texture or density changes the pattern and works like the same word on an object. In a finish transformations are not allowed. Scaling an object after the texture is set scales the texture with it (and its bumps, unless no_bump_scale).
Inside one pattern, the transformations and the warps are applied in the order written (as one list), and the classic turbulence is applied before all of them, regardless of where it is written. To put turbulence at a chosen place, write it in a warp. In a texture map the transformation of the outer texture moves the pattern and, with it, the textures of the map; a transformation inside an entry moves only that entry. pigment_pattern and image_pattern keep their own transformation, independent from the items they choose.
sphere { 0, 1
texture {
pigment {
gradient y
color_map { [0 rgb <1, 0.8, 0>] [1 rgb <0.8, 0, 0>] }
scale 2 // pigment only
}
normal { bumps 0.4 }
rotate x*20 // pigment and normal, not the finish
finish { phong 0.5 }
translate y // pigment and normal; the finish has no position
}
}
Warps
A warp moves the point at which a pattern is evaluated. It is a pattern modifier for pigments, normals, textures and densities. A pattern can have any number of warp { … } statements; they and the transformations are applied in the order written.
warp { one warp }
repeat <direction> [offset <v>] [flip <v>]
black_hole <centre>, radius [strength s] [falloff f] [inverse] [type t] [repeat <v>] [turbulence <v>]
turbulence <amount> [octaves n] [omega o] [lambda l]
cylindrical | spherical [orientation <v>] [dist_exp e]
toroidal [orientation <v>] [dist_exp e] [major_radius r]
planar [<normal>, offset]
cubic
| Warp | Keyword | Value | Default | Meaning |
|---|---|---|---|---|
repeat | repeat | vector along one axis | none | the pattern repeats every width units along that axis, where width is the non-zero component. Two or three non-zero components: “Can only repeat along 1 axis.”; none: “No axis specified in repeat.” |
offset | vector | <0, 0, 0> | moves the pattern by this much for every copy: copy n is sliced at n times the offset | |
flip | vector | <0, 0, 0> (no flip) | every other copy is mirrored about each axis for which the component is non-zero; only zero or non-zero matters | |
black_hole | black_hole | centre vector, radius | none | a sphere inside which the pattern is pulled towards the centre (or pushed away with inverse). Outside the radius nothing changes |
strength | number | 1.0 | multiplies the force. The shift is limited to the distance of the point from the centre | |
falloff | number | 2.0 | the power in force = closeness ^ falloff, where closeness is 0 at the rim and 1 at the centre. 1 is linear, 0 is a force of 1 everywhere inside | |
inverse | off | pushes instead of pulls | ||
type | integer | 0 | only type 0 changes the pattern in this source; any other number leaves the point unchanged | |
repeat | vector | off | repeats the black hole in blocks of this size; the centre is then an offset in each block (positive). The block must hold the whole hole: the repeat in each axis must be at least centre + radius + turbulence, otherwise the parser increases it with a warning; 0 in an axis means no repeat in that axis. If the centre is smaller than the radius it is moved silently | |
turbulence | vector | off | moves each repeated hole randomly (but repeatably) by up to this amount per axis. Only with repeat | |
turbulence | turbulence | number or vector | <0, 0, 0> | pushes the point about with noise, per axis: see turbulence |
octaves | integer | 6 | number of steps, clamped to 1 to 10 | |
omega | number | 0.5 | size of each step relative to the one before | |
lambda | number | 2.0 | frequency factor from step to step | |
cylindrical | orientation | vector (normalised) | <0, 0, 1> | the axis the mapping is wrapped around (the same as the direction of an image map projection) |
dist_exp | number | 0 | exponent of the distance (from the y axis for a cylinder) used as the depth coordinate. With 0 the pattern is a box from <0,0> to <1,1> stretching infinitely along the orientation | |
spherical | orientation | vector | <0, 0, 1> | the pole of the sphere |
dist_exp | number | 0 | exponent of the distance from the origin | |
toroidal | orientation | vector | <0, 0, 1> | the axis of the torus |
dist_exp | number | 0 | exponent of the distance from the major radius | |
major_radius | number | 1 | major radius of the torus | |
planar | planar [<v>, d] | vector, number | <0, 0, 1>, 0 | takes the pattern from the plane of the x-y plane (or the plane with the normal v at the distance d) and extrudes it along z, so a pattern acts like an infinite image map |
cubic | maps the square <0,0> to <1,1> of the x-y plane around the origin the way uv_mapping maps an origin-centred box |
Any other word after warp { is the error “Expected warp type”, and an empty warp: “Empty warp statement.” The warps are not applied to the normal of a pattern; for the perturbed normals only the transformations are.
box { <-3, -1, -1>, <3, 1, 1>
pigment {
wood
color_map { [0 rgb <0.8, 0.5, 0.2>] [1 rgb <0.3, 0.15, 0.05>] }
warp { repeat 1*x offset <0, 0, 0.1> flip <1, 0, 0> }
warp { turbulence 0.2 octaves 3 omega 0.4 lambda 2.5 }
rotate x*90
}
}
sphere { <0, 3, 0>, 1
pigment {
checker rgb 1, rgb 0
scale 0.1
warp { spherical orientation y dist_exp 1 }
}
}
sphere { <-2.5, 0, 0>, 1
pigment {
wood
color_map { [0 rgb <0.8, 0.5, 0.2>] [1 rgb <0.3, 0.15, 0.05>] }
warp { black_hole <0, 0, 0>, 0.5 falloff 3 strength 1.5 inverse }
warp { planar y, 0.25 }
}
}
Turbulence, octaves, omega and lambda
Turbulence is random noise that moves the point at which a pattern is evaluated. It works as a pattern modifier (turbulence amount directly in the pigment, normal, texture or density) and as a warp (warp { turbulence amount … }). It also works in fog and in the iridescence of a finish (see Media, interior and atmosphere and Normals and finishes).
| Keyword | Value | Default | Meaning |
|---|---|---|---|
turbulence | number or vector | <0, 0, 0> (none) | the amount for x, y, z. A single number is used for all three. Typical values are 0 to 1. turbulence <1, 0.6, 0.1> is much in x and little in z |
octaves | number, truncated to an integer | 6 | number of random steps. Values below 1 become 1, above 10 become 10. More octaves look fuzzier and take longer; above 6 hardly any change is visible. No effect without turbulence |
omega | number | 0.5 | each step is this much as large as the one before. Larger values give a sharper, crinkly look |
lambda | number | 2.0 | the frequency factor from step to step. Values near 1 make the steps point in similar directions, which straightens the path |
The point p becomes p + turbulence × d (per axis), where d is the sum over the octaves k = 0 to octaves − 1 of omegak × DNoise(p × lambdak). DNoise is a vector noise: smooth, with a direction at each point. The word “classic turbulence” means the form without warp. It is stored first in the list of the pattern, is always applied before everything else, and is treated specially by agate, marble, spiral1, spiral2 and wood (their formulae use the turbulence value themselves). octaves, omega and lambda outside a warp belong to the classic turbulence and create it even when no amount is given.
Not described
Known, not yet covered
- Reference: the exact blend formulae of the colour map blend modes 1 to 3 and the layer maths (how filter and transmit of each layer combine in the lighting calculation) are described only by effect; the code in
source/core/lightingwas not followed through. - Reference: the surface coordinates of each object for
uv_mappingare listed from the manual, not checked in the object code.