//-------------------------------------------------------------------------------------- CPUTMaterial *CPUTMaterial::CreateMaterial( const cString &absolutePathAndFilename, const cString &modelSuffix, const cString &meshSuffix, char **pShaderMacros, // Note: this is honored only on first load. Subsequent GetMaterial calls will return the material with shaders as compiled with original macros. int numSystemMaterials, cString *pSystemMaterialNames ){ // material was not in the library, so load it #ifdef CPUT_FOR_DX11 CPUTMaterial *pMaterial = new CPUTMaterialDX11(); #else #error You must supply a target graphics API (ex: #define CPUT_FOR_DX11), or implement the target API for this file. #endif CPUTResult result = pMaterial->LoadMaterial(absolutePathAndFilename, modelSuffix, meshSuffix, pShaderMacros, numSystemMaterials, pSystemMaterialNames ); ASSERT( CPUTSUCCESS(result), _L("\nError - CPUTAssetLibrary::GetMaterial() - Error in material file: '")+absolutePathAndFilename+_L("'") ); UNREFERENCED_PARAMETER(result); // add material to material library list // cString finalName = pMaterial->MaterialRequiresPerModelPayload() ? absolutePathAndFilename + modelSuffix + meshSuffix : absolutePathAndFilename; // CPUTAssetLibrary::GetAssetLibrary()->AddMaterial( finalName, pMaterial ); CPUTAssetLibrary::GetAssetLibrary()->AddMaterial( absolutePathAndFilename, pMaterial ); return pMaterial; }
//-------------------------------------------------------------------------------------- CPUTMaterial *CPUTMaterial::CreateMaterial( const cString &absolutePathAndFilename, const CPUTModel *pModel, int meshIndex, const char **pShaderMacros, // Note: this is honored only on first load. Subsequent GetMaterial calls will return the material with shaders as compiled with original macros. int numSystemMaterials, cString *pSystemMaterialNames, int externalCount, cString *pExternalName, float4 *pExternals, int *pExternalOffset, int *pExternalSize ){ // Create the material and load it from file. //#ifdef CPUT_FOR_DX11 // CPUTMaterial *pMaterial = new CPUTMaterialDX11(); //#elif (defined(CPUT_FOR_OGL) || defined(CPUT_FOR_OGLES)) // CPUTMaterial *pMaterial = new CPUTMaterialOGL(); //#else // #error You must supply a target graphics API (ex: #define CPUT_FOR_DX11), or implement the target API for this file. //#endif // pMaterial->mpSubMaterials = NULL; CPUTMaterial* pMaterial = new CPUTMaterial(); CPUTResult result = pMaterial->LoadMaterial( absolutePathAndFilename, pModel, meshIndex, pShaderMacros, numSystemMaterials, pSystemMaterialNames, externalCount, pExternalName, pExternals, pExternalOffset, pExternalSize ); ASSERT( CPUTSUCCESS(result), _L("\nError - CPUTAssetLibrary::GetMaterial() - Error in material file: '")+absolutePathAndFilename+_L("'") ); UNREFERENCED_PARAMETER(result); // Add the material to the asset library. CPUTAssetLibrary::GetAssetLibrary()->AddMaterial( absolutePathAndFilename, _L(""), _L(""), pMaterial, pShaderMacros ); return pMaterial; }
//-------------------------------------------------------------------------------------- CPUTGeometryShaderDX11 *CPUTGeometryShaderDX11::CreateFromMemory( const std::string &name, const std::string &shaderMain, const std::string &shaderProfile, const char *pShaderSource, CPUT_SHADER_MACRO *pShaderMacros ) { ID3DBlob *pCompiledBlob = NULL; ID3D11GeometryShader *pNewGeometryShader = NULL; CPUTAssetLibraryDX11 *pAssetLibrary = (CPUTAssetLibraryDX11*)CPUTAssetLibrary::GetAssetLibrary(); CPUTResult result = pAssetLibrary->CompileShaderFromMemory(pShaderSource, shaderMain, shaderProfile, &pCompiledBlob, pShaderMacros ); ASSERT( CPUTSUCCESS(result), "Error creating Geometry shader:\n\n" ); UNREFERENCED_PARAMETER(result); // Create the Geometry shader ID3D11Device *pD3dDevice = CPUT_DX11::GetDevice(); HRESULT hr = pD3dDevice->CreateGeometryShader( pCompiledBlob->GetBufferPointer(), pCompiledBlob->GetBufferSize(), NULL, &pNewGeometryShader ); ASSERT( SUCCEEDED(hr), "Error creating Geometry shader:\n\n" ); UNREFERENCED_PARAMETER(hr); // std::string DebugName = "CPUTAssetLibraryDX11::GetGeometryShader "+name; // CPUTSetDebugName(pNewGeometryShader, DebugName); CPUTGeometryShaderDX11 *pNewCPUTGeometryShader = new CPUTGeometryShaderDX11( pNewGeometryShader, pCompiledBlob ); // add shader to library pAssetLibrary->AddGeometryShader(name, "", shaderMain + shaderProfile, pNewCPUTGeometryShader); // pNewCPUTGeometryShader->Release(); // We've added it to the library, so release our reference // return the shader (and blob) return pNewCPUTGeometryShader; }
CPUTComputeShaderDX11 *CPUTComputeShaderDX11::Create( const std::string &name, const std::string &shaderMain, const std::string &shaderProfile, CPUT_SHADER_MACRO *pShaderMacros ) { ID3DBlob *pCompiledBlob = NULL; ID3D11ComputeShader *pNewComputeShader = NULL; CPUTAssetLibraryDX11 *pAssetLibrary = (CPUTAssetLibraryDX11*)CPUTAssetLibrary::GetAssetLibrary(); CPUTResult result = pAssetLibrary->CompileShaderFromFile(name, shaderMain, shaderProfile, &pCompiledBlob, pShaderMacros); ASSERT( CPUTSUCCESS(result), "Error compiling compute shader:\n\n" ); UNREFERENCED_PARAMETER(result); // Create the compute shader ID3D11Device *pD3dDevice = CPUT_DX11::GetDevice(); HRESULT hr = pD3dDevice->CreateComputeShader( pCompiledBlob->GetBufferPointer(), pCompiledBlob->GetBufferSize(), NULL, &pNewComputeShader ); ASSERT( SUCCEEDED(hr), "Error creating compute shader:\n\n" ); UNREFERENCED_PARAMETER(hr); // std::string DebugName = "CPUTAssetLibraryDX11::GetComputeShader "+name; // CPUTSetDebugName(pNewComputeShader, DebugName); CPUTComputeShaderDX11 *pNewCPUTComputeShader = new CPUTComputeShaderDX11( pNewComputeShader, pCompiledBlob ); // add shader to library pAssetLibrary->AddComputeShader(name, "", shaderMain + shaderProfile, pNewCPUTComputeShader); // return the shader return pNewCPUTComputeShader; }
//-------------------------------------------------------------------------------------- CPUTPixelShaderDX11 *CPUTPixelShaderDX11::CreatePixelShaderFromMemory( const cString &name, ID3D11Device *pD3dDevice, const cString &shaderMain, const cString &shaderProfile, const char *pShaderSource ) { ID3DBlob *pCompiledBlob = NULL; ID3D11PixelShader *pNewPixelShader = NULL; CPUTAssetLibraryDX11 *pAssetLibrary = (CPUTAssetLibraryDX11*)CPUTAssetLibrary::GetAssetLibrary(); CPUTResult result = pAssetLibrary->CompileShaderFromMemory(pShaderSource, shaderMain, shaderProfile, &pCompiledBlob); ASSERT( CPUTSUCCESS(result), _L("Error compiling pixel shader:\n\n") ); // Create the pixel shader // TODO: Move to pixel shader class HRESULT hr = pD3dDevice->CreatePixelShader( pCompiledBlob->GetBufferPointer(), pCompiledBlob->GetBufferSize(), NULL, &pNewPixelShader ); ASSERT( SUCCEEDED(result), _L("Error compiling pixel shader:\n\n") ); // cString DebugName = _L("CPUTAssetLibraryDX11::GetPixelShader ")+name; // CPUTSetDebugName(pNewPixelShader, DebugName); CPUTPixelShaderDX11 *pNewCPUTPixelShader = new CPUTPixelShaderDX11( pNewPixelShader, pCompiledBlob ); // add shader to library pAssetLibrary->AddPixelShader(name + shaderMain + shaderProfile, pNewCPUTPixelShader); // pNewCPUTPixelShader->Release(); // We've added it to the library, so release our reference // return the shader (and blob) return pNewCPUTPixelShader; }
CPUTComputeShaderDX11 *CPUTComputeShaderDX11::CreateComputeShader( const cString &name, ID3D11Device *pD3dDevice, const cString &shaderMain, const cString &shaderProfile ) { ID3DBlob *pCompiledBlob = NULL; ID3D11ComputeShader *pNewComputeShader = NULL; CPUTAssetLibraryDX11 *pAssetLibrary = (CPUTAssetLibraryDX11*)CPUTAssetLibrary::GetAssetLibrary(); CPUTResult result = pAssetLibrary->CompileShaderFromFile(name, shaderMain, shaderProfile, &pCompiledBlob); ASSERT( CPUTSUCCESS(result), _L("Error compiling compute shader:\n\n") ); // Create the compute shader // TODO: Move to compute shader class HRESULT hr = pD3dDevice->CreateComputeShader( pCompiledBlob->GetBufferPointer(), pCompiledBlob->GetBufferSize(), NULL, &pNewComputeShader ); ASSERT( SUCCEEDED(result), _L("Error compiling compute shader:\n\n") ); // cString DebugName = _L("CPUTAssetLibraryDX11::GetComputeShader ")+name; // CPUTSetDebugName(pNewComputeShader, DebugName); CPUTComputeShaderDX11 *pNewCPUTComputeShader = new CPUTComputeShaderDX11( pNewComputeShader, pCompiledBlob ); // add shader to library pAssetLibrary->AddComputeShader(name + shaderMain + shaderProfile, pNewCPUTComputeShader); // return the shader return pNewCPUTComputeShader; }
// Note that we only need one of these. We don't need to re-create it for every model. //----------------------------------------------------------------------------- void CPUTModelDX11::CreateBoundingBoxMesh() { CPUTResult result = CPUT_SUCCESS; float3 pVertices[8] = { float3( 1.0f, 1.0f, 1.0f ), // 0 float3( 1.0f, 1.0f, -1.0f ), // 1 float3( -1.0f, 1.0f, 1.0f ), // 2 float3( -1.0f, 1.0f, -1.0f ), // 3 float3( 1.0f, -1.0f, 1.0f ), // 4 float3( 1.0f, -1.0f, -1.0f ), // 5 float3( -1.0f, -1.0f, 1.0f ), // 6 float3( -1.0f, -1.0f, -1.0f ) // 7 }; USHORT pIndices[24] = { 0,1, 1,3, 3,2, 2,0, // Top 4,5, 5,7, 7,6, 6,4, // Bottom 0,4, 1,5, 2,6, 3,7 // Verticals }; CPUTVertexElementDesc pVertexElements[] = { { CPUT_VERTEX_ELEMENT_POSITON, tFLOAT, 12, 0 }, }; CPUTMesh *pMesh = mpBoundingBoxMesh = new CPUTMeshDX11(); pMesh->SetMeshTopology(CPUT_TOPOLOGY_INDEXED_LINE_LIST); CPUTBufferInfo vertexElementInfo; vertexElementInfo.mpSemanticName = "POSITION"; vertexElementInfo.mSemanticIndex = 0; vertexElementInfo.mElementType = CPUT_F32; vertexElementInfo.mElementComponentCount = 3; vertexElementInfo.mElementSizeInBytes = 12; vertexElementInfo.mElementCount = 8; vertexElementInfo.mOffset = 0; CPUTBufferInfo indexDataInfo; indexDataInfo.mElementType = CPUT_U16; indexDataInfo.mElementComponentCount = 1; indexDataInfo.mElementSizeInBytes = sizeof(UINT16); indexDataInfo.mElementCount = 24; // 12 lines, 2 verts each indexDataInfo.mOffset = 0; indexDataInfo.mSemanticIndex = 0; indexDataInfo.mpSemanticName = NULL; result = pMesh->CreateNativeResources( this, -1, 1, // vertexFormatDesc.mFormatDescriptorCount, &vertexElementInfo, pVertices, // (void*)vertexFormatDesc.mpVertices, &indexDataInfo, pIndices // &vertexFormatDesc.mpIndices[0] ); ASSERT( CPUTSUCCESS(result), _L("Failed building bounding box mesh") ); cString modelSuffix = ptoc(this); UINT index = mpSubMaterialCount[0] + CPUT_MATERIAL_INDEX_BOUNDING_BOX; CPUTMaterialDX11 *pMaterial = (CPUTMaterialDX11*)(mpMaterial[0][index]); ((CPUTMeshDX11*)pMesh)->BindVertexShaderLayout( pMaterial, &mpInputLayout[0][index] ); }
//----------------------------------------------------------------------------- CPUTAssetSet *CPUTAssetSetDX11::CreateAssetSet( const cString &name, const cString &absolutePathAndFilename ) { CPUTAssetLibraryDX11 *pAssetLibrary = ((CPUTAssetLibraryDX11*)CPUTAssetLibrary::GetAssetLibrary()); // Create the root node. CPUTNullNode *pRootNode = new CPUTNullNode(); pRootNode->SetName(_L("_CPUTAssetSetRootNode_")); // Create the asset set, set its root, and load it CPUTAssetSet *pNewAssetSet = new CPUTAssetSetDX11(); pNewAssetSet->SetRoot( pRootNode ); pAssetLibrary->AddNullNode( name + _L("_Root"), pRootNode ); CPUTResult result = pNewAssetSet->LoadAssetSet(absolutePathAndFilename); if( CPUTSUCCESS(result) ) { pAssetLibrary->AddAssetSet(name, pNewAssetSet); return pNewAssetSet; } ASSERT( CPUTSUCCESS(result), _L("Error loading AssetSet\n'")+absolutePathAndFilename+_L("'")); pNewAssetSet->Release(); return NULL; }
//----------------------------------------------------------------------------- CPUTAssetSet *CPUTAssetSet::Create( const std::string &name, const std::string &absolutePathAndFilename, int numSystemMaterials, std::string *pSystemMaterialNames ) { CPUTAssetLibrary *pAssetLibrary = CPUTAssetLibrary::GetAssetLibrary(); // Create the root node. CPUTNullNode *pRootNode = CPUTNullNode::Create(); pRootNode->SetName("_CPUTAssetSetRootNode_"); // Create the asset set, set its root, and load it CPUTAssetSet *pNewAssetSet = new CPUTAssetSet(); pNewAssetSet->IsEnabled = true; pNewAssetSet->SetRoot( pRootNode ); pAssetLibrary->AddNullNode( name, "", "_Root", pRootNode ); CPUTResult result = pNewAssetSet->LoadAssetSet(absolutePathAndFilename, numSystemMaterials, pSystemMaterialNames); if( CPUTSUCCESS(result) ) { pAssetLibrary->AddAssetSet(name, "", "", pNewAssetSet); return pNewAssetSet; } ASSERT( CPUTSUCCESS(result), "Error loading AssetSet\n'"+absolutePathAndFilename+"'"); pNewAssetSet->Release(); return NULL; }
// Retrieve specified pixel shader // TODO: Delegate creation to asset (AssetLibrary shouldn't know the nitty-gritty details of how to create an asset) //----------------------------------------------------------------------------- CPUTResult CPUTAssetLibraryOGLES::GetPixelShader( const cString &name, const cString &shaderMain, const cString &shaderProfile, CPUTPixelShaderOGLES **ppPixelShader, bool nameIsFullPathAndFilename ) { CPUTResult result = CPUT_SUCCESS; // Resolve name to absolute path before searching cString absolutePathAndFilename; CPUTOSServices* pServices = CPUTOSServices::GetOSServices(); pServices->ResolveAbsolutePathAndFilename( nameIsFullPathAndFilename? name : (m_ShaderDirectoryName + name), &absolutePathAndFilename); // see if the shader is already in the library void *pShader = FindPixelShader(absolutePathAndFilename); if(NULL!=pShader) { *ppPixelShader = (CPUTPixelShaderOGLES*) pShader; (*ppPixelShader)->AddRef(); return result; } // load the pixel shader as null-terminated char* string void* pShaderString=NULL; result = LoadShaderFileString(absolutePathAndFilename, &pShaderString); ASSERT( CPUTSUCCESS(result), _L("Error loading pixel shader: ")+name ); // compile the pixel/fragment shader GLuint NewPixelShaderID = CompileShader(GL_FRAGMENT_SHADER, pShaderString); ASSERT( (0!=NewPixelShaderID), _L("Error compiling pixel shader: "+name) ); // delete the shader's string now that it's no longer needed delete [] pShaderString; // store this new shader CPUTPixelShaderOGLES *pNewCPUTPixelShader = new CPUTPixelShaderOGLES( NewPixelShaderID ); // add shader to library AddPixelShader(absolutePathAndFilename, pNewCPUTPixelShader); // return the shader *ppPixelShader = pNewCPUTPixelShader; return result; }
//----------------------------------------------------------------------------- CPUTTexture *CPUTTextureDX11::CreateTexture( const cString &name, const cString &absolutePathAndFilename, bool loadAsSRGB ) { // TODO: Delegate to derived class. We don't currently have CPUTTextureDX11 ID3D11ShaderResourceView *pShaderResourceView = NULL; ID3D11Resource *pTexture = NULL; ID3D11Device *pD3dDevice= CPUT_DX11::GetDevice(); CPUTResult result = CreateNativeTexture( pD3dDevice, absolutePathAndFilename, &pShaderResourceView, &pTexture, loadAsSRGB ); ASSERT( CPUTSUCCESS(result), _L("Error loading texture: '")+absolutePathAndFilename ); CPUTTextureDX11 *pNewTexture = new CPUTTextureDX11(); pNewTexture->mName = name; pNewTexture->SetTextureAndShaderResourceView( pTexture, pShaderResourceView ); pTexture->Release(); pShaderResourceView->Release(); CPUTAssetLibrary::GetAssetLibrary()->AddTexture( absolutePathAndFilename, pNewTexture); return pNewTexture; }
CPUTMaterial *CPUTMaterial::CreateMaterial( const cString &absolutePathAndFilename, const CPUTModel *pModel, int meshIndex ) { // material was not in the library, so load it #ifdef CPUT_FOR_DX11 CPUTMaterial *pMaterial = new CPUTMaterialDX11(); #else #error You must supply a target graphics API (ex: #define CPUT_FOR_DX11), or implement the target API for this file. #endif CPUTResult result = pMaterial->LoadMaterial(absolutePathAndFilename, pModel, meshIndex); ASSERT( CPUTSUCCESS(result), _L("\nError - CPUTAssetLibrary::GetMaterial() - Error in material file: '")+absolutePathAndFilename+_L("'") ); // add material to material library list if( pModel && pMaterial->MaterialRequiresPerModelPayload() ) { CPUTAssetLibrary::GetAssetLibrary()->AddMaterial( absolutePathAndFilename, pMaterial, pModel, meshIndex ); } else { CPUTAssetLibrary::GetAssetLibrary()->AddMaterial( absolutePathAndFilename, pMaterial ); } return pMaterial; }
//-------------------------------------------------------------------------------------- CPUTMaterialEffect *CPUTMaterialEffect::CreateMaterialEffect( const cString &absolutePathAndFilename, const CPUTModel *pModel, int meshIndex, const char **pShaderMacros, int externalCount, cString *pExternalName, float4 *pExternals, int *pExternalOffset, int *pExternalSize ){ // Create the material and load it from file. #ifdef CPUT_FOR_DX11 CPUTMaterialEffect *pMaterialEffect = new CPUTMaterialEffectDX11(); #else #if (defined(CPUT_FOR_OGL) || defined(CPUT_FOR_OGLES)) CPUTMaterialEffect *pMaterialEffect = new CPUTMaterialEffectOGL(); #else #error You must supply a target graphics API (ex: #define CPUT_FOR_DX11), or implement the target API for this file. #endif #endif CPUTResult result = pMaterialEffect->LoadMaterialEffect( absolutePathAndFilename, pModel, meshIndex, pShaderMacros ); ASSERT( CPUTSUCCESS(result), _L("\nError - CPUTAssetLibrary::GetMaterial() - Error in material file: '")+absolutePathAndFilename+_L("'") ); UNREFERENCED_PARAMETER(result); // Add the material to the asset library. if( pModel && pMaterialEffect->MaterialRequiresPerModelPayload() ) { CPUTAssetLibrary::GetAssetLibrary()->AddMaterialEffect( absolutePathAndFilename, _L(""), _L(""), pMaterialEffect, pShaderMacros, pModel, meshIndex ); } else { CPUTAssetLibrary::GetAssetLibrary()->AddMaterialEffect( absolutePathAndFilename, _L(""), _L(""), pMaterialEffect, pShaderMacros ); } return pMaterialEffect; }
// Load the set file definition of this object // 1. Parse the block of name/parent/transform info for model block // 2. Load the model's binary payload (i.e., the meshes) // 3. Assert the # of meshes matches # of materials // 4. Load each mesh's material //----------------------------------------------------------------------------- CPUTResult CPUTModelOGL::LoadModel(CPUTConfigBlock *pBlock, int *pParentID, CPUTModel *pMasterModel, int numSystemMaterials, cString *pSystemMaterialNames) { CPUTResult result = CPUT_SUCCESS; CPUTAssetLibraryOGL *pAssetLibrary = (CPUTAssetLibraryOGL*)CPUTAssetLibrary::GetAssetLibrary(); cString modelSuffix = ptoc(this); // set the model's name mName = pBlock->GetValueByName(_L("name"))->ValueAsString(); mName = mName + _L(".mdl"); // resolve the full path name cString modelLocation; cString resolvedPathAndFile; modelLocation = ((CPUTAssetLibraryOGL*)CPUTAssetLibrary::GetAssetLibrary())->GetModelDirectoryName(); modelLocation = modelLocation+mName; CPUTFileSystem::ResolveAbsolutePathAndFilename(modelLocation, &resolvedPathAndFile); // Get the parent ID. Note: the caller will use this to set the parent. *pParentID = pBlock->GetValueByName(_L("parent"))->ValueAsInt(); LoadParentMatrixFromParameterBlock( pBlock ); // Get the bounding box information float3 center(0.0f), half(0.0f); pBlock->GetValueByName(_L("BoundingBoxCenter"))->ValueAsFloatArray(center.f, 3); pBlock->GetValueByName(_L("BoundingBoxHalf"))->ValueAsFloatArray(half.f, 3); mBoundingBoxCenterObjectSpace = center; mBoundingBoxHalfObjectSpace = half; mMeshCount = pBlock->GetValueByName(_L("meshcount"))->ValueAsInt(); mpMesh = new CPUTMesh*[mMeshCount]; mpLayoutCount = new UINT[mMeshCount]; mpRootMaterial = new CPUTMaterial*[mMeshCount]; memset( mpRootMaterial, 0, mMeshCount * sizeof(CPUTMaterial*) ); mpMaterialEffect = new CPUTMaterialEffect**[mMeshCount]; memset( mpMaterialEffect, 0, mMeshCount * sizeof(CPUTMaterialEffect*) ); // get the material names, load them, and match them up with each mesh cString materialName,shadowMaterialName; char pNumber[4]; cString materialValueName; CPUTModelOGL *pMasterModelDX = (CPUTModelOGL*)pMasterModel; for(UINT ii=0; ii<mMeshCount; ii++) { if(pMasterModelDX) { // Reference the master model's mesh. Don't create a new one. mpMesh[ii] = pMasterModelDX->mpMesh[ii]; mpMesh[ii]->AddRef(); } else { mpMesh[ii] = new CPUTMeshOGL(); } } if( !pMasterModelDX ) { // Not a clone/instance. So, load the model's binary payload (i.e., vertex and index buffers) // TODO: Change to use GetModel() result = LoadModelPayload(resolvedPathAndFile); ASSERT( CPUTSUCCESS(result), _L("Failed loading model") ); } for(UINT ii=0; ii<mMeshCount; ii++) { // get the right material number ('material0', 'material1', 'material2', etc) materialValueName = _L("material"); snprintf(pNumber, 4, "%d", ii); // _itoa(ii, pNumber, 4, 10); materialValueName.append(s2ws(pNumber)); materialName = pBlock->GetValueByName(materialValueName)->ValueAsString(); shadowMaterialName = pBlock->GetValueByName(_L("shadowCast") + materialValueName)->ValueAsString(); bool isSkinned = pBlock->GetValueByName(_L("skeleton")) != &CPUTConfigEntry::sNullConfigValue; if( shadowMaterialName.length() == 0 ) { if(!isSkinned) { shadowMaterialName = _L("%shadowCast"); } else { shadowMaterialName = _L("%shadowCastSkinned"); } } // Get/load material for this mesh UINT totalNameCount = numSystemMaterials + NUM_GLOBAL_SYSTEM_MATERIALS; cString *pFinalSystemNames = new cString[totalNameCount]; // Copy "global" system materials to caller-supplied list for( int jj=0; jj<numSystemMaterials; jj++ ) { pFinalSystemNames[jj] = pSystemMaterialNames[jj]; } pFinalSystemNames[totalNameCount + CPUT_MATERIAL_INDEX_SHADOW_CAST] = shadowMaterialName; // pFinalSystemNames[totalNameCount + CPUT_MATERIAL_INDEX_BOUNDING_BOX] = _L("%BoundingBox"); int finalNumSystemMaterials = numSystemMaterials + NUM_GLOBAL_SYSTEM_MATERIALS; CPUTMaterial *pMaterial = pAssetLibrary->GetMaterial(materialName, false, this, ii, NULL, finalNumSystemMaterials, pFinalSystemNames); ASSERT( pMaterial, _L("Couldn't find material.") ); delete []pFinalSystemNames; mpLayoutCount[ii] = pMaterial->GetMaterialEffectCount(); SetMaterial(ii, pMaterial); // Release the extra refcount we're holding from the GetMaterial operation earlier // now the asset library, and this model have the only refcounts on that material pMaterial->Release(); // Create two ID3D11InputLayout objects, one for each material. // mpMesh[ii]->BindVertexShaderLayout( mpMaterial[ii], mpShadowCastMaterial); // mpShadowCastMaterial->Release() } return result; }
//----------------------------------------------------------------------------- CPUTResult CPUTModelDX11::LoadModel(CPUTConfigBlock *pBlock, int *pParentID, CPUTModel *pMasterModel) { CPUTResult result = CPUT_SUCCESS; CPUTAssetLibraryDX11 *pAssetLibrary = (CPUTAssetLibraryDX11*)CPUTAssetLibrary::GetAssetLibrary(); cString modelSuffix = ptoc(this); // set the model's name mName = pBlock->GetValueByName(_L("name"))->ValueAsString(); mName = mName + _L(".mdl"); // resolve the full path name cString modelLocation; cString resolvedPathAndFile; modelLocation = ((CPUTAssetLibraryDX11*)CPUTAssetLibrary::GetAssetLibrary())->GetModelDirectory(); modelLocation = modelLocation+mName; CPUTOSServices::GetOSServices()->ResolveAbsolutePathAndFilename(modelLocation, &resolvedPathAndFile); // Get the parent ID. Note: the caller will use this to set the parent. *pParentID = pBlock->GetValueByName(_L("parent"))->ValueAsInt(); LoadParentMatrixFromParameterBlock( pBlock ); // Get the bounding box information float3 center(0.0f), half(0.0f); pBlock->GetValueByName(_L("BoundingBoxCenter"))->ValueAsFloatArray(center.f, 3); pBlock->GetValueByName(_L("BoundingBoxHalf"))->ValueAsFloatArray(half.f, 3); mBoundingBoxCenterObjectSpace = center; mBoundingBoxHalfObjectSpace = half; mMeshCount = pBlock->GetValueByName(_L("meshcount"))->ValueAsInt(); mpMesh = new CPUTMesh*[mMeshCount]; mpMaterial = new CPUTMaterial*[mMeshCount]; memset( mpMaterial, 0, mMeshCount * sizeof(CPUTMaterial*) ); cString materialName; char pNumber[4]; cString materialValueName; CPUTModelDX11 *pMasterModelDX = (CPUTModelDX11*)pMasterModel; for(UINT ii=0; ii<mMeshCount; ii++) { if(pMasterModelDX) { // Reference the master model's mesh. Don't create a new one. mpMesh[ii] = pMasterModelDX->mpMesh[ii]; mpMesh[ii]->AddRef(); } else { mpMesh[ii] = new CPUTMeshDX11(); } } if( !pMasterModelDX ) { // Not a clone/instance. So, load the model's binary payload (i.e., vertex and index buffers) // TODO: Change to use GetModel() result = LoadModelPayload(resolvedPathAndFile); ASSERT( CPUTSUCCESS(result), _L("Failed loading model") ); } #if 0 cString assetSetDirectoryName = pAssetLibrary->GetAssetSetDirectoryName(); cString modelDirectory = pAssetLibrary->GetModelDirectory(); cString materialDirectory = pAssetLibrary->GetMaterialDirectory(); cString textureDirectory = pAssetLibrary->GetTextureDirectory(); cString shaderDirectory = pAssetLibrary->GetShaderDirectory(); cString fontDirectory = pAssetLibrary->GetFontDirectory(); cString up2MediaDirName = assetSetDirectoryName + _L("..\\..\\"); pAssetLibrary->SetMediaDirectoryName( up2MediaDirName ); mpShadowCastMaterial = pAssetLibrary->GetMaterial( _L("shadowCast"), false, this, -2 ); // -2 signifies shadow material. TODO: find a clearer way (e.g., enum?) pAssetLibrary->SetAssetSetDirectoryName( assetSetDirectoryName ); pAssetLibrary->SetModelDirectoryName( modelDirectory ); pAssetLibrary->SetMaterialDirectoryName( materialDirectory ); pAssetLibrary->SetTextureDirectoryName( textureDirectory ); pAssetLibrary->SetShaderDirectoryName( shaderDirectory ); pAssetLibrary->SetFontDirectoryName( fontDirectory ); #endif for(UINT ii=0; ii<mMeshCount; ii++) { // get the right material number ('material0', 'material1', 'material2', etc) materialValueName = _L("material"); _itoa_s(ii, pNumber, 4, 10); materialValueName.append(s2ws(pNumber)); materialName = pBlock->GetValueByName(materialValueName)->ValueAsString(); // Get/load material for this mesh CPUTMaterialDX11 *pMaterial = (CPUTMaterialDX11*)pAssetLibrary->GetMaterial(materialName, false, this, ii); ASSERT( pMaterial, _L("Couldn't find material.") ); // set the material on this mesh // TODO: Model owns the materials. That allows different models to share meshes (aka instancing) that have different materials SetMaterial(ii, pMaterial); // Release the extra refcount we're holding from the GetMaterial operation earlier // now the asset library, and this model have the only refcounts on that material pMaterial->Release(); // Create two ID3D11InputLayout objects, one for each material. mpMesh[ii]->BindVertexShaderLayout( mpMaterial[ii], mpShadowCastMaterial); // mpShadowCastMaterial->Release() } return result; }
//----------------------------------------------------------------------------- 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; }
//----------------------------------------------------------------------------- void CPUTModelDX11::CreateBoundingBoxMesh() { CPUTResult result = CPUT_SUCCESS; if( !mpBoundingBoxMesh ) { float3 pVertices[8] = { float3( 1.0f, 1.0f, 1.0f ), // 0 float3( 1.0f, 1.0f, -1.0f ), // 1 float3( -1.0f, 1.0f, 1.0f ), // 2 float3( -1.0f, 1.0f, -1.0f ), // 3 float3( 1.0f, -1.0f, 1.0f ), // 4 float3( 1.0f, -1.0f, -1.0f ), // 5 float3( -1.0f, -1.0f, 1.0f ), // 6 float3( -1.0f, -1.0f, -1.0f ) // 7 }; USHORT pIndices[24] = { 0,1, 1,3, 3,2, 2,0, // Top 4,5, 5,7, 7,6, 6,4, // Bottom 0,4, 1,5, 2,6, 3,7 // Verticals }; CPUTVertexElementDesc pVertexElements[] = { { CPUT_VERTEX_ELEMENT_POSITON, tFLOAT, 12, 0 }, }; mpBoundingBoxMesh = new CPUTMeshDX11(); mpBoundingBoxMesh->SetMeshTopology(CPUT_TOPOLOGY_INDEXED_LINE_LIST); CPUTBufferInfo vertexElementInfo; vertexElementInfo.mpSemanticName = "POSITION"; vertexElementInfo.mSemanticIndex = 0; vertexElementInfo.mElementType = CPUT_F32; vertexElementInfo.mElementComponentCount = 3; vertexElementInfo.mElementSizeInBytes = 12; vertexElementInfo.mElementCount = 8; vertexElementInfo.mOffset = 0; CPUTBufferInfo indexDataInfo; indexDataInfo.mElementType = CPUT_U16; indexDataInfo.mElementComponentCount = 1; indexDataInfo.mElementSizeInBytes = sizeof(UINT16); indexDataInfo.mElementCount = 24; // 12 lines, 2 verts each indexDataInfo.mOffset = 0; indexDataInfo.mSemanticIndex = 0; indexDataInfo.mpSemanticName = NULL; result = mpBoundingBoxMesh->CreateNativeResources(this, -1, 1, // vertexFormatDesc.mFormatDescriptorCount, &vertexElementInfo, pVertices, // (void*)vertexFormatDesc.mpVertices, &indexDataInfo, pIndices // &vertexFormatDesc.mpIndices[0] ); ASSERT( CPUTSUCCESS(result), _L("Failed building bounding box mesh") ); } if( !mpBoundingBoxMaterialMaster ) { mpBoundingBoxMaterialMaster = CPUTAssetLibrary::GetAssetLibrary()->GetMaterial(_L("BoundingBox"), false, NULL, -3 ); // -1 == mesh independent. -2 == shadow cast material. -3 == bounding box. TODO: how to formalize (enum?) mpBoundingBoxMesh->BindVertexShaderLayout( mpBoundingBoxMaterialMaster, NULL); } mpBoundingBoxMaterial = mpBoundingBoxMaterialMaster; mpBoundingBoxMaterial->AddRef(); }
// Load and register all the resources needed by the GUI system //----------------------------------------------------------------------------- CPUTResult CPUTGuiControllerDX11::RegisterGUIResources(ID3D11DeviceContext *pImmediateContext, cString VertexShaderFilename, cString PixelShaderFilename, cString RenderStateFile, cString DefaultFontFilename, cString ControlAtlasTexture) { if(NULL==pImmediateContext) { return CPUT_ERROR_INVALID_PARAMETER; } CPUTResult result; HRESULT hr; ID3D11Device *pD3dDevice = NULL; CPUTOSServices *pServices = NULL; CPUTAssetLibraryDX11 *pAssetLibrary = NULL; cString ErrorMessage; // Get the services/resource pointers we need pServices = CPUTOSServices::GetOSServices(); pImmediateContext->GetDevice(&pD3dDevice); pAssetLibrary = (CPUTAssetLibraryDX11*)CPUTAssetLibraryDX11::GetAssetLibrary(); // Get the resource directory cString ResourceDirectory; CPUTGuiControllerDX11::GetController()->GetResourceDirectory(ResourceDirectory); // 1. Load the renderstate configuration for the GUI system mpGUIRenderStateBlock = (CPUTRenderStateBlockDX11*) pAssetLibrary->GetRenderStateBlock(ResourceDirectory+RenderStateFile); ASSERT(mpGUIRenderStateBlock, _L("Error loading the render state file (.rs) needed for the CPUT GUI system")); // 2. Store the shader path from AssetLibrary, change it to OUR resource directory cString OriginalAssetLibraryDirectory = pAssetLibrary->GetShaderDirectory(); pAssetLibrary->SetShaderDirectoryName(ResourceDirectory); // 3. load the shaders for gui drawing // Load the GUI Vertex Shader cString FullPath, FinalPath; FullPath = mResourceDirectory + VertexShaderFilename; pServices->ResolveAbsolutePathAndFilename(FullPath, &FinalPath); result = pAssetLibrary->GetVertexShader(FinalPath, pD3dDevice, _L("VS"), _L("vs_4_0"), &mpGUIVertexShader, true); CPUTSetDebugName( mpGUIVertexShader->GetNativeVertexShader(), _L("GUIVertexShader")); if(CPUTFAILED(result)) { ASSERT(CPUTSUCCESS(result), _L("Error loading the vertex shader needed for the CPUT GUI system.")); } ID3DBlob *pVertexShaderBlob = mpGUIVertexShader->GetBlob(); // Load the GUI Pixel Shader FullPath = mResourceDirectory + PixelShaderFilename; pServices->ResolveAbsolutePathAndFilename(FullPath, &FinalPath); result = pAssetLibrary->GetPixelShader(FinalPath, pD3dDevice, _L("PS"), _L("ps_4_0"), &mpGUIPixelShader, true); CPUTSetDebugName( mpGUIPixelShader->GetNativePixelShader(), _L("GUIPixelShader")); if(CPUTFAILED(result)) { ASSERT(CPUTSUCCESS(result), _L("Error loading the pixel shader needed for the CPUT GUI system.")); } // Restore the previous shader directory pAssetLibrary->SetShaderDirectoryName(OriginalAssetLibraryDirectory); // 4. Create the vertex layout description for all the GUI controls we'll draw // set vertex shader as active so we can configure it ID3D11VertexShader *pVertexShader = mpGUIVertexShader->GetNativeVertexShader(); pImmediateContext->VSSetShader( pVertexShader, NULL, 0 ); D3D11_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; UINT numElements = ARRAYSIZE( layout ); // Create the input layout hr = pD3dDevice->CreateInputLayout( layout, numElements, pVertexShaderBlob->GetBufferPointer(), pVertexShaderBlob->GetBufferSize(), &mpVertexLayout ); ASSERT( SUCCEEDED(hr), _L("Error creating CPUT GUI system input layout" )); CPUTSetDebugName( mpVertexLayout, _L("CPUT GUI InputLayout object")); // 5. create the vertex shader constant buffer pointers D3D11_BUFFER_DESC bd; ZeroMemory( &bd, sizeof(bd) ); bd.Usage = D3D11_USAGE_DEFAULT; bd.ByteWidth = sizeof(GUIConstantBufferVS); bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; bd.CPUAccessFlags = 0; hr = pD3dDevice->CreateBuffer( &bd, NULL, &mpConstantBufferVS ); ASSERT( SUCCEEDED(hr), _L("Error creating constant buffer VS" )); CPUTSetDebugName( mpConstantBufferVS, _L("GUI ConstantBuffer")); // Set the texture directory for loading the control texture atlas pAssetLibrary->SetTextureDirectoryName(ResourceDirectory); // load the control atlas mpControlTextureAtlas = (CPUTTextureDX11*) pAssetLibrary->GetTexture(ControlAtlasTexture); if(NULL==mpControlTextureAtlas) { return CPUT_TEXTURE_LOAD_ERROR; } mpControlTextureAtlasView = mpControlTextureAtlas->GetShaderResourceView(); mpControlTextureAtlasView->AddRef(); // restore the asset library's texture directory pAssetLibrary->SetTextureDirectoryName(OriginalAssetLibraryDirectory); // 6. Load the font atlas // store the existing asset library font directory OriginalAssetLibraryDirectory = pAssetLibrary->GetFontDirectory(); // set font directory to the resource directory pAssetLibrary->SetFontDirectoryName(ResourceDirectory); mpFont = (CPUTFontDX11*) pAssetLibrary->GetFont(DefaultFontFilename); if(NULL==mpFont) { return CPUT_TEXTURE_LOAD_ERROR; } mpTextTextureAtlas = mpFont->GetAtlasTexture(); mpTextTextureAtlas->AddRef(); mpTextTextureAtlasView = mpFont->GetAtlasTextureResourceView(); mpTextTextureAtlasView->AddRef(); // restore the asset library's font directory pAssetLibrary->SetTextureDirectoryName(OriginalAssetLibraryDirectory); // 7. Set up the DirectX uber-buffers that the controls draw into int maxSize = max(CPUT_GUI_BUFFER_STRING_SIZE, CPUT_GUI_BUFFER_SIZE); maxSize = max(maxSize, CPUT_GUI_VERTEX_BUFFER_SIZE); maxSize *= sizeof( CPUTGUIVertex ); char *pZeroedBuffer= new char[maxSize]; memset(pZeroedBuffer, 0, maxSize); // set up buffer description ZeroMemory( &bd, sizeof(bd) ); bd.Usage = D3D11_USAGE_DEFAULT; bd.ByteWidth = sizeof( CPUTGUIVertex ) * CPUT_GUI_VERTEX_BUFFER_SIZE; //mUberBufferIndex; bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = 0; // initialization data (all 0's for now) D3D11_SUBRESOURCE_DATA InitData; ZeroMemory( &InitData, sizeof(InitData) ); InitData.pSysMem = mpMirrorBuffer; // mpUberBuffer SAFE_RELEASE(mpUberBuffer); hr = pD3dDevice->CreateBuffer( &bd, &InitData, &mpUberBuffer ); ASSERT( !FAILED( hr ), _L("CPUT GUI FPS counter buffer creation failure")); CPUTSetDebugName(mpUberBuffer, _L("CPUT GUI: Control's main vertex buffer")); // mpTextUberBuffer bd.ByteWidth = sizeof( CPUTGUIVertex ) * CPUT_GUI_BUFFER_STRING_SIZE; hr = pD3dDevice->CreateBuffer( &bd, &InitData, &mpTextUberBuffer ); ASSERT( !FAILED( hr ), _L("CPUT GUI FPS counter buffer creation failure")); CPUTSetDebugName(mpTextUberBuffer, _L("CPUT GUI: control text vertex buffer")); // mpFocusedControlBuffer bd.ByteWidth = sizeof( CPUTGUIVertex ) * CPUT_GUI_VERTEX_BUFFER_SIZE; hr = pD3dDevice->CreateBuffer( &bd, &InitData, &mpFocusedControlBuffer ); ASSERT( !FAILED( hr ), _L("CPUT GUI FPS counter buffer creation failure")); CPUTSetDebugName(mpFocusedControlBuffer, _L("CPUT GUI: focused control images vertex buffer")); // mpFocusedControlTextBuffer bd.ByteWidth = sizeof( CPUTGUIVertex ) * CPUT_GUI_BUFFER_STRING_SIZE; //mFocusedControlTextBufferIndex; hr = pD3dDevice->CreateBuffer( &bd, &InitData, &mpFocusedControlTextBuffer ); ASSERT( !FAILED( hr ), _L("CPUT GUI FPS counter buffer creation failure")); CPUTSetDebugName(mpFocusedControlTextBuffer, _L("CPUT GUI: focused control text vertex buffer")); // mpFPSDirectXBuffer bd.ByteWidth = sizeof( CPUTGUIVertex ) * CPUT_GUI_BUFFER_STRING_SIZE; hr = pD3dDevice->CreateBuffer( &bd, &InitData, &mpFPSDirectXBuffer ); ASSERT( !FAILED( hr ), _L("CPUT GUI FPS counter buffer creation failure")); CPUTSetDebugName(mpFPSDirectXBuffer, _L("CPUT GUI: FPS display text")); // no longer need the device - release it. SAFE_RELEASE(pD3dDevice); SAFE_DELETE_ARRAY(pZeroedBuffer); // 8. Register all GUI sub-resources // Walk all the controls/fonts and have them register all their required static resources // Returning errors if you couldn't find your resources result = CPUTText::RegisterStaticResources(); if(CPUTFAILED(result)) { return result; } result = CPUTButton::RegisterStaticResources(); if(CPUTFAILED(result)) { return result; } result = CPUTCheckbox::RegisterStaticResources(); if(CPUTFAILED(result)) { return result; } result = CPUTSlider::RegisterStaticResources(); if(CPUTFAILED(result)) { return result; } result = CPUTDropdown::RegisterStaticResources(); if(CPUTFAILED(result)) { return result; } // create the FPS CPUTText object for drawing FPS mpFPSCounter = new CPUTText(_L("FPS:"), ID_CPUT_GUI_FPS_COUNTER, mpFont); mpFPSCounter->SetAutoArranged(false); mpFPSCounter->SetPosition(0,0); // start the timer mpFPSTimer->StartTimer(); // done return CPUT_SUCCESS; }
//----------------------------------------------------------------------------- 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 CPUTTextureDX11::CreateNativeTexture( ID3D11Device *pD3dDevice, const cString &fileName, ID3D11ShaderResourceView **ppShaderResourceView, ID3D11Resource **ppTexture, bool ForceLoadAsSRGB ){ CPUTResult result; HRESULT hr; // Set up loading structure // // Indicate all texture parameters should come from the file D3DX11_IMAGE_LOAD_INFO LoadInfo; ZeroMemory(&LoadInfo, sizeof(D3DX11_IMAGE_LOAD_INFO)); LoadInfo.Width = D3DX11_FROM_FILE; LoadInfo.Height = D3DX11_FROM_FILE; LoadInfo.Depth = D3DX11_FROM_FILE; LoadInfo.FirstMipLevel = D3DX11_FROM_FILE; LoadInfo.MipLevels = D3DX11_FROM_FILE; // LoadInfo.Usage = D3D11_USAGE_IMMUTABLE; // TODO: maintain a "mappable" flag? Set immutable if not mappable? LoadInfo.Usage = D3D11_USAGE_DEFAULT; LoadInfo.BindFlags = D3D11_BIND_SHADER_RESOURCE; LoadInfo.CpuAccessFlags = 0; LoadInfo.MiscFlags = 0; LoadInfo.MipFilter = D3DX11_FROM_FILE; LoadInfo.pSrcInfo = NULL; LoadInfo.Format = (DXGI_FORMAT) D3DX11_FROM_FILE; LoadInfo.Filter = D3DX11_FILTER_NONE; // if we're 'forcing' load of sRGB data, we need to verify image is sRGB // or determine image format that best matches the non-sRGB source format in hopes that the conversion will be faster // and data preserved if(true == ForceLoadAsSRGB) { // get the source image info D3DX11_IMAGE_INFO SrcInfo; hr = D3DX11GetImageInfoFromFile(fileName.c_str(), NULL, &SrcInfo, NULL); ASSERT( SUCCEEDED(hr), _L(" - Error loading texture '")+fileName+_L("'.") ); // find a closest equivalent sRGB format result = GetSRGBEquivalent(SrcInfo.Format, LoadInfo.Format); ASSERT( CPUTSUCCESS(result), _L("Error loading texture '")+fileName+_L("'. It is specified this texture must load as sRGB, but the source image is in a format that cannot be converted to sRGB.\n") ); // set filtering mode to interpret 'in'-coming data as sRGB, and storing it 'out' on an sRGB surface // // As it stands, we don't have any tools that support sRGB output in DXT compressed textures. // If we later support a format that does provide sRGB, then the filter 'in' flag will need to be removed LoadInfo.Filter = D3DX11_FILTER_NONE | D3DX11_FILTER_SRGB_IN | D3DX11_FILTER_SRGB_OUT; #if 0 // DWM: TODO: We want to catch the cases where the loader needs to do work. // This happens if the texture's pixel format isn't supported by DXGI. // TODO: how to determine? // if a runtime conversion must happen report a performance warning error. // Note: choosing not to assert here, as this will be a common issue. if( SrcInfo.Format != LoadInfo.Format) { cString dxgiName = GetDXGIFormatString(SrcInfo.Format); cString errorString = _T(__FUNCTION__); errorString += _L("- PERFORMANCE WARNING: '") + fileName +_L("' has an image format ")+dxgiName +_L(" but must be run-time converted to ")+GetDXGIFormatString(LoadInfo.Format) +_L(" based on requested sRGB target buffer.\n"); TRACE( errorString.c_str() ); } #endif } //hr = D3DX11CreateTextureFromFile( pD3dDevice, fileName.c_str(), &LoadInfo, NULL, ppTexture, NULL ); hr = MyCreateTextureFromFile( pD3dDevice, fileName.c_str(), &LoadInfo, NULL, ppTexture, NULL ); ASSERT( SUCCEEDED(hr), _L("Failed to load texture: ") + fileName ); CPUTSetDebugName( *ppTexture, fileName ); hr = pD3dDevice->CreateShaderResourceView( *ppTexture, NULL, ppShaderResourceView ); ASSERT( SUCCEEDED(hr), _L("Failed to create texture shader resource view.") ); CPUTSetDebugName( *ppShaderResourceView, fileName ); return CPUT_SUCCESS; }
// Application entry point. Execution begins here. //----------------------------------------------------------------------------- int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow ) { // Prevent unused parameter compiler warnings UNREFERENCED_PARAMETER(hInstance); UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(nCmdShow); #ifdef DEBUG // tell VS to report leaks at any exit of the program _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); #endif CPUTResult result=CPUT_SUCCESS; int returnCode=0; // create an instance of my sample MySample *pSample = new MySample(); // We make the assumption we are running from the executable's dir in // the CPUT SampleStart directory or it won't be able to use the relative paths to find the default // resources cString ResourceDirectory; CPUTOSServices::GetOSServices()->GetExecutableDirectory(&ResourceDirectory); ResourceDirectory.append(_L(".\\CPUT\\resources\\")); // Initialize the system and give it the base CPUT resource directory (location of GUI images/etc) // For now, we assume it's a relative directory from the executable directory. Might make that resource // directory location an env variable/hardcoded later pSample->CPUTInitialize(ResourceDirectory); // window and device parameters CPUTWindowCreationParams params; params.deviceParams.refreshRate = 60; params.deviceParams.swapChainBufferCount= 1; params.deviceParams.swapChainFormat = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; params.deviceParams.swapChainUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT; // parse out the parameter settings or reset them to defaults if not specified cString AssetFilename; cString CommandLine(lpCmdLine); pSample->CPUTParseCommandLine(CommandLine, ¶ms, &AssetFilename); // create the window and device context result = pSample->CPUTCreateWindowAndContext(_L("CPUTWindow DirectX 11"), params); ASSERT( CPUTSUCCESS(result), _L("CPUT Error creating window and context.") ); // initialize the task manager gTaskMgr.Init(); // start the main message loop returnCode = pSample->CPUTMessageLoop(); pSample->DeviceShutdown(); // shutdown task manage gTaskMgr.Shutdown(); // cleanup resources delete pSample; return returnCode; }
// Load the set file definition of this object // 1. Parse the block of name/parent/transform info for model block // 2. Load the model's binary payload (i.e., the meshes) // 3. Assert the # of meshes matches # of materials // 4. Load each mesh's material //----------------------------------------------------------------------------- CPUTResult CPUTModelDX11::LoadModel(CPUTConfigBlock *pBlock, int *pParentID, CPUTModel *pMasterModel, int numSystemMaterials, cString *pSystemMaterialNames) { CPUTResult result = CPUT_SUCCESS; CPUTAssetLibraryDX11 *pAssetLibrary = (CPUTAssetLibraryDX11*)CPUTAssetLibrary::GetAssetLibrary(); cString modelSuffix = ptoc(this); // set the model's name mName = pBlock->GetValueByName(_L("name"))->ValueAsString(); mName = mName + _L(".mdl"); // resolve the full path name cString modelLocation; cString resolvedPathAndFile; modelLocation = ((CPUTAssetLibraryDX11*)CPUTAssetLibrary::GetAssetLibrary())->GetModelDirectoryName(); modelLocation = modelLocation+mName; CPUTOSServices::GetOSServices()->ResolveAbsolutePathAndFilename(modelLocation, &resolvedPathAndFile); // Get the parent ID. Note: the caller will use this to set the parent. *pParentID = pBlock->GetValueByName(_L("parent"))->ValueAsInt(); LoadParentMatrixFromParameterBlock( pBlock ); // Get the bounding box information float3 center(0.0f), half(0.0f); pBlock->GetValueByName(_L("BoundingBoxCenter"))->ValueAsFloatArray(center.f, 3); pBlock->GetValueByName(_L("BoundingBoxHalf"))->ValueAsFloatArray(half.f, 3); mBoundingBoxCenterObjectSpace = center; mBoundingBoxHalfObjectSpace = half; mMeshCount = pBlock->GetValueByName(_L("meshcount"))->ValueAsInt(); mpMesh = new CPUTMesh*[mMeshCount]; mpSubMaterialCount = new UINT[mMeshCount]; mpMaterial = new CPUTMaterial**[mMeshCount]; memset( mpMaterial, 0, mMeshCount * sizeof(CPUTMaterial*) ); mpInputLayout = new ID3D11InputLayout**[mMeshCount]; memset( mpInputLayout, 0, mMeshCount * sizeof(ID3D11InputLayout**) ); cString materialName; char pNumber[4]; cString materialValueName; CPUTModelDX11 *pMasterModelDX = (CPUTModelDX11*)pMasterModel; for(UINT ii=0; ii<mMeshCount; ii++) { if(pMasterModelDX) { // Reference the master model's mesh. Don't create a new one. mpMesh[ii] = pMasterModelDX->mpMesh[ii]; mpMesh[ii]->AddRef(); } else { mpMesh[ii] = new CPUTMeshDX11(); } } if( !pMasterModelDX ) { // Not a clone/instance. So, load the model's binary payload (i.e., vertex and index buffers) // TODO: Change to use GetModel() result = LoadModelPayload(resolvedPathAndFile); ASSERT( CPUTSUCCESS(result), _L("Failed loading model") ); } for(UINT ii=0; ii<mMeshCount; ii++) { // get the right material number ('material0', 'material1', 'material2', etc) materialValueName = _L("material"); _itoa_s(ii, pNumber, 4, 10); materialValueName.append(s2ws(pNumber)); materialName = pBlock->GetValueByName(materialValueName)->ValueAsString(); // Get/load material for this mesh cString meshSuffix = itoc(ii); #if GENERATE_BILLBOARD_TEXTURES cString *pFinalSystemNames = new cString[numSystemMaterials+2]; pFinalSystemNames[1] = materialName + _L("Color"); pFinalSystemNames[0] = materialName + _L("ColorNormal"); int finalNumSystemMaterials = 2; #else UINT totalNameCount = numSystemMaterials + NUM_GLOBAL_SYSTEM_MATERIALS; cString *pFinalSystemNames = new cString[totalNameCount]; // Copy "global" system materials to caller-supplied list for( int jj=0; jj<numSystemMaterials; jj++ ) { pFinalSystemNames[jj] = pSystemMaterialNames[jj]; } pFinalSystemNames[totalNameCount + CPUT_MATERIAL_INDEX_SHADOW_CAST] = _L("..\\..\\Material\\ShadowCast"); pFinalSystemNames[totalNameCount + CPUT_MATERIAL_INDEX_AMBIENT_SHADOW_CAST] = _L("..\\..\\Material\\AmbientShadowCast"); pFinalSystemNames[totalNameCount + CPUT_MATERIAL_INDEX_HEIGHT_FIELD] = _L("..\\..\\Material\\HeightField"); pFinalSystemNames[totalNameCount + CPUT_MATERIAL_INDEX_BOUNDING_BOX] = _L("..\\..\\Material\\BoundingBox"); pFinalSystemNames[totalNameCount + CPUT_MATERIAL_INDEX_TERRAIN_LIGHT_MAP] = _L("..\\..\\Material\\TerrainLightMap"); pFinalSystemNames[totalNameCount + CPUT_MATERIAL_INDEX_TERRAIN_AND_TREES_LIGHT_MAP] = _L("..\\..\\Material\\TerrainAndTreesLightMap"); int finalNumSystemMaterials = numSystemMaterials + NUM_GLOBAL_SYSTEM_MATERIALS; #endif CPUTMaterialDX11 *pMaterial = (CPUTMaterialDX11*)pAssetLibrary->GetMaterial(materialName, false, modelSuffix, meshSuffix, NULL, finalNumSystemMaterials, pFinalSystemNames); ASSERT( pMaterial, _L("Couldn't find material.") ); delete []pFinalSystemNames; mpSubMaterialCount[ii] = pMaterial->GetSubMaterialCount(); HEAPCHECK; SetSubMaterials(ii, pMaterial->GetSubMaterials()); HEAPCHECK; // Release the extra refcount we're holding from the GetMaterial operation earlier // now the asset library, and this model have the only refcounts on that material pMaterial->Release(); } return result; }