Fix for 34703 Mix node (Hue, Saturation) update and rendering error
authorJeroen Bakker <j.bakker@atmind.nl>
Thu, 4 Apr 2013 19:53:30 +0000 (19:53 +0000)
committerJeroen Bakker <j.bakker@atmind.nl>
Thu, 4 Apr 2013 19:53:30 +0000 (19:53 +0000)
Fix for 34494 Blender 2.65 regression test error - compo_map_uv_cubes.blend - stripe/artifact between cubes

Hue and saturation node has an early break when saturarion is 0. When this happened the input 1 color needed to be used. This behaviour was not merged.

When no FSAA is used in the ZCombine. a mask will be created, this mask will be antialiased and based on this mask the colors between the two images are blended. This was also behaviour that was not merged correctly. Now it is back making much better z-combines.

Hope nobody uses these gabs as a work around.

 - At Mind -
Jeroen & Monique

source/blender/compositor/nodes/COM_ZCombineNode.cpp
source/blender/compositor/operations/COM_MixHueOperation.cpp
source/blender/compositor/operations/COM_MixSaturationOperation.cpp
source/blender/compositor/operations/COM_ZCombineOperation.cpp
source/blender/compositor/operations/COM_ZCombineOperation.h

index f48fca72c05c5683d4b0bdb0f72cdee042b47373..35eedf435f6ed00b5f7f01e6e1da71e5a34415ca 100644 (file)
 #include "COM_ExecutionSystem.h"
 #include "COM_SetValueOperation.h"
 #include "COM_MathBaseOperation.h"
+#include "COM_AntiAliasOperation.h"
+#include "COM_MixBlendOperation.h"
 
 #include "DNA_material_types.h" // the ramp types
 
 void ZCombineNode::convertToOperations(ExecutionSystem *system, CompositorContext *context)
 {
-       if (this->getOutputSocket(0)->isConnected()) {
-               ZCombineOperation *operation = NULL;
-               if (this->getbNode()->custom1) {
-                       operation = new ZCombineAlphaOperation();
+       if (context->getRenderData()->scemode & R_FULL_SAMPLE) {
+               if (this->getOutputSocket(0)->isConnected()) {
+                       ZCombineOperation *operation = NULL;
+                       if (this->getbNode()->custom1) {
+                               operation = new ZCombineAlphaOperation();
+                       }
+                       else {
+                               operation = new ZCombineOperation();
+                       }
+
+                       this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, system);
+                       this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, system);
+                       this->getInputSocket(2)->relinkConnections(operation->getInputSocket(2), 2, system);
+                       this->getInputSocket(3)->relinkConnections(operation->getInputSocket(3), 3, system);
+                       this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket());
+                       system->addOperation(operation);
+                       if (this->getOutputSocket(1)->isConnected()) {
+                               MathMinimumOperation *zoperation = new MathMinimumOperation();
+                               addLink(system, operation->getInputSocket(1)->getConnection()->getFromSocket(), zoperation->getInputSocket(0));
+                               addLink(system, operation->getInputSocket(3)->getConnection()->getFromSocket(), zoperation->getInputSocket(1));
+                               this->getOutputSocket(1)->relinkConnections(zoperation->getOutputSocket());
+                               system->addOperation(zoperation);
+                       }
                }
                else {
-                       operation = new ZCombineOperation();
+                       if (this->getOutputSocket(1)->isConnected()) {
+                               MathMinimumOperation *zoperation = new MathMinimumOperation();
+                               this->getInputSocket(1)->relinkConnections(zoperation->getInputSocket(0), 1, system);
+                               this->getInputSocket(3)->relinkConnections(zoperation->getInputSocket(1), 3, system);
+                               this->getOutputSocket(1)->relinkConnections(zoperation->getOutputSocket());
+                               system->addOperation(zoperation);
+                       }
                }
+       } else {
+               // not full anti alias, use masking for Z combine. be aware it uses anti aliasing.
+               // step 1 create mask
+               MathGreaterThanOperation *maskoperation = new MathGreaterThanOperation();
+               this->getInputSocket(1)->relinkConnections(maskoperation->getInputSocket(0), 1, system);
+               this->getInputSocket(3)->relinkConnections(maskoperation->getInputSocket(1), 3, system);
+
+               // step 2 anti alias mask bit of an expensive operation, but does the trick
+               AntiAliasOperation *antialiasoperation = new AntiAliasOperation();
+               addLink(system, maskoperation->getOutputSocket(), antialiasoperation->getInputSocket(0));
+
+               // use mask to blend between the input colors.
+               ZCombineMaskOperation *zcombineoperation = this->getbNode()->custom1?new ZCombineMaskAlphaOperation():new ZCombineMaskOperation();
+               addLink(system, antialiasoperation->getOutputSocket(), zcombineoperation->getInputSocket(0));
+               this->getInputSocket(0)->relinkConnections(zcombineoperation->getInputSocket(1), 0, system);
+               this->getInputSocket(2)->relinkConnections(zcombineoperation->getInputSocket(2), 2, system);
+               this->getOutputSocket(0)->relinkConnections(zcombineoperation->getOutputSocket());
+
+               system->addOperation(maskoperation);
+               system->addOperation(antialiasoperation);
+               system->addOperation(zcombineoperation);
 
-               this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, system);
-               this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, system);
-               this->getInputSocket(2)->relinkConnections(operation->getInputSocket(2), 2, system);
-               this->getInputSocket(3)->relinkConnections(operation->getInputSocket(3), 3, system);
-               this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket());
-               system->addOperation(operation);
-               if (this->getOutputSocket(1)->isConnected()) {
-                       MathMinimumOperation *zoperation = new MathMinimumOperation();
-                       addLink(system, operation->getInputSocket(1)->getConnection()->getFromSocket(), zoperation->getInputSocket(0));
-                       addLink(system, operation->getInputSocket(3)->getConnection()->getFromSocket(), zoperation->getInputSocket(1));
-                       this->getOutputSocket(1)->relinkConnections(zoperation->getOutputSocket());
-                       system->addOperation(zoperation);
-               }
-       }
-       else {
                if (this->getOutputSocket(1)->isConnected()) {
                        MathMinimumOperation *zoperation = new MathMinimumOperation();
-                       this->getInputSocket(1)->relinkConnections(zoperation->getInputSocket(0), 1, system);
-                       this->getInputSocket(3)->relinkConnections(zoperation->getInputSocket(1), 3, system);
+                       addLink(system, maskoperation->getInputSocket(0)->getConnection()->getFromSocket(), zoperation->getInputSocket(0));
+                       addLink(system, maskoperation->getInputSocket(1)->getConnection()->getFromSocket(), zoperation->getInputSocket(1));
                        this->getOutputSocket(1)->relinkConnections(zoperation->getOutputSocket());
                        system->addOperation(zoperation);
                }
index 5688d6b26f0bfc891d25fc285511144cf66bf27a..1fa393bb362d869ebff7f550b4f3858f9985f8cd 100644 (file)
@@ -56,6 +56,8 @@ void MixHueOperation::executePixel(float output[4], float x, float y, PixelSampl
                output[0] = valuem * (inputColor1[0]) + value * tmpr;
                output[1] = valuem * (inputColor1[1]) + value * tmpg;
                output[2] = valuem * (inputColor1[2]) + value * tmpb;
+       } else {
+                       copy_v3_v3(output, inputColor1);
        }
        output[3] = inputColor1[3];
 
index 401ad8d42476475c8971b77f361d504f5b1e23aa..69207d7fbaab30bfaf82f3e7b09017af79a82f9e 100644 (file)
@@ -52,7 +52,10 @@ void MixSaturationOperation::executePixel(float output[4], float x, float y, Pix
                float colH, colS, colV;
                rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV);
                hsv_to_rgb(rH, (valuem * rS + value * colS), rV, &output[0], &output[1], &output[2]);
+       } else {
+               copy_v3_v3(output, inputColor1);
        }
+
        output[3] = inputColor1[3];
 
        clampIfNeeded(output);
index 5e4f90b02690e6c0121feb90b8b7dbc053fc8e0b..97a4aefbfac5bbd15019af129fe7867b1e2e63b2 100644 (file)
@@ -92,3 +92,71 @@ void ZCombineOperation::deinitExecution()
        this->m_image2Reader = NULL;
        this->m_depth2Reader = NULL;
 }
+
+// MASK combine
+ZCombineMaskOperation::ZCombineMaskOperation() : NodeOperation()
+{
+       this->addInputSocket(COM_DT_VALUE); //mask
+       this->addInputSocket(COM_DT_COLOR);
+       this->addInputSocket(COM_DT_COLOR);
+       this->addOutputSocket(COM_DT_COLOR);
+
+       this->m_maskReader = NULL;
+       this->m_image1Reader = NULL;
+       this->m_image2Reader = NULL;
+}
+
+void ZCombineMaskOperation::initExecution()
+{
+       this->m_maskReader = this->getInputSocketReader(0);
+       this->m_image1Reader = this->getInputSocketReader(1);
+       this->m_image2Reader = this->getInputSocketReader(2);
+}
+
+void ZCombineMaskOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+       float mask[4];
+       float color1[4];
+       float color2[4];
+
+       this->m_maskReader->read(mask, x, y, sampler);
+       this->m_image1Reader->read(color1, x, y, sampler);
+       this->m_image2Reader->read(color2, x, y, sampler);
+
+       float fac = mask[0];
+       // multiply mask with alpha, if mask == 0 color1, else color2 make sure
+       float mfac = 1.0f-fac;
+       output[0] = color1[0]*mfac + color2[0]*fac;
+       output[1] = color1[1]*mfac + color2[1]*fac;
+       output[2] = color1[2]*mfac + color2[2]*fac;
+       output[3] = max(color1[3], color2[3]);
+}
+
+void ZCombineMaskAlphaOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+       float mask[4];
+       float color1[4];
+       float color2[4];
+
+       this->m_maskReader->read(mask, x, y, sampler);
+       this->m_image1Reader->read(color1, x, y, sampler);
+       this->m_image2Reader->read(color2, x, y, sampler);
+
+       float fac = mask[0];
+       // multiply mask with alpha, if mask == 0 color1, else color2 make sure
+       float mfac = 1.0f-fac;
+       float alpha = color1[3]*mfac + color2[3]*fac;
+       float facalpha = fac * alpha;
+       mfac = 1.0f-facalpha;
+       output[0] = color1[0]*mfac + color2[0]*facalpha;
+       output[1] = color1[1]*mfac + color2[1]*facalpha;
+       output[2] = color1[2]*mfac + color2[2]*facalpha;
+       output[3] = max(color1[3], color2[3]);
+}
+
+void ZCombineMaskOperation::deinitExecution()
+{
+       this->m_image1Reader = NULL;
+       this->m_maskReader = NULL;
+       this->m_image2Reader = NULL;
+}
index 61ceca340f72c516036c5892a2110bba843ec75e..4545775f26f2c02f53e8c780cb9e542edca2fb83 100644 (file)
@@ -54,4 +54,20 @@ class ZCombineAlphaOperation : public ZCombineOperation {
        void executePixel(float output[4], float x, float y, PixelSampler sampler);
 };
 
+class ZCombineMaskOperation : public NodeOperation {
+protected:
+       SocketReader *m_maskReader;
+       SocketReader *m_image1Reader;
+       SocketReader *m_image2Reader;
+public:
+       ZCombineMaskOperation();
+
+       void initExecution();
+       void deinitExecution();
+       void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+class ZCombineMaskAlphaOperation : public ZCombineMaskOperation {
+       void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
 #endif