Merge pull request #7698 from unknownbrackets/bezier-minor

Try to optimize bezier color sampling
This commit is contained in:
Henrik Rydgård 2015-04-19 10:24:39 +02:00
commit 52b7bab829
2 changed files with 63 additions and 94 deletions

View File

@ -36,12 +36,16 @@ inline float lerp(float a, float b, float x) {
}
// SLOW!
inline void lerpColor(u8 a[4], u8 b[4], float x, u8 out[4]) {
inline void lerpColor(const Vec4f &a, const Vec4f &b, float x, Vec4f &out) {
for (int i = 0; i < 4; i++) {
out[i] = (u8)((float)a[i] + x * ((float)b[i] - (float)a[i]));
out[i] = a[i] + x * (b[i] - a[i]);
}
}
inline void lerpColor(const u8 *a, const u8 *b, float x, Vec4f &out) {
lerpColor(Vec4f::FromRGBA(a), Vec4f::FromRGBA(b), x, out);
}
// We decode all vertices into a common format for easy interpolation and stuff.
// Not fast but can be optimized later.
struct BezierPatch {
@ -52,53 +56,54 @@ struct BezierPatch {
int index;
struct SamplingParams {
float fracU;
float fracV;
int tl;
int tr;
int bl;
int br;
SamplingParams(float u, float v) {
u *= 3.0f;
v *= 3.0f;
int iu = (int)floorf(u);
int iv = (int)floorf(v);
int iu2 = iu + 1;
int iv2 = iv + 1;
fracU = u - iu;
fracV = v - iv;
if (iu2 > 3)
iu2 = 3;
if (iv2 > 3)
iv2 = 3;
tl = iu + 4 * iv;
tr = iu2 + 4 * iv;
bl = iu + 4 * iv2;
br = iu2 + 4 * iv2;
}
};
// Interpolate colors between control points (bilinear, should be good enough).
void sampleColor(float u, float v, u8 color[4]) const {
u *= 3.0f;
v *= 3.0f;
int iu = (int)floorf(u);
int iv = (int)floorf(v);
int iu2 = iu + 1;
int iv2 = iv + 1;
float fracU = u - iu;
float fracV = v - iv;
if (iu2 > 3) iu2 = 3;
if (iv2 > 3) iv2 = 3;
int tl = iu + 4 * iv;
int tr = iu2 + 4 * iv;
int bl = iu + 4 * iv2;
int br = iu2 + 4 * iv2;
u8 upperColor[4], lowerColor[4];
lerpColor(points[tl]->color, points[tr]->color, fracU, upperColor);
lerpColor(points[bl]->color, points[br]->color, fracU, lowerColor);
lerpColor(upperColor, lowerColor, fracV, color);
const SamplingParams params(u, v);
Vec4f upperColor, lowerColor, resultColor;
lerpColor(points[params.tl]->color, points[params.tr]->color, params.fracU, upperColor);
lerpColor(points[params.bl]->color, points[params.br]->color, params.fracU, lowerColor);
lerpColor(upperColor, lowerColor, params.fracV, resultColor);
resultColor.ToRGBA(color);
}
void sampleTexUV(float u, float v, float &tu, float &tv) const {
u *= 3.0f;
v *= 3.0f;
int iu = (int)floorf(u);
int iv = (int)floorf(v);
int iu2 = iu + 1;
int iv2 = iv + 1;
float fracU = u - iu;
float fracV = v - iv;
if (iu2 > 3) iu2 = 3;
if (iv2 > 3) iv2 = 3;
int tl = iu + 4 * iv;
int tr = iu2 + 4 * iv;
int bl = iu + 4 * iv2;
int br = iu2 + 4 * iv2;
float upperTU = lerp(points[tl]->uv[0], points[tr]->uv[0], fracU);
float upperTV = lerp(points[tl]->uv[1], points[tr]->uv[1], fracU);
float lowerTU = lerp(points[bl]->uv[0], points[br]->uv[0], fracU);
float lowerTV = lerp(points[bl]->uv[1], points[br]->uv[1], fracU);
tu = lerp(upperTU, lowerTU, fracV);
tv = lerp(upperTV, lowerTV, fracV);
const SamplingParams params(u, v);
float upperTU = lerp(points[params.tl]->uv[0], points[params.tr]->uv[0], params.fracU);
float upperTV = lerp(points[params.tl]->uv[1], points[params.tr]->uv[1], params.fracU);
float lowerTU = lerp(points[params.bl]->uv[0], points[params.br]->uv[0], params.fracU);
float lowerTV = lerp(points[params.bl]->uv[1], points[params.br]->uv[1], params.fracU);
tu = lerp(upperTU, lowerTU, params.fracV);
tv = lerp(upperTV, lowerTV, params.fracV);
}
};
@ -108,56 +113,6 @@ struct SplinePatchLocal {
int count_v;
int type_u;
int type_v;
/*
// Interpolate colors between control points (bilinear, should be good enough).
void sampleColor(float u, float v, u8 color[4]) const {
u *= 3.0f;
v *= 3.0f;
int iu = (int)floorf(u);
int iv = (int)floorf(v);
int iu2 = iu + 1;
int iv2 = iv + 1;
float fracU = u - iu;
float fracV = v - iv;
if (iu2 >= count_u) iu2 = count_u - 1;
if (iv2 >= count_v) iv2 = count_v - 1;
int tl = iu + count_u * iv;
int tr = iu2 + count_u * iv;
int bl = iu + count_u * iv2;
int br = iu2 + count_u * iv2;
u8 upperColor[4], lowerColor[4];
lerpColor(points[tl]->color, points[tr]->color, fracU, upperColor);
lerpColor(points[bl]->color, points[br]->color, fracU, lowerColor);
lerpColor(upperColor, lowerColor, fracV, color);
}
void sampleTexUV(float u, float v, float &tu, float &tv) const {
u *= 3.0f;
v *= 3.0f;
int iu = (int)floorf(u);
int iv = (int)floorf(v);
int iu2 = iu + 1;
int iv2 = iv + 1;
float fracU = u - iu;
float fracV = v - iv;
if (iu2 >= count_u) iu2 = count_u - 1;
if (iv2 >= count_v) iv2 = count_v - 1;
int tl = iu + count_u * iv;
int tr = iu2 + count_u * iv;
int bl = iu + count_u * iv2;
int br = iu2 + count_u * iv2;
float upperTU = lerp(points[tl]->uv[0], points[tr]->uv[0], fracU);
float upperTV = lerp(points[tl]->uv[1], points[tr]->uv[1], fracU);
float lowerTU = lerp(points[bl]->uv[0], points[br]->uv[0], fracU);
float lowerTV = lerp(points[bl]->uv[1], points[br]->uv[1], fracU);
tu = lerp(upperTU, lowerTU, fracV);
tv = lerp(upperTV, lowerTV, fracV);
}*/
};
enum quality {

View File

@ -561,7 +561,9 @@ public:
// Only implemented for T=int and T=float
static Vec4 FromRGBA(unsigned int rgba);
static Vec4 FromRGBA(const u8 *rgba);
unsigned int ToRGBA() const;
void ToRGBA(u8 *rgba) const;
static Vec4 AssignToAll(const T& f)
{
@ -1012,6 +1014,12 @@ inline Vec4<float> Vec4<float>::FromRGBA(unsigned int rgba)
#endif
}
template<typename T>
inline Vec4<T> Vec4<T>::FromRGBA(const u8 *rgba)
{
return Vec4<T>::FromRGBA(*(unsigned int *)rgba);
}
template<>
inline Vec4<int> Vec4<int>::FromRGBA(unsigned int rgba)
{
@ -1051,6 +1059,12 @@ __forceinline unsigned int Vec4<int>::ToRGBA() const
#endif
}
template<typename T>
__forceinline void Vec4<T>::ToRGBA(u8 *rgba) const
{
*(u32 *)rgba = ToRGBA();
}
}; // namespace Math3D
// linear interpolation via float: 0.0=begin, 1.0=end