Skip to main content
Skip table of contents

Custom spot merge post-processing

An Apex custom post process step that merges spot components into an existing process result.

A CCustomSpotMergePostProcessSpec represents a custom post process step that merges spot components into an existing process result. It is a custom version of CSpotMergePostProcess that allows a
custom fragment shader to perform this work in order to implement special behavior, such as dealing with complex color interactions.

This step provides a list of the colorant names that it will merge, and a series of shader parameters that are invoked to merge them.

  • Currently, Apex will invoke this step with spot components provided four at a time.

  • Therefore, each step must provide a CShaderParams for each invocation that this represents. For example, if nine merge colorants are specified, then three CShaderParams must be provided. The first for the first four spots, the second for the next four spots, and the third for the last remaining spot. The same shader can be used for all three as appropriate.

The shader is ultimately invoked over the entire image. However, Apex may break rendering into multiple tiles, in which case the draw operation may occur multiple times.

The first input to the shader is the current value of the process components.

If the current color space at the point where this post process is inserted is a gray color space, then the process components will be a single single-channel UNORM image.

  • If RGB, then the input will be a single four-channel UNORM image with the A component ignored.

  • If CMYK, the input will be a single four-channel UNORM image, where R represents Cyan, G represents Magenta, B represents Yellow, and the A channel represents Black.

  • If extended-gamut, then there will be two four-channel UNORM input images, where the first image represents the CMYK components, and the second image represents the extra extended components, with the first such
    component in the R channel.

Following the input process image(s), a single four-component UNORM image will be provided containing the spot tints to be merged for that invocation, with R being the first spot, G being the second, and so forth.

The output image(s) are as per the input, with the same format.

ℹ️ Please note that all the input and output images are in additive form. That is, the components are stored with 0.0 being 100% ink and 1.0 being 0% ink. This mirrors the PDF transparency compositing methods. So take care when interpreting these colors in the shader.

Push constants may be provided to the shader. However, in addition to any supplied push constants, Apex will push an additional two integer values after these push constants representing the top-left offset of the tile being rendered. This, in conjunction with the GLSL gl\_FragCoord variable, allows the shader to discover the current coordinate on the final page render, should this be needed.

The size of the push constant buffer is limited, and may differ from GPU to GPU. Vulkan guarantees a minimum of 128 bytes, but remember that Apex will push eight
additional bytes for tile coordinates, and therefore the minimum guarantee is 120 bytes. In practice, most GPUs will allow significantly more.
Please see: https://vulkan.gpuinfo.org/displaydevicelimit.php?name=maxPushConstantsSize for supported sizes for current GPUs.

The shader and textures may be created by IApexRenderer::createFragmentShader() and IApexRenderer::uploadImage().

Any textures are provided to the shader after the input images.

For example, consider a custom step where:

  • the current color space is extended gamut (e.g. CMYKOG)

  • two textures are provided

  • a single floating point value for a push constant is provided

The shader would have a structure such as the following:

Click here to see the shader code
C
# version 450
// Input images
layout (input\_attachment\_index = 0, binding = 0) uniform subpassInput cmykInput;
layout (input\_attachment\_index = 1, binding = 1) uniform subpassInput ogInput;
layout (input\_attachment\_index = 2, binding = 2) uniform subpassInput spotInput;
// Textures
layout(binding = 3) uniform sampler2D texture1;
layout(binding = 4) uniform sampler2D texture2;
// Outputs
layout (location = 0) out vec4 resultCmyk;
layout (location = 0) out vec4 resultOg;
// Push constants
layout (push\_constant) uniform PushConstants
{
    float floatVal;
    int   tileX;
    int   tileY;
} pushConstants;
void main()
{
    // Read the current process components
    vec4 cmyk = subpassLoad(cmykInput);
    vec2 og = subpassLoad(og).rg;
    // Read the spot tints
    vec4 spotValues = subpassLoad(spotInput);

    // Do work as appropriate to merge the spots into the process, and store the
    // results in resultCmyk and resultOg
}

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.