Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

r_shader.cpp

Go to the documentation of this file.
00001 // OMICRON ENGINE HEADER FILE
00002 //
00003 // --------------------------------------------------------------------------
00004 // Copyright (C) 2001-2002 by Bjoern Paetzel <kolrabi@gmx.de>
00005 //
00006 // This file is part of the Omicron Engine.
00007 //
00008 // The Omicron Engine is free software; you can redistribute it and/or modify
00009 // it under the terms of the  GNU General Public License  as published by the
00010 // Free Software Foundation;  either version  2  of the License,  or (at your
00011 // option) any later version.
00012 //
00013 // The Omicron Engine  is distributed in the hope that it will be useful, but
00014 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00015 // or  FITNESS FOR A PARTICULAR PURPOSE.  See the  GNU General Public License
00016 // for more details.
00017 //
00018 // You should have  received a copy of the  GNU General Public License  along
00019 // with The Omicron Engine;  if not,  write to the  Free Software Foundation,
00020 // Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
00021 //
00022 // --------------------------------------------------------------------------
00023 // Last modified:       $Date: 2002/12/07 19:02:04 $
00024 // By           :       $Author: kolrabi $
00025 // $Id: r_shader.cpp,v 1.1.1.1 2002/12/07 19:02:04 kolrabi Exp $ 
00026 
00027 /*
00028 
00029   $Log: r_shader.cpp,v $
00030   Revision 1.1.1.1  2002/12/07 19:02:04  kolrabi
00031   initial release
00032 
00033 
00034 */
00035 
00040 #include            <string>
00041  
00042 #include            "omicron/internal.h" 
00043 #include            "omicron/render.h" 
00044 #include            "omicron/texture.h"
00045 #include            "omicron/file.h" 
00046 #include            "omicron/list.h"
00047 // #include            "omicron/string.h"
00048  
00049 static ushort      waveform_from_string 
00050 ( 
00051     const char        *t 
00052 ) 
00053 {
00054     AssertReturnValue1(t, 0);
00055 
00056     if (!strcmpi(t, "sine")) 
00057         return WF_SINE; 
00058  
00059     if (!strcmpi(t, "rect")) 
00060         return WF_RECT; 
00061  
00062     if (!strcmpi(t, "sine2d")) 
00063         return WF_SINE2D; 
00064  
00065     if (!strcmpi(t, "rect2d")) 
00066         return WF_RECT2D; 
00067 
00068     if (!strcmpi(t, "none")) 
00069         return WF_NONE; 
00070 
00071     _log_printf(MSG_ERROR,  "ERROR: invalid token \"%s\"", t); 
00072 
00073     return WF_NONE; 
00074 } 
00075  
00076 static ushort     texfilter_from_string 
00077 ( 
00078     const char        *t 
00079 ) 
00080 { 
00081     if (!strcmpi(t, "linear")) 
00082         return TF_LINEAR; 
00083  
00084     if (!strcmpi(t, "nearest_mipmap_nearest")) 
00085         return TF_NEAREST_MIPMAP_NEAREST; 
00086  
00087     if (!strcmpi(t, "nearest_mipmap_linear")) 
00088         return TF_NEAREST_MIPMAP_LINEAR; 
00089  
00090     if (!strcmpi(t, "linear_mipmap_nearest")) 
00091         return TF_LINEAR_MIPMAP_NEAREST; 
00092  
00093     if (!strcmpi(t, "linear_mipmap_linear")) 
00094         return TF_LINEAR_MIPMAP_LINEAR; 
00095  
00096     return TF_NEAREST; 
00097 } 
00098  
00099 static ushort      texwrap_from_string 
00100 ( 
00101     const char        *t 
00102 ) 
00103 { 
00104     AssertReturnValue1(t, 0);
00105 
00106     if (!strcmpi(t, "clamp")) 
00107         return TW_CLAMP; 
00108  
00109     return TW_REPEAT; 
00110 } 
00111  
00112 static ushort     texbtype_from_string 
00113 ( 
00114     const char        *t 
00115 ) 
00116 { 
00117     AssertReturnValue1(t, 0);
00118 
00119     // opaque add blend modulate 
00120     if (!strcmpi(t, "add")) 
00121         return BT_ADD; 
00122     if (!strcmpi(t, "blend")) 
00123         return BT_BLEND; 
00124     if (!strcmpi(t, "modulate")) 
00125         return BT_MODULATE; 
00126     if (!strcmpi(t, "alphatest")) 
00127         return BT_ALPHATEST; 
00128     if (!strcmpi(t, "modulate2x")) 
00129         return BT_MODULATE2X; 
00130  
00131     return BT_OPAQUE; 
00132 } 
00133  
00134 /****************************************************************************
00135  * shader_initstage                                     init a shader stage *
00136  ****************************************************************************/
00137 void            shader_initstage 
00138 ( 
00139     shader_t    *shad, 
00140     ushort      n 
00141 ) 
00142 { 
00143     AssertReturn1(shad);
00144 
00145     shad->passes[n].scalex          = 1; 
00146     shad->passes[n].scaley          = 1; 
00147     shad->passes[n].soffsetx        = 
00148     shad->passes[n].soffsety        =  
00149     shad->passes[n].offsetx         = 
00150     shad->passes[n].offsety         = 0; 
00151     shad->passes[n].magfilter       = TF_LINEAR_MIPMAP_LINEAR; 
00152     shad->passes[n].minfilter       = TF_LINEAR_MIPMAP_LINEAR; 
00153     shad->passes[n].texwrapu        =  
00154     shad->passes[n].texwrapv        = TW_REPEAT; 
00155  
00156     shad->passes[n].rotation        = 
00157     shad->passes[n].angle           =
00158     shad->passes[n].scrollx         = 
00159     shad->passes[n].scrolly         = 0.0f;
00160     shad->passes[n].shiny           = 0; 
00161 
00162     shad->passes[n].matrix          = false;
00163     shad->passes[n].fog             = true;
00164  
00165     shad->passes[n].colorwave.type  = 0; 
00166     shad->passes[n].colorwave.bias  = 1; 
00167  
00168     shad->passes[n].color1          = 
00169     shad->passes[n].color2          = COLOR_WHITE;
00170 
00171     shad->passes[n].color           = false;
00172 
00173     shad->passes[n].scalewavex.type  = 0; 
00174     shad->passes[n].scalewavex.bias  = 1; 
00175     shad->passes[n].scalewavey.type  = 0; 
00176     shad->passes[n].scalewavey.bias  = 1; 
00177 
00178     shad->passes[n].lightmap = 0;
00179     shad->passes[n].lighting = 0;
00180     shad->passes[n].blendtype    = BT_OPAQUE;
00181     shad->passes[n].twosided = 0;
00182     shad->passes[n].nodepth  = 0;
00183     shad->passes[n].ignorediffuse = false;
00184 } 
00185 
00186 /****************************************************************************
00187  * shader_get_waveform_frac                           get waveform fraction *
00188  ****************************************************************************/
00189 float           shader_get_waveform_frac 
00190 ( 
00191     const shader_waveform_t  *wf
00192 ) 
00193 { 
00194     AssertReturnValue1(wf, 0);
00195 
00196     if (wf->type == WF_NONE) 
00197       return 0; 
00198  
00199     if (wf->freq == 0) 
00200       return wf->bias; 
00201  
00202     float invfreq = 1/wf->freq; 
00203     float t = gv.time + wf->phase; 
00204  
00205     switch(wf->type) 
00206     { 
00207         case WF_RECT: 
00208             if (fmod(t, invfreq) < invfreq/2) 
00209                 return wf->bias-wf->amplitude; 
00210             else 
00211                 return wf->bias+wf->amplitude; 
00212             
00213         case WF_SINE: 
00214             return (float)(wf->amplitude*sin(t*PI2*wf->freq)+wf->bias); 
00215  
00216 /*        case WF_TRIANGLE:*/ 
00217 /*        case WF_SAWTOOTH:*/ 
00218 /*        case WF_INVSAWTOOTH:*/ 
00219     } 
00220  
00221     return 0; 
00222 } 
00223 
00224 
00225 /**************************************************************************** 
00226  * _r_simple_shader                                 creates a simple shader * 
00227  ****************************************************************************/ 
00228 shader_t       *shader_create_simple 
00229 ( 
00230     ushort      blendtype, 
00231     sshort      texture 
00232 ) 
00233 { 
00234     shader_t *shad = new shader_t; 
00235  
00236     shader_init(shad, blendtype, texture); 
00237     gv.shaders->add_first(shad); 
00238  
00239     return shad; 
00240 } 
00241  
00242  
00243 /****************************************************************************
00244  * shader_init                                                init a shader *
00245  ****************************************************************************/
00246 void            shader_init 
00247 ( 
00248     shader_t   *shad, 
00249     ushort      blendtype, 
00250     sshort      texture 
00251 ) 
00252 { 
00253     AssertReturn1(shad);
00254 
00255     memset(shad, 0, sizeof(shader_t)); 
00256     shad->passcount = 1; 
00257  
00258     shader_initstage(shad, 0); 
00259     shad->dynamic                   = 0;
00260     shad->passes[0].blendtype       = blendtype; 
00261     shad->passes[0].texture         = texture; 
00262     sprintf(shad->name, "unnamed");
00263 } 
00264  
00265 /****************************************************************************
00266  * shader_create                                       creates a new shader *
00267  ****************************************************************************/
00268 shader_t       *shader_create 
00269 ( 
00270 ) 
00271 { 
00272     shader_t *shad = new shader_t; 
00273     gv.shaders->add_first(shad); 
00274     return shad; 
00275 } 
00276 
00277 /****************************************************************************
00278  * shader_find                                                find a shader * 
00279  ****************************************************************************/
00280 shader_t       *shader_find
00281 (
00282     const char      *name
00283 )
00284 {
00285     AssertReturnValue1(name, NULL);
00286 
00287     shader_t   *shad = (shader_t*)gv.shaders->get_first();
00288 
00289     while(shad)
00290     {
00291         if (!strcmpi(name, shad->name))
00292             return shad;
00293 
00294         shad = (shader_t*)gv.shaders->get_next();
00295     }
00296 
00297     return NULL;
00298 }
00299  
00300  
00301 /****************************************************************************
00302  * shader_load                                      load a shader from file *
00303  ****************************************************************************/
00304 shader_t       *shader_load 
00305 ( 
00306     const char      *fname 
00307 ) 
00308 { 
00309     AssertReturnValue1(fname, NULL);
00310 
00311     shader_t    *shad = NULL; 
00312     file_t      *f; 
00313     std::string fname2;
00314 
00315     shad = shader_find(fname);
00316 
00317     if (shad)
00318         return shad;
00319 
00320     fname2 = fname;
00321     fname2 += ".shader";
00322  
00323     f = gv.fileman->load(fname2.c_str(), false); 
00324  
00325     if (!f) 
00326     {
00327         sshort t = gv.texman->load(fname);
00328 
00329         if (t != TEXTURE_NOTFOUND)
00330         {
00331             shad = shader_create_simple(BT_OPAQUE, t);
00332             sprintf(shad->name, "%s", fname);
00333         }
00334         else
00335         {
00336             shad = shader_find("noshader");
00337         }
00338         return shad;
00339     }
00340  
00341     ushort      currentpass         = 0; 
00342     char        tmp[256]            = ""; 
00343     ulong       linenum             = 0; 
00344 
00345     std::string      cmd                 = "";
00346     std::string      params              = "";
00347     std::string      line                = "";
00348 
00349     slong       comment             = 0;
00350  
00351     shad = shader_create(); 
00352  
00353     if (!shad)
00354     {
00355         gv.fileman->close(f);
00356         return NULL; 
00357     }
00358  
00359     sprintf(shad->name, "%s", fname);
00360     shad->passcount = 0; 
00361     shad->dynamic = 0;
00362  
00363     while(!gv.fileman->eof(f)) 
00364     { 
00365       int i;
00366 
00367         linenum++; 
00368         gv.fileman->gets(tmp, 256, f); 
00369 
00370         line = tmp;
00371         
00372         comment = line.find('#');
00373         if (comment != -1)
00374             line[comment] = 0;
00375 
00376         for (i=line.length(); i>=0; --i)
00377           if (strchr(" \n\r\t", line.at(i)))
00378             line.erase(i);
00379         // line.trim(" \n\r\t");
00380 
00381         if (!line.length()) 
00382             continue; 
00383 
00384         if (line.find_first_of(" \n\t")==line.length())
00385         {
00386             cmd     = line;
00387             params  = "";
00388         }
00389         else
00390         {
00391             slong p = line.find_first_of(" \n\t");
00392             cmd     = line.substr(0, p);
00393             params  = line.substr(p+1, line.length()-p-1);
00394         }
00395 
00396         // newstage 
00397         if (!cmd.compare("newpass")) 
00398         { 
00399             if (currentpass>=7) 
00400             { 
00401                 _log_printf(MSG_ERROR,  "ERROR: while parsing shader \"%s\" line %u: " 
00402                                         "all passes already used. newstage invalid", 
00403                                         fname, linenum); 
00404                 break; 
00405             } 
00406 
00407             shader_initstage(shad, currentpass=++(shad->passcount)-1); 
00408             //                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
00409             // this is a very beautiful piece of code :)
00410             continue; 
00411         } 
00412 
00413         // blendtype 
00414         if (!cmd.compare("blendtype")) 
00415         { 
00416             shad->passes[currentpass].blendtype = texbtype_from_string(params.c_str()); 
00417             continue; 
00418         } 
00419         // texture 
00420         if (!cmd.compare("texture")) 
00421         { 
00422             shad->passes[currentpass].texture = gv.texman->load(params.c_str());
00423             continue; 
00424         } 
00425 
00426         // texture 
00427         if (!cmd.compare("texturenocomp")) 
00428         { 
00429             shad->passes[currentpass].texture = gv.texman->load(params.c_str(), true);
00430             continue; 
00431         } 
00432         
00433         // texture 
00434         if (!cmd.compare("twosided")) 
00435         { 
00436             shad->passes[currentpass].twosided = 1;
00437             continue; 
00438         } 
00439         // nodepth
00440         if (!cmd.compare("nodepth")) 
00441         { 
00442             shad->passes[currentpass].nodepth = 1;
00443             continue; 
00444         } 
00445 
00446         // lightmap
00447         if (!cmd.compare("lightmapped")) 
00448         { 
00449             shad->passes[currentpass].lightmap = !!atoi(params.c_str());
00450             continue; 
00451         } 
00452 
00453         // lightmap
00454         if (!cmd.compare("fog")) 
00455         { 
00456             shad->passes[currentpass].fog = !!atoi(params.c_str());
00457             continue; 
00458         } 
00459 
00460         // lightmap
00461         if (!cmd.compare("ignorediffuse")) 
00462         { 
00463             shad->passes[currentpass].ignorediffuse = !!atoi(params.c_str());
00464             continue; 
00465         } 
00466 
00467         // shiny 
00468         if (!cmd.compare("shiny")) 
00469         { 
00470             shad->passes[currentpass].shiny = !!atoi(params.c_str()); 
00471             continue; 
00472         } 
00473 
00474         // lighting
00475         if (!cmd.compare("lighting")) 
00476         { 
00477             shad->passes[currentpass].lighting = !!atoi(params.c_str()); 
00478             continue; 
00479         } 
00480 
00481  
00482         // rotation 
00483         if (!cmd.compare("rotation")) 
00484         { 
00485             shad->passes[currentpass].rotation = (float)atof(params.c_str()); 
00486             shad->dynamic = 1;
00487             shad->passes[currentpass].matrix = true;
00488             continue; 
00489         } 
00490 
00491         // rotation 
00492         if (!cmd.compare("angle")) 
00493         { 
00494             shad->passes[currentpass].angle = (float)atof(params.c_str()); 
00495             shad->passes[currentpass].matrix = true;
00496             continue; 
00497         } 
00498         
00499         // scale 
00500         if (!cmd.compare("scale")) 
00501         { 
00502             sscanf(params.c_str(), "%f %f",  
00503                 &shad->passes[currentpass].scalex, 
00504                 &shad->passes[currentpass].scaley ); 
00505             
00506             shad->passes[currentpass].matrix = true;
00507             continue; 
00508         } 
00509  
00510         // scroll 
00511         if (!cmd.compare("scroll")) 
00512         { 
00513             sscanf(params.c_str(), "%f %f",  
00514                 &shad->passes[currentpass].scrollx, 
00515                 &shad->passes[currentpass].scrolly ); 
00516             shad->dynamic = 1;
00517             shad->passes[currentpass].matrix = true;
00518             continue; 
00519         } 
00520  
00521         // offset 
00522         if (!cmd.compare("offset")) 
00523         { 
00524             sscanf(params.c_str(), "%f %f",  
00525                 &shad->passes[currentpass].offsetx, 
00526                 &shad->passes[currentpass].offsety ); 
00527             shad->dynamic = 1;
00528             shad->passes[currentpass].matrix = true;
00529             continue; 
00530         } 
00531  
00532         // scaleoffset 
00533         if (!cmd.compare("scaleoffset")) 
00534         { 
00535             sscanf(params.c_str(), "%f %f",  
00536                 &shad->passes[currentpass].soffsetx, 
00537                 &shad->passes[currentpass].soffsety ); 
00538             shad->dynamic = 1;
00539             shad->passes[currentpass].matrix = true;
00540             continue; 
00541         } 
00542  
00543         // filter 
00544         if (!cmd.compare("filter")) 
00545         { 
00546             char filter1[256]; 
00547             char filter2[256]; 
00548  
00549             sscanf(params.c_str(), "%s %s", filter1, filter2 ); 
00550  
00551             shad->passes[currentpass].minfilter = texfilter_from_string(filter1); 
00552             shad->passes[currentpass].magfilter = texfilter_from_string(filter2); 
00553             continue; 
00554         } 
00555  
00556         // wrap 
00557         if (!cmd.compare("wrap")) 
00558         { 
00559             char wrap1[256]; 
00560             char wrap2[256]; 
00561  
00562             sscanf(params.c_str(), "%s %s", wrap1, wrap2 ); 
00563  
00564             shad->passes[currentpass].texwrapu = texwrap_from_string(wrap1); 
00565             shad->passes[currentpass].texwrapv = texwrap_from_string(wrap2); 
00566             continue; 
00567         } 
00568  
00569         // color1 
00570         if (!cmd.compare("color1")) 
00571         { 
00572             vec4_t c; 
00573  
00574             sscanf(params.c_str(), "%f %f %f %f", &c[0], &c[1], &c[2], &c[3]); 
00575             shad->passes[currentpass].color1 = color_from_vec(c); 
00576             shad->passes[currentpass].color = true;
00577             continue; 
00578         } 
00579  
00580         // color2 
00581         if (!cmd.compare("color2")) 
00582         { 
00583             vec4_t c; 
00584  
00585             sscanf(params.c_str(), "%f %f %f %f", &c[0], &c[1], &c[2], &c[3]); 
00586             shad->passes[currentpass].color2 = color_from_vec(c); 
00587             continue; 
00588         } 
00589  
00590         // colorwave 
00591         if (!cmd.compare("colorwave")) 
00592         { 
00593             char    form[256]; 
00594  
00595             sscanf(params.c_str(), "%s %f %f %f %f", form,  
00596                 &shad->passes[currentpass].colorwave.freq, 
00597                 &shad->passes[currentpass].colorwave.phase, 
00598                 &shad->passes[currentpass].colorwave.amplitude, 
00599                 &shad->passes[currentpass].colorwave.bias ); 
00600  
00601             shad->passes[currentpass].colorwave.type = waveform_from_string(form); 
00602             shad->dynamic = 1;
00603             shad->passes[currentpass].color = true;
00604             continue; 
00605         } 
00606  
00607         // scalewavex 
00608         if (!cmd.compare("scalewavex")) 
00609         { 
00610             char    form[256]; 
00611  
00612             sscanf(params.c_str(), "%s %f %f %f %f", form,  
00613                 &shad->passes[currentpass].scalewavex.freq, 
00614                 &shad->passes[currentpass].scalewavex.phase, 
00615                 &shad->passes[currentpass].scalewavex.amplitude, 
00616                 &shad->passes[currentpass].scalewavex.bias ); 
00617  
00618             shad->passes[currentpass].scalewavex.type = waveform_from_string(form); 
00619             shad->dynamic = 1;
00620             shad->passes[currentpass].matrix = true;
00621             continue; 
00622         } 
00623  
00624         // scalewavey
00625         if (!cmd.compare("scalewavey")) 
00626         { 
00627             char    form[256]; 
00628  
00629             sscanf(params.c_str(), "%s %f %f %f %f", form,  
00630                 &shad->passes[currentpass].scalewavey.freq, 
00631                 &shad->passes[currentpass].scalewavey.phase, 
00632                 &shad->passes[currentpass].scalewavey.amplitude, 
00633                 &shad->passes[currentpass].scalewavey.bias ); 
00634  
00635             shad->passes[currentpass].scalewavey.type = waveform_from_string(form); 
00636             shad->dynamic = 1;
00637             shad->passes[currentpass].matrix = true;
00638             continue; 
00639         } 
00640 
00641         _log_printf(MSG_ERROR,  "ERROR: while parsing shader \"%s\" line %u: " 
00642                                         "invalid keyword \"%s\"", 
00643                                         (char*)fname, linenum, cmd.c_str()); 
00644  
00645     } 
00646     
00647     gv.fileman->close(f);
00648 
00649     return shad; 
00650 } 

Generated on Wed Dec 18 15:48:47 2002 for omicron engine by doxygen1.2.18