//---------------------------------------------------------------------------// SharedPtr<Material> AssetStorage::CreateMaterial(const MaterialDesc& aDesc) { const uint64 descHash = aDesc.GetHash(); auto it = myMaterials.find(descHash); if (it != myMaterials.end()) return it->second; TextureViewProperties srvViewProps; srvViewProps.myDimension = GpuResourceDimension::TEXTURE_2D; SharedPtr<Material> mat(new Material); for (uint i = 0u; i < aDesc.mySemanticTextures.size(); ++i) { SharedPtr<Texture> tex = CreateTexture(aDesc.mySemanticTextures[i].c_str()); if (tex != nullptr) mat->mySemanticTextures[i] = RenderCore::CreateTextureView(tex, srvViewProps); } for (const String& texPath : aDesc.myExtraTextures) { SharedPtr<Texture> tex = CreateTexture(texPath.c_str()); if (tex != nullptr) mat->myExtraTextures.push_back(RenderCore::CreateTextureView(tex, srvViewProps)); } for (uint i = 0u; i < aDesc.mySemanticParameters.size(); ++i) mat->mySemanticParameters[i] = aDesc.mySemanticParameters[i]; for (float param : aDesc.myExtraParameters) mat->myExtraParameters.push_back(param); myMaterials[descHash] = mat; return mat; }
//---------------------------------------------------------------------------// bool MaterialDesc::operator==(const MaterialDesc& anOther) const { return GetHash() == anOther.GetHash(); }
uint8_t* LoadMaterialInfo(const char* i_pFile, uint32_t& o_lengthOfWholerMaterialBuffer, uint32_t& o_lengthOfEffectPath) { o_lengthOfWholerMaterialBuffer = 0; o_lengthOfEffectPath = 0; if (!i_pFile) return nullptr; std::ifstream infile(i_pFile, std::ifstream::binary); if (!infile) { std::stringstream decoratedErrorMessage; decoratedErrorMessage << "Failed to load binary material file: " << i_pFile; ErrorMessageBox(decoratedErrorMessage.str().c_str()); return nullptr; } // get size of file infile.seekg(0, infile.end); std::ifstream::pos_type size = infile.tellg(); infile.seekg(0); // allocate memory for file content o_lengthOfWholerMaterialBuffer = (uint32_t)size; char* pBuffer = new char[o_lengthOfWholerMaterialBuffer]; // read content of infile infile.read(pBuffer, size); if (!infile) { std::stringstream decoratedErrorMessage; decoratedErrorMessage << "Failed to load all data from: " << i_pFile << ", only " << infile.gcount() << "could be load."; ErrorMessageBox(decoratedErrorMessage.str().c_str()); infile.close(); delete[] pBuffer; return nullptr; } uint32_t offset = 0; // First, set the convert the buffer to MaterialDesc* MaterialDesc* pMaterialDesc = (MaterialDesc*)((uint8_t*)pBuffer + offset); // Second, load the path of the effect file { // Remember that I did a tricky solution in the MaterialBuilder // that I use the _pEffect to save the offset of the Name in Effect // Because the size of the _handler will be different on x64 and x86, // so I really really should be careful about it. size_t offsetForEffectPathName = *(size_t*)(&pMaterialDesc->_pEffect); char* pathOfEffect = _strdup(pBuffer + offsetForEffectPathName); o_lengthOfEffectPath = (uint32_t)strlen(pBuffer + offsetForEffectPathName) + 1; pMaterialDesc->_pEffect = CreateEffect(pathOfEffect); free(pathOfEffect); } // Set the buffer of each segement UniformBlockDesc* pUniformBlockDescBuffer = nullptr; uint8_t* pUniformBlockNameBuffer = nullptr; UniformDesc* pUniformDescBuffer = nullptr; uint8_t* pUniformVariableValueBuffer = nullptr; uint8_t* pUniformVariableNameBuffer = nullptr; TextureDesc* pTextureDescBuffer = nullptr; uint8_t* pTexturePathBuffer = nullptr; uint8_t* pTextureSamplerNameBuffer = nullptr; { if (pMaterialDesc->_uniformBlockCount > 0) { pUniformBlockDescBuffer = pMaterialDesc->GetUniformBlockDesc(); pUniformBlockNameBuffer = (uint8_t*)pMaterialDesc + pMaterialDesc->_offsetOfUniformBlockNameBuffer; } if (pMaterialDesc->_uniformCount > 0) { pUniformDescBuffer = pMaterialDesc->GetUniformDesc(); pUniformVariableValueBuffer = (uint8_t*)pMaterialDesc + pMaterialDesc->_offsetOfUniformVariableValueBuffer; pUniformVariableNameBuffer = (uint8_t*)pMaterialDesc + pMaterialDesc->_offsetOfUniformVariableNameBuffer; } if (pMaterialDesc->_textureCount > 0) { pTextureDescBuffer = pMaterialDesc->GetTextureDesc(); pTexturePathBuffer = (uint8_t*)pMaterialDesc + pMaterialDesc->_offsetOfTexturePathBuffer; pTextureSamplerNameBuffer = (uint8_t*)pMaterialDesc + pMaterialDesc->_offsetOfTextureSamplerBuffer; } } // Third, Set each UniformDesc of this MaterialDesc for (uint32_t ubIndex = 0; ubIndex < pMaterialDesc->_uniformBlockCount; ++ubIndex) { UniformBlockDesc* pUBD = &pUniformBlockDescBuffer[ubIndex]; size_t offsetInNameBuffer = pUBD->_offsetInUniformBlockNameBuffer; const char* pUBName = (char*)(pUniformBlockNameBuffer + offsetInNameBuffer); uint32_t startIndex = pUBD->_startUniformDescIndex; uint32_t endIndex = pUBD->_endUniformDescIndex; // For the UniformVariable/UniformBlock, // we will save the instance of them in UniformDesc*/UniformBlock*. // Since we have scaned the Uniform Blocks when we were creating Effect, // we should be able to get their reference. if (strcmp(pUBName, "Default") == 0) // Add the default block members to be the Uniform Variables. { for (uint32_t uIndex = startIndex; uIndex <= endIndex; ++uIndex) { UniformDesc* pUD = &pUniformDescBuffer[uIndex]; size_t offsetInNameBuffer = pUD->_offsetInNameBuffer; const char* pUniformName = (char*)(pUniformVariableNameBuffer + offsetInNameBuffer); pUD->SetUniformVariable(pUniformName, pMaterialDesc->_pEffect); } } else // Add the undefault block members to be Uniform Blocks { UniformBlock* pUniformBlock = UniformBlockManager::GetInstance()->GetUniformBlock(pUBName); pUBD->_pUniformBlock = pUniformBlock; } } // Forth, Set each TextureDesc of this MaterialDesc for (uint32_t index = 0; index < pMaterialDesc->_textureCount; ++index) { TextureDesc* pTex = &pTextureDescBuffer[index]; { // Set the value of the Texture. size_t offsetInTexturePathBuffer = pTex->_offsetInSamplerNameBuffer; const char* pTexName = (char*)(pTexturePathBuffer + offsetInTexturePathBuffer); pTex->_pTextureInfo = TextureManager::GetInstance()->LoadTexture(pTexName); // Set the value of the samplerID tSamplerID offsetInSamplerNameBuffer = *(tSamplerID*)(&pTex->_samplerID); const char* pTexSamplerName = (char*)(pTextureSamplerNameBuffer + offsetInSamplerNameBuffer); pTex->_samplerID = pMaterialDesc->_pEffect->GetSamplerID(pTexSamplerName, pTex->_shaderType); } } //Finally, don't forget to close the file infile.close(); return reinterpret_cast<uint8_t*>(pBuffer); }