Changeset 3055
- Timestamp:
- 10/21/08 17:29:12 (16 years ago)
- Location:
- GTP/trunk/App/Demos/Vis/FriendlyCulling
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
GTP/trunk/App/Demos/Vis/FriendlyCulling/FriendlyCulling.vcproj
r3052 r3055 244 244 </File> 245 245 <File 246 RelativePath=".\src\ShaderProgram.cpp"247 >248 </File>249 <File250 RelativePath=".\src\ShaderProgram.h"251 >252 </File>253 <File254 246 RelativePath=".\src\SkyPreetham.cpp" 255 247 > … … 507 499 </File> 508 500 <File 501 RelativePath=".\src\ShaderManager.h" 502 > 503 </File> 504 <File 505 RelativePath=".\src\ShaderProgram.h" 506 > 507 </File> 508 <File 509 509 RelativePath=".\src\ShadowMapping.h" 510 510 > … … 680 680 <File 681 681 RelativePath=".\src\SceneQuery.cpp" 682 > 683 </File> 684 <File 685 RelativePath=".\src\ShaderManager.cpp" 686 > 687 </File> 688 <File 689 RelativePath=".\src\ShaderProgram.cpp" 682 690 > 683 691 </File> -
GTP/trunk/App/Demos/Vis/FriendlyCulling/src/RenderState.h
r3052 r3055 73 73 protected: 74 74 75 /** A special query technique. This material75 /** A special technique for occlusion queries. This material 76 76 has color write, depth write, and lighting turned off 77 77 */ … … 84 84 bool mCullFaceEnabled; 85 85 bool mTexturesEnabled; 86 86 /// Render or query mode 87 87 Mode mMode; 88 88 -
GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ResourceManager.cpp
r3052 r3055 6 6 #include "Texture.h" 7 7 #include "gzstream.h" 8 #include "Matrix4x4.h"9 8 #include "Vector3.h" 10 9 #include "Transform3.h" -
GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ShaderManager.cpp
r3045 r3055 1 #include "ResourceManager.h"2 #include "Matrix4x4.h"3 #include "Geometry.h"4 #include "SceneEntity.h"5 1 #include "Material.h" 6 2 #include "Texture.h" 7 #include "gzstream.h"8 #include "Matrix4x4.h"9 #include "Vector3.h"10 #include "Transform3.h"11 #include "Shape.h"12 #include "LODInfo.h"13 3 #include "RenderState.h" 14 4 #include "ShaderProgram.h" 5 #include "ShaderManager.h" 15 6 #include <Cg/cg.h> 16 7 #include <Cg/cgGL.h> … … 42 33 static CGprofile sCgFragmentProfile; 43 34 static CGprofile sCgVertexProfile; 35 36 static ShaderProgram *sTreeAnimationProgramMrt; 37 static ShaderProgram *sTreeAnimationProgram; 44 38 static ShaderProgram *sTreeAnimation; 45 39 46 // only instance of the resourcemanager47 ResourceManager *ResourceManager::sResourceManager = NULL;40 // only instance of the shader manager 41 ShaderManager *ShaderManager::sShaderManager = NULL; 48 42 49 43 … … 64 58 65 59 66 ResourceManager::ResourceManager() 67 { 68 InitCg(); 69 } 70 71 72 ResourceManager::~ResourceManager() 73 { 74 // delete all resources. 75 CLEAR_CONTAINER(mSceneEntities); 76 CLEAR_CONTAINER(mGeometry); 77 CLEAR_CONTAINER(mMaterials); 78 CLEAR_CONTAINER(mTextures); 79 CLEAR_CONTAINER(mTrafos); 80 CLEAR_CONTAINER(mShapes); 81 CLEAR_CONTAINER(mLODs); 82 CLEAR_CONTAINER(mGPUParameters); 83 CLEAR_CONTAINER(mShaders); 84 85 if (sCgContext) 86 cgDestroyContext(sCgContext); 87 } 88 89 90 SceneEntity *ResourceManager::LoadSceneEntity(igzstream &str) 91 { 92 bool hasTrafo; 93 str.read(reinterpret_cast<char *>(&hasTrafo), sizeof(bool)); 94 95 SceneEntity *sceneGeom; 96 Transform3 *trafo; 97 98 if (!hasTrafo) 99 { 100 // identity 101 trafo = new Transform3(); 102 } 103 else 104 { 105 Matrix4x4 m; 106 str.read(reinterpret_cast<char *>(m.x), sizeof(Matrix4x4)); 107 108 trafo = new Transform3(m); 109 } 110 111 mTrafos.push_back(trafo); 112 113 sceneGeom = new SceneEntity(trafo); 114 115 116 /////////////// 117 //-- load lod levels 118 119 // note: lods must be ordered from smallest distance to largest 120 int numLODs; 121 str.read(reinterpret_cast<char *>(&numLODs), sizeof(int)); 122 123 for (int i = 0; i < numLODs; ++ i) 124 { 125 float dist; 126 str.read(reinterpret_cast<char *>(&dist), sizeof(float)); 127 128 int numShapes; 129 str.read(reinterpret_cast<char *>(&numShapes), sizeof(int)); 130 131 LODLevel *lodLevel = new LODLevel(dist); 132 133 for (int j = 0; j < numShapes; ++ j) 134 { 135 int shapeId; 136 str.read(reinterpret_cast<char *>(&shapeId), sizeof(int)); 137 138 Geometry *geom = mGeometryTable[shapeId]; 139 Material *mat = mMaterialTable[shapeId]; 140 141 // create shape 142 Shape *shape = new Shape(geom, mat, sceneGeom); 143 144 mShapes.push_back(shape); 145 146 sceneGeom->AddShape(shape); 147 lodLevel->AddShape(shape); 148 } 149 150 mLODs.push_back(lodLevel); 151 sceneGeom->AddLODLevel(lodLevel); 152 } 153 154 /////////// 155 //-- hack: tree animation 156 157 if (numLODs > 1) 158 { 159 for (int i = 0; i < min(numLODs, 2); ++ i) 160 { 161 ShapeContainer::iterator sstart, send; 162 sceneGeom->GetLODLevel(i, sstart, send); 163 164 for (ShapeContainer::iterator it = sstart; it != send; ++ it) 165 { 166 Shape *shape = *it; 167 168 Material *mat = shape->GetMaterial(); 169 170 // add the vertex animation program 171 for (int i = 0; i < 2; ++ i) 172 { 173 Technique *tech = mat->GetTechnique(i); 174 tech->SetVertexProgram(sTreeAnimation); 175 176 GPUProgramParameters *vtxParams = tech->GetVertexProgramParameters(); 177 178 vtxParams->SetTimerParam(0); 179 // wind direction 180 static Vector3 windDir = Normalize(Vector3(0.8f, 0.2f, 0.0f)); 181 vtxParams->SetValue3f(1, windDir.x, windDir.y, windDir.z); 182 // amplitude 183 vtxParams->SetValue1f(2, 0.3f); 184 185 AxisAlignedBox3 box = sceneGeom->GetBoundingBox(); 186 vtxParams->SetValue2f(3, box.Min().z, box.Max().z); 187 // frequency 188 vtxParams->SetValue1f(4, 0.1f); 189 } 190 } 191 } 192 } 193 194 return sceneGeom; 195 } 196 197 198 void ResourceManager::LoadTextures(igzstream &str) 199 { 200 int numTextures; 201 str.read(reinterpret_cast<char *>(&numTextures), sizeof(int)); 202 203 for (int i = 0; i < numTextures; ++ i) 204 { 205 // load texture name 206 int texnameSize; 207 str.read(reinterpret_cast<char *>(&texnameSize), sizeof(int)); 208 209 char *texname = new char[texnameSize]; 210 str.read(texname, sizeof(char) * texnameSize); 211 212 Texture *tex = new Texture(model_path + texname); 213 214 int boundS, boundT; 215 216 str.read(reinterpret_cast<char *>(&boundS), sizeof(int)); 217 str.read(reinterpret_cast<char *>(&boundT), sizeof(int)); 218 219 tex->SetBoundaryModeS(boundS); 220 tex->SetBoundaryModeT(boundT); 221 222 tex->Create(); 223 224 mTextureTable[i] = tex; 225 mTextures.push_back(tex); 226 227 delete [] texname; 228 } 229 230 cout << "loaded " << (int)mTextureTable.size() << " textures" << endl; 231 } 232 233 234 void ResourceManager::LoadShapes(igzstream &str) 235 { 236 int numShapes; 237 str.read(reinterpret_cast<char *>(&numShapes), sizeof(int)); 238 239 for (int i = 0; i < numShapes; ++ i) 240 { 241 Geometry *geom = LoadGeometry(str); 242 Material *mat = LoadMaterial(str); 243 244 mGeometryTable[i] = geom; 245 mMaterialTable[i] = mat; 246 247 mGeometry.push_back(geom); 248 mMaterials.push_back(mat); 249 } 250 251 cout << "loaded " << (int)mGeometryTable.size() << " shapes" << endl; 252 } 253 254 255 Material *ResourceManager::LoadMaterial(igzstream &str) 256 { 257 // default material 258 Material *mat = new Material(); 259 260 // set default fragment + vertex programs 261 Technique *tech = mat->GetDefaultTechnique(); 262 263 // texture 264 int texId; 265 str.read(reinterpret_cast<char *>(&texId), sizeof(int)); 266 267 if (texId >= 0) 268 tech->SetTexture(mTextureTable[texId]); 269 270 str.read(reinterpret_cast<char *>(&tech->mAlphaTestEnabled), sizeof(bool)); 271 str.read(reinterpret_cast<char *>(&tech->mCullFaceEnabled), sizeof(bool)); 272 273 // gl material 274 bool hasGlMaterial; 275 str.read(reinterpret_cast<char *>(&hasGlMaterial), sizeof(bool)); 276 277 if (hasGlMaterial) 278 { 279 // only write rgb part of the material 280 str.read(reinterpret_cast<char *>(&tech->mAmbientColor), sizeof(Vector3)); 281 str.read(reinterpret_cast<char *>(&tech->mDiffuseColor), sizeof(Vector3)); 282 str.read(reinterpret_cast<char *>(&tech->mEmmisiveColor), sizeof(Vector3)); 283 str.read(reinterpret_cast<char *>(&tech->mSpecularColor), sizeof(Vector3)); 284 } 285 286 287 /////////////// 288 //-- add technique for deferred shading 289 290 Technique *deferred = new Technique(*tech); 291 292 if (deferred->GetTexture()) 293 { 294 deferred->SetFragmentProgram(mMrtDefaultFragmentTexProgram); 295 deferred->GetFragmentProgramParameters()->SetTexture(0, tech->GetTexture()->GetId()); 296 } 297 else 298 { 299 deferred->SetFragmentProgram(mMrtDefaultFragmentProgram); 300 } 301 302 deferred->SetVertexProgram(mMrtDefaultVertexProgram); 303 304 mat->AddTechnique(deferred); 305 306 return mat; 307 } 308 309 310 Geometry *ResourceManager::LoadGeometry(igzstream &str) 311 { 312 Vector3 *vertices; 313 Vector3 *normals; 314 Texcoord2 *texcoords; 315 316 317 ////////////// 318 //-- read in vertices 319 320 int vertexCount; 321 str.read(reinterpret_cast<char *>(&vertexCount), sizeof(int)); 322 323 // end of file reached 324 if (str.eof()) return NULL; 325 326 //cout << "vertexcount: " << vertexCount << endl; 327 328 vertices = new Vector3[vertexCount]; 329 str.read(reinterpret_cast<char *>(vertices), sizeof(Vector3) * vertexCount); 330 331 normals = new Vector3[vertexCount]; 332 str.read(reinterpret_cast<char *>(normals), sizeof(Vector3) * vertexCount); 333 334 int texCoordCount; 335 str.read(reinterpret_cast<char *>(&texCoordCount), sizeof(int)); 336 337 if (texCoordCount) 338 { 339 texcoords = new Texcoord2[texCoordCount]; 340 str.read(reinterpret_cast<char *>(texcoords), sizeof(Texcoord2) * texCoordCount); 341 } 342 else 343 { 344 texcoords = NULL; 345 } 346 347 return new Geometry(vertices, normals, texcoords, vertexCount, true); 348 //return new Geometry(vertices, normals, texcoords, vertexCount, false); 349 } 350 351 352 void ResourceManager::LoadSceneEntities(igzstream &str, SceneEntityContainer &entities) 353 { 354 int entityCount; 355 str.read(reinterpret_cast<char *>(&entityCount), sizeof(int)); 356 357 entities.reserve(entityCount); 358 359 for (int i = 0; i < entityCount; ++ i) 360 { 361 SceneEntity *ent = LoadSceneEntity(str); 362 363 // return loaded entities 364 entities.push_back(ent); 365 // also store internally 366 mSceneEntities.push_back(ent); 367 } 368 369 cout << "loaded " << entityCount << " scene entities" << endl; 370 } 371 372 373 bool ResourceManager::Load(const std::string &filename, SceneEntityContainer &entities) 374 { 375 igzstream istr(filename.c_str()); 376 377 if (!istr.is_open()) 378 return false; 379 380 cout << "loading textures" << endl; 381 382 // load the texture table 383 LoadTextures(istr); 384 385 cout << "loading shapes (geometry + materials)" << endl; 386 387 // load the shapees 388 LoadShapes(istr); 389 390 cout << "loading scene entites" << endl; 391 LoadSceneEntities(istr, entities); 392 393 cout << "bin loading finished" << endl; 394 395 // clean up 396 mTextureTable.clear(); 397 mGeometryTable.clear(); 398 mMaterialTable.clear(); 399 400 return true; 401 } 402 403 404 405 ShaderProgram *ResourceManager::CreateFragmentProgram(const std::string &filename, 406 const std::string &funcName) 407 { 408 const string fullName = "src/shaders/" + filename + ".cg"; 409 410 ShaderProgram *p = new ShaderProgram(sCgContext, fullName, sCgFragmentProfile, funcName); 411 412 mShaders.push_back(p); 413 414 if (!p->IsValid()) 415 { 416 DEL_PTR(p); 417 cerr << "Program " << funcName << " in " << fullName << " failed to load" << endl; 418 } 419 420 cout << "Program " << funcName << " in " << fullName << " loaded" << endl; 421 422 return p; 423 } 424 425 426 ShaderProgram *ResourceManager::CreateVertexProgram(const std::string &filename, const std::string &funcName) 427 { 428 const string fullName = "src/shaders/" + filename + ".cg"; 429 430 ShaderProgram *p = new ShaderProgram(sCgContext, fullName, sCgVertexProfile, funcName); 431 mShaders.push_back(p); 432 433 if (!p->IsValid()) 434 { 435 DEL_PTR(p); 436 cerr << "Program " << funcName << " in " << fullName << " failed to load" << endl; 437 } 438 439 cout << "Program " << funcName << " in " << fullName << " loaded" << endl; 440 441 return p; 442 } 443 444 445 void ResourceManager::InitCg() 60 ShaderManager::ShaderManager() 446 61 { 447 62 // setup cg … … 459 74 cgGLSetManageTextureParameters(sCgContext, false); 460 75 461 mMrtDefaultVertexProgram = CreateVertexProgram("mrt", "vtx"); 462 mMrtDefaultFragmentProgram = CreateFragmentProgram("mrt", "frag"); 463 mMrtDefaultFragmentTexProgram = CreateFragmentProgram("mrt", "fragtex"); 464 mMrtDefaultFragmentTexProgram->AddParameter("tex", 0); 465 466 sTreeAnimation = CreateVertexProgram("treeanimation", "animateVtxMrt"); 467 468 sTreeAnimation->AddParameter("timer", 0); 469 sTreeAnimation->AddParameter("windDir", 1); 470 sTreeAnimation->AddParameter("windStrength", 2); 471 sTreeAnimation->AddParameter("minMaxPos", 3); 472 sTreeAnimation->AddParameter("frequency", 4); 76 mMrtDefaultVertexProgram = CreateVertexProgram("mrt", "vtx", "defaultMrtVertex"); 77 mMrtDefaultFragmentProgram = CreateFragmentProgram("mrt", "frag", "defaultMrtFragment"); 78 mMrtDefaultFragmentTexProgram = CreateFragmentProgram("mrt", "fragtex", "defaultMrtFragmentTex"); 79 80 // provide the current view matrix 81 mMrtDefaultFragmentProgram->AddParameter("viewMatrix", 0); 82 mMrtDefaultFragmentTexProgram->AddParameter("viewMatrix", 0); 83 // add a texture parameter 84 mMrtDefaultFragmentTexProgram->AddParameter("tex", 1); 85 86 87 ////////////////////////// 88 //-- hack: apply hardcoded tree animation (should be provided with a material script!) 89 90 sTreeAnimationProgram = CreateVertexProgram("treeanimation", "animateVtx", "treeAnimation"); 91 sTreeAnimationProgramMrt = CreateVertexProgram("treeanimation", "animateVtxMrt", "treeAnimationMrt"); 92 93 sTreeAnimationProgram->AddParameter("timer", 0); 94 sTreeAnimationProgram->AddParameter("windDir", 1); 95 sTreeAnimationProgram->AddParameter("windStrength", 2); 96 sTreeAnimationProgram->AddParameter("minMaxPos", 3); 97 sTreeAnimationProgram->AddParameter("frequency", 4); 98 sTreeAnimationProgram->AddParameter("lightDir", 5); 99 100 sTreeAnimationProgramMrt->AddParameter("timer", 0); 101 sTreeAnimationProgramMrt->AddParameter("windDir", 1); 102 sTreeAnimationProgramMrt->AddParameter("windStrength", 2); 103 sTreeAnimationProgramMrt->AddParameter("minMaxPos", 3); 104 sTreeAnimationProgramMrt->AddParameter("frequency", 4); 473 105 474 106 cout << "cg initialization successful" << endl; … … 476 108 477 109 478 void ResourceManager::EnableFragmentProfile() 110 void ShaderManager::DelSingleton() 111 { 112 DEL_PTR(sShaderManager); 113 } 114 115 116 ShaderManager::~ShaderManager() 117 { 118 CLEAR_CONTAINER(mShaders); 119 120 if (sCgContext) 121 cgDestroyContext(sCgContext); 122 } 123 124 125 ShaderProgram *ShaderManager::CreateFragmentProgram(const std::string &filename, 126 const std::string &funcName, 127 const std::string &name) 128 { 129 return CreateShaderProgram(filename, funcName, name, true); 130 } 131 132 133 ShaderProgram *ShaderManager::CreateVertexProgram(const std::string &filename, 134 const std::string &funcName, 135 const std::string &name) 136 { 137 return CreateShaderProgram(filename, funcName, name, false); 138 } 139 140 141 void ShaderManager::EnableFragmentProfile() 479 142 { 480 143 cgGLEnableProfile(sCgFragmentProfile); … … 482 145 483 146 484 void ResourceManager::EnableVertexProfile()147 void ShaderManager::EnableVertexProfile() 485 148 { 486 149 cgGLEnableProfile(sCgVertexProfile); … … 488 151 489 152 490 void ResourceManager::DisableFragmentProfile()153 void ShaderManager::DisableFragmentProfile() 491 154 { 492 155 cgGLDisableProfile(sCgFragmentProfile); … … 494 157 495 158 496 void ResourceManager::DisableVertexProfile()159 void ShaderManager::DisableVertexProfile() 497 160 { 498 161 cgGLDisableProfile(sCgVertexProfile); 499 500 } 501 502 503 } 504 162 } 163 164 165 ShaderProgram *ShaderManager::CreateShaderProgram(const std::string &filename, 166 const std::string &funcName, 167 const std::string &name, 168 bool isFragment) 169 { 170 const string fullName = "src/shaders/" + filename + ".cg"; 171 172 ShaderProgram *p = 173 new ShaderProgram(sCgContext, fullName, 174 isFragment ? sCgFragmentProfile : sCgVertexProfile, funcName); 175 176 ShaderMap::const_iterator it = mShaderMap.find(name); 177 178 if (it == mShaderMap.end()) 179 { 180 DEL_PTR(p); 181 182 cerr << "Program name " << name << "already chosen" << endl; 183 return p; 184 } 185 186 if (!p->IsValid()) 187 { 188 DEL_PTR(p); 189 cerr << "Program " << funcName << " in " << fullName << " failed to load" << endl; 190 return p; 191 } 192 193 cout << "Program " << funcName << " in " << fullName << " loaded" << endl; 194 195 mShaders.push_back(p); 196 mShaderMap[name] = p; 197 198 return p; 199 } 200 201 202 } 203 -
GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ShaderManager.h
r3045 r3055 1 #ifndef __ ResourceManager_H__2 #define __ ResourceManager_H__1 #ifndef __SHADERMANAGER_H__ 2 #define __SHADERMANAGER_H__ 3 3 4 4 … … 9 9 #include "common.h" 10 10 11 12 13 class igzstream;14 15 16 11 namespace CHCDemoEngine 17 12 { 18 13 19 class SceneEntity;20 class Material;21 class Geometry;22 class Texture;23 14 class Matrix4x4; 24 15 class Transform3; 25 16 class ShaderProgram; 26 17 18 typedef std::map<std::string, ShaderProgram *> ShaderMap; 19 27 20 28 21 /** Loads a scene and also handles the cleanup 29 22 */ 30 class ResourceManager23 class ShaderManager 31 24 { 32 25 public: … … 34 27 /** Returns the resource manager as a singleton. 35 28 */ 36 static ResourceManager *GetSingleton() 37 { 38 if (!sResourceManager) 39 { 40 sResourceManager = new ResourceManager(); 41 } 42 43 return sResourceManager; 44 } 45 29 static ShaderManager *GetSingleton(); 46 30 /** We also want full control over the delete. 47 31 */ 48 static void DelSingleton() 49 { 50 DEL_PTR(sResourceManager); 51 } 52 53 /** Loads a model 54 */ 55 bool Load(const std::string &filename, SceneEntityContainer &geometry); 56 57 int GetNumEntities() const { return (int)mSceneEntities.size(); } 58 59 /** Creates new gpu program parameters. 60 */ 61 GPUProgramParameters *CreateGPUProgramParameters(ShaderProgram *p); 32 static void DelSingleton(); 62 33 /** Creates a new shader program. 63 34 */ 64 ShaderProgram *CreateFragmentProgram(const std::string &filename, const std::string &funcName); 65 ShaderProgram *CreateVertexProgram(const std::string &filename, const std::string &funcName); 35 ShaderProgram *CreateFragmentProgram(const std::string &filename, 36 const std::string &funcName, 37 const std::string &name); 38 39 ShaderProgram *CreateVertexProgram(const std::string &filename, 40 const std::string &funcName, 41 const std::string &name); 66 42 67 43 void EnableFragmentProfile(); … … 70 46 void DisableFragmentProfile(); 71 47 void DisableVertexProfile(); 48 49 ShaderProgram *GetShaderProgram(const std::string &name); 72 50 73 51 … … 78 56 singleton pattern. 79 57 */ 80 ResourceManager();58 ShaderManager(); 81 59 82 ~ ResourceManager();60 ~ShaderManager(); 83 61 62 ShaderProgram *CreateShaderProgram(const std::string &filename, 63 const std::string &funcName, 64 const std::string &name, 65 bool isFragment); 84 66 85 void InitCg();67 //////////////////////// 86 68 87 void LoadTextures(igzstream &str);88 void LoadShapes(igzstream &str);89 void LoadSceneEntities(igzstream &str, SceneEntityContainer &entities);90 91 SceneEntity *LoadSceneEntity(igzstream &str);92 Material *LoadMaterial(igzstream &str);93 Geometry *LoadGeometry(igzstream &str);94 95 std::map<int, Texture *> mTextureTable;96 std::map<int, Material *> mMaterialTable;97 std::map<int, Geometry *> mGeometryTable;98 //std::map<int, Shape *> mShapesTable;99 100 101 /////////////102 //-- these are kept to be able to delete these resources afterwards103 104 TextureContainer mTextures;105 MaterialContainer mMaterials;106 GeometryContainer mGeometry;107 TransformContainer mTrafos;108 GPUParamContainer mGPUParameters;109 69 ShaderContainer mShaders; 110 ShapeContainer mShapes; 111 LODContainer mLODs; 112 113 //////// 114 115 /// the scene entities 116 117 SceneEntityContainer mSceneEntities; 118 70 ShaderMap mShaderMap; 119 71 120 72 //////////// … … 128 80 private: 129 81 130 static ResourceManager *sResourceManager;82 static ShaderManager *sShaderManager; 131 83 }; 132 84 133 85 86 ShaderManager *ShaderManager::GetSingleton() 87 { 88 if (!sShaderManager) 89 { 90 sShaderManager = new ShaderManager(); 91 } 92 93 return sShaderManager; 94 } 95 134 96 } 135 97 #endif
Note: See TracChangeset
for help on using the changeset viewer.