Granites are classified as intrusive, or plutonic, igneous rocks. Slow cooling of plutonic magma beneath the surface of the Earth results in macroscopic assemblages of juxtaposed and closely packed minerals that show different forms, colours, sizes, and compositions. In contrast, volcanic glasses such as obsidian, are the amorphous product of rapidly cooling volcanic igneous rocks which solidify before crystallization can occur.
The overall colour of granites (white, pink, or grey) is the result of the relative proportion of each mineral, which facilitates the optical classification of a given rock sample. Sometimes, particularly large crystals (phenocrysts, often plagioclase) are present, and can help with the identification.
Figure 1 shows a QAPF diagram (Quartz, Alkali feldspar, Plagioclase, Feldspathoids, also known as a Streckeisen diagram) which is used by the scientific community for the classification of igneous rocks. More information on this can be found here, and for granites in general, see here. The International Union of Geological Sciences IUGS, approved the QAPF diagram in 1974.
To simulate a real world granite in POV-Ray, we make use of a colour map representing the different minerals/colours of the granite as basis for its pigment, and a colour mask, a colour_map-based pigment_pattern used within the granite texture, which controls the distribution of those same minerals/colours. Necessarily, there is a close relationship between maps and masks as mineral/colour boundaries within a particular granite must correspond to their mask boundaries. The final texture is pretty complex as additional differential scaling perturbs the final aspect of the texture. In the following paragraphs we shall explain how this is achieved by the macro, illustrated by comprehensive examples and diagrams. To make things easier to understand, the different parts of the macro are described separately.
Sections 1 through 3 of the macro concerns the creation of granite pigments (Fig. 2). The input to this part of the macro – independent from the different parameters which will be described later – consists of three different colour map arrays (prefixed with A_) for each granite type file:
All examples shown below use the (default) Dakota Red Granite data (Table 1).
The close-packed, discrete assemblages typical of granites can be simulated by sharply-bounded groups of colours, with each group representing a different mineral (Table 1). The first array (A_Granite_map1) is read into the macro's C_Granite_map1 colour map. The second array (A_Granite_mask) is read into the macro's C_Granite_mask colour map. This last one controls either the cells or the step noise (SN) pigment patterns, while the crackle pattern uses its own colour_map (Fig. 2). These pigment_patterns controlling the C_Granite_map1 colour map, then generate one of the following pigments: P_Granite_crackle, P_Granite_cells, or P_Granite_SN.
Note that mask maps do not always have the same number of indices as their corresponding colour maps, though the indices representing the boundaries between minerals are identical (of necessity); see Table and the file data in Annexes.
An additional pattern, Blend (blend_mask, Fig. 2), developed originally by Tekno Frannansa (aka Tek), makes use of the generated pigments to provide a blended version. This can be very useful to simulate a weathered aspect of the granite, for example.
As the granite mask is used as a pigment_pattern, changing the RGB-values of its colour_map changes the aspect of the granite pigment and, as explained later, the aspect of the granite texture. How pigment patterns work exactly is explained in the POV-Ray documentation. The user is invited to experiment by making changes to the mask's colour_map when choosing the cells or the step noise pigment pattern (remember that the crackle pattern uses its own map), for instance by reversing the RGB-values in the list, and compare the rendered texture with the original one (Fig. 3). A very large number of different granites can thus be generated from a single basic concept. Do not change the colour_map entries in the A_Granite_mask array however, without also changing the corresponding entries in the A_Granite_mask1 array!
A_Granite_map2, which controls the appearance of the (quartz) veins intersecting a given granite, is a mixed array with the following format:
#declare Map2_entries = 5; #declare A_Granite_map2 = array mixed [Map2_entries][3] { {0.000, <0.800, 0.800, 0.800>, 0.150}, {0.005, <0.800, 0.800, 0.800>, 0.000}, {0.010, <0.800, 0.800, 0.800>, 0.150}, {0.011, <1.000, 1.000, 1.000>, 1.000}, {1.000, <1.000, 1.000, 1.000>, 1.000} }
This array describes the colour map of the quartz. It is a bit different from the minerals colour map in that it also contains filter and transmit information. Especially the filter information is highly experimental at this stage and may substantially change in the future. When enabled, a veins texture will be layered over the main granite texture. As this feature is still in an experimental phase, for the time being simply copy the array without modification, when you use it.
In section 4 of the macro, the data from this array are fed into the internal C_Granite_map2 colour map, which in turn is the core of the P_Granite_veins (marble pattern) pigment.
In section 5 of the macro (Fig. 4), the texture generation, we employ the same pigment patterns used in section 3 (Fig. 2). However, they are implemented for a different reason, and in a different way. This time they control the distribution of the granite pigments at different scales throughout the granite texture. An array (A_Granite_var) serves as input for additional variations. It has the following format:
#declare Var_entries = 8; #declare A_Granite_var = array [Var_entries][3] { {0.20, 0.50, 0.15}, {0.25, 1.00, 0.18}, {0.35, 1.00, 0.18}, {0.40, 0.50, 0.15}, {0.60, 1.00, 0.15}, {0.65, 0.50, 0.18}, {0.75, 1.00, 0.18}, {0.80, 0.50, 0.15} }
Like in the arrays discussed previously, the first elements are the pigment or normal map entries. The second elements control the strength of the normal pattern (only for the frosted version of the granite) in the normal map. The third elements scale both the pigments in the pigment map, and the normal patterns in the normal map. The purpose is to provide visual variation of the granite minerals in the texture. When experimenting with these values, be careful to keep the variations relatively small, and close to each other. A large variation may rapidly become 'artificial' (fig. 5).
Also in this section, different finish blocks are generated, corresponding to either the polished or the frosted versions of the granite, and whether or not the granite contains veins (layered texture). As the final step, the normal block for the frosted version of the granite is generated.
The veins texture (Fig. 4) has its own finish blocks (polished and frosted) and a normal block where the normal map is controlled by the same pigment (P_Granite_veins) used in the pigment pattern.
Still experimental is the use of subsurface light transmission. The macro parameter SubS enables the feature in this section's finish blocks. This needs to be developed further in the future.
The granite textures have been structured and scaled in such a way that they correspond to a fairly fine to medium-grained real-world granite. This means that applying this texture to an arbitrarily-sized object without any further scaling will show a real-world-scale granite texture. One POV-unit corresponds to 100 cm (fig. 3 and 5). This may need some more explanation. In the examples shown in this documentation, the objects have been scaled to a one POV-unit cubic size (mostly for convenience). Applied to these objects and without further scaling, the granite pattern will appear to be as a real-world one cubic meter granitic rock from which an object (the Bunny!) had been sculpted. Similarly, any POV-Ray object, whatever its size, with the granite texture applied and without further scaling, will simulate real-world granitic objects. In other words: Scale the object and THEN apply the Granite_21() macro. This is exemplified by Figure 6. Evidently, for each scene, the user has to determine what the "real-world" dimensions of his or her world are and maybe scale the granite texture accordingly.
In section 6 of the macro, everything is pulled together into the final material. An interior block is added with an ior 1.6 value chosen as a good compromise for feldspars and quartz. Further development of the interior may include media, to be combined with the subsurface light transport.
Still within the macro structure, the users can apply internal transformations to the texture. They may for instance want to rotate the texture (can be useful when using veins), translate it (also useful with veins enabled), or scale the complete texture. The parameters M_scale (defaults to <1,1,1>), M_rotat (defaults to <0,0,0>), and M_trans (defaults to <0,0,0>) are provided as input parameters (see below).
![]() |
![]() |
![]() |
![]() |
![]() |
|
Required: Granite_file. | Required: CSC. | Required: Pol. | Required: Type. | Required: Pat1. | |
![]() |
![]() |
![]() |
![]() |
![]() |
|
Required: Pat2. | Required: Blend. | Optional: SN_Start; SN_End; SN_Turb. |
Optional: BC_Blur. | SSLT: SubS. |
The following annexes describe seven granites based on the original code by Daniel Mecklenburg Jr. Not all annexes however, describe true granites. Of the seven, Annex 1 (Dakota Red Granite) and Annex 2 (North American Pink Granite) can be considered as true granites according to scientific standards. Annex 3 (Southern Gray Granite) and Annex 4 (Medium Barre Gray Granite) can be considered as belonging to the diorite or gabbro groups. Annex 5 (Saint-André Green Granite) and Annex 6 (Saint-André Green Dark Granite) from Quebec, Canada, are difficult to classify and may represent special cases within the plutonic rocks group, possibly a monzonite equivalent. Finally, Annex 7 (Impala Black Granite) which describes a very dark when polished, stone from the Bushveld in South Africa, represents a gabbronorite. These last three granites contain significant additions of dark minerals.
Note that the use of "not_0" in the arrays represents a value of 1/265, small enough to render a completely black pixel, but which retains the ability to contribute to the multiplicative result of colour and intensity calculations resulting from strong illumination, radiosity, etc.).
The POV-Ray macro tabulated.inc by jr has been used to visualize the granite arrays in Table 1 and Figures 5. Likewise, his ruled.inc macro was used in most illustrations to visualise the dimensions of the shown objects. Last but not least, jr threw in his not negligible webpage building skills to improve this document.
The "Stanford Bunny" which appears profusely throughout this documentation, was gratefully downloaded from here.
The Scene Description Language (SDL) code was written for the Persistence of Vision Raytracer version 3.8, or later. Because the Granite_21 macro uses version 3.8 specific features, in particular in the granite arrays, it cannot be used as is in the earlier versions.
In January 1996, Daniel Mecklenburg Jr. (aka Code Warrior), posted the first known version of the original set of code for POV-Ray that lies at the basis of the present macro. Somehow, this set of code found its way into early include files developed at the time by different users. It is probable that one of us (TdeG) found the set late in the nineteen nineties or early in the twenty first century. Nothing really important happened after then until the early months of 2021. The Granite_21 macro is the result.
July 2021