Implemented multisampling for texture nodes.
[blender-staging.git] / source / blender / nodes / intern / TEX_nodes / TEX_output.c
1 /**
2  *
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. 
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2006 Blender Foundation.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): Robin Allen
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include "../TEX_util.h"
30
31 /* **************** COMPOSITE ******************** */
32 static bNodeSocketType inputs[]= {
33         { SOCK_RGBA,   1, "Color",  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
34         { SOCK_VECTOR, 1, "Normal", 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f},
35         { -1, 0, ""     }
36 };
37
38 static void osa(
39         void (*input_fn)(float *, bNodeStack *, TexParams *, short),
40         float *out,
41         bNodeStack *in,
42         TexParams *p,
43         short thread
44 ){
45         if(!p->dxt) {
46                 input_fn(out, in, p, thread);
47         } else {
48                 float sample[4] = {0};
49                 float coord[3];
50                 TexParams sp = *p;
51                 int i;
52         
53                 sp.coord = coord;
54                 sp.dxt = sp.dyt = 0;
55                 
56                 QUATCOPY(out, sample);
57                 
58                 for(i=0; i<5; i++) {
59                         VECCOPY(coord, p->coord);
60                         
61                         if(i < 4)
62                         {
63                                 if(i % 2) VECADD(coord, coord, p->dxt);
64                                 if(i > 1) VECADD(coord, coord, p->dyt);
65                         }
66                         else
67                         {
68                                 VECADDFAC(coord, coord, p->dxt, 0.5);
69                                 VECADDFAC(coord, coord, p->dyt, 0.5);
70                         }
71                         
72                         input_fn(sample, in, &sp, thread);
73                         
74                         QUATADDFAC(out, out, sample, 0.2);
75                 }
76         }
77 }
78         
79
80 /* applies to render pipeline */
81 static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
82 {
83         TexCallData *cdata = (TexCallData *)data;
84         TexResult *target = cdata->target;
85         
86         if(in[1]->hasinput && !in[0]->hasinput)
87                 tex_do_preview(node, in[1], data);
88         else
89                 tex_do_preview(node, in[0], data);
90         
91         if(!cdata->do_preview) {
92                 if(cdata->which_output == node->custom1)
93                 {
94                         TexParams params;
95                         params_from_cdata(&params, cdata);
96                         
97                         osa(tex_input_rgba, &target->tr, in[0], &params, cdata->thread);
98                 
99                         target->tin = (target->tr + target->tg + target->tb) / 3.0f;
100                         target->talpha = 1.0f;
101                 
102                         if(target->nor) {
103                                 if(in[1]->hasinput)
104                                         osa(tex_input_vec, target->nor, in[1], &params, cdata->thread);
105                                 else
106                                         target->nor = 0;
107                         }
108                 }
109         }
110 }
111
112 static void unique_name(bNode *node)
113 {
114         TexNodeOutput *tno = (TexNodeOutput *)node->storage;
115         char *new_name = 0;
116         int new_len;
117         int suffix;
118         bNode *i;
119         char *name = tno->name;
120         
121         i = node;
122         while(i->prev) i = i->prev;
123         for(; i; i=i->next) {
124                 if(
125                         i == node ||
126                         i->type != TEX_NODE_OUTPUT ||
127                         strcmp(name, ((TexNodeOutput*)(i->storage))->name)
128                 )
129                         continue;
130                 
131                 if(!new_name) {
132                         int len = strlen(name);
133                         if(len >= 4 && sscanf(name + len - 4, ".%03d", &suffix) == 1) {
134                                 new_len = len;
135                         } else {
136                                 suffix = 0;
137                                 new_len = len + 4;
138                                 if(new_len > 31)
139                                         new_len = 31;
140                         }
141                         
142                         new_name = malloc(new_len + 1);
143                         strcpy(new_name, name);
144                         name = new_name;
145                 }
146                 sprintf(new_name + new_len - 4, ".%03d", ++suffix);
147         }
148         
149         if(new_name) {
150                 strcpy(tno->name, new_name);
151                 free(new_name);
152         }
153 }
154
155 static void init(bNode *node)
156 {
157         TexNodeOutput *tno = MEM_callocN(sizeof(TexNodeOutput), "TEX_output");
158         node->storage= tno;
159         
160         strcpy(tno->name, "Default");
161         unique_name(node);
162         ntreeTexAssignIndex(0, node);
163 }
164
165 static void copy(bNode *orig, bNode *new)
166 {
167         node_copy_standard_storage(orig, new);
168         unique_name(new);
169         ntreeTexAssignIndex(0, new);
170 }
171
172
173 bNodeType tex_node_output= {
174         /* *next,*prev     */  NULL, NULL,
175         /* type code       */  TEX_NODE_OUTPUT,
176         /* name            */  "Output",
177         /* width+range     */  150, 60, 200,
178         /* class+opts      */  NODE_CLASS_OUTPUT, NODE_PREVIEW | NODE_OPTIONS, 
179         /* input sock      */  inputs,
180         /* output sock     */  NULL,
181         /* storage         */  "TexNodeOutput",
182         /* execfunc        */  exec,
183         /* butfunc         */  NULL,
184         /* initfunc        */  init,
185         /* freestoragefunc */  node_free_standard_storage,
186         /* copystoragefunc */  copy,  
187         /* id              */  NULL
188 };