//-------------------------------------------------------------------------------------- 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::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; }
//-------------------------------------------------------------------------------------- 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::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; }
//----------------------------------------------------------------------------- void CPUTMaterialDX11::BindTextures( CPUTShaderParameters ¶ms, const CPUTModel *pModel, int meshIndex ) { CPUTAssetLibraryDX11 *pAssetLibrary = (CPUTAssetLibraryDX11*)CPUTAssetLibrary::GetAssetLibrary(); for(params.mTextureCount=0; params.mTextureCount < params.mTextureParameterCount; params.mTextureCount++) { cString textureName; UINT textureCount = params.mTextureCount; cString tagName = params.mpTextureParameterName[textureCount]; CPUTConfigEntry *pValue = mConfigBlock.GetValueByName(tagName); if( !pValue->IsValid() ) { // We didn't find our property in the file. Is it in the global config block? pValue = mGlobalProperties.GetValueByName(tagName); } ASSERT( pValue->IsValid(), L"Can't find texture '" + tagName + L"'." ); // TODO: fix message textureName = pValue->ValueAsString(); // If the texture name not specified. Load default.dds instead if( 0 == textureName.length() ) { textureName = _L("default.dds"); } UINT bindPoint = params.mpTextureParameterBindPoint[textureCount]; ASSERT( bindPoint < CPUT_MATERIAL_MAX_TEXTURE_SLOTS, _L("Texture bind point out of range.") ); if( textureName[0] == '@' ) { // This is a per-mesh value. Add to per-mesh list. textureName += ptoc(pModel) + itoc(meshIndex); } else if( textureName[0] == '#' ) { // This is a per-mesh value. Add to per-mesh list. textureName += ptoc(pModel); } // Get the sRGB flag (default to true) cString SRGBName = tagName+_L("sRGB"); CPUTConfigEntry *pSRGBValue = mConfigBlock.GetValueByName(SRGBName); bool loadAsSRGB = pSRGBValue->IsValid() ? loadAsSRGB = pSRGBValue->ValueAsBool() : true; if( !mpTexture[textureCount] ) { mpTexture[textureCount] = pAssetLibrary->GetTexture( textureName, false, loadAsSRGB ); ASSERT( mpTexture[textureCount], _L("Failed getting texture ") + textureName); } // The shader file (e.g. .fx) can specify the texture bind point (e.g., t0). Those specifications // might not be contiguous, and there might be gaps (bind points without assigned textures) // TODO: Warn about missing bind points? params.mppBindViews[bindPoint] = ((CPUTTextureDX11*)mpTexture[textureCount])->GetShaderResourceView(); params.mppBindViews[bindPoint]->AddRef(); } }
//----------------------------------------------------------------------------- void CPUTMaterialDX11::BindConstantBuffers( CPUTShaderParameters ¶ms, const CPUTModel *pModel, int meshIndex ) { CPUTConfigEntry *pValue; CPUTAssetLibraryDX11 *pAssetLibrary = (CPUTAssetLibraryDX11*)CPUTAssetLibrary::GetAssetLibrary(); for(params.mConstantBufferCount=0; params.mConstantBufferCount < params.mConstantBufferParameterCount; params.mConstantBufferCount++) { cString constantBufferName; UINT constantBufferCount = params.mConstantBufferCount; cString tagName = params.mpConstantBufferParameterName[constantBufferCount]; { pValue = mConfigBlock.GetValueByName(tagName); if( !pValue->IsValid() ) { // We didn't find our property in the file. Is it in the global config block? pValue = mGlobalProperties.GetValueByName(tagName); } ASSERT( pValue->IsValid(), L"Can't find constant buffer '" + tagName + L"'." ); // TODO: fix message constantBufferName = pValue->ValueAsString(); } UINT bindPoint = params.mpConstantBufferParameterBindPoint[constantBufferCount]; ASSERT( bindPoint < CPUT_MATERIAL_MAX_CONSTANT_BUFFER_SLOTS, _L("Constant buffer bind point out of range.") ); const CPUTModel *pWhichModel = NULL; int whichMesh = -1; if( constantBufferName[0] == '@' ) { pWhichModel = pModel; whichMesh = meshIndex; } else if( constantBufferName[0] == '#' ) { pWhichModel = pModel; } if( !mpConstantBuffer[constantBufferCount] ) { if( pWhichModel ) { mpConstantBuffer[constantBufferCount] = pAssetLibrary->GetConstantBuffer( constantBufferName, pWhichModel, whichMesh ); } else { mpConstantBuffer[constantBufferCount] = pAssetLibrary->GetConstantBuffer( constantBufferName ); } ASSERT( mpConstantBuffer[constantBufferCount], _L("Failed getting constant buffer ") + constantBufferName); } // If has constant buffer, then add to mppBindConstantBuffer params.mppBindConstantBuffers[bindPoint] = ((CPUTBufferDX11*)mpConstantBuffer[constantBufferCount])->GetNativeBuffer(); if( params.mppBindConstantBuffers[bindPoint] ) { params.mppBindConstantBuffers[bindPoint]->AddRef();} } }
//----------------------------------------------------------------------------- void CPUTMaterialDX11::BindUAVs( CPUTShaderParameters ¶ms, const CPUTModel *pModel, int meshIndex ) { CPUTConfigEntry *pValue; CPUTAssetLibraryDX11 *pAssetLibrary = (CPUTAssetLibraryDX11*)CPUTAssetLibrary::GetAssetLibrary(); memset( params.mppBindUAVs, 0, sizeof(params.mppBindUAVs) ); for(params.mUAVCount=0; params.mUAVCount < params.mUAVParameterCount; params.mUAVCount++) { cString uavName; UINT uavCount = params.mUAVCount; cString tagName = params.mpUAVParameterName[uavCount]; { pValue = mConfigBlock.GetValueByName(tagName); if( !pValue->IsValid() ) { // We didn't find our property in the file. Is it in the global config block? pValue = mGlobalProperties.GetValueByName(tagName); } ASSERT( pValue->IsValid(), L"Can't find UAV '" + tagName + L"'." ); // TODO: fix message uavName = pValue->ValueAsString(); } UINT bindPoint = params.mpUAVParameterBindPoint[uavCount]; ASSERT( bindPoint < CPUT_MATERIAL_MAX_UAV_SLOTS, _L("UAV bind point out of range.") ); const CPUTModel *pWhichModel = NULL; int whichMesh = -1; if( uavName[0] == '@' ) { pWhichModel = pModel; whichMesh = meshIndex; } else if( uavName[0] == '#' ) { pWhichModel = pModel; } if( !mpUAV[uavCount] ) { mpUAV[uavCount] = pAssetLibrary->GetBuffer( uavName, pWhichModel, whichMesh ); ASSERT( mpUAV[uavCount], _L("Failed getting UAV ") + uavName); } // If has UAV, then add to mppBindUAV params.mppBindUAVs[bindPoint] = ((CPUTBufferDX11*)mpUAV[uavCount])->GetUnorderedAccessView(); if( params.mppBindUAVs[bindPoint] ) { params.mppBindUAVs[bindPoint]->AddRef();} } }
//----------------------------------------------------------------------------- void CPUTModelDX11::CreateModelConstantBuffer() { CPUTAssetLibraryDX11 *pAssetLibrary = (CPUTAssetLibraryDX11*)CPUTAssetLibrary::GetAssetLibrary(); // Create the model constant buffer. HRESULT hr; D3D11_BUFFER_DESC bd = {0}; bd.ByteWidth = sizeof(CPUTModelConstantBuffer); bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; bd.Usage = D3D11_USAGE_DYNAMIC; bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; hr = (CPUT_DX11::GetDevice())->CreateBuffer( &bd, NULL, &mpModelConstantBuffer ); ASSERT( !FAILED( hr ), _L("Error creating constant buffer.") ); CPUTSetDebugName( mpModelConstantBuffer, _L("Model Constant buffer") ); cString name = _L("$cbPerModelValues"); CPUTBufferDX11 *pBuffer = new CPUTBufferDX11(name, mpModelConstantBuffer); pAssetLibrary->AddConstantBuffer( name, pBuffer ); pBuffer->Release(); // We're done with it. We added it to the library. Release our reference. }
//----------------------------------------------------------------------------- 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; }
// incoming resize event to be handled and translated //----------------------------------------------------------------------------- void CPUT_DX11::ResizeWindow(UINT width, UINT height) { HRESULT hr; CPUTResult result; CPUTAssetLibraryDX11 *pAssetLibrary = (CPUTAssetLibraryDX11*)CPUTAssetLibraryDX11::GetAssetLibrary(); // TODO: Making the back and depth buffers into CPUTRenderTargets should simplify this (CPUTRenderTarget* manages RTV, SRV, UAV, etc.) if( mpBackBuffer ) ((CPUTBufferDX11*)mpBackBuffer)->ReleaseBuffer(); if( mpDepthBuffer ) ((CPUTBufferDX11*)mpDepthBuffer)->ReleaseBuffer(); if( mpBackBufferTexture ) ((CPUTTextureDX11*)mpBackBufferTexture)->ReleaseTexture(); if( mpDepthBufferTexture ) ((CPUTTextureDX11*)mpDepthBufferTexture)->ReleaseTexture(); // Make sure we don't have any buffers bound. mpContext->ClearState(); Present(); mpContext->Flush(); SAFE_RELEASE(mpBackBufferRTV); SAFE_RELEASE(mpBackBufferSRV); SAFE_RELEASE(mpBackBufferUAV); SAFE_RELEASE(mpDepthStencilSRV); CPUT::ResizeWindow( width, height ); // Call the sample's clean up code if present. ReleaseSwapChain(); // handle the internals of a resize int windowWidth, windowHeight; CPUTOSServices *pServices = CPUTOSServices::GetOSServices(); pServices->GetClientDimensions( &windowWidth, &windowHeight); // resize the swap chain hr = mpSwapChain->ResizeBuffers(mSwapChainBufferCount, windowWidth, windowHeight, mSwapChainFormat, 0); ASSERT( SUCCEEDED(hr), _L("Error resizing swap chain") ); // re-create the render-target view ID3D11Texture2D *pSwapChainBuffer = NULL; hr = mpSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D), (LPVOID*) (&pSwapChainBuffer)); ASSERT(SUCCEEDED(hr), _L("")); hr = mpD3dDevice->CreateRenderTargetView( pSwapChainBuffer, NULL, &mpBackBufferRTV); ASSERT(SUCCEEDED(hr), _L("")); hr = mpD3dDevice->CreateShaderResourceView( pSwapChainBuffer, NULL, &mpBackBufferSRV); ASSERT(SUCCEEDED(hr), _L("")); #ifdef CREATE_SWAP_CHAIN_UAV // Not every DXGI format supports UAV. So, create UAV only if sample chooses to do so. hr = mpD3dDevice->CreateUnorderedAccessView( pSwapChainBuffer, NULL, &mpBackBufferUAV); ASSERT(SUCCEEDED(hr), _L("")); #endif // Add the back buffer to the asset library. Create CPUTBuffer and a CPUTTexture forms and add them. if( mpBackBuffer ) { ((CPUTBufferDX11*)mpBackBuffer)->SetBufferAndViews( NULL, mpBackBufferSRV, mpBackBufferUAV ); } else { cString backBufferName = _L("$BackBuffer"); mpBackBuffer = new CPUTBufferDX11( backBufferName, NULL, mpBackBufferUAV ); pAssetLibrary->AddBuffer( backBufferName, mpBackBuffer ); } if( mpBackBufferTexture ) { ((CPUTTextureDX11*)mpBackBufferTexture)->SetTextureAndShaderResourceView( NULL, mpBackBufferSRV ); } else { cString backBufferName = _L("$BackBuffer"); mpBackBufferTexture = new CPUTTextureDX11( backBufferName, NULL, mpBackBufferSRV ); pAssetLibrary->AddTexture( backBufferName, mpBackBufferTexture ); } // release the old depth buffer objects // release the temporary swap chain buffer SAFE_RELEASE(pSwapChainBuffer); SAFE_RELEASE(mpDepthStencilBuffer); SAFE_RELEASE(mpDepthStencilState); SAFE_RELEASE(mpDepthStencilView); result = CreateAndBindDepthBuffer(windowWidth, windowHeight); if(CPUTFAILED(result)) { // depth buffer creation error ASSERT(0,_L("")); } if( mpDepthBuffer ) { ((CPUTBufferDX11*)mpDepthBuffer)->SetBufferAndViews( NULL, mpDepthStencilSRV, NULL ); } else { cString depthBufferName = _L("$DepthBuffer"); mpDepthBuffer = new CPUTBufferDX11( depthBufferName, NULL, mpDepthStencilSRV ); pAssetLibrary->AddBuffer( depthBufferName, mpDepthBuffer ); } if( mpDepthBufferTexture ) { ((CPUTTextureDX11*)mpDepthBufferTexture)->SetTextureAndShaderResourceView( NULL, mpDepthStencilSRV ); } else { cString DepthBufferName = _L("$DepthBuffer"); mpDepthBufferTexture = new CPUTTextureDX11( DepthBufferName, NULL, mpDepthStencilSRV ); pAssetLibrary->AddTexture( DepthBufferName, mpDepthBufferTexture ); } // Release our extra reference to each view. // if(mpBackBufferSRV) mpBackBufferSRV->Release(); // if(mpBackBufferUAV) mpBackBufferUAV->Release(); // if(mpDepthStencilSRV) mpDepthStencilSRV->Release();; // set the viewport D3D11_VIEWPORT vp; vp.Width = (FLOAT) windowWidth; vp.Height = (FLOAT)windowHeight; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0; vp.TopLeftY = 0; mpContext->RSSetViewports( 1, &vp ); // trigger the GUI manager to resize CPUTGuiControllerDX11::GetController()->Resize(); }
//----------------------------------------------------------------------------- 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; }
// 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 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; }
// 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; }