Thursday, April 29, 2010
Thursday, April 15, 2010
*.flam4 Overview
A simple *flam4 file looks like the following:
The base node is <flam4>. This identifies that the file is in fact in the *.flam4 format, but more importantly, allows the file to (eventually) contain multiple flames, since XML only allows for a single base node. Ultimately, it will contain some other data. In particular, there will be a version attribute introduced once the format reaches a point where I can consider maintaining backwards compatibility, allowing the format to evolve over time.
Inside the <flam4> node is the <flame> node. Currently, you can only have a single <flame> in the file, but in the future it will be more representative of a single frame, such as a keyframe in an animation. The flame node contains all the necessary data to render a single frame. It contains the following:
The <viewport> node defines the view area. Unlike flam3, <viewport> is completely resolution independent, meaning that you don't have to edit the file to render a preview frame, for instance. Eventually, the viewport will define a minimal coverage area for the fractal, so flam4 will grow the viewport to accommodate the entire specified area, plus some extra at the top and bottom or at the left and right to force a square aspect ratio for whatever resolution the image is to be. The minimal coverage area is defined simply by the <coefs> needed to map the canonical viewport to the desired image region. Hopefully, this will simplify some tricky operations in flam3, such as dividing the image into strips for rendering very high resolution images.
The <gamut> node contains information specifying how the raw accumulation buffer is tone mapped to produce the final image. Right now, this only includes brightness, gamma, and vibrancy, defined very similarly to flam3. Eventually, this will be expanded to include things like density estimation and advanced (custom) post processing algorithms.
The <code> node contains all necessary code for custom variations (and eventually other things) used by the flame. Note that you can use an <include> node to import custom code from another file, which allows for a library of standard variations to be included with flam4.
The <palette> node contains the palette. It has a format attribute that can be set to rgb_unorm, where the standard display range is mapped from 0.0-1.0, rgb_255norm, which maps the standard display range to 0-255, rgb8_hex, in which it is encoded as a hexadecimal string, three bytes or six digits to a color, and the more exotic rgb32_unorm_hex and rgb32_255norm_hex, where a hexadecimal string representing the palette expressed in 32 bit floating point is used. In all cases (except rgb_hex, which is limited to 0-255 by definition), out of gamut values are perfectly legal, which includes strange things like negative numbers. Thus, the palette is defined in true HDR.
The last two types of nodes form the core of any flame fractal, the <xform_node> and the <xform>. These each come in two flavors, the literal definition, and the reference. This allows us to reuse xforms, and more importantly, to link xform nodes together.
The <xform> nodes are the simplest. Each <xform> contains a color_index and a color_speed attribute, which control the xform's usage of the palette. They also contain a <coefs> node, as well as one or more <var> nodes. Each <xform_node> is allowed to have a single <xform> node, which describes the xform attached to that node in the chaos game. Literal <xform>s can also be defined outside of any <xform_node>, where they can be only used by an appropriate reference.
<xform_node>s are used to describe the behavior of the chaos game in creating the fractal. Each literal <xform_node> can (optionally at some point, but required right now) contain a single <xform>, and must contain at least one other <xform_node>, with an attached weight, opacity, and state, from which the <xform_node> for the next iteration will be selected. These children <xform_node>s can either be empty references to literal <xform_node>s described elsewhere, or can be full literal nodes themselves.
Of the three attributes of any <xform_node> child, which we call a node link, weight and opacity are obvious in usage. Weight determines the chance that node will be selected from among its siblings when iterating out of a given node, while opacity describes the opacity of the linked node. State is more complex.
As a point it iterated through the flowchart of xform nodes, it maintains a stack, containing it's "history" at key locations. Using this stack, an xform link can either save a state, or else revert to a previous point. In the simplest case, this is used for final xforms, where a point is saved after going through a normal xform, then passed through the final xform, after which it is ploted. As the control flow goes through the links out of the final xform, the state dictates that it restore the last point on the stack, which produces the behavier of a final xform, which is applied at each iteration to the plotted point, but not fed back into the chaos game.
The actual values for state are hold, push, and pop. Hold tells the node link to do nothing to the state stack. Push tells it to push the current point onto the stack and continue, while pop tells it to revert to the topmost point on the stack. You can also do more advanced operations like pop 2, which tells it to use the point beneath the topmost point on the stack, sorta like hitting undo twice. You can also do things like pop -1, which is analogous to redo, and push -1, which basically just moves the current index down the stack without replacing the current point.
Applying this, one always enters a final xform with standard opacity and state push, and leaves it with opacity 0 and state pop. One can also render multiple independent fractals by defining each fractal with its own node network, and then randomly going back and forth with a pop operation, pop 1 one direction and pop -1 the other, which basically forces the active point to be drawn from the current fractal's pool.
The base node is <flam4>. This identifies that the file is in fact in the *.flam4 format, but more importantly, allows the file to (eventually) contain multiple flames, since XML only allows for a single base node. Ultimately, it will contain some other data. In particular, there will be a version attribute introduced once the format reaches a point where I can consider maintaining backwards compatibility, allowing the format to evolve over time.
Inside the <flam4> node is the <flame> node. Currently, you can only have a single <flame> in the file, but in the future it will be more representative of a single frame, such as a keyframe in an animation. The flame node contains all the necessary data to render a single frame. It contains the following:
The <viewport> node defines the view area. Unlike flam3, <viewport> is completely resolution independent, meaning that you don't have to edit the file to render a preview frame, for instance. Eventually, the viewport will define a minimal coverage area for the fractal, so flam4 will grow the viewport to accommodate the entire specified area, plus some extra at the top and bottom or at the left and right to force a square aspect ratio for whatever resolution the image is to be. The minimal coverage area is defined simply by the <coefs> needed to map the canonical viewport to the desired image region. Hopefully, this will simplify some tricky operations in flam3, such as dividing the image into strips for rendering very high resolution images.
The <gamut> node contains information specifying how the raw accumulation buffer is tone mapped to produce the final image. Right now, this only includes brightness, gamma, and vibrancy, defined very similarly to flam3. Eventually, this will be expanded to include things like density estimation and advanced (custom) post processing algorithms.
The <code> node contains all necessary code for custom variations (and eventually other things) used by the flame. Note that you can use an <include> node to import custom code from another file, which allows for a library of standard variations to be included with flam4.
The <palette> node contains the palette. It has a format attribute that can be set to rgb_unorm, where the standard display range is mapped from 0.0-1.0, rgb_255norm, which maps the standard display range to 0-255, rgb8_hex, in which it is encoded as a hexadecimal string, three bytes or six digits to a color, and the more exotic rgb32_unorm_hex and rgb32_255norm_hex, where a hexadecimal string representing the palette expressed in 32 bit floating point is used. In all cases (except rgb_hex, which is limited to 0-255 by definition), out of gamut values are perfectly legal, which includes strange things like negative numbers. Thus, the palette is defined in true HDR.
The last two types of nodes form the core of any flame fractal, the <xform_node> and the <xform>. These each come in two flavors, the literal definition, and the reference. This allows us to reuse xforms, and more importantly, to link xform nodes together.
The <xform> nodes are the simplest. Each <xform> contains a color_index and a color_speed attribute, which control the xform's usage of the palette. They also contain a <coefs> node, as well as one or more <var> nodes. Each <xform_node> is allowed to have a single <xform> node, which describes the xform attached to that node in the chaos game. Literal <xform>s can also be defined outside of any <xform_node>, where they can be only used by an appropriate reference.
<xform_node>s are used to describe the behavior of the chaos game in creating the fractal. Each literal <xform_node> can (optionally at some point, but required right now) contain a single <xform>, and must contain at least one other <xform_node>, with an attached weight, opacity, and state, from which the <xform_node> for the next iteration will be selected. These children <xform_node>s can either be empty references to literal <xform_node>s described elsewhere, or can be full literal nodes themselves.
Of the three attributes of any <xform_node> child, which we call a node link, weight and opacity are obvious in usage. Weight determines the chance that node will be selected from among its siblings when iterating out of a given node, while opacity describes the opacity of the linked node. State is more complex.
As a point it iterated through the flowchart of xform nodes, it maintains a stack, containing it's "history" at key locations. Using this stack, an xform link can either save a state, or else revert to a previous point. In the simplest case, this is used for final xforms, where a point is saved after going through a normal xform, then passed through the final xform, after which it is ploted. As the control flow goes through the links out of the final xform, the state dictates that it restore the last point on the stack, which produces the behavier of a final xform, which is applied at each iteration to the plotted point, but not fed back into the chaos game.
The actual values for state are hold, push, and pop. Hold tells the node link to do nothing to the state stack. Push tells it to push the current point onto the stack and continue, while pop tells it to revert to the topmost point on the stack. You can also do more advanced operations like pop 2, which tells it to use the point beneath the topmost point on the stack, sorta like hitting undo twice. You can also do things like pop -1, which is analogous to redo, and push -1, which basically just moves the current index down the stack without replacing the current point.
Applying this, one always enters a final xform with standard opacity and state push, and leaves it with opacity 0 and state pop. One can also render multiple independent fractals by defining each fractal with its own node network, and then randomly going back and forth with a pop operation, pop 1 one direction and pop -1 the other, which basically forces the active point to be drawn from the current fractal's pool.
Sunday, April 11, 2010
Welcome to the Flam4 Development Blog!
Welcome to the Flam4 Development Blog! Here we will discuss the trials and tribulations of the ongoing development of the flam4 flame fractal renderer. We shall also cover the various aspects of usage, in particular the *.flam4 format and how to make the most of it's features. Come join us as we explore the frontier of flame fractal rendering!
Understanding the *.flam4 format: Part 1: Introduction
When I first envisioned creating a new *.flam4 format to describe the parameters of a particular flame or set of flames, I was pondering how to go about adding support for custom variations in the flame code, so that the user could enter their own fractal equations instead of relying on an increasingly long (and thus hard to maintain) list of predefined variations. Apophysis had already taken this path, but the problem here was that adding a new variation required writing a plugin, which is basically a .dll containing the function call wrapping the little piece of code that the user wanted to try out. The downsides of this approach are obvious. First, the amount of work involved in writing and compiling a plugin was absurd given the scope of a variation, which may be a simple as taking a point (x,y) and returning (sin(x),sin(y)). A second, more nefarious problem was that in order for any one else to render a flame that uses a given nonstandard variation, the user must first track down and obtain the plugin for that variation, which, owing to the nature of the internet, may indeed be lost, perhaps forever.
Another goal was to replace the chaos tag with something more sensable, but hopefully more powerful. As it proved, doing this allowed boiling down several special cases in flam3 to use a single general case in flam4, namely post transformations, final xforms, symmetry kind, and pre/post variations, as well as expanding above and beyond.
Finally, I wanted to provide a cleaner format than the flam3 format, which, to put it bluntly, is a textbook example of how not to use XML.
Other topics also came up, even if they haven't (yet!) all been implemented into the *.flam4 format. These include more control over animations, post processing procedures, and true 3D support.
With this in mind, the next series of posts will detail the anatomy of the *.flam4 format, and how you can (ab)use it to generate images not otherwise possible.
Another goal was to replace the chaos tag with something more sensable, but hopefully more powerful. As it proved, doing this allowed boiling down several special cases in flam3 to use a single general case in flam4, namely post transformations, final xforms, symmetry kind, and pre/post variations, as well as expanding above and beyond.
Finally, I wanted to provide a cleaner format than the flam3 format, which, to put it bluntly, is a textbook example of how not to use XML.
Other topics also came up, even if they haven't (yet!) all been implemented into the *.flam4 format. These include more control over animations, post processing procedures, and true 3D support.
With this in mind, the next series of posts will detail the anatomy of the *.flam4 format, and how you can (ab)use it to generate images not otherwise possible.
Subscribe to:
Posts (Atom)