Rename tess's pow2 and pow4 suffixes to p2 and p4
Consolidates some other constants, removes the pow2 and pow4 functions that just computed `x*x` or `x*x*x*x`. Moves the `mix` function into PatchWriter since that's the only place it's used. Change-Id: Idaaba40f1007e1f0331ec8d335e6afbe69ddfbad Reviewed-on: https://skia-review.googlesource.com/c/skia/+/540920 Reviewed-by: Jim Van Verth <jvanverth@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
This commit is contained in:
parent
13980102a5
commit
d325dbd05f
@ -141,7 +141,7 @@ AtlasPathRenderer::AtlasPathRenderer(GrDirectContext* dContext) {
|
||||
bool AtlasPathRenderer::pathFitsInAtlas(const SkRect& pathDevBounds,
|
||||
GrAAType fallbackAAType) const {
|
||||
SkASSERT(fallbackAAType != GrAAType::kNone); // The atlas doesn't support non-AA.
|
||||
float atlasMaxPathHeight_pow2 = (fallbackAAType == GrAAType::kMSAA)
|
||||
float atlasMaxPathHeight_p2 = (fallbackAAType == GrAAType::kMSAA)
|
||||
? kAtlasMaxPathHeightWithMSAAFallback * kAtlasMaxPathHeightWithMSAAFallback
|
||||
: kAtlasMaxPathHeight * kAtlasMaxPathHeight;
|
||||
auto [topLeftFloor, botRightCeil] = round_out(pathDevBounds);
|
||||
@ -151,7 +151,7 @@ bool AtlasPathRenderer::pathFitsInAtlas(const SkRect& pathDevBounds,
|
||||
// Since we will transpose tall skinny paths, limiting to atlasMaxPathHeight^2 pixels
|
||||
// guarantees heightInAtlas <= atlasMaxPathHeight, while also allowing paths that are
|
||||
// very wide and short.
|
||||
size[0] * size[1] <= atlasMaxPathHeight_pow2;
|
||||
size[0] * size[1] <= atlasMaxPathHeight_p2;
|
||||
}
|
||||
|
||||
void AtlasPathRenderer::AtlasPathKey::set(const SkMatrix& m, const SkPath& path) {
|
||||
|
@ -131,10 +131,10 @@ bool TessellationPathRenderer::onDrawPath(const DrawPathArgs& args) {
|
||||
args.fShape->asPath(&path);
|
||||
|
||||
const SkRect pathDevBounds = args.fViewMatrix->mapRect(args.fShape->bounds());
|
||||
float n4 = wangs_formula::worst_case_cubic_pow4(tess::kPrecision,
|
||||
pathDevBounds.width(),
|
||||
pathDevBounds.height());
|
||||
if (n4 > pow4(tess::kMaxSegmentsPerCurve)) {
|
||||
float n4 = wangs_formula::worst_case_cubic_p4(tess::kPrecision,
|
||||
pathDevBounds.width(),
|
||||
pathDevBounds.height());
|
||||
if (n4 > tess::kMaxSegmentsPerCurve_p4) {
|
||||
// The path is extremely large. Pre-chop its curves to keep the number of tessellation
|
||||
// segments tractable. This will also flatten curves that fall completely outside the
|
||||
// viewport.
|
||||
@ -223,10 +223,10 @@ void TessellationPathRenderer::onStencilPath(const StencilPathArgs& args) {
|
||||
SkPath path;
|
||||
args.fShape->asPath(&path);
|
||||
|
||||
float n4 = wangs_formula::worst_case_cubic_pow4(tess::kPrecision,
|
||||
pathDevBounds.width(),
|
||||
pathDevBounds.height());
|
||||
if (n4 > pow4(tess::kMaxSegmentsPerCurve)) {
|
||||
float n4 = wangs_formula::worst_case_cubic_p4(tess::kPrecision,
|
||||
pathDevBounds.width(),
|
||||
pathDevBounds.height());
|
||||
if (n4 > tess::kMaxSegmentsPerCurve_p4) {
|
||||
SkRect viewport = SkRect::Make(*args.fClipConservativeBounds);
|
||||
path = PreChopPathCurves(tess::kPrecision, path, *args.fViewMatrix, viewport);
|
||||
}
|
||||
|
@ -26,27 +26,27 @@ const GrPipeline* GrTessellationShader::MakePipeline(const ProgramArgs& args,
|
||||
|
||||
const char* GrTessellationShader::WangsFormulaSkSL() {
|
||||
static_assert(skgpu::wangs_formula::length_term<3>(1) == 0.75);
|
||||
static_assert(skgpu::wangs_formula::length_term_pow2<3>(1) == 0.5625);
|
||||
static_assert(skgpu::wangs_formula::length_term_p2<3>(1) == 0.5625);
|
||||
|
||||
return R"(
|
||||
// Returns the length squared of the largest forward difference from Wang's cubic formula.
|
||||
float wangs_formula_max_fdiff_pow2(float2 p0, float2 p1, float2 p2, float2 p3,
|
||||
float2x2 matrix) {
|
||||
float wangs_formula_max_fdiff_p2(float2 p0, float2 p1, float2 p2, float2 p3,
|
||||
float2x2 matrix) {
|
||||
float2 d0 = matrix * (fma(float2(-2), p1, p2) + p0);
|
||||
float2 d1 = matrix * (fma(float2(-2), p2, p3) + p1);
|
||||
return max(dot(d0,d0), dot(d1,d1));
|
||||
}
|
||||
float wangs_formula_cubic(float _precision_, float2 p0, float2 p1, float2 p2, float2 p3,
|
||||
float2x2 matrix) {
|
||||
float m = wangs_formula_max_fdiff_pow2(p0, p1, p2, p3, matrix);
|
||||
float m = wangs_formula_max_fdiff_p2(p0, p1, p2, p3, matrix);
|
||||
return max(ceil(sqrt(0.75 * _precision_ * sqrt(m))), 1.0);
|
||||
}
|
||||
float wangs_formula_cubic_log2(float _precision_, float2 p0, float2 p1, float2 p2, float2 p3,
|
||||
float2x2 matrix) {
|
||||
float m = wangs_formula_max_fdiff_pow2(p0, p1, p2, p3, matrix);
|
||||
float m = wangs_formula_max_fdiff_p2(p0, p1, p2, p3, matrix);
|
||||
return ceil(log2(max(0.5625 * _precision_ * _precision_ * m, 1.0)) * .25);
|
||||
}
|
||||
float wangs_formula_conic_pow2(float _precision_, float2 p0, float2 p1, float2 p2, float w) {
|
||||
float wangs_formula_conic_p2(float _precision_, float2 p0, float2 p1, float2 p2, float w) {
|
||||
// Translate the bounding box center to the origin.
|
||||
float2 C = (min(min(p0, p1), p2) + max(max(p0, p1), p2)) * 0.5;
|
||||
p0 -= C;
|
||||
@ -69,11 +69,11 @@ float wangs_formula_conic_pow2(float _precision_, float2 p0, float2 p1, float2 p
|
||||
return numer/denom;
|
||||
}
|
||||
float wangs_formula_conic(float _precision_, float2 p0, float2 p1, float2 p2, float w) {
|
||||
float n2 = wangs_formula_conic_pow2(_precision_, p0, p1, p2, w);
|
||||
float n2 = wangs_formula_conic_p2(_precision_, p0, p1, p2, w);
|
||||
return max(ceil(sqrt(n2)), 1.0);
|
||||
}
|
||||
float wangs_formula_conic_log2(float _precision_, float2 p0, float2 p1, float2 p2, float w) {
|
||||
float n2 = wangs_formula_conic_pow2(_precision_, p0, p1, p2, w);
|
||||
float n2 = wangs_formula_conic_p2(_precision_, p0, p1, p2, w);
|
||||
return ceil(log2(max(n2, 1.0)) * .5);
|
||||
})";
|
||||
}
|
||||
|
@ -33,14 +33,14 @@ namespace skgpu::tess {
|
||||
*/
|
||||
class LinearTolerances {
|
||||
public:
|
||||
float numParametricSegments_pow4() const { return fNumParametricSegments_pow4; }
|
||||
float numParametricSegments_p4() const { return fNumParametricSegments_p4; }
|
||||
float numRadialSegmentsPerRadian() const { return fNumRadialSegmentsPerRadian; }
|
||||
int numEdgesInJoins() const { return fEdgesInJoins; }
|
||||
|
||||
// Fast log2 of minimum required # of segments per tracked Wang's formula calculations.
|
||||
int requiredResolveLevel() const {
|
||||
// log16(n^4) == log2(n)
|
||||
return wangs_formula::nextlog16(fNumParametricSegments_pow4);
|
||||
return wangs_formula::nextlog16(fNumParametricSegments_p4);
|
||||
}
|
||||
|
||||
int requiredStrokeEdges() const {
|
||||
@ -49,7 +49,7 @@ public:
|
||||
std::max(SkScalarCeilToInt(fNumRadialSegmentsPerRadian * SK_ScalarPI), 1);
|
||||
|
||||
int maxParametricSegmentsInStroke =
|
||||
SkScalarCeilToInt(wangs_formula::root4(fNumParametricSegments_pow4));
|
||||
SkScalarCeilToInt(wangs_formula::root4(fNumParametricSegments_p4));
|
||||
SkASSERT(maxParametricSegmentsInStroke >= 1);
|
||||
|
||||
// Now calculate the maximum number of edges we will need in the stroke portion of the
|
||||
@ -79,7 +79,7 @@ public:
|
||||
|
||||
void setParametricSegments(float n4) {
|
||||
SkASSERT(n4 >= 0.f);
|
||||
fNumParametricSegments_pow4 = n4;
|
||||
fNumParametricSegments_p4 = n4;
|
||||
}
|
||||
|
||||
void setStroke(const StrokeParams& strokeParams, float maxScale) {
|
||||
@ -103,8 +103,8 @@ public:
|
||||
}
|
||||
|
||||
void accumulate(const LinearTolerances& tolerances) {
|
||||
if (tolerances.fNumParametricSegments_pow4 > fNumParametricSegments_pow4) {
|
||||
fNumParametricSegments_pow4 = tolerances.fNumParametricSegments_pow4;
|
||||
if (tolerances.fNumParametricSegments_p4 > fNumParametricSegments_p4) {
|
||||
fNumParametricSegments_p4 = tolerances.fNumParametricSegments_p4;
|
||||
}
|
||||
if (tolerances.fNumRadialSegmentsPerRadian > fNumRadialSegmentsPerRadian) {
|
||||
fNumRadialSegmentsPerRadian = tolerances.fNumRadialSegmentsPerRadian;
|
||||
@ -116,7 +116,7 @@ public:
|
||||
|
||||
private:
|
||||
// Used for both fills and strokes, always at least one parametric segment
|
||||
float fNumParametricSegments_pow4 = 1.f;
|
||||
float fNumParametricSegments_p4 = 1.f;
|
||||
// Used for strokes, adding additional segments along the curve to account for its rotation
|
||||
// TODO: Currently we assume the worst case 180 degree rotation for any curve, but tracking
|
||||
// max(radialSegments * patch curvature) would be tighter. This would require computing
|
||||
|
@ -166,17 +166,17 @@ VertexWriter& operator<<(VertexWriter& w, const AttribValue<A, T, Required, Opti
|
||||
// Stores state and deferred patch data when TrackJoinControlPoints is used for a PatchWriter.
|
||||
template <size_t Stride>
|
||||
struct PatchStorage {
|
||||
float fN_pow4 = -1.f; // The parametric segment value to restore on LinearTolerances
|
||||
float fN_p4 = -1.f; // The parametric segment value to restore on LinearTolerances
|
||||
bool fMustDefer = true; // True means next patch must be deferred
|
||||
|
||||
// Holds an entire patch, except with an undefined join control point.
|
||||
char fData[Stride];
|
||||
|
||||
bool hasPending() const {
|
||||
return fN_pow4 >= 0.f;
|
||||
return fN_p4 >= 0.f;
|
||||
}
|
||||
void reset() {
|
||||
fN_pow4 = -1.f;
|
||||
fN_p4 = -1.f;
|
||||
fMustDefer = true;
|
||||
}
|
||||
};
|
||||
@ -298,7 +298,7 @@ public:
|
||||
// Assuming that the stroke parameters aren't changing within a contour, we only have
|
||||
// to set the parametric segments in order to recover the LinearTolerances state at the
|
||||
// time the deferred patch was recorded.
|
||||
fTolerances.setParametricSegments(fDeferredPatch.fN_pow4);
|
||||
fTolerances.setParametricSegments(fDeferredPatch.fN_p4);
|
||||
if (VertexWriter vw = fPatchAllocator.append(fTolerances)) {
|
||||
vw << VertexWriter::Array<char>(fDeferredPatch.fData, fPatchAllocator.stride());
|
||||
}
|
||||
@ -367,7 +367,7 @@ public:
|
||||
|
||||
// Write a cubic curve with its four control points.
|
||||
AI void writeCubic(float2 p0, float2 p1, float2 p2, float2 p3) {
|
||||
float n4 = wangs_formula::cubic_pow4(kPrecision, p0, p1, p2, p3, fApproxTransform);
|
||||
float n4 = wangs_formula::cubic_p4(kPrecision, p0, p1, p2, p3, fApproxTransform);
|
||||
if constexpr (kDiscardFlatCurves) {
|
||||
if (n4 <= 1.f) {
|
||||
// This cubic only needs one segment (e.g. a line) but we're not filling space with
|
||||
@ -390,7 +390,7 @@ public:
|
||||
// Write a conic curve with three control points and 'w', with the last coord of the last
|
||||
// control point signaling a conic by being set to infinity.
|
||||
AI void writeConic(float2 p0, float2 p1, float2 p2, float w) {
|
||||
float n2 = wangs_formula::conic_pow2(kPrecision, p0, p1, p2, w, fApproxTransform);
|
||||
float n2 = wangs_formula::conic_p2(kPrecision, p0, p1, p2, w, fApproxTransform);
|
||||
if constexpr (kDiscardFlatCurves) {
|
||||
if (n2 <= 1.f) {
|
||||
// This conic only needs one segment (e.g. a line) but we're not filling space with
|
||||
@ -414,7 +414,7 @@ public:
|
||||
// Write a quadratic curve that automatically converts its three control points into an
|
||||
// equivalent cubic.
|
||||
AI void writeQuadratic(float2 p0, float2 p1, float2 p2) {
|
||||
float n4 = wangs_formula::quadratic_pow4(kPrecision, p0, p1, p2, fApproxTransform);
|
||||
float n4 = wangs_formula::quadratic_p4(kPrecision, p0, p1, p2, fApproxTransform);
|
||||
if constexpr (kDiscardFlatCurves) {
|
||||
if (n4 <= 1.f) {
|
||||
// This quad only needs one segment (e.g. a line) but we're not filling space with
|
||||
@ -460,8 +460,8 @@ public:
|
||||
AI void writeTriangle(float2 p0, float2 p1, float2 p2) {
|
||||
// No chopping needed, the max supported segment count should always support 2 lines
|
||||
// (which form a triangle when implicitly closed).
|
||||
static constexpr float kTriangleSegments_pow4 = 2.f * 2.f * 2.f * 2.f;
|
||||
fTolerances.setParametricSegments(kTriangleSegments_pow4);
|
||||
static constexpr float kTriangleSegments_p4 = 2.f * 2.f * 2.f * 2.f;
|
||||
fTolerances.setParametricSegments(kTriangleSegments_p4);
|
||||
this->writePatch(p0, p1, p2, {SK_FloatInfinity, SK_FloatInfinity},
|
||||
kTriangularConicCurveType);
|
||||
}
|
||||
@ -499,7 +499,7 @@ private:
|
||||
SkASSERT(fPatchAllocator.stride() <= kMaxStride);
|
||||
// Save the computed parametric segment tolerance value so that we can pass that to
|
||||
// the PatchAllocator when flushing the deferred patch.
|
||||
fDeferredPatch.fN_pow4 = fTolerances.numParametricSegments_pow4();
|
||||
fDeferredPatch.fN_p4 = fTolerances.numParametricSegments_p4();
|
||||
return {fDeferredPatch.fData, fPatchAllocator.stride()};
|
||||
}
|
||||
}
|
||||
@ -546,19 +546,27 @@ private:
|
||||
}
|
||||
|
||||
int accountForCurve(float n4) {
|
||||
if (n4 <= pow4(kMaxParametricSegments)) {
|
||||
if (n4 <= kMaxParametricSegments_p4) {
|
||||
// Record n^4 and return 0 to signal no chopping
|
||||
fTolerances.setParametricSegments(n4);
|
||||
return 0;
|
||||
} else {
|
||||
// Clamp to max allowed segmentation for a patch and return required number of chops
|
||||
// to achieve visual correctness.
|
||||
fTolerances.setParametricSegments(pow4(kMaxParametricSegments));
|
||||
return SkScalarCeilToInt(wangs_formula::root4(std::min(n4, pow4(kMaxSegmentsPerCurve)) /
|
||||
pow4(kMaxParametricSegments)));
|
||||
fTolerances.setParametricSegments(kMaxParametricSegments_p4);
|
||||
return SkScalarCeilToInt(wangs_formula::root4(std::min(n4, kMaxSegmentsPerCurve_p4) /
|
||||
kMaxParametricSegments_p4));
|
||||
}
|
||||
}
|
||||
|
||||
// This does not return b when t==1, but it otherwise seems to get better precision than
|
||||
// "a*(1 - t) + b*t" for things like chopping cubics on exact cusp points.
|
||||
// The responsibility falls on the caller to check that t != 1 before calling.
|
||||
static AI float4 mix(float4 a, float4 b, float4 T) {
|
||||
SkASSERT(all((0 <= T) & (T < 1)));
|
||||
return (b - a)*T + a;
|
||||
}
|
||||
|
||||
// Helpers that chop the curve type into 'numPatches' parametrically uniform curves. It is
|
||||
// assumed that 'numPatches' is calculated such that the resulting curves require the maximum
|
||||
// number of segments to draw appropriately (since the original presumably needed even more).
|
||||
|
@ -61,8 +61,8 @@ public:
|
||||
if (!fCullTest.areVisible3(p)) {
|
||||
fPath.lineTo(p[2]);
|
||||
} else {
|
||||
float n4 = wangs_formula::quadratic_pow4(fTessellationPrecision, p, fVectorXform);
|
||||
if (n4 > pow4(kMaxSegmentsPerCurve) && numChops < kMaxChopsPerCurve) {
|
||||
float n4 = wangs_formula::quadratic_p4(fTessellationPrecision, p, fVectorXform);
|
||||
if (n4 > kMaxSegmentsPerCurve_p4 && numChops < kMaxChopsPerCurve) {
|
||||
SkPoint chops[5];
|
||||
SkChopQuadAtHalf(p, chops);
|
||||
fPointStack.pop_back_n(3);
|
||||
@ -90,8 +90,8 @@ public:
|
||||
if (!fCullTest.areVisible3(p)) {
|
||||
fPath.lineTo(p[2]);
|
||||
} else {
|
||||
float n2 = wangs_formula::conic_pow2(fTessellationPrecision, p, w, fVectorXform);
|
||||
if (n2 > pow2(kMaxSegmentsPerCurve) && numChops < kMaxChopsPerCurve) {
|
||||
float n2 = wangs_formula::conic_p2(fTessellationPrecision, p, w, fVectorXform);
|
||||
if (n2 > kMaxSegmentsPerCurve_p2 && numChops < kMaxChopsPerCurve) {
|
||||
SkConic chops[2];
|
||||
if (!SkConic(p,w).chopAt(.5, chops)) {
|
||||
SkPoint line[2] = {p[0], p[2]};
|
||||
@ -125,8 +125,8 @@ public:
|
||||
if (!fCullTest.areVisible4(p)) {
|
||||
fPath.lineTo(p[3]);
|
||||
} else {
|
||||
float n4 = wangs_formula::cubic_pow4(fTessellationPrecision, p, fVectorXform);
|
||||
if (n4 > pow4(kMaxSegmentsPerCurve) && numChops < kMaxChopsPerCurve) {
|
||||
float n4 = wangs_formula::cubic_p4(fTessellationPrecision, p, fVectorXform);
|
||||
if (n4 > kMaxSegmentsPerCurve_p4 && numChops < kMaxChopsPerCurve) {
|
||||
SkPoint chops[7];
|
||||
SkChopCubicAtHalf(p, chops);
|
||||
fPointStack.pop_back_n(4);
|
||||
|
@ -45,23 +45,6 @@ AI float cross(float2 a, float2 b) {
|
||||
return x[0] - x[1];
|
||||
}
|
||||
|
||||
// This does not return b when t==1, but it otherwise seems to get better precision than
|
||||
// "a*(1 - t) + b*t" for things like chopping cubics on exact cusp points.
|
||||
// The responsibility falls on the caller to check that t != 1 before calling.
|
||||
template<int N>
|
||||
AI vec<N> mix(vec<N> a, vec<N> b, vec<N> T) {
|
||||
SkASSERT(all((0 <= T) & (T < 1)));
|
||||
return (b - a)*T + a;
|
||||
}
|
||||
|
||||
template<int N>
|
||||
AI vec<N> mix(vec<N> a, vec<N> b, float T) {
|
||||
return mix(a, b, vec<N>(T));
|
||||
}
|
||||
|
||||
AI constexpr float pow2(float x) { return x*x; }
|
||||
AI constexpr float pow4(float x) { return pow2(x*x); }
|
||||
|
||||
#undef AI
|
||||
} // namespace skgpu
|
||||
|
||||
@ -81,6 +64,9 @@ constexpr static int kMaxResolveLevel = 5;
|
||||
// path filling algorithms snap their dynamic vertex counts to powers-of-two, whereas the stroking
|
||||
// algorithm does not.
|
||||
constexpr static int kMaxParametricSegments = 1 << kMaxResolveLevel;
|
||||
constexpr static int kMaxParametricSegments_p2 = kMaxParametricSegments * kMaxParametricSegments;
|
||||
constexpr static int kMaxParametricSegments_p4 = kMaxParametricSegments_p2 *
|
||||
kMaxParametricSegments_p2;
|
||||
|
||||
// Don't tessellate paths that might have an individual curve that requires more than 1024 segments.
|
||||
// (See wangs_formula::worst_case_cubic). If this is the case, call "PreChopPathCurves" first.
|
||||
@ -88,6 +74,8 @@ constexpr static int kMaxParametricSegments = 1 << kMaxResolveLevel;
|
||||
// kMaxTessellationSegmentsPerCurve is handled automatically by PatchWriter. It differs from
|
||||
// PreChopPathCurves in that it does no culling of offscreen chopped paths.
|
||||
constexpr static float kMaxSegmentsPerCurve = 1024;
|
||||
constexpr static float kMaxSegmentsPerCurve_p2 = kMaxSegmentsPerCurve * kMaxSegmentsPerCurve;
|
||||
constexpr static float kMaxSegmentsPerCurve_p4 = kMaxSegmentsPerCurve_p2 * kMaxSegmentsPerCurve_p2;
|
||||
|
||||
// Returns a new path, equivalent to 'path' within the given viewport, whose verbs can all be drawn
|
||||
// with 'maxSegments' tessellation segments or fewer, while staying within '1/tessellationPrecision'
|
||||
|
@ -32,7 +32,7 @@ namespace skgpu::wangs_formula {
|
||||
template<int Degree> constexpr float length_term(float precision) {
|
||||
return (Degree * (Degree - 1) / 8.f) * precision;
|
||||
}
|
||||
template<int Degree> constexpr float length_term_pow2(float precision) {
|
||||
template<int Degree> constexpr float length_term_p2(float precision) {
|
||||
return ((Degree * Degree) * ((Degree - 1) * (Degree - 1)) / 64.f) * (precision * precision);
|
||||
}
|
||||
|
||||
@ -113,29 +113,29 @@ private:
|
||||
};
|
||||
|
||||
// Returns Wang's formula, raised to the 4th power, specialized for a quadratic curve.
|
||||
AI float quadratic_pow4(float precision,
|
||||
float2 p0, float2 p1, float2 p2,
|
||||
const VectorXform& vectorXform = VectorXform()) {
|
||||
AI float quadratic_p4(float precision,
|
||||
float2 p0, float2 p1, float2 p2,
|
||||
const VectorXform& vectorXform = VectorXform()) {
|
||||
float2 v = -2*p1 + p0 + p2;
|
||||
v = vectorXform(v);
|
||||
float2 vv = v*v;
|
||||
return (vv[0] + vv[1]) * length_term_pow2<2>(precision);
|
||||
return (vv[0] + vv[1]) * length_term_p2<2>(precision);
|
||||
}
|
||||
AI float quadratic_pow4(float precision,
|
||||
const SkPoint pts[],
|
||||
const VectorXform& vectorXform = VectorXform()) {
|
||||
return quadratic_pow4(precision,
|
||||
skvx::bit_pun<float2>(pts[0]),
|
||||
skvx::bit_pun<float2>(pts[1]),
|
||||
skvx::bit_pun<float2>(pts[2]),
|
||||
vectorXform);
|
||||
AI float quadratic_p4(float precision,
|
||||
const SkPoint pts[],
|
||||
const VectorXform& vectorXform = VectorXform()) {
|
||||
return quadratic_p4(precision,
|
||||
skvx::bit_pun<float2>(pts[0]),
|
||||
skvx::bit_pun<float2>(pts[1]),
|
||||
skvx::bit_pun<float2>(pts[2]),
|
||||
vectorXform);
|
||||
}
|
||||
|
||||
// Returns Wang's formula specialized for a quadratic curve.
|
||||
AI float quadratic(float precision,
|
||||
const SkPoint pts[],
|
||||
const VectorXform& vectorXform = VectorXform()) {
|
||||
return root4(quadratic_pow4(precision, pts, vectorXform));
|
||||
return root4(quadratic_p4(precision, pts, vectorXform));
|
||||
}
|
||||
|
||||
// Returns the log2 value of Wang's formula specialized for a quadratic curve, rounded up to the
|
||||
@ -144,37 +144,37 @@ AI int quadratic_log2(float precision,
|
||||
const SkPoint pts[],
|
||||
const VectorXform& vectorXform = VectorXform()) {
|
||||
// nextlog16(x) == ceil(log2(sqrt(sqrt(x))))
|
||||
return nextlog16(quadratic_pow4(precision, pts, vectorXform));
|
||||
return nextlog16(quadratic_p4(precision, pts, vectorXform));
|
||||
}
|
||||
|
||||
// Returns Wang's formula, raised to the 4th power, specialized for a cubic curve.
|
||||
AI float cubic_pow4(float precision,
|
||||
float2 p0, float2 p1, float2 p2, float2 p3,
|
||||
const VectorXform& vectorXform = VectorXform()) {
|
||||
AI float cubic_p4(float precision,
|
||||
float2 p0, float2 p1, float2 p2, float2 p3,
|
||||
const VectorXform& vectorXform = VectorXform()) {
|
||||
float4 p01{p0, p1};
|
||||
float4 p12{p1, p2};
|
||||
float4 p23{p2, p3};
|
||||
float4 v = -2*p12 + p01 + p23;
|
||||
v = vectorXform(v);
|
||||
float4 vv = v*v;
|
||||
return std::max(vv[0] + vv[1], vv[2] + vv[3]) * length_term_pow2<3>(precision);
|
||||
return std::max(vv[0] + vv[1], vv[2] + vv[3]) * length_term_p2<3>(precision);
|
||||
}
|
||||
AI float cubic_pow4(float precision,
|
||||
const SkPoint pts[],
|
||||
const VectorXform& vectorXform = VectorXform()) {
|
||||
return cubic_pow4(precision,
|
||||
skvx::bit_pun<float2>(pts[0]),
|
||||
skvx::bit_pun<float2>(pts[1]),
|
||||
skvx::bit_pun<float2>(pts[2]),
|
||||
skvx::bit_pun<float2>(pts[3]),
|
||||
vectorXform);
|
||||
AI float cubic_p4(float precision,
|
||||
const SkPoint pts[],
|
||||
const VectorXform& vectorXform = VectorXform()) {
|
||||
return cubic_p4(precision,
|
||||
skvx::bit_pun<float2>(pts[0]),
|
||||
skvx::bit_pun<float2>(pts[1]),
|
||||
skvx::bit_pun<float2>(pts[2]),
|
||||
skvx::bit_pun<float2>(pts[3]),
|
||||
vectorXform);
|
||||
}
|
||||
|
||||
// Returns Wang's formula specialized for a cubic curve.
|
||||
AI float cubic(float precision,
|
||||
const SkPoint pts[],
|
||||
const VectorXform& vectorXform = VectorXform()) {
|
||||
return root4(cubic_pow4(precision, pts, vectorXform));
|
||||
return root4(cubic_p4(precision, pts, vectorXform));
|
||||
}
|
||||
|
||||
// Returns the log2 value of Wang's formula specialized for a cubic curve, rounded up to the next
|
||||
@ -183,29 +183,29 @@ AI int cubic_log2(float precision,
|
||||
const SkPoint pts[],
|
||||
const VectorXform& vectorXform = VectorXform()) {
|
||||
// nextlog16(x) == ceil(log2(sqrt(sqrt(x))))
|
||||
return nextlog16(cubic_pow4(precision, pts, vectorXform));
|
||||
return nextlog16(cubic_p4(precision, pts, vectorXform));
|
||||
}
|
||||
|
||||
// Returns the maximum number of line segments a cubic with the given device-space bounding box size
|
||||
// would ever need to be divided into, raised to the 4th power. This is simply a special case of the
|
||||
// cubic formula where we maximize its value by placing control points on specific corners of the
|
||||
// bounding box.
|
||||
AI float worst_case_cubic_pow4(float precision, float devWidth, float devHeight) {
|
||||
float kk = length_term_pow2<3>(precision);
|
||||
AI float worst_case_cubic_p4(float precision, float devWidth, float devHeight) {
|
||||
float kk = length_term_p2<3>(precision);
|
||||
return 4*kk * (devWidth * devWidth + devHeight * devHeight);
|
||||
}
|
||||
|
||||
// Returns the maximum number of line segments a cubic with the given device-space bounding box size
|
||||
// would ever need to be divided into.
|
||||
AI float worst_case_cubic(float precision, float devWidth, float devHeight) {
|
||||
return root4(worst_case_cubic_pow4(precision, devWidth, devHeight));
|
||||
return root4(worst_case_cubic_p4(precision, devWidth, devHeight));
|
||||
}
|
||||
|
||||
// Returns the maximum log2 number of line segments a cubic with the given device-space bounding box
|
||||
// size would ever need to be divided into.
|
||||
AI int worst_case_cubic_log2(float precision, float devWidth, float devHeight) {
|
||||
// nextlog16(x) == ceil(log2(sqrt(sqrt(x))))
|
||||
return nextlog16(worst_case_cubic_pow4(precision, devWidth, devHeight));
|
||||
return nextlog16(worst_case_cubic_p4(precision, devWidth, devHeight));
|
||||
}
|
||||
|
||||
// Returns Wang's formula specialized for a conic curve, raised to the second power.
|
||||
@ -214,10 +214,10 @@ AI int worst_case_cubic_log2(float precision, float devWidth, float devHeight) {
|
||||
// This is not actually due to Wang, but is an analogue from (Theorem 3, corollary 1):
|
||||
// J. Zheng, T. Sederberg. "Estimating Tessellation Parameter Intervals for
|
||||
// Rational Curves and Surfaces." ACM Transactions on Graphics 19(1). 2000.
|
||||
AI float conic_pow2(float precision,
|
||||
float2 p0, float2 p1, float2 p2,
|
||||
float w,
|
||||
const VectorXform& vectorXform = VectorXform()) {
|
||||
AI float conic_p2(float precision,
|
||||
float2 p0, float2 p1, float2 p2,
|
||||
float w,
|
||||
const VectorXform& vectorXform = VectorXform()) {
|
||||
p0 = vectorXform(p0);
|
||||
p1 = vectorXform(p1);
|
||||
p2 = vectorXform(p2);
|
||||
@ -249,16 +249,16 @@ AI float conic_pow2(float precision,
|
||||
// If not, the number of segments is (tmax - tmin) / sqrt(denom / numer).
|
||||
return numer / denom;
|
||||
}
|
||||
AI float conic_pow2(float precision,
|
||||
const SkPoint pts[],
|
||||
float w,
|
||||
const VectorXform& vectorXform = VectorXform()) {
|
||||
return conic_pow2(precision,
|
||||
skvx::bit_pun<float2>(pts[0]),
|
||||
skvx::bit_pun<float2>(pts[1]),
|
||||
skvx::bit_pun<float2>(pts[2]),
|
||||
w,
|
||||
vectorXform);
|
||||
AI float conic_p2(float precision,
|
||||
const SkPoint pts[],
|
||||
float w,
|
||||
const VectorXform& vectorXform = VectorXform()) {
|
||||
return conic_p2(precision,
|
||||
skvx::bit_pun<float2>(pts[0]),
|
||||
skvx::bit_pun<float2>(pts[1]),
|
||||
skvx::bit_pun<float2>(pts[2]),
|
||||
w,
|
||||
vectorXform);
|
||||
}
|
||||
|
||||
// Returns the value of Wang's formula specialized for a conic curve.
|
||||
@ -266,7 +266,7 @@ AI float conic(float tolerance,
|
||||
const SkPoint pts[],
|
||||
float w,
|
||||
const VectorXform& vectorXform = VectorXform()) {
|
||||
return sqrtf(conic_pow2(tolerance, pts, w, vectorXform));
|
||||
return sqrtf(conic_p2(tolerance, pts, w, vectorXform));
|
||||
}
|
||||
|
||||
// Returns the log2 value of Wang's formula specialized for a conic curve, rounded up to the next
|
||||
@ -276,7 +276,7 @@ AI int conic_log2(float tolerance,
|
||||
float w,
|
||||
const VectorXform& vectorXform = VectorXform()) {
|
||||
// nextlog4(x) == ceil(log2(sqrt(x)))
|
||||
return nextlog4(conic_pow2(tolerance, pts, w, vectorXform));
|
||||
return nextlog4(conic_p2(tolerance, pts, w, vectorXform));
|
||||
}
|
||||
|
||||
} // namespace skgpu::wangs_formula
|
||||
|
@ -1,4 +1,4 @@
|
||||
static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,12,2,
|
||||
7,36,68,101,103,114,101,101,
|
||||
5,102,108,111,97,116,
|
||||
10,36,80,114,101,99,105,115,105,111,110,
|
||||
@ -11,12 +11,12 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
2,112,51,
|
||||
6,109,97,116,114,105,120,
|
||||
8,102,108,111,97,116,50,120,50,
|
||||
28,119,97,110,103,115,95,102,111,114,109,117,108,97,95,109,97,120,95,102,100,105,102,102,95,112,111,119,50,
|
||||
26,119,97,110,103,115,95,102,111,114,109,117,108,97,95,109,97,120,95,102,100,105,102,102,95,112,50,
|
||||
11,95,112,114,101,99,105,115,105,111,110,95,
|
||||
19,119,97,110,103,115,95,102,111,114,109,117,108,97,95,99,117,98,105,99,
|
||||
24,119,97,110,103,115,95,102,111,114,109,117,108,97,95,99,117,98,105,99,95,108,111,103,50,
|
||||
1,119,
|
||||
24,119,97,110,103,115,95,102,111,114,109,117,108,97,95,99,111,110,105,99,95,112,111,119,50,
|
||||
22,119,97,110,103,115,95,102,111,114,109,117,108,97,95,99,111,110,105,99,95,112,50,
|
||||
19,119,97,110,103,115,95,102,111,114,109,117,108,97,95,99,111,110,105,99,
|
||||
24,119,97,110,103,115,95,102,111,114,109,117,108,97,95,99,111,110,105,99,95,108,111,103,50,
|
||||
12,114,101,115,111,108,118,101,76,101,118,101,108,
|
||||
@ -101,7 +101,7 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
17,90,0,5,5,0,6,0,7,0,8,0,9,0,
|
||||
51,255,255,10,0,
|
||||
55,11,0,
|
||||
17,119,0,
|
||||
17,117,0,
|
||||
51,255,255,10,0,3,
|
||||
55,12,0,
|
||||
17,55,0,
|
||||
@ -119,10 +119,10 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
17,74,0,
|
||||
51,255,255,81,0,3,
|
||||
28,17,0,
|
||||
17,131,0,6,11,0,12,0,13,0,14,0,15,0,16,0,
|
||||
17,129,0,6,11,0,12,0,13,0,14,0,15,0,16,0,
|
||||
51,255,255,10,0,
|
||||
55,18,0,
|
||||
17,119,0,
|
||||
17,117,0,
|
||||
51,255,255,10,0,3,
|
||||
55,19,0,
|
||||
17,55,0,
|
||||
@ -140,10 +140,10 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
17,74,0,
|
||||
51,255,255,81,0,3,
|
||||
28,24,0,
|
||||
17,151,0,6,18,0,19,0,20,0,21,0,22,0,23,0,
|
||||
17,149,0,6,18,0,19,0,20,0,21,0,22,0,23,0,
|
||||
51,255,255,10,0,
|
||||
55,25,0,
|
||||
17,119,0,
|
||||
17,117,0,
|
||||
51,255,255,10,0,3,
|
||||
55,26,0,
|
||||
17,55,0,
|
||||
@ -155,13 +155,13 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
17,68,0,
|
||||
51,255,255,58,0,3,
|
||||
55,29,0,
|
||||
17,176,0,
|
||||
17,174,0,
|
||||
51,255,255,10,0,3,
|
||||
28,30,0,
|
||||
17,178,0,5,25,0,26,0,27,0,28,0,29,0,
|
||||
17,176,0,5,25,0,26,0,27,0,28,0,29,0,
|
||||
51,255,255,10,0,
|
||||
55,31,0,
|
||||
17,119,0,
|
||||
17,117,0,
|
||||
51,255,255,10,0,3,
|
||||
55,32,0,
|
||||
17,55,0,
|
||||
@ -173,13 +173,13 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
17,68,0,
|
||||
51,255,255,58,0,3,
|
||||
55,35,0,
|
||||
17,176,0,
|
||||
17,174,0,
|
||||
51,255,255,10,0,3,
|
||||
28,36,0,
|
||||
17,203,0,5,31,0,32,0,33,0,34,0,35,0,
|
||||
17,199,0,5,31,0,32,0,33,0,34,0,35,0,
|
||||
51,255,255,10,0,
|
||||
55,37,0,
|
||||
17,119,0,
|
||||
17,117,0,
|
||||
51,255,255,10,0,3,
|
||||
55,38,0,
|
||||
17,55,0,
|
||||
@ -191,43 +191,43 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
17,68,0,
|
||||
51,255,255,58,0,3,
|
||||
55,41,0,
|
||||
17,176,0,
|
||||
17,174,0,
|
||||
51,255,255,10,0,3,
|
||||
28,42,0,
|
||||
17,223,0,5,37,0,38,0,39,0,40,0,41,0,
|
||||
17,219,0,5,37,0,38,0,39,0,40,0,41,0,
|
||||
51,255,255,10,0,
|
||||
55,43,0,
|
||||
17,248,0,
|
||||
17,244,0,
|
||||
51,255,255,10,0,3,
|
||||
55,44,0,
|
||||
17,5,1,
|
||||
17,1,1,
|
||||
51,255,255,10,0,3,
|
||||
55,45,0,
|
||||
17,23,1,
|
||||
51,255,255,27,1,3,
|
||||
17,19,1,
|
||||
51,255,255,23,1,3,
|
||||
55,46,0,
|
||||
17,34,1,
|
||||
51,255,255,27,1,3,
|
||||
17,30,1,
|
||||
51,255,255,23,1,3,
|
||||
28,47,0,
|
||||
17,38,1,4,43,0,44,0,45,0,46,0,
|
||||
17,34,1,4,43,0,44,0,45,0,46,0,
|
||||
51,255,255,58,0,
|
||||
55,48,0,
|
||||
17,248,0,
|
||||
17,244,0,
|
||||
51,255,255,10,0,3,
|
||||
55,49,0,
|
||||
17,5,1,
|
||||
17,1,1,
|
||||
51,255,255,10,0,3,
|
||||
55,50,0,
|
||||
17,23,1,
|
||||
51,255,255,27,1,3,
|
||||
17,19,1,
|
||||
51,255,255,23,1,3,
|
||||
55,51,0,
|
||||
17,34,1,
|
||||
51,255,255,27,1,3,
|
||||
17,30,1,
|
||||
51,255,255,23,1,3,
|
||||
55,52,0,
|
||||
17,55,1,
|
||||
17,51,1,
|
||||
51,255,255,58,0,3,
|
||||
28,53,0,
|
||||
17,70,1,5,48,0,49,0,50,0,51,0,52,0,
|
||||
17,66,1,5,48,0,49,0,50,0,51,0,52,0,
|
||||
51,255,255,58,0,12,0,
|
||||
0,0,
|
||||
2,0,
|
||||
@ -266,10 +266,10 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
2,
|
||||
52,1,2,0,
|
||||
55,54,0,
|
||||
17,87,1,
|
||||
17,83,1,
|
||||
51,255,255,58,0,2,
|
||||
55,55,0,
|
||||
17,90,1,
|
||||
17,86,1,
|
||||
51,255,255,58,0,2,2,0,
|
||||
0,0,
|
||||
1,0,3,
|
||||
@ -279,7 +279,7 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
57,9,0,0,2,
|
||||
1,
|
||||
27,
|
||||
51,255,255,58,0,255,255,93,1,3,
|
||||
51,255,255,58,0,255,255,89,1,3,
|
||||
13,
|
||||
51,255,255,58,0,1,
|
||||
25,
|
||||
@ -293,7 +293,7 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
57,9,0,0,2,
|
||||
1,
|
||||
27,
|
||||
51,255,255,58,0,255,255,93,1,3,
|
||||
51,255,255,58,0,255,255,89,1,3,
|
||||
13,
|
||||
51,255,255,58,0,1,
|
||||
25,
|
||||
@ -303,20 +303,20 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
57,6,0,0,
|
||||
44,
|
||||
27,
|
||||
51,255,255,10,0,255,255,93,1,2,
|
||||
27,
|
||||
51,255,255,10,0,255,255,97,1,2,
|
||||
27,
|
||||
51,255,255,10,0,255,255,101,1,2,
|
||||
57,54,0,0,
|
||||
57,54,0,0,
|
||||
27,
|
||||
51,255,255,10,0,255,255,101,1,2,
|
||||
51,255,255,10,0,255,255,97,1,2,
|
||||
57,55,0,0,
|
||||
57,55,0,0,1,
|
||||
29,17,0,
|
||||
2,
|
||||
52,1,1,0,
|
||||
55,56,0,
|
||||
17,105,1,
|
||||
17,101,1,
|
||||
51,255,255,10,0,2,1,0,
|
||||
0,0,2,
|
||||
56,56,0,
|
||||
@ -330,17 +330,17 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
57,16,0,0,
|
||||
44,
|
||||
27,
|
||||
51,255,255,10,0,255,255,97,1,2,
|
||||
51,255,255,10,0,255,255,93,1,2,
|
||||
27,
|
||||
51,255,255,10,0,255,255,107,1,1,
|
||||
51,255,255,10,0,255,255,103,1,1,
|
||||
27,
|
||||
51,255,255,10,0,255,255,112,1,1,
|
||||
51,255,255,10,0,255,255,108,1,1,
|
||||
1,
|
||||
1,
|
||||
57,3,0,0,2,
|
||||
57,11,0,0,2,
|
||||
27,
|
||||
51,255,255,10,0,255,255,112,1,1,
|
||||
51,255,255,10,0,255,255,108,1,1,
|
||||
57,56,0,0,
|
||||
25,
|
||||
51,255,255,10,0,0,0,128,63,1,
|
||||
@ -348,7 +348,7 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
2,
|
||||
52,1,1,0,
|
||||
55,57,0,
|
||||
17,105,1,
|
||||
17,101,1,
|
||||
51,255,255,10,0,2,1,0,
|
||||
0,0,2,
|
||||
56,57,0,
|
||||
@ -362,12 +362,12 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
57,23,0,0,
|
||||
44,
|
||||
27,
|
||||
51,255,255,10,0,255,255,107,1,1,
|
||||
51,255,255,10,0,255,255,103,1,1,
|
||||
1,
|
||||
27,
|
||||
51,255,255,10,0,255,255,117,1,1,
|
||||
51,255,255,10,0,255,255,113,1,1,
|
||||
27,
|
||||
51,255,255,10,0,255,255,97,1,2,
|
||||
51,255,255,10,0,255,255,93,1,2,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
@ -383,25 +383,25 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
2,
|
||||
52,1,7,0,
|
||||
55,58,0,
|
||||
17,122,1,
|
||||
17,118,1,
|
||||
51,255,255,58,0,2,
|
||||
55,59,0,
|
||||
17,105,1,
|
||||
17,101,1,
|
||||
51,255,255,10,0,2,
|
||||
55,60,0,
|
||||
17,124,1,
|
||||
17,120,1,
|
||||
51,255,255,58,0,2,
|
||||
55,61,0,
|
||||
17,127,1,
|
||||
17,123,1,
|
||||
51,255,255,10,0,2,
|
||||
55,62,0,
|
||||
17,130,1,
|
||||
17,126,1,
|
||||
51,255,255,10,0,2,
|
||||
55,63,0,
|
||||
17,141,1,
|
||||
17,137,1,
|
||||
51,255,255,10,0,2,
|
||||
55,64,0,
|
||||
17,147,1,
|
||||
17,143,1,
|
||||
51,255,255,10,0,2,7,0,
|
||||
0,0,
|
||||
6,0,
|
||||
@ -415,16 +415,16 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
1,
|
||||
1,
|
||||
27,
|
||||
51,255,255,58,0,255,255,153,1,2,
|
||||
51,255,255,58,0,255,255,149,1,2,
|
||||
27,
|
||||
51,255,255,58,0,255,255,153,1,2,
|
||||
51,255,255,58,0,255,255,149,1,2,
|
||||
57,26,0,0,
|
||||
57,27,0,0,
|
||||
57,28,0,0,0,
|
||||
27,
|
||||
51,255,255,58,0,255,255,97,1,2,
|
||||
51,255,255,58,0,255,255,93,1,2,
|
||||
27,
|
||||
51,255,255,58,0,255,255,97,1,2,
|
||||
51,255,255,58,0,255,255,93,1,2,
|
||||
57,26,0,0,
|
||||
57,27,0,0,
|
||||
57,28,0,0,2,
|
||||
@ -445,28 +445,28 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
56,59,0,
|
||||
51,255,255,10,0,0,
|
||||
27,
|
||||
51,255,255,10,0,255,255,112,1,1,
|
||||
51,255,255,10,0,255,255,108,1,1,
|
||||
27,
|
||||
51,255,255,10,0,255,255,93,1,2,
|
||||
27,
|
||||
51,255,255,10,0,255,255,93,1,2,
|
||||
27,
|
||||
51,255,255,10,0,255,255,97,1,2,
|
||||
27,
|
||||
51,255,255,10,0,255,255,97,1,2,
|
||||
27,
|
||||
51,255,255,10,0,255,255,101,1,2,
|
||||
57,26,0,0,
|
||||
57,26,0,0,
|
||||
27,
|
||||
51,255,255,10,0,255,255,101,1,2,
|
||||
51,255,255,10,0,255,255,97,1,2,
|
||||
57,27,0,0,
|
||||
57,27,0,0,
|
||||
27,
|
||||
51,255,255,10,0,255,255,101,1,2,
|
||||
51,255,255,10,0,255,255,97,1,2,
|
||||
57,28,0,0,
|
||||
57,28,0,0,
|
||||
56,60,0,
|
||||
51,255,255,58,0,0,
|
||||
1,
|
||||
27,
|
||||
51,255,255,58,0,255,255,93,1,3,
|
||||
51,255,255,58,0,255,255,89,1,3,
|
||||
13,
|
||||
51,255,255,58,0,1,
|
||||
1,
|
||||
@ -479,9 +479,9 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
56,61,0,
|
||||
51,255,255,10,0,0,
|
||||
27,
|
||||
51,255,255,10,0,255,255,157,1,1,
|
||||
51,255,255,10,0,255,255,153,1,1,
|
||||
27,
|
||||
51,255,255,10,0,255,255,93,1,3,
|
||||
51,255,255,10,0,255,255,89,1,3,
|
||||
25,
|
||||
51,255,255,10,0,0,0,0,192,
|
||||
57,29,0,0,
|
||||
@ -490,11 +490,11 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
56,62,0,
|
||||
51,255,255,10,0,0,
|
||||
27,
|
||||
51,255,255,10,0,255,255,97,1,2,
|
||||
51,255,255,10,0,255,255,93,1,2,
|
||||
25,
|
||||
51,255,255,10,0,0,0,0,0,
|
||||
27,
|
||||
51,255,255,10,0,255,255,93,1,3,
|
||||
51,255,255,10,0,255,255,89,1,3,
|
||||
57,59,0,0,
|
||||
57,25,0,0,
|
||||
25,
|
||||
@ -504,7 +504,7 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
1,
|
||||
1,
|
||||
27,
|
||||
51,255,255,10,0,255,255,161,1,1,
|
||||
51,255,255,10,0,255,255,157,1,1,
|
||||
57,60,0,0,2,
|
||||
57,25,0,0,0,
|
||||
1,
|
||||
@ -516,7 +516,7 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
25,
|
||||
51,255,255,10,0,0,0,128,64,2,
|
||||
27,
|
||||
51,255,255,10,0,255,255,153,1,2,
|
||||
51,255,255,10,0,255,255,149,1,2,
|
||||
57,29,0,0,
|
||||
25,
|
||||
51,255,255,10,0,0,0,128,63,
|
||||
@ -528,7 +528,7 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
2,
|
||||
52,1,1,0,
|
||||
55,65,0,
|
||||
17,168,1,
|
||||
17,164,1,
|
||||
51,255,255,10,0,2,1,0,
|
||||
0,0,2,
|
||||
56,65,0,
|
||||
@ -542,11 +542,11 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
57,35,0,0,
|
||||
44,
|
||||
27,
|
||||
51,255,255,10,0,255,255,97,1,2,
|
||||
51,255,255,10,0,255,255,93,1,2,
|
||||
27,
|
||||
51,255,255,10,0,255,255,107,1,1,
|
||||
51,255,255,10,0,255,255,103,1,1,
|
||||
27,
|
||||
51,255,255,10,0,255,255,112,1,1,
|
||||
51,255,255,10,0,255,255,108,1,1,
|
||||
57,65,0,0,
|
||||
25,
|
||||
51,255,255,10,0,0,0,128,63,1,
|
||||
@ -554,7 +554,7 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
2,
|
||||
52,1,1,0,
|
||||
55,66,0,
|
||||
17,168,1,
|
||||
17,164,1,
|
||||
51,255,255,10,0,2,1,0,
|
||||
0,0,2,
|
||||
56,66,0,
|
||||
@ -568,12 +568,12 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
57,41,0,0,
|
||||
44,
|
||||
27,
|
||||
51,255,255,10,0,255,255,107,1,1,
|
||||
51,255,255,10,0,255,255,103,1,1,
|
||||
1,
|
||||
27,
|
||||
51,255,255,10,0,255,255,117,1,1,
|
||||
51,255,255,10,0,255,255,113,1,1,
|
||||
27,
|
||||
51,255,255,10,0,255,255,97,1,2,
|
||||
51,255,255,10,0,255,255,93,1,2,
|
||||
57,66,0,0,
|
||||
25,
|
||||
51,255,255,10,0,0,0,128,63,2,
|
||||
@ -583,7 +583,7 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
2,
|
||||
52,1,1,0,
|
||||
55,67,0,
|
||||
17,171,1,
|
||||
17,167,1,
|
||||
51,255,255,58,0,2,1,0,
|
||||
0,0,3,
|
||||
56,67,0,
|
||||
@ -591,7 +591,7 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
58,
|
||||
32,0,
|
||||
27,
|
||||
51,255,255,182,1,255,255,187,1,1,
|
||||
51,255,255,178,1,255,255,183,1,1,
|
||||
50,
|
||||
57,46,0,0,1,2,
|
||||
2,
|
||||
@ -630,13 +630,13 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
17,71,0,
|
||||
51,255,255,58,0,2,
|
||||
55,72,0,
|
||||
17,176,0,
|
||||
17,174,0,
|
||||
51,255,255,10,0,2,
|
||||
55,73,0,
|
||||
17,193,1,
|
||||
17,189,1,
|
||||
51,255,255,10,0,2,
|
||||
55,74,0,
|
||||
17,209,1,
|
||||
17,205,1,
|
||||
51,255,255,10,0,2,7,0,
|
||||
6,0,
|
||||
5,0,
|
||||
@ -672,7 +672,7 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
58,
|
||||
32,0,
|
||||
27,
|
||||
51,255,255,182,1,255,255,187,1,1,
|
||||
51,255,255,178,1,255,255,183,1,1,
|
||||
50,
|
||||
57,46,0,0,1,3,
|
||||
2,
|
||||
@ -728,12 +728,12 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
1,
|
||||
57,44,0,1,15,
|
||||
27,
|
||||
51,255,255,10,0,255,255,223,1,1,
|
||||
51,255,255,10,0,255,255,219,1,1,
|
||||
27,
|
||||
51,255,255,10,0,255,255,229,1,2,
|
||||
51,255,255,10,0,255,255,225,1,2,
|
||||
57,44,0,0,
|
||||
12,
|
||||
51,255,255,235,1,1,
|
||||
51,255,255,231,1,1,
|
||||
1,
|
||||
57,73,0,0,1,
|
||||
57,43,0,0,
|
||||
@ -745,15 +745,15 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
56,74,0,
|
||||
51,255,255,10,0,0,
|
||||
27,
|
||||
51,255,255,10,0,255,255,223,1,1,
|
||||
51,255,255,10,0,255,255,219,1,1,
|
||||
1,
|
||||
25,
|
||||
51,255,255,10,0,0,0,0,63,0,
|
||||
27,
|
||||
51,255,255,10,0,255,255,229,1,2,
|
||||
51,255,255,10,0,255,255,225,1,2,
|
||||
57,44,0,0,
|
||||
12,
|
||||
51,255,255,235,1,1,
|
||||
51,255,255,231,1,1,
|
||||
1,
|
||||
25,
|
||||
51,255,255,10,0,0,0,160,64,1,
|
||||
@ -771,34 +771,34 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
2,
|
||||
52,1,10,0,
|
||||
55,75,0,
|
||||
17,239,1,
|
||||
17,235,1,
|
||||
51,255,255,10,0,2,
|
||||
55,76,0,
|
||||
17,241,1,
|
||||
17,237,1,
|
||||
51,255,255,58,0,2,
|
||||
55,77,0,
|
||||
17,244,1,
|
||||
17,240,1,
|
||||
51,255,255,58,0,2,
|
||||
55,78,0,
|
||||
17,247,1,
|
||||
17,243,1,
|
||||
51,255,255,58,0,2,
|
||||
55,79,0,
|
||||
17,250,1,
|
||||
17,246,1,
|
||||
51,255,255,58,0,2,
|
||||
55,80,0,
|
||||
17,254,1,
|
||||
17,250,1,
|
||||
51,255,255,58,0,2,
|
||||
55,81,0,
|
||||
17,2,2,
|
||||
17,254,1,
|
||||
51,255,255,58,0,2,
|
||||
55,82,0,
|
||||
17,7,2,
|
||||
17,3,2,
|
||||
51,255,255,10,0,2,
|
||||
55,83,0,
|
||||
17,9,2,
|
||||
17,5,2,
|
||||
51,255,255,10,0,2,
|
||||
55,84,0,
|
||||
17,11,2,
|
||||
17,7,2,
|
||||
51,255,255,10,0,2,10,0,
|
||||
0,0,
|
||||
1,0,
|
||||
@ -819,49 +819,49 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
56,76,0,
|
||||
51,255,255,58,0,0,
|
||||
27,
|
||||
51,255,255,58,0,255,255,14,2,3,
|
||||
51,255,255,58,0,255,255,10,2,3,
|
||||
57,68,0,0,
|
||||
57,69,0,0,
|
||||
57,75,0,0,
|
||||
56,77,0,
|
||||
51,255,255,58,0,0,
|
||||
27,
|
||||
51,255,255,58,0,255,255,14,2,3,
|
||||
51,255,255,58,0,255,255,10,2,3,
|
||||
57,69,0,0,
|
||||
57,70,0,0,
|
||||
57,75,0,0,
|
||||
56,78,0,
|
||||
51,255,255,58,0,0,
|
||||
27,
|
||||
51,255,255,58,0,255,255,14,2,3,
|
||||
51,255,255,58,0,255,255,10,2,3,
|
||||
57,70,0,0,
|
||||
57,71,0,0,
|
||||
57,75,0,0,
|
||||
56,79,0,
|
||||
51,255,255,58,0,0,
|
||||
27,
|
||||
51,255,255,58,0,255,255,14,2,3,
|
||||
51,255,255,58,0,255,255,10,2,3,
|
||||
57,76,0,0,
|
||||
57,77,0,0,
|
||||
57,75,0,0,
|
||||
56,80,0,
|
||||
51,255,255,58,0,0,
|
||||
27,
|
||||
51,255,255,58,0,255,255,14,2,3,
|
||||
51,255,255,58,0,255,255,10,2,3,
|
||||
57,77,0,0,
|
||||
57,78,0,0,
|
||||
57,75,0,0,
|
||||
56,81,0,
|
||||
51,255,255,58,0,0,
|
||||
27,
|
||||
51,255,255,58,0,255,255,14,2,3,
|
||||
51,255,255,58,0,255,255,10,2,3,
|
||||
57,79,0,0,
|
||||
57,80,0,0,
|
||||
57,75,0,0,
|
||||
56,82,0,
|
||||
51,255,255,10,0,0,
|
||||
27,
|
||||
51,255,255,10,0,255,255,14,2,3,
|
||||
51,255,255,10,0,255,255,10,2,3,
|
||||
25,
|
||||
51,255,255,10,0,0,0,128,63,
|
||||
57,72,0,0,
|
||||
@ -877,7 +877,7 @@ static uint8_t SKSL_INCLUDE_sksl_graphite_vert[] = {10,0,16,2,
|
||||
56,84,0,
|
||||
51,255,255,10,0,0,
|
||||
27,
|
||||
51,255,255,10,0,255,255,14,2,3,
|
||||
51,255,255,10,0,255,255,10,2,3,
|
||||
57,82,0,0,
|
||||
57,83,0,0,
|
||||
57,75,0,0,
|
||||
|
@ -18,8 +18,8 @@ const float $LengthTermPow2 = (($Degree * $Degree) * (($Degree - 1) * ($Degree -
|
||||
($Precision * $Precision);
|
||||
|
||||
// Returns the length squared of the largest forward difference from Wang's cubic formula.
|
||||
float wangs_formula_max_fdiff_pow2(float2 p0, float2 p1, float2 p2, float2 p3,
|
||||
float2x2 matrix) {
|
||||
float wangs_formula_max_fdiff_p2(float2 p0, float2 p1, float2 p2, float2 p3,
|
||||
float2x2 matrix) {
|
||||
float2 d0 = matrix * (fma(float2(-2), p1, p2) + p0);
|
||||
float2 d1 = matrix * (fma(float2(-2), p2, p3) + p1);
|
||||
return max(dot(d0,d0), dot(d1,d1));
|
||||
@ -27,17 +27,17 @@ float wangs_formula_max_fdiff_pow2(float2 p0, float2 p1, float2 p2, float2 p3,
|
||||
|
||||
float wangs_formula_cubic(float _precision_, float2 p0, float2 p1, float2 p2, float2 p3,
|
||||
float2x2 matrix) {
|
||||
float m = wangs_formula_max_fdiff_pow2(p0, p1, p2, p3, matrix);
|
||||
float m = wangs_formula_max_fdiff_p2(p0, p1, p2, p3, matrix);
|
||||
return max(ceil(sqrt($LengthTerm * _precision_ * sqrt(m))), 1.0);
|
||||
}
|
||||
|
||||
float wangs_formula_cubic_log2(float _precision_, float2 p0, float2 p1, float2 p2, float2 p3,
|
||||
float2x2 matrix) {
|
||||
float m = wangs_formula_max_fdiff_pow2(p0, p1, p2, p3, matrix);
|
||||
float m = wangs_formula_max_fdiff_p2(p0, p1, p2, p3, matrix);
|
||||
return ceil(log2(max($LengthTermPow2 * _precision_ * _precision_ * m, 1.0)) * .25);
|
||||
}
|
||||
|
||||
float wangs_formula_conic_pow2(float _precision_, float2 p0, float2 p1, float2 p2, float w) {
|
||||
float wangs_formula_conic_p2(float _precision_, float2 p0, float2 p1, float2 p2, float w) {
|
||||
// Translate the bounding box center to the origin.
|
||||
float2 C = (min(min(p0, p1), p2) + max(max(p0, p1), p2)) * 0.5;
|
||||
p0 -= C;
|
||||
@ -61,12 +61,12 @@ float wangs_formula_conic_pow2(float _precision_, float2 p0, float2 p1, float2 p
|
||||
}
|
||||
|
||||
float wangs_formula_conic(float _precision_, float2 p0, float2 p1, float2 p2, float w) {
|
||||
float n2 = wangs_formula_conic_pow2(_precision_, p0, p1, p2, w);
|
||||
float n2 = wangs_formula_conic_p2(_precision_, p0, p1, p2, w);
|
||||
return max(ceil(sqrt(n2)), 1.0);
|
||||
}
|
||||
|
||||
float wangs_formula_conic_log2(float _precision_, float2 p0, float2 p1, float2 p2, float w) {
|
||||
float n2 = wangs_formula_conic_pow2(_precision_, p0, p1, p2, w);
|
||||
float n2 = wangs_formula_conic_p2(_precision_, p0, p1, p2, w);
|
||||
return ceil(log2(max(n2, 1.0)) * .5);
|
||||
}
|
||||
|
||||
|
@ -342,7 +342,7 @@ DEF_TEST(wangs_formula_worst_case_cubic, r) {
|
||||
}
|
||||
// Make sure overflow saturates at infinity (not NaN).
|
||||
constexpr static float inf = std::numeric_limits<float>::infinity();
|
||||
REPORTER_ASSERT(r, wangs_formula::worst_case_cubic_pow4(kPrecision, inf, inf) == inf);
|
||||
REPORTER_ASSERT(r, wangs_formula::worst_case_cubic_p4(kPrecision, inf, inf) == inf);
|
||||
REPORTER_ASSERT(r, wangs_formula::worst_case_cubic(kPrecision, inf, inf) == inf);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user