//----------------------------------------------------------------------------- CPUTResult CPUTAssetSetDX11::LoadAssetSet(cString name) { CPUTResult result = CPUT_SUCCESS; // if not found, load the set file CPUTConfigFile ConfigFile; result = ConfigFile.LoadFile(name); #if 1 if( !CPUTSUCCESS(result) ) { return result; } // ASSERT( CPUTSUCCESS(result), _L("Failed loading set file '") + name + _L("'.") ); mAssetCount = ConfigFile.BlockCount() + 1; // Add one for the implied root node // mAssetCount = min(2, mAssetCount); // Add one for the implied root node mppAssetList = new CPUTRenderNode*[mAssetCount]; mppAssetList[0] = mpRootNode; mpRootNode->AddRef(); CPUTAssetLibraryDX11 *pAssetLibrary = (CPUTAssetLibraryDX11*)CPUTAssetLibrary::GetAssetLibrary(); for(UINT ii=0; ii<mAssetCount-1; ii++) // Note: -1 because we added one for the root node (we don't load it) { CPUTConfigBlock *pBlock = ConfigFile.GetBlock(ii); int assetIndex = pBlock->GetNameValue(); cString nodeType = pBlock->GetValueByName(_L("type"))->ValueAsString(); CPUTRenderNode *pParentNode = NULL; // TODO: use Get*() instead of Load*() ? cString name = pBlock->GetValueByName(_L("name"))->ValueAsString(); int parentIndex; CPUTRenderNode *pNode; if(0==nodeType.compare(_L("null"))) { pNode = pNode = new CPUTNullNode(); result = ((CPUTNullNode*)pNode)->LoadNullNode(pBlock, &parentIndex); pParentNode = mppAssetList[parentIndex+1]; cString &parentPrefix = pParentNode->GetPrefix(); pNode->SetPrefix( parentPrefix + _L(".") + name ); pAssetLibrary->AddNullNode(parentPrefix + name, (CPUTNullNode*)pNode); // Add this null's name to our prefix // Append this null's name to our parent's prefix pNode->SetParent( pParentNode ); pParentNode->AddChild( pNode ); } else if(0==nodeType.compare(_L("model"))) { CPUTConfigEntry *pValue = pBlock->GetValueByName( _L("instance") ); CPUTModelDX11 *pModel = new CPUTModelDX11(); if( pValue == &CPUTConfigEntry::sNullConfigValue ) { // Not found. So, not an instance. pModel->LoadModel(pBlock, &parentIndex, NULL); } else { int instance = pValue->ValueAsInt(); pModel->LoadModel(pBlock, &parentIndex, (CPUTModel*)mppAssetList[instance+1]); } pParentNode = mppAssetList[parentIndex+1]; pModel->SetParent( pParentNode ); pParentNode->AddChild( pModel ); cString &parentPrefix = pParentNode->GetPrefix(); pModel->SetPrefix( parentPrefix ); pAssetLibrary->AddModel(parentPrefix + name, pModel); pModel->UpdateBoundsWorldSpace(); #ifdef SUPPORT_DRAWING_BOUNDING_BOXES // Create a mesh for rendering the bounding box // TODO: There is definitely a better way to do this. But, want to see the bounding boxes! pModel->CreateBoundingBoxMesh(); #endif pNode = pModel; } else if(0==nodeType.compare(_L("light"))) { pNode = new CPUTLight(); ((CPUTLight*)pNode)->LoadLight(pBlock, &parentIndex); pParentNode = mppAssetList[parentIndex+1]; // +1 because we added a root node to the start pNode->SetParent( pParentNode ); pParentNode->AddChild( pNode ); cString &parentPrefix = pParentNode->GetPrefix(); pNode->SetPrefix( parentPrefix ); pAssetLibrary->AddLight(parentPrefix + name, (CPUTLight*)pNode); } else if(0==nodeType.compare(_L("camera"))) { pNode = new CPUTCamera(); ((CPUTCamera*)pNode)->LoadCamera(pBlock, &parentIndex); pParentNode = mppAssetList[parentIndex+1]; // +1 because we added a root node to the start pNode->SetParent( pParentNode ); pParentNode->AddChild( pNode ); cString &parentPrefix = pParentNode->GetPrefix(); pNode->SetPrefix( parentPrefix ); pAssetLibrary->AddCamera(parentPrefix + name, (CPUTCamera*)pNode); if( !mpFirstCamera ) { mpFirstCamera = (CPUTCamera*)pNode; mpFirstCamera->AddRef();} ++mCameraCount; } else { ASSERT(0,_L("Unsupported node type '") + nodeType + _L("'.")); } // Add the node to our asset list (i.e., the linear list, not the hierarchical) mppAssetList[ii+1] = pNode; // Don't AddRef.Creating it set the refcount to 1. We add it to the list, and then we're done with it. // Net effect is 0 (+1 to add to list, and -1 because we're done with it) // pNode->AddRef(); } #endif HEAPCHECK return result; }
//----------------------------------------------------------------------------- CPUTResult CPUTMaterialDX11::LoadMaterial(const cString &fileName, const CPUTModel *pModel, int meshIndex) { CPUTResult result = CPUT_SUCCESS; mMaterialName = fileName; mMaterialNameHash = CPUTComputeHash( mMaterialName ); // Open/parse the file CPUTConfigFile file; result = file.LoadFile(fileName); if(CPUTFAILED(result)) { return result; } // Make a local copy of all the parameters mConfigBlock = *file.GetBlock(0); // get necessary device and AssetLibrary pointers ID3D11Device *pD3dDevice = CPUT_DX11::GetDevice(); CPUTAssetLibraryDX11 *pAssetLibrary = (CPUTAssetLibraryDX11*)CPUTAssetLibrary::GetAssetLibrary(); // TODO: The following code is very repetitive. Consider generalizing so we can call a function instead. // see if there are any pixel/vertex/geo shaders to load CPUTConfigEntry *pValue, *pEntryPointName, *pProfileName; pValue = mConfigBlock.GetValueByName(_L("VertexShaderFile")); if( pValue->IsValid() ) { pEntryPointName = mConfigBlock.GetValueByName(_L("VertexShaderMain")); pProfileName = mConfigBlock.GetValueByName(_L("VertexShaderProfile")); pAssetLibrary->GetVertexShader(pValue->ValueAsString(), pD3dDevice, pEntryPointName->ValueAsString(), pProfileName->ValueAsString(), &mpVertexShader ); ReadShaderSamplersAndTextures( mpVertexShader->GetBlob(), &mVertexShaderParameters ); } // load and store the pixel shader if it was specified pValue = mConfigBlock.GetValueByName(_L("PixelShaderFile")); if( pValue->IsValid() ) { pEntryPointName = mConfigBlock.GetValueByName(_L("PixelShaderMain")); pProfileName = mConfigBlock.GetValueByName(_L("PixelShaderProfile")); pAssetLibrary->GetPixelShader(pValue->ValueAsString(), pD3dDevice, pEntryPointName->ValueAsString(), pProfileName->ValueAsString(), &mpPixelShader); ReadShaderSamplersAndTextures( mpPixelShader->GetBlob(), &mPixelShaderParameters ); } // load and store the compute shader if it was specified pValue = mConfigBlock.GetValueByName(_L("ComputeShaderFile")); if( pValue->IsValid() ) { pEntryPointName = mConfigBlock.GetValueByName(_L("ComputeShaderMain")); pProfileName = mConfigBlock.GetValueByName(_L("ComputeShaderProfile")); pAssetLibrary->GetComputeShader(pValue->ValueAsString(), pD3dDevice, pEntryPointName->ValueAsString(), pProfileName->ValueAsString(), &mpComputeShader); ReadShaderSamplersAndTextures( mpComputeShader->GetBlob(), &mComputeShaderParameters ); } // load and store the geometry shader if it was specified pValue = mConfigBlock.GetValueByName(_L("GeometryShaderFile")); if( pValue->IsValid() ) { pEntryPointName = mConfigBlock.GetValueByName(_L("GeometryShaderMain")); pProfileName = mConfigBlock.GetValueByName(_L("GeometryShaderProfile")); pAssetLibrary->GetGeometryShader(pValue->ValueAsString(), pD3dDevice, pEntryPointName->ValueAsString(), pProfileName->ValueAsString(), &mpGeometryShader); ReadShaderSamplersAndTextures( mpGeometryShader->GetBlob(), &mGeometryShaderParameters ); } // load and store the hull shader if it was specified pValue = mConfigBlock.GetValueByName(_L("HullShaderFile")); if( pValue->IsValid() ) { pEntryPointName = mConfigBlock.GetValueByName(_L("HullShaderMain")); pProfileName = mConfigBlock.GetValueByName(_L("HullShaderProfile")); pAssetLibrary->GetHullShader(pValue->ValueAsString(), pD3dDevice, pEntryPointName->ValueAsString(), pProfileName->ValueAsString(), &mpHullShader); ReadShaderSamplersAndTextures( mpHullShader->GetBlob(), &mHullShaderParameters ); } // load and store the domain shader if it was specified pValue = mConfigBlock.GetValueByName(_L("DomainShaderFile")); if( pValue->IsValid() ) { pEntryPointName = mConfigBlock.GetValueByName(_L("DomainShaderMain")); pProfileName = mConfigBlock.GetValueByName(_L("DomainShaderProfile")); pAssetLibrary->GetDomainShader(pValue->ValueAsString(), pD3dDevice, pEntryPointName->ValueAsString(), pProfileName->ValueAsString(), &mpDomainShader); ReadShaderSamplersAndTextures( mpDomainShader->GetBlob(), &mDomainShaderParameters ); } // load and store the render state file if it was specified pValue = mConfigBlock.GetValueByName(_L("RenderStateFile")); if( pValue->IsValid() ) { mpRenderStateBlock = pAssetLibrary->GetRenderStateBlock(pValue->ValueAsString()); } // For each of the shader stages, bind shaders and buffers for( CPUTShaderParameters **pCur = mpShaderParametersList; *pCur; pCur++ ) // Bind textures and buffersfor each shader stage { BindTextures( **pCur, pModel, meshIndex ); BindBuffers( **pCur, pModel, meshIndex ); BindUAVs( **pCur, pModel, meshIndex ); BindConstantBuffers( **pCur, pModel, meshIndex ); } return result; }
//----------------------------------------------------------------------------- CPUTResult CPUTAssetSet::LoadAssetSet(std::string name, int numSystemMaterials, std::string *pSystemMaterialNames) { CPUTResult result = CPUT_SUCCESS; // if not found, load the set file CPUTConfigFile ConfigFile; result = ConfigFile.LoadFile(name); if( !CPUTSUCCESS(result) ) { return result; } // ASSERT( CPUTSUCCESS(result), "Failed loading set file '" + name + "'." ); mAssetCount = ConfigFile.BlockCount() + 1; // Add one for the implied root node mppAssetList = new CPUTRenderNode*[mAssetCount]; mppAssetList[0] = mpRootNode; mpRootNode->AddRef(); CPUTAssetLibrary *pAssetLibrary = (CPUTAssetLibrary*)CPUTAssetLibrary::GetAssetLibrary(); CPUTAnimation *pDefaultAnimation = NULL; for(UINT ii=0; ii<mAssetCount-1; ii++) // Note: -1 because we added one for the root node (we don't load it) { CPUTConfigBlock *pBlock = ConfigFile.GetBlock(ii); ASSERT(pBlock != NULL, "Cannot find block"); if( !pBlock ) { return CPUT_ERROR_PARAMETER_BLOCK_NOT_FOUND; } std::string nodeType = pBlock->GetValueByName("type")->ValueAsString(); CPUTRenderNode *pParentNode = NULL; // TODO: use Get*() instead of Load*() ? std::string name = pBlock->GetValueByName("name")->ValueAsString(); int parentIndex; CPUTRenderNode *pNode = NULL; if(0==nodeType.compare("null")) { pNode = pNode = CPUTNullNode::Create(); result = ((CPUTNullNode*)pNode)->LoadNullNode(pBlock, &parentIndex); pParentNode = mppAssetList[parentIndex+1]; std::string &parentPrefix = pParentNode->GetPrefix(); std::string prefix = parentPrefix; prefix.append("."); prefix.append(name); pNode->SetPrefix(prefix); // pNode->SetPrefix( parentPrefix + "." + name ); pAssetLibrary->AddNullNode("", parentPrefix + name, "", (CPUTNullNode*)pNode); // Add this null's name to our prefix // Append this null's name to our parent's prefix pNode->SetParent( pParentNode ); pParentNode->AddChild( pNode ); } else if(0==nodeType.compare("model")) { CPUTConfigEntry *pValue = pBlock->GetValueByName( "instance" ); CPUTModel *pModel = CPUTModel::Create(); if( pValue == &CPUTConfigEntry::sNullConfigValue ) { // Not found. So, not an instance. pModel->LoadModel(pBlock, &parentIndex, NULL, numSystemMaterials, pSystemMaterialNames); } else { int instance = pValue->ValueAsInt(); // If the current node is an instance of itself then it has no "master" model if(ii == instance) { // TODO: create instance model object pModel->LoadModel(pBlock, &parentIndex, NULL, numSystemMaterials, pSystemMaterialNames); } else { pModel->LoadModel(pBlock, &parentIndex, (CPUTModel*)mppAssetList[instance+1], numSystemMaterials, pSystemMaterialNames); } } pParentNode = mppAssetList[parentIndex+1]; pModel->SetParent( pParentNode ); pParentNode->AddChild( pModel ); std::string &parentPrefix = pParentNode->GetPrefix(); pModel->SetPrefix( parentPrefix ); pAssetLibrary->AddModel(name, parentPrefix, "", pModel); pModel->UpdateBoundsWorldSpace(); #ifdef SUPPORT_DRAWING_BOUNDING_BOXES // Create a mesh for rendering the bounding box // TODO: There is definitely a better way to do this. But, want to see the bounding boxes! pModel->CreateBoundingBoxMesh(); #endif pNode = pModel; } else if(0==nodeType.compare("light")) { pNode = CPUTLight::Create(); ((CPUTLight*)pNode)->LoadLight(pBlock, &parentIndex); pParentNode = mppAssetList[parentIndex+1]; // +1 because we added a root node to the start pNode->SetParent( pParentNode ); pParentNode->AddChild( pNode ); std::string &parentPrefix = pParentNode->GetPrefix(); pNode->SetPrefix( parentPrefix ); pAssetLibrary->AddLight(name, parentPrefix, "", (CPUTLight*)pNode); } else if(0==nodeType.compare("camera")) { pNode = CPUTCamera::Create(CPUT_PERSPECTIVE); ((CPUTCamera*)pNode)->LoadCamera(pBlock, &parentIndex); pParentNode = mppAssetList[parentIndex+1]; // +1 because we added a root node to the start pNode->SetParent( pParentNode ); pParentNode->AddChild( pNode ); std::string &parentPrefix = pParentNode->GetPrefix(); pNode->SetPrefix( parentPrefix ); pAssetLibrary->AddCamera(name, parentPrefix, "", (CPUTCamera*)pNode); if( !mpFirstCamera ) { mpFirstCamera = (CPUTCamera*)pNode; mpFirstCamera->AddRef();} ++mCameraCount; } else { ASSERT(0,"Unsupported node type '" + nodeType + "'."); } CPUTConfigEntry *pAnimValue = pBlock->GetValueByName( "Animation0" ); //int autoPlayAnimationIndex = pBlock->GetValueByName( "DefaultAnimation" ); for(int i = 1; pAnimValue != &CPUTConfigEntry::sNullConfigValue; ++i ) { CPUTAnimation *pCurrentAnimation = pAssetLibrary->GetAnimation(pAnimValue->ValueAsString()); //First Animation will be default for now if(pCurrentAnimation != NULL && i == 1 /*autoPlayAnimationIndex*/) { pDefaultAnimation = pCurrentAnimation ; pCurrentAnimation->AddRef(); } std::stringstream animName; animName << "Animation" << i; pAnimValue = pBlock->GetValueByName(animName.str()); pNode->mAnimationList.push_back(pCurrentAnimation); } // Add the node to our asset list (i.e., the linear list, not the hierarchical) mppAssetList[ii+1] = pNode; // Don't AddRef.Creating it set the refcount to 1. We add it to the list, and then we're done with it. // Net effect is 0 (+1 to add to list, and -1 because we're done with it) // pNode->AddRef(); } //Set the default animation to the current Asset Set if(pDefaultAnimation != NULL && mAssetCount > 1) { //Apply Animation to root of the setfile mppAssetList[1]->SetAnimation(pDefaultAnimation); } SAFE_RELEASE(pDefaultAnimation); return result; }
CPUTResult CPUTMaterialEffectOGL::LoadMaterialEffect( const cString &fileName, const CPUTModel *pModel, int meshIndex, const char **pShaderMacros, int externalCount, cString *pExternalName, float4 *pExternals, int *pExternalOffset, int *pExternalSize ){ CPUTResult result = CPUT_SUCCESS; CPUTConfigEntry *pValue; mMaterialName = fileName; mMaterialNameHash = CPUTComputeHash( mMaterialName ); // Open/parse the file CPUTConfigFile file; result = file.LoadFile(fileName); if(CPUTFAILED(result)) { return result; } // Make a local copy of all the parameters CPUTConfigBlock *pBlock = file.GetBlock(0); ASSERT( pBlock, _L("Error getting parameter block") ); if( !pBlock ) { return CPUT_ERROR_PARAMETER_BLOCK_NOT_FOUND; } mConfigBlock = *pBlock; // get necessary device and AssetLibrary pointers //ID3D11Device *pD3dDevice = CPUT_DX11::GetDevice(); CPUTAssetLibraryOGL *pAssetLibrary = (CPUTAssetLibraryOGL*)CPUTAssetLibrary::GetAssetLibrary(); { CPUTConfigEntry *pEntryPointName, *pProfileName; int numFiles = 0; cString pBase = _L("VertexShaderFileOGL_"); cString pName = pBase + to_cString(numFiles+1); std::vector<cString> filenames; while (mConfigBlock.GetValueByName(pName)->IsValid()) { filenames.push_back(mConfigBlock.GetValueByName(pName)->ValueAsString()); numFiles++; pName = pBase + to_cString(numFiles+1); } if(numFiles > 0) { pEntryPointName = mConfigBlock.GetValueByName(_L("VertexShaderMain")); pProfileName = mConfigBlock.GetValueByName(_L("VertexShaderProfile")); pAssetLibrary->GetVertexShader( filenames, /*pD3dDevice,*/ _L("VertexShaderMain"), pProfileName->ValueAsString(), &mpVertexShader, false, (CPUT_SHADER_MACRO*)pShaderMacros ); } } #ifdef CPUT_SUPPORT_TESSELLATION { int numFiles = 0; cString pBase = _L("ControlShaderFileOGL_"); cString pName = pBase + to_cString(numFiles+1); std::vector<cString> filenames; while (mConfigBlock.GetValueByName(pName)->IsValid()) { filenames.push_back(mConfigBlock.GetValueByName(pName)->ValueAsString()); numFiles++; pName = pBase + to_cString(numFiles+1); } if(numFiles > 0) { pAssetLibrary->GetHullShader( filenames, /* pD3dDevice,*/ _L("ControlShaderMain"), _L(""), &mpControlShader, false, (CPUT_SHADER_MACRO*)pShaderMacros ); } } { int numFiles = 0; cString pBase = _L("EvaluationShaderFileOGL_"); cString pName = pBase + to_cString(numFiles+1); std::vector<cString> filenames; while (mConfigBlock.GetValueByName(pName)->IsValid()) { filenames.push_back(mConfigBlock.GetValueByName(pName)->ValueAsString()); numFiles++; pName = pBase + to_cString(numFiles+1); } if(numFiles > 0) { pAssetLibrary->GetDomainShader( filenames, /* pD3dDevice,*/ _L("EvaluationShaderMain"), _L(""), &mpEvaluationShader, false, (CPUT_SHADER_MACRO*)pShaderMacros ); } } #endif { int numFiles = 0; cString pBase = _L("GeometryShaderFileOGL_"); cString pName = pBase + to_cString(numFiles+1); std::vector<cString> filenames; while (mConfigBlock.GetValueByName(pName)->IsValid()) { filenames.push_back(mConfigBlock.GetValueByName(pName)->ValueAsString()); numFiles++; pName = pBase + to_cString(numFiles+1); } if(numFiles > 0) { pAssetLibrary->GetGeometryShader( filenames, /* pD3dDevice,*/ _L("GeometryShaderMain"), _L(""), &mpGeometryShader, false, (CPUT_SHADER_MACRO*)pShaderMacros ); } } // load and store the pixel shader if it was specified { int numFiles = 0; cString pBase = _L("FragmentShaderFileOGL_"); cString pName = pBase + to_cString(numFiles+1); std::vector<cString> filenames; while (mConfigBlock.GetValueByName(pName)->IsValid()) { filenames.push_back(mConfigBlock.GetValueByName(pName)->ValueAsString()); numFiles++; pName = pBase + to_cString(numFiles+1); } if(numFiles > 0) { pAssetLibrary->GetPixelShader( filenames, /* pD3dDevice,*/ _L("FragmentShaderMain"), //mConfigBlock.GetValueByName(_L("FragmentShaderMain"))->ValueAsString(), mConfigBlock.GetValueByName(_L("FragmentShaderProfile"))->ValueAsString(), &mpFragmentShader, false, (CPUT_SHADER_MACRO*)pShaderMacros ); } } // load and store the render state file if it was specified pValue = mConfigBlock.GetValueByName(_L("RenderStateFile")); if( pValue->IsValid() ) { mpRenderStateBlock = pAssetLibrary->GetRenderStateBlock(pValue->ValueAsString()); } int IsLinked; char *shaderProgramInfoLog; int maxLength; mShaderProgram = glCreateProgram(); // Attach our shaders to our program // Attach our shaders to our program if (mpVertexShader) { GL_CHECK(glAttachShader(mShaderProgram, mpVertexShader->GetShaderID())); } if (mpFragmentShader) { GL_CHECK(glAttachShader(mShaderProgram, mpFragmentShader->GetShaderID())); } if (mpControlShader) { GL_CHECK(glAttachShader(mShaderProgram, mpControlShader->GetShaderID())); } if (mpEvaluationShader) { GL_CHECK(glAttachShader(mShaderProgram, mpEvaluationShader->GetShaderID())); } if (mpGeometryShader) { GL_CHECK(glAttachShader(mShaderProgram, mpGeometryShader->GetShaderID())); } /* GL_CHECK(glBindAttribLocation(mShaderProgram, 0, "in_Position")); GL_CHECK(glBindAttribLocation(mShaderProgram, 1, "inNormal")); GL_CHECK(glBindAttribLocation(mShaderProgram, 2, "inBinormal")); GL_CHECK(glBindAttribLocation(mShaderProgram, 3, "inTangent")); GL_CHECK(glBindAttribLocation(mShaderProgram, 4, "inTex")); */ // Link our program // At this stage, the vertex and fragment programs are inspected, optimized and a binary code is generated for the shader. // The binary code is uploaded to the GPU, if there is no error. GL_CHECK(glLinkProgram(mShaderProgram)); // Again, we must check and make sure that it linked. If it fails, it would mean either there is a mismatch between the vertex // and fragment shaders. It might be that you have surpassed your GPU's abilities. Perhaps too many ALU operations or // too many texel fetch instructions or too many interpolators or dynamic loops. GL_CHECK(glGetProgramiv(mShaderProgram, GL_LINK_STATUS, (int *)&IsLinked)); if(IsLinked == false) { // Noticed that glGetProgramiv is used to get the length for a shader program, not glGetShaderiv. glGetProgramiv(mShaderProgram, GL_INFO_LOG_LENGTH, &maxLength); // The maxLength includes the NULL character shaderProgramInfoLog = (char *)malloc(maxLength); // Notice that glGetProgramInfoLog, not glGetShaderInfoLog. glGetProgramInfoLog(mShaderProgram, maxLength, &maxLength, shaderProgramInfoLog); DEBUG_PRINT_ALWAYS((_L("Failed to link shader program:\n%s\n"), shaderProgramInfoLog)); ASSERT(false, _L("glLinkProgram failed")); // Handle the error in an appropriate way such as displaying a message or writing to a log file. // In this simple program, we'll just leave //DEBUG_PRINT_ALWAYS(("Failed to link shader program:\n%s\n", shaderProgramInfoLog)); free(shaderProgramInfoLog); } // Shader must be successfully linked before we can query uniform locations ReadShaderSamplersAndTextures( mShaderProgram, &mVertexShaderParameters ); glUseProgram(0); // For each of the shader stages, bind shaders and buffers // for( CPUTShaderParameters **pCur = mpShaderParametersList; *pCur; pCur++ ) // Bind textures and buffersfor each shader stage { BindTextures( mVertexShaderParameters, pModel, meshIndex ); //BindTextures( **pCur, pModel, meshIndex ); //BindBuffers( **pCur, pModel, meshIndex ); BindUAVs( mVertexShaderParameters, pModel, meshIndex ); BindConstantBuffers( mVertexShaderParameters, pModel, meshIndex ); } return result; }
//----------------------------------------------------------------------------- CPUTResult CPUTMaterial::LoadMaterial( const cString &fileName, const CPUTModel *pModel, int meshIndex, const char **pShaderMacros, int systemMaterialCount, cString *pSystemMaterialNames, int externalCount, cString *pExternalName, float4 *pExternals, int *pExternalOffset, int *pExternalSize ){ CPUTResult result = CPUT_SUCCESS; mMaterialName = fileName; mMaterialNameHash = CPUTComputeHash( mMaterialName ); // Open/parse the file CPUTConfigFile file; result = file.LoadFile(fileName); if(CPUTFAILED(result)) { return result; } // Make a local copy of all the parameters CPUTConfigBlock *pBlock = file.GetBlock(0); ASSERT( pBlock, _L("Error getting parameter block") ); if( !pBlock ) { return CPUT_ERROR_PARAMETER_BLOCK_NOT_FOUND; } mConfigBlock = *pBlock; CPUTAssetLibrary *pAssetLibrary = (CPUTAssetLibrary*)CPUTAssetLibrary::GetAssetLibrary(); mMaterialEffectCount = 0; if( mConfigBlock.GetValueByName( _L("MultiMaterial") )->ValueAsBool() ) { // Count materials; for(;;) { CPUTConfigEntry *pValue = mConfigBlock.GetValueByName( _L("Material") + itoc(mMaterialEffectCount) ); if( pValue->IsValid() ) { ++mMaterialEffectCount; } else { break; } } ASSERT(mMaterialEffectCount != 0, _L("MultiMaterial specified, but no sub materials given.") ); // Reserve space for "authored" materials plus system materials mpMaterialEffectNames = new cString[mMaterialEffectCount+systemMaterialCount]; int ii; for( ii=0; ii<mMaterialEffectCount; ii++ ) { CPUTConfigEntry *pValue = mConfigBlock.GetValueByName( _L("Material") + itoc(ii) ); mpMaterialEffectNames[ii] = pAssetLibrary->GetMaterialEffectPath(pValue->ValueAsString(), false); } } else { mMaterialEffectCount = 1; mpMaterialEffectNames = new cString[mMaterialEffectCount+systemMaterialCount]; mpMaterialEffectNames[0] = fileName; } CPUT_SHADER_MACRO *pFinalShaderMacros = (CPUT_SHADER_MACRO*)pShaderMacros; CPUT_SHADER_MACRO *pUserSpecifiedMacros = NULL; // The real material count includes the system material count mMaterialEffectCount += systemMaterialCount; for( int ii=0; ii<systemMaterialCount; ii++ ) { // Read additional macros from .mtl file cString macroBlockName = _L("defines") + itoc(ii); CPUTConfigBlock *pMacrosBlock = file.GetBlockByName(macroBlockName); int numUserSpecifiedMacros = 0; if( pMacrosBlock ) { ReadMacrosFromConfigBlock( pMacrosBlock, (CPUT_SHADER_MACRO*)pShaderMacros, &pUserSpecifiedMacros, &numUserSpecifiedMacros, &pFinalShaderMacros ); } // System materials "grow" from the end; the 1st system material is at the end of the list. mpMaterialEffectNames[mMaterialEffectCount-systemMaterialCount+ii] = pSystemMaterialNames[ii]; for( int kk=0; kk<numUserSpecifiedMacros; kk++ ) { // ReadMacrosFromConfigBlock allocates memory (ws2s does). Delete it here. SAFE_DELETE(pUserSpecifiedMacros[kk].Name); SAFE_DELETE(pUserSpecifiedMacros[kk].Definition); } SAFE_DELETE_ARRAY( pFinalShaderMacros ); SAFE_DELETE_ARRAY( pUserSpecifiedMacros ); } mpMaterialEffects = new CPUTMaterialEffect*[mMaterialEffectCount+1]; for( int ii=0; ii<mMaterialEffectCount; ii++ ) { mpMaterialEffects[ii] = pAssetLibrary->GetMaterialEffect( mpMaterialEffectNames[ii], true, pModel, meshIndex,(const char**)pFinalShaderMacros ); } mpMaterialEffects[mMaterialEffectCount] = NULL; return result; // This material is a multi-material, so we're done. }