Fractal Architect 4 Help Index
Lua API Reference
Applies to:FA 4
New feature of Fractal Architect 4 !
See Also: Using Lua Scripts
Lua Engine Version
Lua version 5.2.3 interpreter has been added to the app. When you search for info, make sure you specify that Lua version number, as it is continually being updated with no language features / API changes.
Lua Scripting Primer
Ralf Flicker wrote an excellent Lua primer for scripting fractals on the Oxidizer flame fractal app. (No longer maintained by its developer it seems.)
His Oxidizer Lua scripts and Lua Primer can be downloaded here:
Tutorial and Example Lua Scripts
Ralf was a brilliant scripter. Tweaked versions of his simil3.lua and simil4.lua scripts are included with Fractal Architect and show the full power of Lua when applied to flame fractal creation.
Lua Engine’s LUAPATH
You may create your own reusable Lua modules to hold reusable Lua functions that you create. Custom scripts will use the Lua require function to load any modules the script wants to use.
Lua require functions search for Lua modules by looking in these directories, in this order:
- My Scripts/makeRandom
- My Scripts/makeVariants
- Factory/makeRandom
- Factory/makeVariants
The My Scripts folder’s location is can be changed by pressing the Choose Folder for My Scripts button.
The factory Lua tweak scripts provided with the app includes 2 example Lua modules and some example scripts that use those modules. (See below for more info.)
Builtin Variables Used by the Fractal Architect Lua Runtime
Fractal Architect uses several Lua global variables that it expects scripts to use for sending fractal definitions back to the app.
- flame
- The Lua table that represents the current fractal being modified.
- flames
-
The list of flame tables that you can add new flames to
(Note the oxidizer_genomes table is actually the same table. It is intended for compatibility with older Oxidizer Lua scripts created specifically for the Oxidizer app).
How a Fractal is Represented in Lua
Fractals in Lua are represented as a single Lua table.
That table holds a complex assortment of other tables representing other data structures needed by the fractal definition.
It is recommended that you use the Fractal creation utility functions
(see Utility Functions for Creating Blank Fractals )
to create a empty fractal (instead of setting each and every field shown in the table below).
- flame
- The table representing the entire fractal
- Image parameters
- flame.time
- flame.width
- flame.height
- flame.centre_x
- flame.center_x — alternate name
- flame.centre_y
- flame.center_y — alternate name
- flame.rotate
- flame.symmetry
- flame.zoom
- flame.scale
- 3D Camera parameters
- flame.cam_yaw
- flame.cam_pitch
- flame.cam_perspective
- flame.clipToNDC
- flame.cam_dof
- flame.cam_zpos
- flame.cam_fov
- flame.cam_near
- flame.cam_orthowide
- flame.cam_x
- flame.cam_y
- flame.cam_z
- Color parameters
- flame.palette {string}
- flame.hue
- flame.brightness
- flame.vibrancy
- flame.gamma
- flame.alpha_gamma
- flame.gamma_threshold
- flame.background_image_path - image file path - for composite over image rendering mode
-
flame.colors {tables, one per index}
flame.colors[n].index
flame.colors[n].red
flame.colors[n].green
flame.colors[n].blue
flame.colors[n].alpha
-
flame.background {table}
flame.background.red
flame.background.green
flame.background.blue
-
flame.composite_color {table} - for use with compositing render mode (see below)
flame.composite_color.red
flame.composite_color.green
flame.composite_color.blue
- Render parameters
- flame.render_mode - set to one of “normal”, “compositeOverColor”, “compositeOverImage”, “transparent”
- flame.oversample
- flame.supersample_width
- flame.highlight_power
- flame.cpufuse
- flame.gpufuse
- flame.palette_mode
- flame.filter
- flame.filter_shape {string}
- flame.quality
- flame.estimator_radius
- Edit parameters
- flame.name {string}
- flame.uuid {string}
- flame.varsetUuid {string}
- Xform parameters
- flame.xforms[n].weight
- flame.xforms[n].color
- flame.xforms[n].symmetry
- flame.xforms[n].color_speed
- flame.xforms[n].is_finalxform {string}
- flame.xforms[n].opacity
- flame.xforms[n].rotates
- flame.xforms[n].rotates_ignores_symmetry – for older scripts , rotates looks at symmetry first
- flame.xforms[n].var_color
-
flame.xforms[n].coefs
- flame.xforms[n].post
- Variations
- This is the table for the Normal variation group. It holds a list of variation tables.
- One subtable per variation. See examples below
-
flame.xforms[n].variations {table - one table per variation instance}
- flame.xforms[n].variations[v].name
- flame.xforms[n].variations[v].weight
- flame.xforms[n].variations[v].instance
- flame.xforms[n].variations[v]…. variation-parameter-specific string
- flame.xforms[n].variations[v].coefs {table - special for matrix variations}
- Pre-Variation Groups
- This is the table for the Pre variation groups. It holds a list of variation group tables.
- One subtable per variation group. See examples below
-
flame.xforms[n].preVarGroups {table - one table per Pre variation group}
- Each variatin group subtable has a list of variation tables
- flame.xforms[n].preVarGroups[g][v].name
- flame.xforms[n].preVarGroups[g][v].weight
- flame.xforms[n].preVarGroups[g][v].instance
- flame.xforms[n].preVarGroups[g][v]…. variation-parameter-specific string
- flame.xforms[n].preVarGroups[g][v].coefs {table - special for matrix variations}
- Post-Variation Groups
- This is the table for the Post variation groups. It holds a list of variation group tables.
- One subtable per variation group. See examples below
-
flame.xforms[n].postVarGroups {table - one table per Post variation group}
- Each variatin group subtable has a list of variation tables
- flame.xforms[n].postVarGroups[g][v].name
- flame.xforms[n].postVarGroups[g][v].weight
- flame.xforms[n].postVarGroups[g][v].instance
- flame.xforms[n].postVarGroups[g][v]…. variation-parameter-specific string
- flame.xforms[n].postVarGroups[g][v].coefs {table - special for matrix variations}
- Final Xform parameters:
- flame.finalxform.weight
- flame.finalxform.color
- flame.finalxform.symmetry
- flame.finalxform.is_finalxform {string}
- flame.finalxform.coefs
- flame.finalxform.post
- flame.finalxform.variations
- flame.finalxform.variations.name
- flame.finalxform.variations.weight
- flame.finalxform.variations…. variation-specific string
- Color Curve parameters: (optional)
- flame.rgb_curve {table} has one subtable for each x,y curve node
- flame.rgb_curve[n].x
- flame.rgb_curve[n].y
- flame.red_curve {table} has one subtable for each x,y curve node
- flame.red_curve[n].x
- flame.red_curve[n].y
- flame.green_curve {table} has one subtable for each x,y curve node
- flame.green_curve[n].x
- flame.green_curve[n].y
- flame.blue_curve {table} has one subtable for each x,y curve node
- flame.blue_curve[n].x
- flame.blue_curve[n].y
Examples of Specifying a Variation Instance
- flame.xforms[1].variations[2] = { name=“linear”, weight=1. }
- Xform #1’s variation#2 is a linear variation with weight of 1.
- table.insert(xform.variations({ name=“modulus”, weight=0.5, modulus_x = 2., modulus_y = 3. })
- Insert a modulus variation with weight 0.5 and its x parameter of 2 and y parameter of 3.
Examples of Creating a Matrix Variation Group
Here we are creating a “matrix2d” variation instance,
randomizing the matrix,
then creating a new variation group and appending it onto the variation chain.
matrix2d = { name=“matrix2d”, weight=1., coefs=makeCoefs() }
randomPreMatrix(matrix2d)
table.insert(chain, { matrix2d })
Utility Functions for Creating Blank Fractals
- make a new blank fractal
- makeBlankFractal(xformCount) – returns table or nil if xformCount == 0
- make a Xaos table prepopulated with all from/to values = 1
- makeNormalXaos(xformCount) – returns table or nil if xformCount == 0
- make a random Color map
- makeRandomColors(colorCount) – returns color table on stack or nil on stack if colorCount == 0
- make an identity Transformation matrix – returns the table
- makeIdentityMatrix() – returns table
-
identity matrix:
[ 1 0 0 ] where [ a b c ]
[ 0 1 0 ] [ d e f ]
- make a Coefs matrix – returns the table
- makeCoefs() – returns table
-
identity matrix:
[ 1 0 0 ] where [ a b c ]
[ 0 1 0 ] [ d e f ]
- make a new blank xform
- makeBlankXform() – returns table
- Prepopulated with:
- weight = 1
- color = 0
- symmetry = 0
- opacity = 1
- var_color = 1
- No variations defined - empty variations table is included
- make a new blank final xform
- makeBlankFinalXform() – returns table
- Prepopulated with:
- weight = 1
- color = 0
- symmetry = 0
- opacity = 1
- var_color = 1
- No variations defined - empty variations table is included
Utils.lua
Most Make Fractal scripts will use include this Lua package file. This is how they include the package file.
require("Utils")
Useful Lua functions in Utils.lua
This file written by Ralf Flicker and used in his scripts and other Lua scripts has some
functions to rotate, scale and translate an xform’s Pre triangle. (The Triangle is just a way to graphically show the affect of the matrix transformation.)
- Convert Cartesian coordinates to Polar coordinates
- c2p (x,y)
- Convert Polar coordinates to Cartesian coordinates
- p2c (x,y)
- Rotate the xform Pre-matrix triangle about its own Triangle origin
-
affine_rotate (xform,phs) OR affine_Prot (xform,phs)
xform - the xform table
phs - the rotation amount in degrees units
- Rotate the xform Pre-matrix triangle about the World origin
-
affine_Orot (xform,phs)
xform - the xform table
phs - the rotation amount in degrees units
- Translate (move) the xform Pre-matrix triangle
-
affine_translate (xform,x,y)
xform - the xform table
x - the translation along the X axis
y - the translation along the Y axis
- Scale the xform Pre-matrix triangle (relative to the Triangle’s own origin)
-
affine_scale (xform,sf)
xform - the xform table
sf - the scale factor
- Rotate the xform Post-matrix triangle about its own Triangle origin
-
postAffine_rotate (xform,phs) OR postAffine_Prot (xform,phs)
xform - the xform table
phs - the rotation amount in degrees units
- Rotate the xform Post-matrix triangle about the World origin
-
postAffine_Orot (xform,phs)
xform - the xform table
phs - the rotation amount in degrees units
- Translate (move) the xform Post-matrix triangle
-
postAffine_translate (xform,x,y)
xform - the xform table
x - the translation along the X axis
y - the translation along the Y axis
- Scale the xform Post-matrix triangle (relative to the Triangle’s own origin)
-
postAffine_scale (xform,sf)
xform - the xform table
sf - the scale factor
- Pick a random variation name from the current variation set.
- random_variation()
- Randomize the Pre Matrix
-
randomPreMatrix (xform)
xform - the xform table
- Randomize the Post Matrix
-
randomPostMatrix (xform)
xform - the xform table
The 2 dimensional transformation matrix used by most flame renderers today all have 6 values in each transformation matrix. Each Xform structure in a flame fractal has two transformation matrices: coefs and post.
The Fractal Architect app refers to the Lua coefs matrix table as the Pre matrix, and the Lua post matrix table as the Post matrix.
Special Rule: Matrix variation types have a coefs matrix table too.
NOTE: A little confusion between FA/flam3 and Apophysis notation for the individual transformation matrix fields a - f.
Apophysis uses column order labeling, whereas flam3/Factal Architect uses row order labeling.
The table below shows how to convert between the notations
upper case letters ==> Apophysis
lower case letters ==> flam3 and Fractal Architect
Flam3 labels - row ordered
| a b c |
| d e f |
Apophysis labels - column ordered
| A C E |
| B D F |
Lua Matrix Cell Indexing
| m[1][1] m[2][1] m[3][1] |
| m[1][2] m[2][2] m[3][2] |
Each row here all refers to the same matrix cell value:
coefs.a = coefs[1][1] = coefs.A(coefs) = coefs:A()
coefs.b = coefs[2][1] = coefs.C(coefs) = coefs:C()
coefs.c = coefs[3][1] = coefs.E(coefs) = coefs:E()
coefs.d = coefs[1][2] = coefs.B(coefs) = coefs:B()
coefs.e = coefs[2][2] = coefs.D(coefs) = coefs:D()
coefs.f = coefs[3][2] = coefs.F(coefs) = coefs:F()
post.a = post[1][1] = post.A(post) = post:A()
post.b = post[2][1] = post.C(post) = post:C()
post.c = post[3][1] = post.E(post) = post:E()
post.d = post[1][2] = post.B(post) = post:B()
post.e = post[2][2] = post.D(post) = post:D()
post.f = post[3][2] = post.F(post) = post:F()
Apophysis-Like Getter/Setter functions
These are the Apophysis-like getter/setter functions to make it easier to port Apophysis scripts to Lua.
- get A - returns A
- coefs.A(coefs) OR coefs:A()
- set A - sets the A and also returns it
- coefs.A(coefs, A) OR coefs:A(A)
- get B - returns B
- coefs.B(coefs) OR coefs:B()
- set B - sets the B and also returns it
- coefs.B(coefs, B) OR coefs:B(B)
- get C - returns C
- coefs.C(coefs) OR coefs:C()
- set C - sets the C and also returns it
- coefs.C(coefs, C) OR coefs:C(C)
- get D - returns D
- coefs.D(coefs) OR coefs:D()
- set D - sets the D and also returns it
- coefs.D(coefs, D) OR coefs:D(D)
- get E - returns E
- coefs.E(coefs) OR coefs:E()
- set E - sets the E and also returns it
- coefs.E(coefs, E) OR coefs:E(E)
- get F - returns F
- coefs.F(coefs) OR coefs:F()
- set F - sets the F and also returns it
- coefs.F(coefs, F) OR coefs:F(F)
The variationset table holds all of the variations and their parameter info for the app’s current variation set. A variation set determines the variations available to the renderer (for a single fractal render). Fractal Architect can simultaneously render fractals that use different variation sets. However the Random Fractal Generator works uses a single Variation set for creating fractals. (Those fractals will all refer to that variation set.)
Scripts typically use the Variation Set information to learn what variations are available for the current variation set.
The Variationset Lua Table and Its Contents
- variationSet
- variationSet table (table)
- variationSet.name
- variationSet’s name (string)
- variationSet.uuid
- variationSet’s uuid (string)
- variationSet.defaultVariation
- variationSet’s default variation (string)
- variationSet.is3D
- variationSet’s is3D (bool)
- variationSet.variations
- variation subtables indexed by name (table)
- variationSet.variationlist
- list of variation names (table)
- variationSet.variationlist[n]
- nth variation’s name (string)
- variationSet[n]
- list of variation tables (table)
- variationSet[n].variation
- variation name (string)
- variationSet[n].param_count
- parameter count (integer)
- variationSet[n].param_names
- parameter name list for it (table)
- variationSet[n].param_names[n]
- parameter name (string)
- variationSet[n].parame_keys
- parameter key list for it (table)
- variationSet[n].param_keys[n]
- expanded parameter key (string)
- expanded parameter name is variationName_parameterName
- for example: “julian” has a “power” parameter, whose expanded name ====> julian_power
Builtin Variation Set Utility Functions
- variationSet.filterVariations(variationNamesList)
- returns filtered variationNamesList retaining only the variation names supported by this variation set
- bool variationSet.hasVariations(variationNamesList)
- return whether the input list of variation names is serviced by the current variation set
- bool switchToVariationSetWithUuid(uuid)
- switch variation set - supply the new variation set’s uuid – returns if it was successful
- variation set uuids will always be unique
- switchToVariationSetWithName(name)
- switch variation set - supply the new variation set’s name – returns if it was successful
- it returns the first variation set it finds that matches the name
- variation set names are not necessarily unique
- switchToFirstVariationSetWithRequiredVariations(varlist)
- returns true if a variation set supporting the varlist is found and switched to
- for example: switchToFirstVariationSetWithRequiredVariations({“julian”, “linear”})
- variationset.variationIs2D( variation_name )
- returns whether that variation is a 2D variation
Example Lua code Snippet: to find the parameter names and keys for variation “julian”
-- get the variations table for "julian" and return its name
varName = variationSet.variations.julian.variation
OR
varName = variationSet.variations["julian"].variation
-- Print the list of parameter names
for i, name in variationSet.variations.julian.param_names do
print(name)
end
-- Print the list of parameter names
for i, key in variationSet.variations.julian.param_keys do
print(key)
end
Other new functions defined by Fractal Architect
- open the Lua console if it not open already
- showLuaConsole()
- open the Preview window for fractal - defaults to “flame”
- openPreview( [table] )
- open the Quicklook window for fractal - defaults to “flame”
- quicklook( [table] )
- open the standard Variants window for fractal - defaults to “flame”
- variants( [table] )
- open the Super Variants window for fractal - defaults to “flame”
- superVariants( [table] )
- open the fractal info viewer for fractal - defaults to “flame”
- showInfo( [table] )
- open the XML viewer for fractal - defaults to “flame”
- showXml( [table] )
- Round number to nearest integer
- math.round(number) – rounds the number to the nearest integer
- see round() in standard C library
FA Library - Other Builtin Utility Functions
The FA library has several useful functions for printing out intermediate results
- FA.print(string)
- Print the string to Lua console.
- FA.print_stack()
- Print the Lua stack contents to Lua console.
- FA.print_item(item)
- Print the item’s contents to Lua console.
- FA.quality_adjust(adjust)
- Multiply the render quality by this quality multiplier
- Some fractals need higher than normal render quality. If your scripts creates fractals needing longer render times, this quality multiplier will tell the app to set the render quality higher.
-
GPU rendering tends to have higher noise at typical preview quality amounts. The multiplier here tells the app to increase the preview render by this quality multiplier.
Other Modules
Fractal Architect provides a couple of very useful factory modules:
GradientsModule.lua - Create/Change Color Gradient
Example usage in a custom Lua script:
In this example, a monochromatic color gradient is created, with a 20% probability of totally random colors being added because no weightRandom parameter is used.
The third line shows how to not have random colors added to the gradient.
local Gradients = require "GradientsModule"
Gradients.monochromaticScheme() -- 20% probability of random color
Gradients.monochromaticScheme(0.) -- 0% probability of random color
- Make color gradient using Analogous color scheme.
- It has an optional parameter, weightRandom, that determines the probability that a totally random color is added, instead of an analogous one.
-
Gradients.analogousScheme(weightRandom)
weightRandom - probability that a totally random color will be chosen. Range between 0 and 1 inclusive. Default value = 0.2 (20% probability)
- Make color gradient using Complementary color scheme
- It has an optional parameter, weightRandom, that determines the probability that a totally random color is added, instead of an analogous one.
-
Gradients.complementaryScheme(weightRandom)
weightRandom - probability that a totally random color will be chosen. Range between 0 and 1 inclusive. Default value = 0.2 (20% probability)
- Make color gradient using Grayscale color scheme
- It has an optional parameter, weightRandom, that determines the probability that a totally random color is added, instead of an analogous one.
-
Gradients.grayscaleScheme(weightRandom)
weightRandom - probability that a totally random color will be chosen. Range between 0 and 1 inclusive. Default value = 0.2 (20% probability)
- Make color gradient using Monochromatic color scheme
- It has an optional parameter, weightRandom, that determines the probability that a totally random color is added, instead of an analogous one.
-
Gradients.monochromaticScheme(weightRandom)
weightRandom - probability that a totally random color will be chosen. Range between 0 and 1 inclusive. Default value = 0.2 (20% probability)
- Make color gradient using Random color scheme
- Gradients.randomColorsScheme()
- Rotate color gradient by a random number of color stops
- Gradients.rotateGradient()
PrePostVariationsModule.lua - Modify Variations in Pre/Post Variation Groups
Example usage in a custom Lua script:
In this example, we are adding a Julian variation to the Pre Variation Group of every transform (probability of adding it to a transform here is 66.66667%).
local PrePostVariations = require "PrePostVariationsModule"
PrePostVariations.preVarPar(
{ name="julian", weight=2.*math.random(),
julian_power = math.random(1,3),
julian_dist = 0.1 + math.random() * 2.9},
0.666667) --66.6667% chance of adding Julian variation to Pre variation Group
- Randomly insert the group of variation and variation parameters into the first Pre Variation Group of each transform.
-
PrePostVariations.preVarPar(varpars, weight)
varpars - table containing a list of variation names, variation weights, and their variation parameter values (if any)
weight - probability that the varpars is inserted - should be between 0. and 1 inclusive. Default value = 0.3 (30% probability)
- A varpars table must have these fields for a variation’s attributes (see example):
- name - variation name
- weight - variation weight
- optional fully qualified variation parameters i.e. cpow_power = math.random(1, 5)
- Randomly insert the group of variation and variation parameters into the first Post Variation Group of each transform.
-
PrePostVariations.postVarPar(varpars, weight)
varpars - table containing a list of variation names, variation weights, and their variation parameter values (if any)
weight - probability that the varpars is inserted - should be between 0. and 1 inclusive. Default value = 0.3 (30% probability)
- Randomly prepend new first Pre-Variation Group to each transform
then insert the varpars (group of variation and variation parameters) into the new Pre Variation Group.
-
PrePostVariations.prependNewPreVarGroup(varpars, weight)
varpars - table containing a list of variation names, variation weights, and their variation parameter values (if any)
weight - probability that the varpars is inserted - should be between 0. and 1 inclusive. Default value = 0.3 (30% probability)
- Randomly append new first Pre-Variation Group to each transform
then insert the varpars (group of variation and variation parameters) into the new Pre Variation Group.
-
PrePostVariations.appendNewPreVarGroup(varpars, weight)
varpars - table containing a list of variation names, variation weights, and their variation parameter values (if any)
weight - probability that the varpars is inserted - should be between 0. and 1 inclusive. Default value = 0.3 (30% probability)
- Randomly append new first Pre-Variation Group to each transform - but only if the pre var group list is not empty
then insert the varpars (group of variation and variation parameters) into the new Pre Variation Group.
-
PrePostVariations.appendAnotherNewPreVarGroup(varpars, weight)
varpars - table containing a list of variation names, variation weights, and their variation parameter values (if any)
weight - probability that the varpars is inserted - should be between 0. and 1 inclusive. Default value = 0.3 (30% probability)
- Randomly prepend new first Post-Variation Group to each transform
then insert the varpars (group of variation and variation parameters) into the new Post Variation Group.
-
PostPostVariations.postpendNewPostVarGroup(varpars, weight)
varpars - table containing a list of variation names, variation weights, and their variation parameter values (if any)
weight - probability that the varpars is inserted - should be between 0. and 1 inclusive. Default value = 0.3 (30% probability)
- Randomly append new first Post-Variation Group to each transform
then insert the varpars (group of variation and variation parameters) into the new Post Variation Group.
-
PostPostVariations.appendNewPostVarGroup(varpars, weight)
varpars - table containing a list of variation names, variation weights, and their variation parameter values (if any)
weight - probability that the varpars is inserted - should be between 0. and 1 inclusive. Default value = 0.3 (30% probability)
- Randomly append new first Post-Variation Group to each transform - but only if the post var group list is not empty
then insert the varpars (group of variation and variation parameters) into the new Post Variation Group.
-
PostPostVariations.appendAnotherNewPostVarGroup(varpars, weight)
varpars - table containing a list of variation names, variation weights, and their variation parameter values (if any)
weight - probability that the varpars is inserted - should be between 0. and 1 inclusive. Default value = 0.3 (30% probability)