00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <string.h>
00012 #include <stdlib.h>
00013 #include "Common/Assert.h"
00014 #include "Common/Error.h"
00015 #include "Common/Directory.h"
00016 #include "Common/Console.h"
00017
00018 #include "Render/Render.h"
00019
00020 #include "Common/SearchFile.h"
00021 #include "Common/Parser.h"
00022 #include "Common/File.h"
00023
00024 #include "Render/Shader.h"
00025
00026
00027
00028
00029 void KShader::LoadTextures( u32 Size )
00030 {
00031
00032 if( !GetnStages() )
00033 {
00034 m_hTexture = GetpShaderBank()->GetTexture( m_pName, true, Size );
00035 KTexture* pTexture = m_pRender->GetpTextureBank()->GetpTexture( m_hTexture );
00036 m_bAlpha = pTexture ? pTexture->HasAlpha() : false;
00037 return;
00038 }
00039
00040
00041 for( u32 l = 0; l < GetnStages(); l ++ )
00042 {
00043 char* pMapName;
00044 char* pTemp;
00045
00046 if( !m_StageList[l]->m_nTextures )
00047 continue;
00048
00049 if( m_StageList[l]->m_pTextureList )
00050 continue;
00051
00052 m_StageList[l]->m_pTextureList = new KTEXTURE[ m_StageList[l]->m_nTextures];
00053
00054 pMapName = m_StageList[l]->m_pMapName;
00055
00056
00057 u32 Length = (u32)strlen( pMapName );
00058 for( u32 j = 0; j < Length; j ++ )
00059 {
00060 if( pMapName[j] == ',' )
00061 pMapName[j] = '\0';
00062 }
00063
00064
00065 pTemp = pMapName;
00066 for( u32 i = 0; i < m_StageList[l]->m_nTextures; i ++ )
00067 {
00068 KTEXTURE TextureId = GetpShaderBank()->GetTexture( pTemp, m_bMipMap, Size );
00069
00070 m_StageList[l]->m_pTextureList[i] = TextureId;
00071 pTemp += strlen( pTemp ) + 1;
00072 }
00073 }
00074 }
00075
00076
00077 void KShader::AddStage( char* pMapName, KRBLEND BlendSrc, KRBLEND BlendDst )
00078 {
00079 KShaderStage* pStage = new KShaderStage();
00080 pStage->m_pMapName = strdup( pMapName );
00081 pStage->m_nTextures = 1;
00082 pStage->m_BlendSrc = BlendSrc;
00083 pStage->m_BlendDst = BlendDst;
00084
00085 m_StageList.Add( pStage );
00086 }
00087
00088 void KShader::SetStageBlend( u32 Stage, KRBLEND BlendSrc, KRBLEND BlendDst )
00089 {
00090 KASSERT( Stage < m_StageList.GetSize() );
00091
00092 m_StageList[Stage]->m_BlendSrc = BlendSrc;
00093 m_StageList[Stage]->m_BlendDst = BlendDst;
00094 }
00095
00096
00097 void KShader::FlushAllStages()
00098 {
00099 u32 Size = m_StageList.GetSize();
00100 for( u32 s = 0; s < Size; s ++ )
00101 {
00102 if( m_StageList[s] )
00103 {
00104
00105 if( m_StageList[s]->m_pTextureList )
00106 for( u32 i = 0; i < m_StageList[s]->m_nTextures; i ++ )
00107 GetpShaderBank()->UnloadTexture( m_StageList[s]->m_pTextureList[i] );
00108
00109 Deletep( m_StageList[s] );
00110 }
00111 }
00112 m_StageList.Clear();
00113 }
00114
00115
00116 void KShader::FlushAllTextures()
00117 {
00118
00119
00120
00121 u32 Size = m_StageList.GetSize();
00122 for( u32 s = 0; s < Size; s ++ )
00123 {
00124 if( m_StageList[s] )
00125 {
00126
00127 if( m_StageList[s]->m_pTextureList )
00128 {
00129 for( u32 i = 0; i < m_StageList[s]->m_nTextures; i ++ )
00130 {
00131 GetpShaderBank()->UnloadTexture( m_StageList[s]->m_pTextureList[i] );
00132
00133 }
00134 Deletev( m_StageList[s]->m_pTextureList );
00135 }
00136 }
00137 }
00138
00139
00140
00141
00142 if( m_hTexture != KTEXTURE_NO )
00143 {
00144 GetpShaderBank()->UnloadTexture( m_hTexture );
00145 m_hTexture = KTEXTURE_NO;
00146 }
00147 }
00148
00149
00150
00151
00152 KShaderBank::KShaderBank( KRender* pRender )
00153 {
00154 m_pRender = pRender;
00155 }
00156
00157
00158 KShaderBank::~KShaderBank()
00159 {
00160 while( GetnDatas() )
00161 {
00162 FlushShader( GethFirst() );
00163 }
00164 }
00165
00166
00167 bool KShaderBank::PreLoad()
00168 {
00169 for( s32 Path = 0; Path < g_Directory.GetnPath(); Path ++ )
00170 {
00171 KStr sPath = g_Directory.GetPath( KStr( "Shaders" ), Path );
00172 KStr sSearchPath = sPath;
00173 sSearchPath += "*.sdr";
00174
00175
00176 KSearchFile SearchFile( sSearchPath );
00177
00178 KStr sFullName;
00179 for( u32 i = 0; i < SearchFile.GetnFiles(); i ++ )
00180 {
00181 sFullName = sPath;
00182 sFullName += SearchFile.GetpFile( i );
00183
00184 if( !LoadFile( sFullName ) )
00185 KError::Warning( NULL, "KShader::Load(...) : Cannot load shader file %s", (char*)sFullName );
00186 }
00187 }
00188
00189 return true;
00190 }
00191
00192
00193 void KShaderBank::FlushShader( KSHADER Handle )
00194 {
00195 KShader* pShader;
00196
00197 pShader = GetpData( Handle );
00198 KASSERT( pShader );
00199
00200 if( pShader->GetnInstances() != 0 )
00201 KError::Debug( NULL, "KShaderBank::FlushShader(...) : Bad instance counter : %i\nShader : %s", pShader->GetnInstances(), pShader->m_pName );
00202
00203 RemoveData( Handle );
00204 Deletep( pShader );
00205 }
00206
00207
00208
00209 #define FINDTOKEN Parser.FindToken()
00210 #define TOKEN Parser.GetToken()
00211 #define NEWLINETOKEN Parser.IsNewLine()
00212 #define CMPTOKEN(__s) (stricmp(__s,Parser.GetToken()) == 0)
00213
00214
00215 bool KShaderBank::LoadFile( char* pFileName )
00216 {
00217 KSHADER Handle;
00218 KParser Parser( pFileName );
00219
00220
00221 if( Parser.IsEOF() )
00222 return true;
00223
00224 do
00225 {
00226 KShader* pShader;
00227
00228 FINDTOKEN;
00229
00230
00231 if( Parser.IsEOF() )
00232 return true;
00233
00234 KASSERT( TOKEN[0] );
00235
00236
00237 bool bDuplicate = false;
00238 for( Handle = GethFirst(); Handle != KSHADER_NO; Handle = GethNext( Handle ) )
00239 {
00240 pShader = GetpShader( Handle );
00241 if( pShader && !stricmp( pShader->m_pName, TOKEN ) )
00242 {
00243 KError::Warning( NULL, "KShaderBank::LoadFile(...) : Duplicate shader found : [%s]", TOKEN );
00244
00245
00246 u32 i = 0;
00247 do
00248 {
00249 FINDTOKEN;
00250 if( CMPTOKEN( "{" ) )
00251 i ++;
00252 if( CMPTOKEN( "}" ) )
00253 i --;
00254 }while( i );
00255 bDuplicate = true;
00256 break;
00257 }
00258 }
00259 if( bDuplicate )
00260 continue;
00261
00262 KSHADER Handle;
00263 pShader = new KShader( m_pRender, this );
00264 Handle = AddData( pShader );
00265 pShader->m_hShader = Handle;
00266
00267
00268 pShader->m_pName = strdup( TOKEN );
00269
00270 FINDTOKEN;
00271 if( !CMPTOKEN( "{" ) )
00272 return false;
00273
00274
00275 do
00276 {
00277 continue_shader:
00278 FINDTOKEN;
00279
00280
00281 if CMPTOKEN( "surfaceparm" )
00282 {
00283 FINDTOKEN;
00284 if CMPTOKEN( "alphashadow" ) pShader->m_SurfaceParm |= KSSP_ALPHASHADOW;
00285 if CMPTOKEN( "areaportal" ) pShader->m_SurfaceParm |= KSSP_AREAPORTAL;
00286 if CMPTOKEN( "clusterportal") pShader->m_SurfaceParm |= KSSP_CLUSTERPORTAL;
00287 if CMPTOKEN( "donotenter" ) pShader->m_SurfaceParm |= KSSP_DONOTENTER;
00288 if CMPTOKEN( "flesh" ) pShader->m_SurfaceParm |= KSSP_FLESH;
00289 if CMPTOKEN( "fog" ) pShader->m_SurfaceParm |= KSSP_FOG;
00290 if CMPTOKEN( "lava" ) pShader->m_SurfaceParm |= KSSP_LAVA;
00291 if CMPTOKEN( "metalsteps" ) pShader->m_SurfaceParm |= KSSP_METALSTEPS;
00292 if CMPTOKEN( "nodamage" ) pShader->m_SurfaceParm |= KSSP_NODAMAGE;
00293 if CMPTOKEN( "nodlight" ) pShader->m_SurfaceParm |= KSSP_NODLIGHT;
00294 if CMPTOKEN( "nodraw" ) pShader->m_SurfaceParm |= KSSP_NODRAW;
00295 if CMPTOKEN( "nodrop" ) pShader->m_SurfaceParm |= KSSP_NODROP;
00296 if CMPTOKEN( "noimpact" ) pShader->m_SurfaceParm |= KSSP_NOIMPACT;
00297 if CMPTOKEN( "nomarks" ) pShader->m_SurfaceParm |= KSSP_NOMARKS;
00298 if CMPTOKEN( "nolightmap" ) pShader->m_SurfaceParm |= KSSP_NOLIGHTMAP;
00299 if CMPTOKEN( "nosteps" ) pShader->m_SurfaceParm |= KSSP_NOSTEPS;
00300 if CMPTOKEN( "nonsolid" ) pShader->m_SurfaceParm |= KSSP_NONSOLID;
00301 if CMPTOKEN( "origin" ) pShader->m_SurfaceParm |= KSSP_ORIGIN;
00302 if CMPTOKEN( "playerclip" ) pShader->m_SurfaceParm |= KSSP_PLAYERCLIP;
00303 if CMPTOKEN( "slick" ) pShader->m_SurfaceParm |= KSSP_SLICK;
00304 if CMPTOKEN( "slime" ) pShader->m_SurfaceParm |= KSSP_SLIME;
00305 if CMPTOKEN( "structural" ) pShader->m_SurfaceParm |= KSSP_STRUCTURAL;
00306 if CMPTOKEN( "trans" ) pShader->m_SurfaceParm |= KSSP_TRANS;
00307 if CMPTOKEN( "water" ) pShader->m_SurfaceParm |= KSSP_WATER;
00308 if CMPTOKEN( "sky" ) pShader->m_SurfaceParm |= KSSP_SKY;
00309 goto continue_shader;
00310 }
00311
00312
00313 if CMPTOKEN( "cull" )
00314 {
00315 FINDTOKEN;
00316 if CMPTOKEN( "front" ) pShader->m_Cull = KSGC_CW;
00317 if CMPTOKEN( "back" ) pShader->m_Cull = KSGC_CCW;
00318 if CMPTOKEN( "none" ) pShader->m_Cull = KSGC_NONE;
00319 if CMPTOKEN( "disable" ) pShader->m_Cull = KSGC_NONE;
00320 }
00321
00322 if CMPTOKEN( "nomipmap" )
00323 {
00324 pShader->m_bMipMap = false;
00325 }
00326
00327 if( CMPTOKEN( "sort" ) )
00328 {
00329 FINDTOKEN;
00330 if( CMPTOKEN( "portal" ) )
00331 pShader->m_SortValue = 1;
00332 else
00333 if( CMPTOKEN( "sky" ) )
00334 pShader->m_SortValue = 2;
00335 else
00336 if( CMPTOKEN( "opaque" ) )
00337 pShader->m_SortValue = 3;
00338 else
00339 if( CMPTOKEN( "banner" ) )
00340 pShader->m_SortValue = 6;
00341 else
00342 if( CMPTOKEN( "underwater" ) )
00343 pShader->m_SortValue = 8;
00344 else
00345 if( CMPTOKEN( "additive" ) )
00346 pShader->m_SortValue = 9;
00347 else
00348 if( CMPTOKEN( "nearest" ) )
00349 pShader->m_SortValue = 16;
00350 else
00351 pShader->m_SortValue = atoi( TOKEN );
00352
00353 }
00354
00355 if( CMPTOKEN( "{" ) )
00356 {
00357
00358 KShaderStage* pShaderStage;
00359
00360 pShaderStage = new KShaderStage();
00361 pShader->m_StageList.Add( pShaderStage );
00362
00363 do
00364 {
00365 continue_shaderstage:
00366 FINDTOKEN;
00367
00368
00369 if( CMPTOKEN( "map" ) )
00370 {
00371
00372 if( pShaderStage->m_pMapName )
00373 {
00374 KError::Warning( NULL, "KShaderBank::LoadFile(...) : Shader [%s] has already a map, ignoring...", pShader->m_pName );
00375 continue;
00376 }
00377
00378
00379 FINDTOKEN;
00380 pShaderStage->m_StageFlags |= KSSF_MAP;
00381 pShaderStage->m_pMapName = strdup( TOKEN );
00382 pShaderStage->m_nTextures = 1;
00383 if( CMPTOKEN( "$lightmap" ) )
00384 {
00385 pShader->m_Flags |= KSF_LIGHTMAP;
00386 pShaderStage->m_StageFlags |= KSSF_LIGHTMAP;
00387 }
00388 goto continue_shaderstage;
00389 }
00390 if( CMPTOKEN( "bumpmap" ) )
00391 {
00392
00393 if( pShaderStage->m_pMapName )
00394 {
00395 KError::Warning( NULL, "KShaderBank::LoadFile(...) : Shader [%s] has already a map, ignoring...", pShader->m_pName );
00396 continue;
00397 }
00398
00399 pShaderStage->m_StageFlags |= KSSF_BUMPMAP;
00400
00401 char* pTemp;
00402 u32 nTextures = 0;
00403
00404
00405 do
00406 {
00407 FINDTOKEN;
00408 pTemp = (char*)malloc( strlen( TOKEN ) + 1 + (pShaderStage->m_pMapName ? strlen( pShaderStage->m_pMapName ) : 0) + 1 );
00409
00410 strcpy( pTemp, pShaderStage->m_pMapName ? pShaderStage->m_pMapName : "" );
00411 strcat( pTemp, pShaderStage->m_pMapName ? "," : "" );
00412 strcat( pTemp, TOKEN );
00413
00414 if( pShaderStage->m_pMapName )
00415 free( pShaderStage->m_pMapName );
00416
00417 pShaderStage->m_pMapName = pTemp;
00418 nTextures ++;
00419 }while( !NEWLINETOKEN );
00420 pShaderStage->m_nTextures = nTextures;
00421 goto continue_shaderstage;
00422 }
00423 if( CMPTOKEN( "clampmap" ) )
00424 {
00425
00426 if( pShaderStage->m_pMapName )
00427 {
00428 KError::Warning( NULL, "KShaderBank::LoadFile(...) : Shader [%s] has already a map, ignoring...", pShader->m_pName );
00429 continue;
00430 }
00431
00432 FINDTOKEN;
00433 pShaderStage->m_StageFlags |= KSSF_CLAMPMAP;
00434 pShaderStage->m_pMapName = strdup( TOKEN );
00435 pShaderStage->m_nTextures = 1;
00436 if( CMPTOKEN( "$lightmap" ) )
00437 {
00438 pShader->m_Flags |= KSF_LIGHTMAP;
00439 pShaderStage->m_StageFlags |= KSSF_LIGHTMAP;
00440 }
00441 goto continue_shaderstage;
00442 }
00443 if( CMPTOKEN( "animmap" ) )
00444 {
00445
00446 if( pShaderStage->m_pMapName )
00447 {
00448 KError::Warning( NULL, "KShaderBank::LoadFile(...) : Shader [%s] has already a map, ignoring...", pShader->m_pName );
00449 continue;
00450 }
00451
00452 FINDTOKEN;
00453 pShaderStage->m_StageFlags |= KSSF_ANIMMAP;
00454 pShaderStage->m_Frequency = (float)atof( TOKEN );
00455
00456 char* pTemp;
00457 u32 nTextures = 0;
00458
00459
00460 do
00461 {
00462 FINDTOKEN;
00463 pTemp = (char*)malloc( strlen( TOKEN ) + 1 + (pShaderStage->m_pMapName ? strlen( pShaderStage->m_pMapName ) : 0) + 1 );
00464
00465 strcpy( pTemp, pShaderStage->m_pMapName ? pShaderStage->m_pMapName : "" );
00466 strcat( pTemp, pShaderStage->m_pMapName ? "," : "" );
00467 strcat( pTemp, TOKEN );
00468
00469 if( pShaderStage->m_pMapName )
00470 free( pShaderStage->m_pMapName );
00471
00472 pShaderStage->m_pMapName = pTemp;
00473 nTextures ++;
00474 }while( !NEWLINETOKEN );
00475 pShaderStage->m_nTextures = nTextures;
00476 goto continue_shaderstage;
00477 }
00478 if( CMPTOKEN( "blendfunc" ) )
00479 {
00480 FINDTOKEN;
00481 pShaderStage->m_StageFlags |= KSSF_BLEND;
00482 if( CMPTOKEN( "add" ) )
00483 {
00484
00485 pShaderStage->m_BlendSrc = KRBLEND_ONE;
00486 pShaderStage->m_BlendDst = KRBLEND_ONE;
00487
00488 if( !pShader->m_SortValue )
00489 pShader->m_SortValue = 9;
00490 }
00491 else
00492 if( CMPTOKEN( "filter" ) )
00493 {
00494
00495 pShaderStage->m_BlendSrc = KRBLEND_DST;
00496 pShaderStage->m_BlendDst = KRBLEND_ZERO;
00497 }
00498 else
00499 if( CMPTOKEN( "blend" ) )
00500 {
00501
00502 pShaderStage->m_BlendSrc = KRBLEND_SRCALPHA;
00503 pShaderStage->m_BlendDst = KRBLEND_INVSRCALPHA;
00504 }
00505 else
00506 if( CMPTOKEN( "factor" ) )
00507 {
00508
00509 pShaderStage->m_BlendSrc = KRBLEND_BLENDFACTOR;
00510 pShaderStage->m_BlendDst = KRBLEND_INVBLENDFACTOR;
00511 }
00512 else
00513 {
00514 pShaderStage->m_BlendSrc = GetBlendByText( TOKEN );
00515 FINDTOKEN;
00516 pShaderStage->m_BlendDst = GetBlendByText( TOKEN );
00517
00518 if( !pShader->m_SortValue && ( pShaderStage->m_BlendSrc == KRBLEND_ONE ) && ( pShaderStage->m_BlendDst == KRBLEND_ONE ) )
00519 {
00520 pShader->m_SortValue = 9;
00521
00522 }
00523 }
00524
00525 goto continue_shaderstage;
00526 }
00527
00528
00529
00530
00531 if( CMPTOKEN( "rgbGen" ) )
00532 {
00533 pShader->m_Flags |= KSF_RGBGEN;
00534
00535 FINDTOKEN;
00536 if( CMPTOKEN( "identityLighting" ) )
00537 {
00538 pShaderStage->m_RgbGen = KSSR_IDENTITYLIGHTING;
00539 }
00540 else
00541 if( CMPTOKEN( "identity" ) )
00542 {
00543 pShaderStage->m_RgbGen = KSSR_IDENTITY;
00544 }
00545 else
00546 if( CMPTOKEN( "wave" ) )
00547 {
00548 pShaderStage->m_RgbGen = KSSR_WAVE;
00549
00550 FINDTOKEN;
00551 if( CMPTOKEN( "sin" ) )
00552 pShaderStage->m_RgbGenWaveFunc = KSSTW_SIN;
00553 else
00554 if( CMPTOKEN( "triangle" ) )
00555 pShaderStage->m_RgbGenWaveFunc = KSSTW_TRIANGLE;
00556 else
00557 if( CMPTOKEN( "square" ) )
00558 pShaderStage->m_RgbGenWaveFunc = KSSTW_SQUARE;
00559 else
00560 if( CMPTOKEN( "sawtooth" ) )
00561 pShaderStage->m_RgbGenWaveFunc = KSSTW_SAWTOOTH;
00562 else
00563 if( CMPTOKEN( "inversesawtooth" ) )
00564 pShaderStage->m_RgbGenWaveFunc = KSSTW_INVERSESAWTOOTH;
00565 else
00566 KError::Warning( NULL, "KShaderBank::LoadFile(...) : Unknown TcMod StretchFunc [%s] in shader [%s]", TOKEN, pShader->m_pName );
00567
00568 FINDTOKEN;
00569 pShaderStage->m_RgbGenWaveParam1 = (float)atof( TOKEN );
00570 FINDTOKEN;
00571 pShaderStage->m_RgbGenWaveParam2 = (float)atof( TOKEN );
00572 FINDTOKEN;
00573 pShaderStage->m_RgbGenWaveParam3 = (float)atof( TOKEN );
00574 FINDTOKEN;
00575 pShaderStage->m_RgbGenWaveParam4 = (float)atof( TOKEN );
00576 }
00577 else
00578 if( CMPTOKEN( "entity" ) )
00579 {
00580 pShaderStage->m_RgbGen = KSSR_ENTITY;
00581 }
00582 else
00583 if( CMPTOKEN( "oneMinusEntity" ) )
00584 {
00585 pShaderStage->m_RgbGen = KSSR_ONEMINUSENTITY;
00586 }
00587 else
00588 if( CMPTOKEN( "vertex" ) )
00589 {
00590 pShaderStage->m_RgbGen = KSSR_VERTEX;
00591 }
00592 else
00593 if( CMPTOKEN( "exactVertex" ) )
00594 {
00595 pShaderStage->m_RgbGen = KSSR_VERTEX;
00596 }
00597 else
00598 if( CMPTOKEN( "oneMinusVertex" ) )
00599 {
00600 pShaderStage->m_RgbGen = KSSR_ONEMINUSVERTEX;
00601 }
00602 else
00603 if( CMPTOKEN( "lightingDiffuse" ) )
00604 {
00605 pShaderStage->m_RgbGen = KSSR_LIGHTINGDIFFUSE;
00606 }
00607 else
00608 KError::Warning( NULL, "KShaderBank::LoadFile(...) : Unknown rgbGen [%s] in shader [%s]", TOKEN, pShader->m_pName );
00609 }
00610
00611
00612
00613
00614 if( CMPTOKEN( "depthWrite" ) )
00615 {
00616 pShaderStage->m_bDepthWrite = true;
00617 }
00618
00619 if( CMPTOKEN( "noDepthWrite" ) )
00620 {
00621 pShaderStage->m_bDepthWrite = false;
00622 }
00623
00624
00625
00626
00627 if( CMPTOKEN( "depthFunc" ) )
00628 {
00629
00630 pShaderStage->m_StageFlags |= KSSF_DEPTHTEST;
00631
00632 FINDTOKEN;
00633 if( stricmp( TOKEN, "lequal" ) == 0 )
00634 pShaderStage->m_DepthFunc = KRCMP_LESSEQUAL;
00635 else
00636 if( stricmp( TOKEN, "equal" ) == 0 )
00637 pShaderStage->m_DepthFunc = KRCMP_EQUAL;
00638 else
00639 if( stricmp( TOKEN, "always" ) == 0 )
00640 pShaderStage->m_DepthFunc = KRCMP_ALWAYS;
00641 else
00642 KError::Warning( NULL, "KShaderBank::LoadFile(...) : Unknown depthFunc [%s] in shader [%s]", TOKEN, pShader->m_pName );
00643 }
00644
00645
00646
00647
00648 if( CMPTOKEN( "alphaFunc" ) )
00649 {
00650
00651 pShaderStage->m_StageFlags |= KSSF_ALPHATEST;
00652
00653 FINDTOKEN;
00654 if( stricmp( TOKEN, "always" ) == 0 )
00655 pShaderStage->m_AlphaFunc = KRCMP_ALWAYS;
00656 else
00657 if( strnicmp( TOKEN, "ge", 2 ) == 0 )
00658 pShaderStage->m_AlphaFunc = KRCMP_GREATEREQUAL;
00659 else
00660 if( strnicmp( TOKEN, "gt", 2 ) == 0 )
00661 pShaderStage->m_AlphaFunc = KRCMP_GREATER;
00662 else
00663 if( strnicmp( TOKEN, "lt", 2 ) == 0 )
00664 pShaderStage->m_AlphaFunc = KRCMP_LESS;
00665 else
00666 KError::Warning( NULL, "KShaderBank::LoadFile(...) : Unknown alphaFunc [%s] in shader [%s]", TOKEN, pShader->m_pName );
00667
00668 pShaderStage->m_AlphaRef = atoi( &TOKEN[2] );
00669 }
00670
00671
00672
00673
00674 if( CMPTOKEN( "tcMod" ) )
00675 {
00676 pShader->m_Flags |= KSF_TCMOD;
00677
00678 KShaderTcMod* pShaderTcMod = new KShaderTcMod();
00679 pShaderStage->m_TcModList.Add( pShaderTcMod );
00680
00681 FINDTOKEN;
00682 if( CMPTOKEN( "rotate" ) )
00683 {
00684 pShaderTcMod->m_TcMod = KSST_ROTATE;
00685 FINDTOKEN;
00686 pShaderTcMod->m_TcModParam1 = (float)atof( TOKEN );
00687 }
00688 else
00689 if( CMPTOKEN( "scale" ) )
00690 {
00691 pShaderTcMod->m_TcMod = KSST_SCALE;
00692 FINDTOKEN;
00693 pShaderTcMod->m_TcModParam1 = (float)atof( TOKEN );
00694 FINDTOKEN;
00695 pShaderTcMod->m_TcModParam2 = (float)atof( TOKEN );
00696 }
00697 else
00698 if( CMPTOKEN( "scroll" ) )
00699 {
00700 pShaderTcMod->m_TcMod = KSST_SCROLL;
00701 FINDTOKEN;
00702 pShaderTcMod->m_TcModParam1 = (float)atof( TOKEN );
00703 FINDTOKEN;
00704 pShaderTcMod->m_TcModParam2 = (float)atof( TOKEN );
00705 }
00706 else
00707 if( CMPTOKEN( "stretch" ) )
00708 {
00709 pShaderTcMod->m_TcMod = KSST_STRETCH;
00710 FINDTOKEN;
00711 if( CMPTOKEN( "sin" ) )
00712 pShaderTcMod->m_TcModFunc = KSSTF_SIN;
00713 else
00714 if( CMPTOKEN( "triangle" ) )
00715 pShaderTcMod->m_TcModFunc = KSSTF_TRIANGLE;
00716 else
00717 if( CMPTOKEN( "square" ) )
00718 pShaderTcMod->m_TcModFunc = KSSTF_SQUARE;
00719 else
00720 if( CMPTOKEN( "sawtooth" ) )
00721 pShaderTcMod->m_TcModFunc = KSSTF_SAWTOOTH;
00722 else
00723 if( CMPTOKEN( "inversesawtooth" ) )
00724 pShaderTcMod->m_TcModFunc = KSSTF_INVERSESAWTOOTH;
00725 else
00726 KError::Warning( NULL, "KShaderBank::LoadFile(...) : Unknown TcMod StretchFunc [%s] in shader [%s]", TOKEN, pShader->m_pName );
00727
00728 FINDTOKEN;
00729 pShaderTcMod->m_TcModParam1 = (float)atof( TOKEN );
00730 FINDTOKEN;
00731 pShaderTcMod->m_TcModParam2 = (float)atof( TOKEN );
00732 FINDTOKEN;
00733 pShaderTcMod->m_TcModParam3 = (float)atof( TOKEN );
00734 FINDTOKEN;
00735 pShaderTcMod->m_TcModParam4 = (float)atof( TOKEN );
00736 }
00737 else
00738 if( CMPTOKEN( "transform" ) )
00739 {
00740 pShaderTcMod->m_TcMod = KSST_TRANSFORM;
00741 FINDTOKEN;
00742 pShaderTcMod->m_TcModParam1 = (float)atof( TOKEN );
00743 FINDTOKEN;
00744 pShaderTcMod->m_TcModParam2 = (float)atof( TOKEN );
00745 FINDTOKEN;
00746 pShaderTcMod->m_TcModParam3 = (float)atof( TOKEN );
00747 FINDTOKEN;
00748 pShaderTcMod->m_TcModParam4 = (float)atof( TOKEN );
00749 FINDTOKEN;
00750 pShaderTcMod->m_TcModParam5 = (float)atof( TOKEN );
00751 FINDTOKEN;
00752 pShaderTcMod->m_TcModParam6 = (float)atof( TOKEN );
00753 }
00754 else
00755 if( CMPTOKEN( "turb" ) )
00756 {
00757 pShaderTcMod->m_TcMod = KSST_TURB;
00758 FINDTOKEN;
00759 pShaderTcMod->m_TcModParam1 = (float)atof( TOKEN );
00760 FINDTOKEN;
00761 pShaderTcMod->m_TcModParam2 = (float)atof( TOKEN );
00762 FINDTOKEN;
00763 pShaderTcMod->m_TcModParam3 = (float)atof( TOKEN );
00764 FINDTOKEN;
00765 pShaderTcMod->m_TcModParam4 = (float)atof( TOKEN );
00766 }
00767 else
00768 KError::Warning( NULL, "KShaderBank::LoadFile(...) : Unknown TcMod [%s] in shader [%s]", TOKEN, pShader->m_pName );
00769 }
00770
00771 }while( !CMPTOKEN( "}" ) );
00772 goto continue_shader;
00773
00774 }
00775 }while( !CMPTOKEN( "}" ) );
00776
00777 }while( TOKEN[0] );
00778
00779 return true;
00780 }
00781
00782
00783 KTEXTURE KShaderBank::GetTexture( char* pFileName, bool GenerateMipMap, u32 Size )
00784 {
00785 if( stricmp( pFileName, "$lightmap" ) == 0 )
00786 return KTEXTURE_NO;
00787
00788 if( stricmp( pFileName, "noshader" ) == 0 )
00789 return KTEXTURE_NO;
00790
00791 char pFullName[1024];
00792 char* pExtension;
00793
00794 strcpy( pFullName, pFileName );
00795 pExtension = KFile::GetFileExtension( pFullName );
00796 if( pExtension )
00797 {
00798
00799 pFullName[strlen(pFullName) - strlen( pExtension ) - 1] = '\0';
00800 }
00801
00802
00803 for( s32 i = 0; i < g_Directory.GetnPath(); i ++ )
00804 {
00805 KTEXTURE TextureId = KTEXTURE_NO;
00806
00807 KStr sTexturePath = g_Directory.GetPath( KStr( "Textures" ), i );
00808 sTexturePath += pFullName;
00809
00810 TextureId = m_pRender->GetpTextureBank()->LoadTexture( sTexturePath, GenerateMipMap, Size );
00811 if( TextureId != KTEXTURE_NO )
00812 {
00813 g_Console << "Texture loaded : " << pFileName << KENDL;
00814 return TextureId;
00815 }
00816 }
00817
00818 KError::Warning( NULL, "Cannot load texture %s", pFileName );
00819
00820 return KTEXTURE_NO;
00821 }
00822
00823
00824 KSHADER KShaderBank::LoadShader( char* pShaderName, u32 Size )
00825 {
00826 KSHADER Handle;
00827 KShader* pShader;
00828
00829
00830 for( Handle = GethFirst(); Handle != KSHADER_NO; Handle = GethNext( Handle ) )
00831 {
00832 pShader = GetpShader( Handle );
00833 if( pShader && stricmp( pShader->m_pName, pShaderName ) == 0 )
00834 {
00835
00836 pShader->AddInstance();
00837
00838
00839 pShader->LoadTextures( Size );
00840
00841 return Handle;
00842 }
00843 }
00844
00845 KError::Debug( NULL, "%s not found, default loaded.", pShaderName );
00846
00847
00848
00849 pShader = new KShader( m_pRender, this );
00850 pShader->AddInstance();
00851 Handle = AddData( pShader );
00852
00853 pShader->m_hShader = Handle;
00854 pShader->m_pName = strdup( pShaderName );
00855 pShader->LoadTextures( Size );
00856
00857
00858
00859
00860
00861 return Handle;
00862 }
00863
00864
00865 KSHADER KShaderBank::CreateShader( char* pShaderName )
00866 {
00867 KShader* pShader;
00868 KSHADER Handle;
00869
00870 pShader = new KShader( m_pRender, this );
00871 pShader->AddInstance();
00872 Handle = AddData( pShader );
00873
00874 pShader->m_hShader = Handle;
00875 pShader->m_pName = strdup( pShaderName );
00876
00877 return Handle;
00878 }
00879
00880
00881 void KShaderBank::UnloadShader( KSHADER& hShader )
00882 {
00883 KShader* pShader;
00884
00885 if( hShader == KSHADER_NO )
00886 return;
00887
00888 pShader = GetpData( hShader );
00889 KASSERT( pShader );
00890
00891 pShader->RemoveInstance();
00892 KASSERT( pShader->GetnInstances() >= 0 );
00893
00894 if( !pShader->GetnInstances() )
00895 {
00896
00897 pShader->FlushAllTextures();
00898 }
00899
00900 hShader = KSHADER_NO;
00901 }
00902
00903
00904 void KShaderBank::UnloadTexture( KTEXTURE hTexture )
00905 {
00906 m_pRender->GetpTextureBank()->UnloadTexture( hTexture );
00907 }
00908
00909
00910 KRBLEND KShaderBank::GetBlendByText( char* pBlendText )
00911 {
00912 if( stricmp( pBlendText, "GL_ZERO" ) == 0 )
00913 return KRBLEND_ZERO;
00914 else
00915 if( stricmp( pBlendText, "GL_ONE" ) == 0 )
00916 return KRBLEND_ONE;
00917 else
00918 if( stricmp( pBlendText, "GL_SRC_COLOR" ) == 0 )
00919 return KRBLEND_SRC;
00920 else
00921 if( stricmp( pBlendText, "GL_ONE_MINUS_SRC_COLOR" ) == 0 )
00922 return KRBLEND_INVSRC;
00923 else
00924 if( stricmp( pBlendText, "GL_DST_COLOR" ) == 0 )
00925 return KRBLEND_DST;
00926 else
00927 if( stricmp( pBlendText, "GL_ONE_MINUS_DST_COLOR" ) == 0 )
00928 return KRBLEND_INVDST;
00929 else
00930 if( stricmp( pBlendText, "GL_SRC_ALPHA" ) == 0 )
00931 return KRBLEND_SRCALPHA;
00932 else
00933 if( stricmp( pBlendText, "GL_ONE_MINUS_SRC_ALPHA" ) == 0 )
00934 return KRBLEND_INVSRCALPHA;
00935 else
00936 if( stricmp( pBlendText, "GL_DST_ALPHA" ) == 0 )
00937 return KRBLEND_DSTALPHA;
00938 else
00939 if( stricmp( pBlendText, "GL_ONE_MINUS_DST_ALPHA" ) == 0 )
00940 return KRBLEND_INVDSTALPHA;
00941 else
00942 if( stricmp( pBlendText, "GL_SRC_ALPHA_SATURATE" ) == 0 )
00943 return KRBLEND_SRCALPHASAT;
00944
00945 return (KRBLEND)-1;
00946 }
00947
00948
00949 void KShaderBank::DumpUsed()
00950 {
00951 KSHADER Handle;
00952 KShader* pShader;
00953 s32 n = 0;
00954
00955
00956 for( Handle = GethFirst(); Handle != KSHADER_NO; Handle = GethNext( Handle ) )
00957 {
00958 pShader = GetpShader( Handle );
00959 if( pShader && pShader->GetnInstances() )
00960 {
00961 g_Console << Handle << ":" << pShader->m_pName << " " << pShader->GetnInstances() << " instance(s)" << KENDL;
00962 n ++;
00963 }
00964 }
00965 g_Console << n << " shader(s) loaded." << KENDL;
00966 }
00967