diff options
author | Jeroen Bakker <j.bakker@atmind.nl> | 2012-07-03 13:05:19 +0400 |
---|---|---|
committer | Jeroen Bakker <j.bakker@atmind.nl> | 2012-07-03 13:05:19 +0400 |
commit | 2f5735a9d4745f33e850a163248c6c18a1305f64 (patch) | |
tree | a6f2712af50c9abcfc3c4853f0bda7c5e04df958 /source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp | |
parent | 63810ffcef825930b034899f54107fc35b159349 (diff) |
Optimized the area of interest of the lensdistortion node.
This will have faster feedback to the user, as lensdistortion is mostly
a node that is located at the end of a composite
Diffstat (limited to 'source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp')
-rw-r--r-- | source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp | 194 |
1 files changed, 169 insertions, 25 deletions
diff --git a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp index e3abf2aa70b..ea8483734d3 100644 --- a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp @@ -42,6 +42,10 @@ ScreenLensDistortionOperation::ScreenLensDistortionOperation() : NodeOperation() void ScreenLensDistortionOperation::initExecution() { this->m_inputProgram = this->getInputSocketReader(0); + this->initMutex(); + this->m_cx = 0.5f * (float)getWidth(); + this->m_cy = 0.5f * (float)getHeight(); + } void *ScreenLensDistortionOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers) @@ -139,52 +143,192 @@ void ScreenLensDistortionOperation::executePixel(float *outputColor, int x, int void ScreenLensDistortionOperation::deinitExecution() { + this->deinitMutex(); this->m_inputProgram = NULL; } -void ScreenLensDistortionOperation::determineUV(float result[2], float x, float y) const +void ScreenLensDistortionOperation::determineUV(float result[4], float x, float y, float distortion, float dispersion) +{ + if (!this->m_valuesAvailable) { + updateVariables(distortion, dispersion); + } + determineUV(result, x, y); +} + +void ScreenLensDistortionOperation::determineUV(float result[4], float x, float y) const { + const float height = this->getHeight(); + const float width = this->getWidth(); + + float d, t, ln[6] = {0, 0, 0, 0, 0, 0}; const float v = this->m_sc * ((y + 0.5f) - this->m_cy) / this->m_cy; const float u = this->m_sc * ((x + 0.5f) - this->m_cx) / this->m_cx; - const float t = ABS(MIN3(this->m_kr, this->m_kg, this->m_kb) * 4); - float d = 1.f / (1.f + sqrtf(t)); - result[0] = (u * d + 0.5f) * getWidth() - 0.5f; - result[1] = (v * d + 0.5f) * getHeight() - 0.5f; + const float uv_dot = u * u + v * v; + + if ((t = 1.f - this->m_kr4 * uv_dot) >= 0.f) { + d = 1.f / (1.f + sqrtf(t)); + ln[0] = (u * d + 0.5f) * width - 0.5f, ln[1] = (v * d + 0.5f) * height - 0.5f; + } + if ((t = 1.f - this->m_kg4 * uv_dot) >= 0.f) { + d = 1.f / (1.f + sqrtf(t)); + ln[2] = (u * d + 0.5f) * width - 0.5f, ln[3] = (v * d + 0.5f) * height - 0.5f; + } + if ((t = 1.f - this->m_kb4 * uv_dot) >= 0.f) { + d = 1.f / (1.f + sqrtf(t)); + ln[4] = (u * d + 0.5f) * width - 0.5f, ln[5] = (v * d + 0.5f) * height - 0.5f; + } + + float jit = this->m_data->jit; + float z; + { + // RG + const int dx = ln[2] - ln[0], dy = ln[3] - ln[1]; + const float dsf = sqrtf((float)dx * dx + dy * dy) + 1.f; + const int ds = (int)(jit ? ((dsf < 4.f) ? 2.f : sqrtf(dsf)) : dsf); + const float sd = 1.f / (float)ds; + + z = ds; + const float tz = ((float)z + (1.0f)) * sd; + t = 1.0f - (this->m_kr4 + tz * this->m_drg) * uv_dot; + d = 1.0f / (1.f + sqrtf(t)); + const float nx = (u * d + 0.5f) * width - 0.5f; + const float ny = (v * d + 0.5f) * height - 0.5f; + result[0] = nx; + result[1] = ny; + } + { + // GB + const int dx = ln[4] - ln[2], dy = ln[5] - ln[3]; + const float dsf = sqrtf((float)dx * dx + dy * dy) + 1.f; + const int ds = (int)(jit ? ((dsf < 4.f) ? 2.f : sqrtf(dsf)) : dsf); + const float sd = 1.f / (float)ds; + + z = ds; + const float tz = ((float)z + (1.0f)) * sd; + t = 1.f - (this->m_kg4 + tz * this->m_dgb) * uv_dot; + d = 1.f / (1.f + sqrtf(t)); + const float nx = (u * d + 0.5f) * width - 0.5f; + const float ny = (v * d + 0.5f) * height - 0.5f; + result[2] = nx; + result[3] = ny; + } } bool ScreenLensDistortionOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) { + rcti newInputValue; + newInputValue.xmin = 0; + newInputValue.ymin = 0; + newInputValue.xmax = 2; + newInputValue.ymax = 2; + + NodeOperation *operation = getInputOperation(1); + if (operation->determineDependingAreaOfInterest(&newInputValue, readOperation, output) ) { + return true; + } + + operation = getInputOperation(2); + if (operation->determineDependingAreaOfInterest(&newInputValue, readOperation, output) ) { + return true; + } + +#define MARGIN 64 + +#define UPDATE_INPUT \ + newInput.xmin = MIN3(newInput.xmin, coords[0], coords[2]); \ + newInput.ymin = MIN3(newInput.ymin, coords[1], coords[3]); \ + newInput.xmax = MAX3(newInput.xmax, coords[0], coords[2]); \ + newInput.ymax = MAX3(newInput.ymax, coords[1], coords[3]); + rcti newInput; - newInput.xmin = 0; - newInput.ymin = 0; - newInput.ymax = this->m_inputProgram->getHeight(); - newInput.xmax = this->m_inputProgram->getWidth(); - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + float margin; + float coords[4]; + if (m_valuesAvailable) { + determineUV(coords, input->xmin, input->ymin); + newInput.xmin = coords[0]; + newInput.ymin = coords[1]; + newInput.xmax = coords[0]; + newInput.ymax = coords[1]; + UPDATE_INPUT; + determineUV(coords, input->xmin, input->ymax); + UPDATE_INPUT; + determineUV(coords, input->xmax, input->ymax); + UPDATE_INPUT; + determineUV(coords, input->xmax, input->ymin); + UPDATE_INPUT; + margin = (ABS(this->m_distortion)+this->m_dispersion)*MARGIN; + } + else + { + determineUV(coords, input->xmin, input->ymin, 1.0f, 1.0f); + newInput.xmin = coords[0]; + newInput.ymin = coords[1]; + newInput.xmax = coords[0]; + newInput.ymax = coords[1]; + UPDATE_INPUT; + determineUV(coords, input->xmin, input->ymin, -1.0f, 1.0f); + UPDATE_INPUT; + + determineUV(coords, input->xmin, input->ymax, -1.0f, 1.0f); + UPDATE_INPUT; + determineUV(coords, input->xmin, input->ymax, 1.0f, 1.0f); + UPDATE_INPUT; + + determineUV(coords, input->xmax, input->ymax, -1.0f, 1.0f); + UPDATE_INPUT; + determineUV(coords, input->xmax, input->ymax, 1.0f, 1.0f); + UPDATE_INPUT; + + determineUV(coords, input->xmax, input->ymin, -1.0f, 1.0f); + UPDATE_INPUT; + determineUV(coords, input->xmax, input->ymin, 1.0f, 1.0f); + UPDATE_INPUT; + margin=MARGIN; + } + +#undef UPDATE_INPUT + newInput.xmin -= margin; + newInput.ymin -= margin; + newInput.xmax += margin; + newInput.ymax += margin; + + operation = getInputOperation(0); + if (operation->determineDependingAreaOfInterest(&newInput, readOperation, output) ) { + return true; + } + return false; +} + +void ScreenLensDistortionOperation::updateVariables(float distortion, float dispersion) +{ + this->m_kg = MAX2(MIN2(distortion, 1.f), -0.999f); + // smaller dispersion range for somewhat more control + const float d = 0.25f * MAX2(MIN2(dispersion, 1.f), 0.f); + this->m_kr = MAX2(MIN2((this->m_kg + d), 1.0f), -0.999f); + this->m_kb = MAX2(MIN2((this->m_kg - d), 1.0f), -0.999f); + this->m_maxk = MAX3(this->m_kr, this->m_kg, this->m_kb); + this->m_sc = (this->m_data->fit && (this->m_maxk > 0.f)) ? (1.f / (1.f + 2.f * this->m_maxk)) : (1.f / (1.f + this->m_maxk)); + this->m_drg = 4.f * (this->m_kg - this->m_kr); + this->m_dgb = 4.f * (this->m_kb - this->m_kg); + + this->m_kr4 = this->m_kr * 4.0f; + this->m_kg4 = this->m_kg * 4.0f; + this->m_kb4 = this->m_kb * 4.0f; } void ScreenLensDistortionOperation::updateDispersionAndDistortion(MemoryBuffer **inputBuffers) { + if (this->m_valuesAvailable) return; + + this->lockMutex(); if (!this->m_valuesAvailable) { float result[4]; this->getInputSocketReader(1)->read(result, 0, 0, COM_PS_NEAREST, inputBuffers); this->m_distortion = result[0]; this->getInputSocketReader(2)->read(result, 0, 0, COM_PS_NEAREST, inputBuffers); this->m_dispersion = result[0]; - this->m_kg = MAX2(MIN2(this->m_distortion, 1.f), -0.999f); - // smaller dispersion range for somewhat more control - const float d = 0.25f * MAX2(MIN2(this->m_dispersion, 1.f), 0.f); - this->m_kr = MAX2(MIN2((this->m_kg + d), 1.0f), -0.999f); - this->m_kb = MAX2(MIN2((this->m_kg - d), 1.0f), -0.999f); - this->m_maxk = MAX3(this->m_kr, this->m_kg, this->m_kb); - this->m_sc = (this->m_data->fit && (this->m_maxk > 0.f)) ? (1.f / (1.f + 2.f * this->m_maxk)) : (1.f / (1.f + this->m_maxk)); - this->m_drg = 4.f * (this->m_kg - this->m_kr); - this->m_dgb = 4.f * (this->m_kb - this->m_kg); - - this->m_kr4 = this->m_kr * 4.0f; - this->m_kg4 = this->m_kg * 4.0f; - this->m_kb4 = this->m_kb * 4.0f; - this->m_cx = 0.5f * (float)getWidth(); - this->m_cy = 0.5f * (float)getHeight(); + updateVariables(this->m_distortion, this->m_dispersion); this->m_valuesAvailable = true; } + this->unlockMutex(); } |