OSDN Git Service

321
[psychlops/cpp.git] / psychlops / extension / standard / shader / psychlops_g_shader_fig.cpp
1 /*
2  *  psychlops_g_shader_fig.cpp
3  *  Psychlops Standard Library (Universal)
4  *
5  *  Last Modified 2009/12/14 by Kenchi HOSOKAWA
6  *  (C) 2009 Kenchi HOSOKAWA, Kazushi MARUYA and Takao SATO
7  */
8
9 #include <iostream>
10 #include <fstream>
11 #include "../../../core/ApplicationInterfaces/psychlops_app_info.h"
12 #include "psychlops_g_shader_fig.h"
13
14
15 namespace Psychlops {
16
17                 void ShaderInterface::reparseGLSL1_1(const std::string &source, std::string &result, std::vector<std::string> &args)
18                 {
19                         int main_i, after_main_i, in_i, in_finish_i;
20                         main_i = source.find("void main");
21                         std::string argstr, argtmp;
22                         int begin=0, len;
23                         args.clear();
24                         if( main_i != std::string::npos ) {
25                                 after_main_i = source.find_first_of("{", main_i );
26                                 in_i = source.find("in float ");
27                                 if( in_i != std::string::npos && in_i<main_i ) {
28                                         in_finish_i = source.find_first_of(";", in_i );
29                                         argstr = source.substr(in_i+9, in_finish_i-(in_i+9)+1);
30                                         for(int i=0; i<argstr.length(); i++) {
31                                                 if(argstr[i]==',' || argstr[i]==';') {
32                                                         len = i-begin;
33                                                         argtmp = argstr.substr(begin, len);
34                                                         args.push_back(argtmp);
35                                                         begin = i+1;
36                                                 }
37                                         }
38                                         result = "";
39                                         std::stringstream ss;
40                                         ss << source.substr(0, in_i);
41                                         ss << source.substr(in_finish_i+1, after_main_i-in_finish_i) << std::endl;
42                                         if(!args.empty()) {
43                                                 ss << "\tfloat ";
44                                                 for(int i=0; i<args.size(); i++) {
45                                                         ss << args[i] << " = gl_TexCoord[" << i/4+4 << "][" << i%4 << "]";
46                                                         if(i<args.size()-1) ss << ", ";
47                                                 }
48                                                 ss << ";" << std::endl;
49                                         }
50                                         ss << source.substr(after_main_i+1);
51                                         result.assign(ss.str());
52                                         return;
53                                 }
54                         }
55                         result.assign(source);
56                 }
57
58 namespace Internal
59 {
60         std::string error_message;
61         void loadGLSL(std::stringstream &buf, const std::string path)
62         {
63                 char one;
64                 std::ifstream is;
65                 is.open(path.c_str(), std::ifstream::in);
66                 if(is.fail()) {
67                         AppState::alert("Shader: File was not found, or failed to read for some reasons.");
68                         return;
69                 }
70                 while(is.good()) {
71                         is.get(one);
72                         buf << one;
73                 }
74         }
75
76         void logError()
77         {
78                 std::ofstream os;
79                 os.open("GLSLErrorLog.txt");
80                 if(os.fail()) {
81                         AppState::alert("Shader: error log file was not found, or failed to read for some reasons.");
82                         return;
83                 }
84                 os << error_message;
85         }
86 }
87
88 namespace Figures {
89
90
91         ShaderImage::~ShaderImage()
92         {
93         }
94         ShaderImage::ShaderImage()
95         : api() {
96                 initialized = false;
97                 setBase();
98                 orig_source =
99                 "void main(void){ "
100                 "gl_FragColor = getPix(); }";
101                 arg_tmp[0] = 0; arg_tmp[1] = 0; arg_tmp[2] = 0; arg_tmp[3] = 0;
102                 arg_tmp[4] = 0; arg_tmp[5] = 0; arg_tmp[6] = 0; arg_tmp[7] = 0;
103                 arg_tmp[8] = 0; arg_tmp[9] = 0; arg_tmp[10]= 0; arg_tmp[11]= 0;
104                 arg_tmp[12]= 0; arg_tmp[13]= 0; arg_tmp[14]= 0; arg_tmp[15]= 0;
105         }
106         void ShaderImage::setBase()
107         {
108         }
109         void ShaderImage::setFunction(const char *source, ShaderInterface::Version reparse)
110         {
111                 std::string tmp(source);
112                 setFunction(tmp);
113         }
114         void ShaderImage::setFunction(const std::string &source, ShaderInterface::Version reparse)
115         {\r
116                 glslversion = reparse;
117                 switch(reparse) {
118                 case ShaderInterface::THROUGH:
119                         orig_source = source;
120                         break;
121                 case ShaderInterface::AUTO_DETECT:
122                 case ShaderInterface::GLSL1_1:
123                         ShaderInterface::reparseGLSL1_1(source, orig_source, orig_args);
124                         break;
125                 default:
126                         orig_source = source;
127                         break;
128                 }
129         }
130         void ShaderImage::argf(
131                 double  a0, double  a1, double  a2, double  a3,
132                 double  a4, double  a5, double  a6, double  a7,
133                 double  a8, double  a9, double a10, double a11,
134                 double a12, double a13, double a14, double a15
135         )
136         {
137                 arg_tmp[0] =  a0; arg_tmp[1] =  a1; arg_tmp[2] =  a2; arg_tmp[3] =  a3;
138                 arg_tmp[4] =  a4; arg_tmp[5] =  a5; arg_tmp[6] =  a6; arg_tmp[7] =  a7;
139                 arg_tmp[8] =  a8; arg_tmp[9] =  a9; arg_tmp[10]= a10; arg_tmp[11]= a11;
140                 arg_tmp[12]= a12; arg_tmp[13]= a13; arg_tmp[14]= a14; arg_tmp[15]= a15;
141         }
142
143         void ShaderImage::cache(DrawableWithCache &target)
144         {
145                 api.cacheTex(orig_source, orig_args, target);
146         }
147         void ShaderImage::cache(const char *source, DrawableWithCache &target)
148         {
149                 if(!initialized && &target!=0) {
150                         setFunction(source);
151                         cache(target);
152                         initialized = true;
153                 }
154         }
155         void ShaderImage::cacheFromFile(const std::string path, DrawableWithCache &target)
156         {
157                 std::stringstream buf;
158                 Internal::loadGLSL(buf, path);
159                 Internal::error_message.clear();
160                 try{
161                         setFunction(buf.str().c_str());
162                         cache(*Display::the_canvas);
163                 } catch (Exception e) {
164                         Internal::error_message = e.getErrorString();
165                         Internal::logError();
166                 } catch (Exception *e) {
167                         Internal::error_message = e->getErrorString();
168                         Internal::logError();
169                 }
170         }
171         ShaderImage& ShaderImage::draw(Image &img, const double* argv, const int argn, Canvas &target)
172         {
173                 //if() cache(target);
174                 api.drawImage(img, argv, argn, target);
175                 return *this;
176         }
177         void ShaderImage::to(Image &dest, Image &img, const double* argv, const int argn, Canvas &media)
178         {
179                 Point tmp = img.getDatum();
180                 api.imageToImage(dest, img, argv, argn, media);
181                 img.setDatum(tmp);
182         }
183         ShaderImage& ShaderImage::draw(Image &img, Canvas &target)
184         {
185                 return draw(img, arg_tmp, 4, target);
186         }
187         void ShaderImage::to(Image &dest, Image &img, Canvas &media)
188         {
189                 to(dest, img, arg_tmp, 4, media);
190         }
191 \r
192 \r
193         void ShaderImage2::cache(DrawableWithCache &target)\r
194         {\r
195                 api.cacheTex(orig_source, orig_args, target, 1);\r
196         }\r
197         ShaderImage2& ShaderImage2::draw(Image &img, const double* argv, const int argn, Canvas &target)\r
198         {\r
199                 //if() cache(target);\r
200                 api.drawImage(img, argv, argn, params, target);\r
201                 return *this;\r
202         }\r
203 \r
204
205
206         ShaderField::~ShaderField()
207         {
208         }
209         ShaderField::ShaderField()
210         : api() {
211                 initialized = false;
212                 setBase();
213                 orig_source =
214                 "void main(void){ "
215                 "pix(vec4(0.0, 0.0, 1.0, 0.5)); }";
216                 arg_tmp[0] = 0; arg_tmp[1] = 0; arg_tmp[2] = 0; arg_tmp[3] = 0;
217                 arg_tmp[4] = 0; arg_tmp[5] = 0; arg_tmp[6] = 0; arg_tmp[7] = 0;
218                 arg_tmp[8] = 0; arg_tmp[9] = 0; arg_tmp[10]= 0; arg_tmp[11]= 0;
219                 arg_tmp[12]= 0; arg_tmp[13]= 0; arg_tmp[14]= 0; arg_tmp[15]= 0;
220         }
221         void ShaderField::setBase()
222         {
223         }
224         void ShaderField::setFunction(const char* source, ShaderInterface::Version reparse)
225         {
226                 std::string tmp(source);
227                 setFunction(tmp, reparse);
228         }
229         void ShaderField::setFunction(const std::string &source, ShaderInterface::Version reparse)
230         {\r
231                 glslversion = reparse;
232                 switch(reparse) {
233                 case ShaderInterface::THROUGH:
234                         orig_source = source;
235                         break;
236                 case ShaderInterface::AUTO_DETECT:
237                 case ShaderInterface::GLSL1_1:
238                         ShaderInterface::reparseGLSL1_1(source, orig_source, orig_args);
239                         break;
240                 default:
241                         orig_source = source;
242                         break;
243                 }
244         }
245         void ShaderField::argf(
246                 double  a0, double  a1, double  a2, double  a3,
247                 double  a4, double  a5, double  a6, double  a7,
248                 double  a8, double  a9, double a10, double a11,
249                 double a12, double a13, double a14, double a15
250         )
251         {
252                 arg_tmp[0] =  a0; arg_tmp[1] =  a1; arg_tmp[2] =  a2; arg_tmp[3] =  a3;
253                 arg_tmp[4] =  a4; arg_tmp[5] =  a5; arg_tmp[6] =  a6; arg_tmp[7] =  a7;
254                 arg_tmp[8] =  a8; arg_tmp[9] =  a9; arg_tmp[10]= a10; arg_tmp[11]= a11;
255                 arg_tmp[12]= a12; arg_tmp[13]= a13; arg_tmp[14]= a14; arg_tmp[15]= a15;
256         }
257         void ShaderField::cache(DrawableWithCache &target)
258         {
259                 switch(glslversion) {
260                 case ShaderInterface::THROUGH:
261                         api.cache(orig_source, orig_args, target);
262                         break;
263                 case ShaderInterface::AUTO_DETECT:
264                 case ShaderInterface::GLSL1_1:
265                         api.cacheField(orig_source, orig_args, target);
266                         break;
267                 default:
268                         api.cacheField(orig_source, orig_args, target);
269                         break;
270                 }
271         }
272         void ShaderField::cache(const char *source, DrawableWithCache &target)
273         {
274                 if(!initialized && &target!=0) {
275                         setFunction(source);
276                         cache(target);
277                         initialized = true;
278                 }
279         }
280         void ShaderField::cacheFromFile(const std::string path, DrawableWithCache &target)
281         {
282                 std::stringstream buf;
283                 Internal::loadGLSL(buf, path);
284                 Internal::error_message.clear();
285                 try{
286                         setFunction(buf.str().c_str());
287                         cache(*Display::the_canvas);
288                 } catch (Exception e) {
289                         Internal::error_message = e.getErrorString();
290                         Internal::logError();
291                 } catch (Exception *e) {
292                         Internal::error_message = e->getErrorString();
293                         Internal::logError();
294                 }
295         }
296         void ShaderField::draw(const Rectangle &rect, const double* argv, const int argn, Drawable &target)
297         {
298                 api.drawField(rect, argv, argn);
299         }
300         void ShaderField::to(Image &dest, const Rectangle &rect, const double* argv, const int argn, Canvas &media)
301         {
302                 api.fieldToImage(dest, rect, argv, argn, media);
303         }
304         void ShaderField::draw(const Rectangle &rect, Drawable &target)
305         {
306                 api.drawField(rect, arg_tmp, 4);
307         }
308         void ShaderField::to(Image &dest, const Rectangle &rect, Canvas &media)
309         {
310                 api.fieldToImage(dest, rect, arg_tmp, 4, media);
311         }
312
313
314
315         ShaderCoordinateTuner::ShaderCoordinateTuner()
316         {
317                 cache();
318                 set(256*pixel, 256*pixel);
319         }
320         ShaderCoordinateTuner& ShaderCoordinateTuner::cache(DrawableWithCache &target)
321         {
322                 field.cache(glsl_source, target);
323                 return *this;
324         }
325         ShaderCoordinateTuner& ShaderCoordinateTuner::draw(Canvas &target)
326         {
327                 cache(target);
328                 const double Z[4] = { 0,0,0,0 };
329                 field.draw(*this, Z, 0, target);
330                 return *this;
331         }
332         void ShaderCoordinateTuner::to(Image &dest, Canvas &media)
333         {
334                 cache(media);
335                 const double Z[4] = { 0,0,0,0 };
336                 field.to(dest, *this, Z, 0, media);
337         }
338         ShaderField ShaderCoordinateTuner::field;
339         const char *ShaderCoordinateTuner::glsl_source =
340                         "void main(void){ "
341                         "float r = floor(abs(gl_TexCoord[0][0]))/255.0;"
342                         "float g = fract(abs(gl_TexCoord[0][0]));"
343                         "pix( r, g, 0.0); }";
344
345
346
347         ShaderGrating::ShaderGrating()
348         {
349                 cache();
350                 set(10*pixel, 10*pixel);
351         }
352         ShaderGrating& ShaderGrating::setWave(double wavelen, double cont, double orient, double phs)
353         {
354                 return setWave(wavelen*pixel, cont, orient*degree, phs*degree);
355         }
356         ShaderGrating& ShaderGrating::setWave(Length wavelen, double cont, Angle orient, Angle phs)
357         {
358                 contrast = cont;
359                 wavelength = wavelen;
360                 orientation = orient;
361                 phase = phs;
362                 return *this;
363         }
364         ShaderGrating& ShaderGrating::cache(DrawableWithCache &target)
365         {
366                 field.cache(glsl_source, target);
367                 return *this;
368         }
369         ShaderGrating& ShaderGrating::draw(Drawable &target)
370         {
371                 cache();
372                 //const double Z[4] = { phase.at_degree(), contrast, orientation.at_degree(), PI/wavelength*getWidth() };
373                 const double Z[4] = { phase.at_degree(), contrast, orientation.at_degree(), 2*PI/wavelength };
374                 field.draw(*this, Z, 1, target);
375                 return *this;
376         }
377
378         void ShaderGrating::to(Image &dest, Canvas &media)
379         {
380                 cache(media);
381 //              const double Z[4] = { phase.at_degree(), contrast, orientation.at_degree(), PI/wavelength*getWidth() };
382                 const double Z[4] = { phase.at_degree(), contrast, orientation.at_degree(), 2*PI/wavelength };
383                 field.to(dest, *this, Z, 1, media);
384         }
385
386         ShaderField ShaderGrating::field;
387         const char *ShaderGrating::glsl_source =
388                         "void main(void){ "
389                         "float phase = gl_TexCoord[4][0], contrast = gl_TexCoord[4][1], orientation = gl_TexCoord[4][2], frequency = gl_TexCoord[4][3];"
390                         "float _x = sin(orientation)*xp()-cos(orientation)*yp();"
391                         "pix(0.5 + contrast*0.5*cos(frequency*_x + phase) ); }";
392
393
394         ShaderGaussianDot::ShaderGaussianDot()
395         {
396                 cache();
397                 bgcolor = Color::null_color;
398                 Rectangle::fill = Color::black;
399         }
400         ShaderGaussianDot& ShaderGaussianDot::setSigma(double sigma)
401         {
402                 Rectangle::set(sigma*8.0, sigma*8.0);
403                 return *this;
404         }
405         ShaderGaussianDot& ShaderGaussianDot::cache(DrawableWithCache &target)
406         {
407                 field.cache(glsl_source, target);
408                 return *this;
409         }
410         ShaderGaussianDot& ShaderGaussianDot::draw(Drawable &target)
411         {
412                 cache();
413                 const double Z[12] = {
414                         2.0/getWidth(), 0, 0, 0,
415                         Rectangle::fill.getR(), Rectangle::fill.getG(), Rectangle::fill.getB(), Rectangle::fill.getA(),
416                         bgcolor.getR(), bgcolor.getG(), bgcolor.getB(), bgcolor.getA()
417                 };
418                 field.draw(*this, Z, 3, target);
419                 return *this;
420         }
421         void ShaderGaussianDot::to(Image &dest, Canvas &media)
422         {
423                 cache(media);
424                 const double Z[12] = {
425                         2.0/getWidth(), 0, 0, 0,
426                         Rectangle::fill.getR(), Rectangle::fill.getG(), Rectangle::fill.getB(), Rectangle::fill.getA(),
427                         bgcolor.getR(), bgcolor.getG(), bgcolor.getB(), bgcolor.getA()
428                 };
429                 field.to(dest, *this, Z, 3, media);
430         }
431         ShaderField ShaderGaussianDot::field;
432         const char *ShaderGaussianDot::glsl_source =
433                         "void main(void) {"
434                         "float r = rp()*gl_TexCoord[4][0]*4.0;"
435                         "float r2 = -(r*r) / 2.0;"
436                         "vec4 env = mix(gl_TexCoord[6], gl_TexCoord[5], exp(r2));"
437                         "pix(env);"
438                         "}";
439
440
441         ShaderGabor::ShaderGabor()
442         {
443                 cache();
444                 set(10*pixel, 10*pixel);
445                 contrast = 1;
446                 wavelength = 5;
447                 orientation = 0;
448                 phase = 0;
449         }
450         ShaderGabor& ShaderGabor::setSigma(double sigma)
451         {
452                 return setSigma(sigma*pixel);
453         }
454         ShaderGabor& ShaderGabor::setSigma(Length sigma)
455         {
456                 Rectangle::set(sigma*8.0, sigma*8.0);
457                 return *this;
458         }
459         ShaderGabor& ShaderGabor::setWave(double wavelen, double cont, double orient, double phs)
460         {
461                 return setWave(wavelen*pixel, cont, orient*degree, phs*degree);
462         }
463         ShaderGabor& ShaderGabor::setWave(Length wavelen, double cont, Angle orient, Angle phs)
464         {
465                 contrast = cont;
466                 wavelength = wavelen;
467                 orientation = orient;
468                 phase = phs;
469                 return *this;
470         }
471
472         ShaderGabor& ShaderGabor::cache(DrawableWithCache &target)
473         {
474                 field.cache(glsl_source, target);
475                 return *this;
476         }
477         ShaderGabor& ShaderGabor::draw(Drawable &target)
478         {
479                 cache();
480                 const double Z[8] = { 2.0/getWidth(),0,0,0, phase, contrast, orientation, 2*PI/wavelength };
481                 field.draw(*this, Z, 2, target);
482                 return *this;
483         }
484         void ShaderGabor::to(Image &dest, Canvas &media)
485         {
486                 cache(media);
487                 const double Z[8] = { 2.0/getWidth(),0,0,0, phase, contrast, orientation, 2*PI/wavelength };
488                 field.to(dest, *this, Z, 2, media);
489         }
490
491         ShaderField ShaderGabor::field;
492         const char *ShaderGabor::glsl_source =
493                         "void main(void) {"
494                         "float _r = rp()*gl_TexCoord[4][0]*4.0;"
495                         "float env = exp( -(_r*_r) / 2.0 );"
496                         "float phase = gl_TexCoord[5][0], contrast = gl_TexCoord[5][1], orientation = gl_TexCoord[5][2], frequency = gl_TexCoord[5][3];"
497                         "float _x = sin(orientation)*xp()-cos(orientation)*yp();"
498                         //"float level = 0.5+contrast*0.5*cos(frequency*_x + phase);"
499                         //"pix(level,env);"
500                         "float level = 0.996078*(0.5+env*( contrast*0.5*cos(frequency*_x + phase) ));"
501                         "pix(level);"
502                         "}";
503 \r
504 \r
505 \r
506         ShaderGaborAlpha::ShaderGaborAlpha()\r
507         {\r
508                 cache();\r
509                 set(10*pixel, 10*pixel);\r
510                 contrast = 1;\r
511                 wavelength = 5;\r
512                 orientation = 0;\r
513                 alpha = 1.0;\r
514                 phase = 0;\r
515         }\r
516         ShaderGaborAlpha& ShaderGaborAlpha::setSigma(double sigma)\r
517         {\r
518                 return setSigma(sigma*pixel);\r
519         }\r
520         ShaderGaborAlpha& ShaderGaborAlpha::setSigma(Length sigma)\r
521         {\r
522                 Rectangle::set(sigma*8.0, sigma*8.0);\r
523                 return *this;\r
524         }\r
525         ShaderGaborAlpha& ShaderGaborAlpha::setWave(double wavelen, double cont, double orient, double phs)\r
526         {\r
527                 return setWave(wavelen*pixel, cont, orient*degree, phs*degree);\r
528         }\r
529         ShaderGaborAlpha& ShaderGaborAlpha::setWave(Length wavelen, double cont, Angle orient, Angle phs)\r
530         {\r
531                 contrast = cont;\r
532                 wavelength = wavelen;\r
533                 orientation = orient;\r
534                 phase = phs;\r
535                 return *this;\r
536         }\r
537 \r
538         ShaderGaborAlpha& ShaderGaborAlpha::cache(DrawableWithCache &target)\r
539         {\r
540                 field.cache(glsl_source, target);\r
541                 return *this;\r
542         }\r
543         ShaderGaborAlpha& ShaderGaborAlpha::draw(Drawable &target)\r
544         {\r
545                 cache();\r
546                 const double Z[8] = { 2.0/getWidth(),alpha,0,0, phase, contrast, orientation, 2*PI/wavelength };\r
547                 field.draw(*this, Z, 2, target);\r
548                 return *this;\r
549         }\r
550         void ShaderGaborAlpha::to(Image &dest, Canvas &media)\r
551         {\r
552                 cache(media);\r
553                 const double Z[8] = { 2.0/getWidth(),alpha,0,0, phase, contrast, orientation, 2*PI/wavelength };\r
554                 field.to(dest, *this, Z, 2, media);\r
555         }\r
556 \r
557         ShaderField ShaderGaborAlpha::field;\r
558         const char *ShaderGaborAlpha::glsl_source =\r
559                         "void main(void) {"\r
560                         "float _r = rp()*gl_TexCoord[4][0]*4.0;"\r
561                         "float env = exp( -(_r*_r) / 2.0 ) * gl_TexCoord[4][1];"\r
562                         "float phase = gl_TexCoord[5][0], contrast = gl_TexCoord[5][1], orientation = gl_TexCoord[5][2], frequency = gl_TexCoord[5][3];"\r
563                         "float _x = sin(orientation)*xp()-cos(orientation)*yp();"\r
564                         "float level = 0.5+contrast*0.5*cos(frequency*_x + phase);"\r
565                         "pix(level,env);"\r
566                         "}";
567 \r
568 \r
569
570
571         ShaderPlaid::ShaderPlaid()
572         {
573                 cache();
574                 set(10*pixel, 10*pixel);
575         }
576         ShaderPlaid& ShaderPlaid::setSigma(double sigma)
577         {
578                 return setSigma(sigma*pixel);
579         }
580         ShaderPlaid& ShaderPlaid::setSigma(Length sigma)
581         {
582                 Rectangle::set(sigma*8.0, sigma*8.0);
583                 return *this;
584         }
585         ShaderPlaid& ShaderPlaid::setWave(double wavelen, double cont, double orient, double phs)
586         {
587                 return setWave(wavelen*pixel, cont, orient*degree, phs*degree);
588         }
589         ShaderPlaid& ShaderPlaid::setWave(Length wavelen, double cont, Angle orient, Angle phs)
590         {
591                 contrast = cont;
592                 wavelength = wavelen;
593                 orientation = orient;
594                 phase = phs;
595                 return *this;
596         }
597         ShaderPlaid& ShaderPlaid::setWave2(double wavelen, double cont, double orient, double phs)
598         {
599                 return setWave2(wavelen*pixel, cont, orient*degree, phs*degree);
600         }
601         ShaderPlaid& ShaderPlaid::setWave2(Length wavelen, double cont, Angle orient, Angle phs)
602         {
603                 contrast2 = cont;
604                 wavelength2 = wavelen;
605                 orientation2 = orient;
606                 phase2 = phs;
607                 return *this;
608         }
609         ShaderPlaid& ShaderPlaid::cache(DrawableWithCache &target)
610         {
611                 field.cache(glsl_source, target);
612                 return *this;
613         }
614         ShaderPlaid& ShaderPlaid::draw(Drawable &target)
615         {
616                 cache();
617                 const double Z[12] =
618                 {
619                         2.0/getWidth(),0,0,0,
620                         phase.at_degree(), contrast, orientation.at_degree(), 2*PI/wavelength,
621                         phase2.at_degree(), contrast2, orientation2.at_degree(), 2*PI/wavelength2
622                 };
623                 field.draw(*this, Z, 3, target);
624                 return *this;
625         }
626
627         void ShaderPlaid::to(Image &dest, Canvas &media)
628         {
629                 cache(media);
630                 const double Z[12] =
631                 {
632                         2.0/getWidth(),0,0,0,
633                         phase.at_degree(), contrast, orientation.at_degree(), 2*PI/wavelength,
634                         phase2.at_degree(), contrast2, orientation2.at_degree(), 2*PI/wavelength2
635                 };
636                 field.to(dest, *this, Z, 3, media);
637         }
638
639         ShaderField ShaderPlaid::field;
640         const char *ShaderPlaid::glsl_source =
641                         "void main(void) {"
642                         "float phase = gl_TexCoord[5][0], contrast = gl_TexCoord[5][1], orientation = gl_TexCoord[5][2], frequency = gl_TexCoord[5][3];"
643                         "float phase2 = gl_TexCoord[6][0], contrast2 = gl_TexCoord[6][1], orientation2 = gl_TexCoord[6][2], frequency2 = gl_TexCoord[6][3];"
644                         "float _x  = sin(orientation)*xp()-cos(orientation)*yp();"
645                         "float _x2 = sin(orientation2)*xp()-cos(orientation2)*yp();"
646                         "float _r = rp()*gl_TexCoord[4][0]*4.0;"
647                         "float env = exp( -(_r*_r) / 2.0 );"
648                         "float level = 0.996078*(0.5+env*( contrast*0.5*cos(frequency*_x + phase) + contrast2*0.5*cos(frequency2*_x2 + phase2) ));"
649                         "pix(level);"
650                         //"float level = 0.5 + contrast*0.5*cos(frequency*_x + phase) + contrast2*0.5*cos(frequency2*_x2 + phase2);"
651                         //"pix(level, level, level, env);"
652                         "}";
653
654 \r
655 \r
656         ShaderPlaidAlpha::ShaderPlaidAlpha()\r
657         {\r
658                 cache();\r
659                 set(10*pixel, 10*pixel);\r
660                 alpha = 1.0;\r
661         }\r
662         ShaderPlaidAlpha& ShaderPlaidAlpha::setSigma(double sigma)\r
663         {\r
664                 return setSigma(sigma*pixel);\r
665         }\r
666         ShaderPlaidAlpha& ShaderPlaidAlpha::setSigma(Length sigma)\r
667         {\r
668                 Rectangle::set(sigma*8.0, sigma*8.0);\r
669                 return *this;\r
670         }\r
671         ShaderPlaidAlpha& ShaderPlaidAlpha::setWave(double wavelen, double cont, double orient, double phs)\r
672         {\r
673                 return setWave(wavelen*pixel, cont, orient*degree, phs*degree);\r
674         }\r
675         ShaderPlaidAlpha& ShaderPlaidAlpha::setWave(Length wavelen, double cont, Angle orient, Angle phs)\r
676         {\r
677                 contrast = cont;\r
678                 wavelength = wavelen;\r
679                 orientation = orient;\r
680                 phase = phs;\r
681                 return *this;\r
682         }\r
683         ShaderPlaidAlpha& ShaderPlaidAlpha::setWave2(double wavelen, double cont, double orient, double phs)\r
684         {\r
685                 return setWave2(wavelen*pixel, cont, orient*degree, phs*degree);\r
686         }\r
687         ShaderPlaidAlpha& ShaderPlaidAlpha::setWave2(Length wavelen, double cont, Angle orient, Angle phs)\r
688         {\r
689                 contrast2 = cont;\r
690                 wavelength2 = wavelen;\r
691                 orientation2 = orient;\r
692                 phase2 = phs;\r
693                 return *this;\r
694         }\r
695         ShaderPlaidAlpha& ShaderPlaidAlpha::cache(DrawableWithCache &target)\r
696         {\r
697                 field.cache(glsl_source, target);\r
698                 return *this;\r
699         }\r
700         ShaderPlaidAlpha& ShaderPlaidAlpha::draw(Drawable &target)\r
701         {\r
702                 cache();\r
703                 const double Z[12] =\r
704                 {\r
705                         2.0/getWidth(),alpha,0,0,\r
706                         phase.at_degree(), contrast, orientation.at_degree(), 2*PI/wavelength,\r
707                         phase2.at_degree(), contrast2, orientation2.at_degree(), 2*PI/wavelength2\r
708                 };\r
709                 field.draw(*this, Z, 3, target);\r
710                 return *this;\r
711         }\r
712 \r
713         void ShaderPlaidAlpha::to(Image &dest, Canvas &media)\r
714         {\r
715                 cache(media);\r
716                 const double Z[12] =\r
717                 {\r
718                         2.0/getWidth(),alpha,0,0,\r
719                         phase.at_degree(), contrast, orientation.at_degree(), 2*PI/wavelength,\r
720                         phase2.at_degree(), contrast2, orientation2.at_degree(), 2*PI/wavelength2\r
721                 };\r
722                 field.to(dest, *this, Z, 3, media);\r
723         }\r
724 \r
725         ShaderField ShaderPlaidAlpha::field;\r
726         const char *ShaderPlaidAlpha::glsl_source =\r
727                         "void main(void) {"\r
728                         "float phase = gl_TexCoord[5][0], contrast = gl_TexCoord[5][1], orientation = gl_TexCoord[5][2], frequency = gl_TexCoord[5][3];"\r
729                         "float phase2 = gl_TexCoord[6][0], contrast2 = gl_TexCoord[6][1], orientation2 = gl_TexCoord[6][2], frequency2 = gl_TexCoord[6][3];"\r
730                         "float _x  = sin(orientation)*xp()-cos(orientation)*yp();"\r
731                         "float _x2 = sin(orientation2)*xp()-cos(orientation2)*yp();"\r
732                         "float _r = rp()*gl_TexCoord[4][0]*4.0;"\r
733                         "float env = exp( -(_r*_r) / 2.0 ) * gl_TexCoord[4][1];"\r
734                         //"float level = 0.996078*(0.5+env*( contrast*0.5*cos(frequency*_x + phase) + contrast2*0.5*cos(frequency2*_x2 + phase2) ));"\r
735                         //"pix(level);"\r
736                         "float level = 0.5 + contrast*0.5*cos(frequency*_x + phase) + contrast2*0.5*cos(frequency2*_x2 + phase2);"\r
737                         "pix(level, level, level, env);"\r
738                         "}";\r
739 \r
740
741 }       /*      <- namespace Figures    */
742 }       /*      <- namespace Psycholops         */
743