improvement to the DOF node, after blurring the radius buffer (derived from the depth...
[blender.git] / source / blender / compositor / nodes / COM_DefocusNode.cpp
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor: 
19  *              Jeroen Bakker 
20  *              Monique Dewanchand
21  */
22
23 #include "COM_DefocusNode.h"
24 #include "DNA_scene_types.h"
25 #include "DNA_camera_types.h"
26 #include "DNA_object_types.h"
27 #include "DNA_node_types.h"
28 #include "COM_ExecutionSystem.h"
29 #include "COM_ConvertDepthToRadiusOperation.h"
30 #include "COM_VariableSizeBokehBlurOperation.h"
31 #include "COM_BokehImageOperation.h"
32 #include "COM_MathBaseOperation.h"
33 #include "COM_SetValueOperation.h"
34 #include "COM_GammaCorrectOperation.h"
35 #include "COM_FastGaussianBlurOperation.h"
36
37 DefocusNode::DefocusNode(bNode *editorNode) : Node(editorNode)
38 {
39         /* pass */
40 }
41
42 void DefocusNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
43 {
44         bNode *node = this->getbNode();
45         Scene *scene = (Scene *)node->id;
46         Object *camob = (scene) ? scene->camera : NULL;
47         NodeDefocus *data = (NodeDefocus *)node->storage;
48
49         NodeOperation *radiusOperation;
50         if (data->no_zbuf) {
51                 MathMultiplyOperation *multiply = new MathMultiplyOperation();
52                 SetValueOperation *multiplier = new SetValueOperation();
53                 multiplier->setValue(data->scale);
54                 SetValueOperation *maxRadius = new SetValueOperation();
55                 maxRadius->setValue(data->maxblur);
56                 MathMinimumOperation *minimize = new MathMinimumOperation();
57                 this->getInputSocket(1)->relinkConnections(multiply->getInputSocket(0), 1, graph);
58                 addLink(graph, multiplier->getOutputSocket(), multiply->getInputSocket(1));
59                 addLink(graph, maxRadius->getOutputSocket(), minimize->getInputSocket(1));
60                 addLink(graph, multiply->getOutputSocket(), minimize->getInputSocket(0));
61                 
62                 graph->addOperation(multiply);
63                 graph->addOperation(multiplier);
64                 graph->addOperation(maxRadius);
65                 graph->addOperation(minimize);
66                 radiusOperation = minimize;
67         }
68         else {
69                 ConvertDepthToRadiusOperation *converter = new ConvertDepthToRadiusOperation();
70                 converter->setCameraObject(camob);
71                 converter->setfStop(data->fstop);
72                 converter->setMaxRadius(data->maxblur);
73                 this->getInputSocket(1)->relinkConnections(converter->getInputSocket(0), 1, graph);
74                 graph->addOperation(converter);
75                 
76                 FastGaussianBlurValueOperation *blur = new FastGaussianBlurValueOperation();
77                 addLink(graph, converter->getOutputSocket(0), blur->getInputSocket(0));
78                 graph->addOperation(blur);
79                 radiusOperation = blur;
80                 converter->setPostBlur(blur);
81
82                 /* maintain close pixels so far Z values don't bleed into the foreground */
83                 blur->setOverlay(FAST_GAUSS_OVERLAY_MIN);
84         }
85         
86         BokehImageOperation *bokeh = new BokehImageOperation();
87         NodeBokehImage *bokehdata = new NodeBokehImage();
88         bokehdata->angle = data->rotation;
89         bokehdata->rounding = 0.0f;
90         bokehdata->flaps = data->bktype;
91         if (data->bktype < 3) {
92                 bokehdata->flaps = 5;
93                 bokehdata->rounding = 1.0f;
94         }
95         bokehdata->catadioptric = 0.0f;
96         bokehdata->lensshift = 0.0f;
97         
98         bokeh->setData(bokehdata);
99         bokeh->deleteDataOnFinish();
100         graph->addOperation(bokeh);
101
102 #ifdef COM_DEFOCUS_SEARCH       
103         InverseSearchRadiusOperation *search = new InverseSearchRadiusOperation();
104         addLink(graph, radiusOperation->getOutputSocket(0), search->getInputSocket(0));
105         search->setMaxBlur(data->maxblur);
106         graph->addOperation(search);
107 #endif
108         VariableSizeBokehBlurOperation *operation = new VariableSizeBokehBlurOperation();
109         if (data->preview) {
110                 operation->setQuality(COM_QUALITY_LOW);
111         }
112         else {
113                 operation->setQuality(context->getQuality());
114         }
115         operation->setMaxBlur(data->maxblur);
116         operation->setbNode(node);
117         operation->setThreshold(data->bthresh);
118         addLink(graph, bokeh->getOutputSocket(), operation->getInputSocket(1));
119         addLink(graph, radiusOperation->getOutputSocket(), operation->getInputSocket(2));
120 #ifdef COM_DEFOCUS_SEARCH
121         addLink(graph, search->getOutputSocket(), operation->getInputSocket(3));
122 #endif
123         if (data->gamco) {
124                 GammaCorrectOperation *correct = new GammaCorrectOperation();
125                 GammaUncorrectOperation *inverse = new GammaUncorrectOperation();
126                 this->getInputSocket(0)->relinkConnections(correct->getInputSocket(0), 0, graph);
127                 addLink(graph, correct->getOutputSocket(), operation->getInputSocket(0));
128                 addLink(graph, operation->getOutputSocket(), inverse->getInputSocket(0));
129                 this->getOutputSocket()->relinkConnections(inverse->getOutputSocket());
130                 graph->addOperation(correct);
131                 graph->addOperation(inverse);
132         }
133         else {
134                 this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
135                 this->getOutputSocket()->relinkConnections(operation->getOutputSocket());
136         }
137         graph->addOperation(operation);
138 }