Radial¶
The RadialKernel generates a radial shape around a specified center with customizable transitions, defined by parameters such as size, center position, and edge smoothness.
Note
The RadialKernel functions as a generator and does not utilize an input image. When used within the timeline, a dummy input must be provided since every soft effect requires an input. However, in the node graph, the kernel can be modified to operate without needing an external input.
kernel Radial : ImageComputationKernel<ePixelWise> {
// Input and output images
Image<eRead, eAccessRandom, eEdgeClamped> src; // randomly accessing and edge clamping
Image<eWrite, eAccessPoint> dst;
// Parameters are made available to the user as knobs.
param:
float rotation; // rotation in degrees
float width; // width
float height; // height
float2 centre; // centre
float smoothStep; // step
// Local variables can be initialized once in init() and used from all pixel positions.
local:
float angle;
float2 scaleFactors;
float2 scaledCentre;
float size;
float scaledStep;
// Size and Centre are affected by the proxy scaling.
void define() {
defineParam(rotation, "Rotation", 180.0f);
defineParam(width, "Width", 240.0f, eParamProxyScale);
defineParam(height, "Height", 120.0f, eParamProxyScale);
defineParam(centre, "Centre", float2(120.0f, 120.0f), eParamProxyScale);
defineParam(smoothStep, "Step", 80.0f, eParamProxyScale);
}
float smoothstep(float edge0, float edge1, float x)
{
float denom = edge1 - edge0;
// Replace max(denom, eps) with a ternary operator
float eps = float(1e-6f);
denom = max(denom,eps);
// Ensure denominator is not zero to avoid division by zero
float t = clamp((x - edge0) / denom, 0.0f, 1.0f);
return t * t * (3.0f - 2.0f * t);
}
// The init() function is run once before any calls to process().
void init() {
const float imgW = dst.bounds.x2 - dst.bounds.x1;
const float imgH = dst.bounds.y2 - dst.bounds.y1;
float minImgWH = min(imgW, imgH);
size = max(1.0f, minImgWH);
width = max(width, 1.0f);
height = max(height, 1.0f);
scaleFactors = float2(width / size, height / size);
scaledCentre = float2(centre.x / size, centre.y / size);
// Replace smoothStep / size with direct division (assuming size >= 1.0f from above)
scaledStep = smoothStep / size;
const float toRadians = PI / 180.0f;
angle = rotation * toRadians;
}
// The process() function runs over all pixel positions of the output image.
// The int2 pos parameter is used to indicate positions x, y.
void process(int2 pos) {
// Calculate the distance from the centre.
const float x = float(pos.x) / size - scaledCentre.x;
const float y = float(pos.y) / size - scaledCentre.y;
const float sine = sin(angle);
const float cosine = cos(angle);
const float x2 = x * cosine + y * sine;
const float y2 = y * cosine - x * sine;
const float2 st = float2(x2, y2);
const float2 e = float2(st.x / scaleFactors.x, st.y / scaleFactors.y);
const float d = sqrt(e.x * e.x + e.y * e.y);
// Calculate color with smooth step transition
const float color = smoothstep(d, d + scaledStep, 1.0f);
const float4 result = float4(color, color, color, 1.0f);
for(int i = 0; i < dst.kComps ; i++){
dst(i) = result[i];
}
}
};