Fix T52927: Compositor wrong scale when scale size input is connected to complex...
authorSergey Sharybin <sergey.vfx@gmail.com>
Mon, 2 Oct 2017 10:54:08 +0000 (15:54 +0500)
committerSergey Sharybin <sergey.vfx@gmail.com>
Mon, 2 Oct 2017 10:55:52 +0000 (15:55 +0500)
The issue here is that we can not read scale from socket when determining
dependent area of interest. This area will depend on current pixel. Now fall
back to more stupid but reliable thing: if scale size input is connected to some
nodes, we use the whole frame as area of interest.

source/blender/compositor/nodes/COM_ScaleNode.cpp
source/blender/compositor/operations/COM_ScaleOperation.cpp
source/blender/compositor/operations/COM_ScaleOperation.h

index 61eea9227dcf1b382a8e7f4f0e2a151899f9840c..ef4128a78b4eb55c9712fe3c3d4990b43f91c80d 100644 (file)
@@ -52,6 +52,9 @@ void ScaleNode::convertToOperations(NodeConverter &converter, const CompositorCo
                        converter.mapInputSocket(inputXSocket, operation->getInputSocket(1));
                        converter.mapInputSocket(inputYSocket, operation->getInputSocket(2));
                        converter.mapOutputSocket(outputSocket, operation->getOutputSocket(0));
+
+                       operation->setVariableSize(inputXSocket->isLinked() ||
+                                                  inputYSocket->isLinked());
                        break;
                }
                case CMP_SCALE_SCENEPERCENT:
@@ -67,6 +70,10 @@ void ScaleNode::convertToOperations(NodeConverter &converter, const CompositorCo
                        converter.addLink(scaleFactorOperation->getOutputSocket(), operation->getInputSocket(1));
                        converter.addLink(scaleFactorOperation->getOutputSocket(), operation->getInputSocket(2));
                        converter.mapOutputSocket(outputSocket, operation->getOutputSocket(0));
+
+                       operation->setVariableSize(inputXSocket->isLinked() ||
+                                                  inputYSocket->isLinked());
+
                        break;
                }
                case CMP_SCALE_RENDERPERCENT:
@@ -81,9 +88,13 @@ void ScaleNode::convertToOperations(NodeConverter &converter, const CompositorCo
                        operation->setNewHeight(rd->ysch * rd->size / 100.0f);
                        operation->getInputSocket(0)->setResizeMode(COM_SC_NO_RESIZE);
                        converter.addOperation(operation);
-                       
+
                        converter.mapInputSocket(inputSocket, operation->getInputSocket(0));
                        converter.mapOutputSocket(outputSocket, operation->getOutputSocket(0));
+
+                       operation->setVariableSize(inputXSocket->isLinked() ||
+                                                  inputYSocket->isLinked());
+
                        break;
                }
                case CMP_SCALE_ABSOLUTE:
@@ -91,11 +102,15 @@ void ScaleNode::convertToOperations(NodeConverter &converter, const CompositorCo
                        /* TODO: what is the use of this one.... perhaps some issues when the ui was updated... */
                        ScaleAbsoluteOperation *operation = new ScaleAbsoluteOperation();
                        converter.addOperation(operation);
-                       
+
                        converter.mapInputSocket(inputSocket, operation->getInputSocket(0));
                        converter.mapInputSocket(inputXSocket, operation->getInputSocket(1));
                        converter.mapInputSocket(inputYSocket, operation->getInputSocket(2));
                        converter.mapOutputSocket(outputSocket, operation->getOutputSocket(0));
+
+                       operation->setVariableSize(inputXSocket->isLinked() ||
+                                                  inputYSocket->isLinked());
+
                        break;
                }
        }
index 46e155e43b55b65c76c61c9f7be2d01bd10d4254..b498b359144f8a0abd67c1457c882fd3bd020e93 100644 (file)
@@ -36,6 +36,7 @@ BaseScaleOperation::BaseScaleOperation()
 #else
        m_sampler = -1;
 #endif
+       m_variable_size = false;
 }
 
 ScaleOperation::ScaleOperation() : BaseScaleOperation()
@@ -87,20 +88,27 @@ void ScaleOperation::executePixelSampled(float output[4], float x, float y, Pixe
 bool ScaleOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
 {
        rcti newInput;
-       float scaleX[4];
-       float scaleY[4];
-
-       this->m_inputXOperation->readSampled(scaleX, 0, 0, COM_PS_NEAREST);
-       this->m_inputYOperation->readSampled(scaleY, 0, 0, COM_PS_NEAREST);
+       if (!m_variable_size) {
+               float scaleX[4];
+               float scaleY[4];
 
-       const float scx = scaleX[0];
-       const float scy = scaleY[0];
+               this->m_inputXOperation->readSampled(scaleX, 0, 0, COM_PS_NEAREST);
+               this->m_inputYOperation->readSampled(scaleY, 0, 0, COM_PS_NEAREST);
 
-       newInput.xmax = this->m_centerX + (input->xmax - this->m_centerX) / scx;
-       newInput.xmin = this->m_centerX + (input->xmin - this->m_centerX) / scx;
-       newInput.ymax = this->m_centerY + (input->ymax - this->m_centerY) / scy;
-       newInput.ymin = this->m_centerY + (input->ymin - this->m_centerY) / scy;
+               const float scx = scaleX[0];
+               const float scy = scaleY[0];
 
+               newInput.xmax = this->m_centerX + (input->xmax - this->m_centerX) / scx;
+               newInput.xmin = this->m_centerX + (input->xmin - this->m_centerX) / scx;
+               newInput.ymax = this->m_centerY + (input->ymax - this->m_centerY) / scy;
+               newInput.ymin = this->m_centerY + (input->ymin - this->m_centerY) / scy;
+       }
+       else {
+               newInput.xmax = this->getWidth();
+               newInput.xmin = 0;
+               newInput.ymax = this->getHeight();
+               newInput.ymin = 0;
+       }
        return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
 }
 
@@ -162,24 +170,32 @@ void ScaleAbsoluteOperation::executePixelSampled(float output[4], float x, float
 bool ScaleAbsoluteOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
 {
        rcti newInput;
-       float scaleX[4];
-       float scaleY[4];
-
-       this->m_inputXOperation->readSampled(scaleX, 0, 0, COM_PS_NEAREST);
-       this->m_inputYOperation->readSampled(scaleY, 0, 0, COM_PS_NEAREST);
-
-       const float scx = scaleX[0];
-       const float scy = scaleY[0];
-       const float width = this->getWidth();
-       const float height = this->getHeight();
-       //div
-       float relateveXScale = scx / width;
-       float relateveYScale = scy / height;
-
-       newInput.xmax = this->m_centerX + (input->xmax - this->m_centerX) / relateveXScale;
-       newInput.xmin = this->m_centerX + (input->xmin - this->m_centerX) / relateveXScale;
-       newInput.ymax = this->m_centerY + (input->ymax - this->m_centerY) / relateveYScale;
-       newInput.ymin = this->m_centerY + (input->ymin - this->m_centerY) / relateveYScale;
+       if (!m_variable_size) {
+               float scaleX[4];
+               float scaleY[4];
+
+               this->m_inputXOperation->readSampled(scaleX, 0, 0, COM_PS_NEAREST);
+               this->m_inputYOperation->readSampled(scaleY, 0, 0, COM_PS_NEAREST);
+
+               const float scx = scaleX[0];
+               const float scy = scaleY[0];
+               const float width = this->getWidth();
+               const float height = this->getHeight();
+               //div
+               float relateveXScale = scx / width;
+               float relateveYScale = scy / height;
+
+               newInput.xmax = this->m_centerX + (input->xmax - this->m_centerX) / relateveXScale;
+               newInput.xmin = this->m_centerX + (input->xmin - this->m_centerX) / relateveXScale;
+               newInput.ymax = this->m_centerY + (input->ymax - this->m_centerY) / relateveYScale;
+               newInput.ymin = this->m_centerY + (input->ymin - this->m_centerY) / relateveYScale;
+       }
+       else {
+               newInput.xmax = this->getWidth();
+               newInput.xmin = 0;
+               newInput.ymax = this->getHeight();
+               newInput.ymin = 0;
+       }
 
        return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
 }
index 706a5898027eefe6d62d03f67c809a442d5ac663..17cd31f9710c349306592b09a05780ea8e30a45a 100644 (file)
@@ -28,6 +28,7 @@
 class BaseScaleOperation : public NodeOperation {
 public:
        void setSampler(PixelSampler sampler) { this->m_sampler = (int) sampler; }
+       void setVariableSize(bool variable_size) { m_variable_size = variable_size; };
 
 protected:
        BaseScaleOperation();
@@ -35,6 +36,7 @@ protected:
        PixelSampler getEffectiveSampler(PixelSampler sampler) { return (m_sampler == -1) ? sampler : (PixelSampler) m_sampler;  }
 
        int m_sampler;
+       bool m_variable_size;
 };
 
 class ScaleOperation : public BaseScaleOperation {