diff --git a/GPU/Common/SplineCommon.h b/GPU/Common/SplineCommon.h index 9ecd113e9..0ab10fd6b 100644 --- a/GPU/Common/SplineCommon.h +++ b/GPU/Common/SplineCommon.h @@ -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 { diff --git a/GPU/Math3D.h b/GPU/Math3D.h index 921786ba5..f9d63222e 100644 --- a/GPU/Math3D.h +++ b/GPU/Math3D.h @@ -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 Vec4::FromRGBA(unsigned int rgba) #endif } +template +inline Vec4 Vec4::FromRGBA(const u8 *rgba) +{ + return Vec4::FromRGBA(*(unsigned int *)rgba); +} + template<> inline Vec4 Vec4::FromRGBA(unsigned int rgba) { @@ -1051,6 +1059,12 @@ __forceinline unsigned int Vec4::ToRGBA() const #endif } +template +__forceinline void Vec4::ToRGBA(u8 *rgba) const +{ + *(u32 *)rgba = ToRGBA(); +} + }; // namespace Math3D // linear interpolation via float: 0.0=begin, 1.0=end