/* SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include #include "BLI_float3x3.hh" #include "BLI_math_vec_types.hh" namespace blender::realtime_compositor { /* Possible interpolations to use when realizing an input result of some domain on another domain. * See the RealizationOptions struct for more information. */ enum class Interpolation : uint8_t { Nearest, Bilinear, Bicubic, }; /* ------------------------------------------------------------------------------------------------ * Realization Options * * The options that describe how an input result prefer to be realized on some other domain. This * is used by the Realize On Domain Operation to identify the appropriate method of realization. * See the Domain class for more information. */ struct RealizationOptions { /* The interpolation method that should be used when performing realization. Since realizing a * result involves projecting it on a different domain, which in turn, involves sampling the * result at arbitrary locations, the interpolation identifies the method used for computing the * value at those arbitrary locations. */ Interpolation interpolation = Interpolation::Bilinear; /* If true, the result will be repeated infinitely along the horizontal axis when realizing the * result. If false, regions outside of bounds of the result along the horizontal axis will be * filled with zeros. */ bool repeat_x = false; /* If true, the result will be repeated infinitely along the vertical axis when realizing the * result. If false, regions outside of bounds of the result along the vertical axis will be * filled with zeros. */ bool repeat_y = false; }; /* ------------------------------------------------------------------------------------------------ * Domain * * The compositor is designed in such a way as to allow compositing in an infinite virtual * compositing space. Consequently, any result of an operation is not only represented by its image * output, but also by its transformation in that virtual space. The transformation of the result * together with the dimension of its image is stored and represented by a Domain. In the figure * below, two results of different domains are illustrated on the virtual compositing space. One of * the results is centered in space with an image dimension of 800px × 600px, and the other result * is scaled down and translated such that it lies in the upper right quadrant of the space with an * image dimension of 800px × 400px. The position of the domain is in pixel space, and the domain * is considered centered if it has an identity transformation. Note that both results have the * same resolution, but occupy different areas of the virtual compositing space. * * y * ^ * 800px x 600px | * .---------------------|---------------------. * | | 800px x 600px | * | | .-------------. | * | | | | | * | | '-------------' | * ------|---------------------|---------------------|------> x * | | | * | | | * | | | * | | | * '---------------------|---------------------' * | * * By default, results have domains of identity transformations, that is, they are centered in * space, but a transformation operation like the rotate, translate, or transform operations will * adjust the transformation to make the result reside somewhere different in space. The domain of * a single value result is irrelevant and always set to an identity domain. * * An operation is typically only concerned about a subset of the virtual compositing space, this * subset is represented by a domain which is called the Operation Domain. It follows that before * the operation itself is executed, inputs will typically be realized on the operation domain to * be in the same domain and have the same dimension as that of the operation domain. This process * is called Domain Realization and is implemented using an operation called the Realize On Domain * Operation. Realization involves projecting the result onto the target domain, copying the area * of the result that intersects the target domain, and filling the rest with zeros or repetitions * of the result depending on the realization options that can be set by the user. Consequently, * operations can generally expect their inputs to have the same dimension and can operate on them * directly and transparently. For instance, if an operation takes both results illustrated in * the figure above, and the operation has an operation domain that matches the bigger domain, the * result with the bigger domain will not need to be realized because it already has a domain that * matches that of the operation domain, but the result with the smaller domain will have to be * realized into a new result that has the same domain as the domain of the bigger result. Assuming * no repetition, the output of the realization will be an all zeros image with dimension 800px × * 600px with a small scaled version of the smaller result copied into the upper right quadrant of * the image. The following figure illustrates the realization process on a different set of * results * * Realized Result * +-------------+ +-------------+ * | Operation | | | * | Domain | | Zeros | * | | ----> | | * +-----|-----+ | |-----+ | * | | C | | | C | | * | +-----|-------+ +-----'-------+ * | Domain Of | * | Input | * +-----------+ * * An operation can operate in an arbitrary operation domain, but in most cases, the operation * domain is inferred from the inputs of the operation. In particular, one of the inputs is said to * be the Domain Input of the operation and the operation domain is inferred from its domain. It * follows that this particular input will not need realization, because it already has the correct * domain. The domain input selection mechanism is as follows. Each of the inputs are assigned a * value by the developer called the Domain Priority, the domain input is then chosen as the * non-single value input with the highest domain priority, zero being the highest priority. See * Operation::compute_domain for more information. * * The aforementioned logic for operation domain computation is only a default that works for most * cases, but an operation can override the compute_domain method to implement a different logic. * For instance, output nodes have an operation domain the same size as the viewport and with an * identity transformation, their operation domain doesn't depend on the inputs at all. * * For instance, a filter operation has two inputs, a factor and a color, the latter of which is * assigned a domain priority of 0 and the former is assigned a domain priority of 1. If the color * input is not a single value input, then the color input is considered to be the domain input of * the operation and the operation domain is computed to be the same domain as the color input, * because it has the highest priority. It follows that if the factor input has a different domain * than the computed domain of the operation, it will be projected and realized on it to have the * same domain as described above. On the other hand, if the color input is a single value input, * then the factor input is considered to be the domain input and the operation domain will be the * same as the domain of the factor input, because it has the second highest domain priority. * Finally, if both inputs are single value inputs, the operation domain will be an identity domain * and is irrelevant, because the output will be a domain-less single value. */ class Domain { public: /* The size of the domain in pixels. */ int2 size; /* The 2D transformation of the domain defining its translation in pixels, rotation, and scale in * the virtual compositing space. */ float3x3 transformation; /* The options that describe how this domain prefer to be realized on some other domain. See the * RealizationOptions struct for more information. */ RealizationOptions realization_options; public: /* A size only constructor that sets the transformation to identity. */ Domain(int2 size); Domain(int2 size, float3x3 transformation); /* Transform the domain by the given transformation. This effectively pre-multiply the given * transformation by the current transformation of the domain. */ void transform(const float3x3 &input_transformation); /* Returns a domain of size 1x1 and an identity transformation. */ static Domain identity(); }; /* Compare the size and transformation of the domain. The realization_options are not compared * because they only describe the method of realization on another domain, which is not technically * a property of the domain itself. */ bool operator==(const Domain &a, const Domain &b); /* Inverse of the above equality operator. */ bool operator!=(const Domain &a, const Domain &b); } // namespace blender::realtime_compositor