Add mipmap scaling according to alphatest coverage.
This commit is contained in:
@ -194,10 +194,16 @@ void FloatImage::scaleBias(uint base_component, uint num, float scale, float bia
|
||||
}
|
||||
|
||||
/// Clamp the elements of the image.
|
||||
void FloatImage::clamp(float low, float high)
|
||||
void FloatImage::clamp(uint base_component, uint num, float low, float high)
|
||||
{
|
||||
for(uint i = 0; i < m_count; i++) {
|
||||
m_mem[i] = nv::clamp(m_mem[i], low, high);
|
||||
const uint size = m_width * m_height;
|
||||
|
||||
for(uint c = 0; c < num; c++) {
|
||||
float * ptr = this->channel(base_component + c);
|
||||
|
||||
for(uint i = 0; i < size; i++) {
|
||||
ptr[i] = nv::clamp(ptr[i], low, high);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -945,6 +951,54 @@ void FloatImage::flip()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float FloatImage::alphaTestCoverage(float alphaRef, int alphaChannel) const
|
||||
{
|
||||
const uint w = m_width;
|
||||
const uint h = m_height;
|
||||
|
||||
float coverage = 0.0f;
|
||||
|
||||
for (uint y = 0; y < h; y++) {
|
||||
const float * alpha = scanline(y, alphaChannel);
|
||||
for (uint x = 0; x < w; x++) {
|
||||
if (alpha[x] > alphaRef) coverage += 1.0f; // @@ gt or lt?
|
||||
}
|
||||
}
|
||||
|
||||
return coverage / float(w * h);
|
||||
}
|
||||
|
||||
void FloatImage::scaleAlphaToCoverage(float desiredCoverage, float alphaRef, int alphaChannel)
|
||||
{
|
||||
float minAlphaRef = 0.0f;
|
||||
float maxAlphaRef = 1.0f;
|
||||
float midAlphaRef = 0.5f;
|
||||
|
||||
// Determine desired scale using a binary search. Hardcoded to 8 steps max.
|
||||
for (int i = 0; i < 8; i++) {
|
||||
float currentCoverage = alphaTestCoverage(midAlphaRef, alphaChannel);
|
||||
|
||||
if (currentCoverage > desiredCoverage) {
|
||||
maxAlphaRef = midAlphaRef;
|
||||
}
|
||||
else if (currentCoverage < desiredCoverage) {
|
||||
minAlphaRef = midAlphaRef;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
|
||||
midAlphaRef = (minAlphaRef + maxAlphaRef) * 0.5f;
|
||||
}
|
||||
|
||||
float alphaScale = alphaRef / midAlphaRef;
|
||||
|
||||
// Scale alpha channel.
|
||||
scaleBias(alphaChannel, 1, alphaScale, 0.0f);
|
||||
}
|
||||
|
||||
|
||||
FloatImage* FloatImage::clone() const
|
||||
{
|
||||
FloatImage* copy = new FloatImage();
|
||||
|
||||
@ -59,10 +59,9 @@ public:
|
||||
|
||||
NVIMAGE_API void packNormals(uint base_component);
|
||||
NVIMAGE_API void expandNormals(uint base_component);
|
||||
NVIMAGE_API void scaleBias(uint base_component, uint num, float scale, float add);
|
||||
NVIMAGE_API void scaleBias(uint base_component, uint num, float scale, float bias);
|
||||
|
||||
//NVIMAGE_API void clamp(uint base_component, uint num);
|
||||
NVIMAGE_API void clamp(float low, float high);
|
||||
NVIMAGE_API void clamp(uint base_component, uint num, float low, float high);
|
||||
|
||||
NVIMAGE_API void toLinear(uint base_component, uint num, float gamma = 2.2f);
|
||||
NVIMAGE_API void toGamma(uint base_component, uint num, float gamma = 2.2f);
|
||||
@ -87,6 +86,9 @@ public:
|
||||
NVIMAGE_API void applyKernelHorizontal(const PolyphaseKernel & k, int y, uint c, uint a, WrapMode wm, float * output) const;
|
||||
|
||||
NVIMAGE_API void flip();
|
||||
|
||||
NVIMAGE_API float alphaTestCoverage(float alphaRef, int alphaChannel) const;
|
||||
NVIMAGE_API void scaleAlphaToCoverage(float coverage, float alphaRef, int alphaChannel);
|
||||
//@}
|
||||
|
||||
uint width() const { return m_width; }
|
||||
|
||||
Reference in New Issue
Block a user