blob: 33cb5fb0f7363213bf52d6640960136f9c1d465d [file]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef RSE_SDF_GLSL_
#define RSE_SDF_GLSL_
#include "sdf_functions.glsl"
#include "sdf_utils.glsl"
bool useCircularDistance(vec2 p, float radius, float span) {
// Grab the angle offset of the point.
float theta = atan(p.y, p.x);
// The angular distance between the point and the 45 degree midline.
float d_theta = theta - PI_OVER_FOUR;
d_theta = mod(d_theta + PI, TWO_PI) - PI;
// If the point is within the span of the corner circle's arc,
// use a circle SDF.
// This works because the normals of the circular and superelliptical sections
// agree at the transition angle, the total RSE curve is continuous and
// the closest point on a continuous curve to a point lies along the normal.
if (abs(d_theta) < abs(span)) {
return true;
}
return false;
}
float distanceFromRSEOctant(vec2 p_oct,
vec2 circle_center,
float radius,
float span,
float axis_length,
float se_degree) {
// Move the point to the corner circle's coordinate system.
vec2 p_rel = p_oct - circle_center;
if (useCircularDistance(p_rel, radius, span)) {
return length(p_rel) - radius;
}
return sdSuperellipse(p_oct / axis_length, se_degree) * axis_length;
}
vec3 distanceFromRSEOctantWithGrad(vec2 p_oct,
vec2 circle_center,
float radius,
float span,
float axis_length,
float se_degree) {
// Move the point to the corner circle's coordinate system.
vec2 p_rel = p_oct - circle_center;
// Gradient of the sdf.
vec2 grad_oct;
if (useCircularDistance(p_rel, radius, span)) {
grad_oct = normalize(p_rel);
float dist = length(p_rel) - radius;
return vec3(dist, grad_oct);
}
// Clamp the coordinate to avoid division by zero
vec2 p_oct_clamped = max(p_oct, vec2(0.001));
float max_p = max(p_oct_clamped.x, p_oct_clamped.y);
vec2 p_safe = p_oct_clamped / max_p;
// Approximation of the gradient
grad_oct = normalize(pow(p_safe, vec2(se_degree - 1.0)));
float dist = sdSuperellipse(p_oct / axis_length, se_degree) * axis_length;
return vec3(dist, grad_oct);
}
#endif // RSE_SDF_GLSL_