forked from bartvdbraak/blender
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
This commit is contained in:
parent
63810ffcef
commit
2f5735a9d4
@ -48,13 +48,21 @@ void LensDistortionNode::convertToOperations(ExecutionSystem *graph, CompositorC
|
||||
}
|
||||
else {
|
||||
ScreenLensDistortionOperation *operation = new ScreenLensDistortionOperation();
|
||||
operation->setData(data);
|
||||
if (!(this->getInputSocket(1)->isConnected() || this->getInputSocket(2)->isConnected()))
|
||||
{
|
||||
// no nodes connected to the distortion and dispersion. We can precalculate some values
|
||||
float distortion = ((const bNodeSocketValueFloat *)this->getInputSocket(1)->getbNodeSocket()->default_value)->value;
|
||||
float dispersion = ((const bNodeSocketValueFloat *)this->getInputSocket(2)->getbNodeSocket()->default_value)->value;
|
||||
operation->setDistortionAndDispersion(distortion, dispersion);
|
||||
}
|
||||
|
||||
this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
|
||||
this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph);
|
||||
this->getInputSocket(2)->relinkConnections(operation->getInputSocket(2), 2, graph);
|
||||
|
||||
this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket(0));
|
||||
|
||||
operation->setData(data);
|
||||
graph->addOperation(operation);
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -66,9 +66,23 @@ public:
|
||||
|
||||
bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
|
||||
|
||||
/**
|
||||
* @brief Set the distortion and dispersion and precalc some values
|
||||
* @param distortion
|
||||
* @param dispersion
|
||||
*/
|
||||
void setDistortionAndDispersion(float distortion, float dispersion) {
|
||||
this->m_distortion = distortion;
|
||||
this->m_dispersion = dispersion;
|
||||
updateVariables(distortion, dispersion);
|
||||
this->m_valuesAvailable = true;
|
||||
}
|
||||
|
||||
private:
|
||||
void determineUV(float *result, float x, float y) const;
|
||||
void determineUV(float result[4], float x, float y) const;
|
||||
void determineUV(float result[4], float x, float y, float distortion, float dispersion);
|
||||
void updateDispersionAndDistortion(MemoryBuffer **inputBuffers);
|
||||
void updateVariables(float distortion, float dispersion);
|
||||
|
||||
};
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user