// sets the resource directory to use when loading GUI resources //----------------------------------------------------------------------------- CPUTResult CPUTGuiController::SetResourceDirectory(const cString ResourceDirectory) { // check to see if the specified directory is valid CPUTResult result = CPUT_SUCCESS; // resolve the directory to a full path cString FullPath; CPUTOSServices *pServices = CPUTOSServices::GetOSServices(); result = pServices->ResolveAbsolutePathAndFilename(ResourceDirectory, &FullPath); if(CPUTFAILED(result)) { return result; } // check existence of directory result = pServices->DoesDirectoryExist(FullPath); if(CPUTFAILED(result)) { return result; } // set the resource directory (absolute path) mResourceDirectory = FullPath; return result; }
// Set where CPUT will look for it's button images, fonts, etc //----------------------------------------------------------------------------- CPUTResult CPUT_DX11::SetCPUTResourceDirectory(const cString ResourceDirectory) { // check to see if the specified directory is valid CPUTResult result = CPUT_SUCCESS; // resolve the directory to a full path cString fullPath; CPUTOSServices *pServices = CPUTOSServices::GetOSServices(); result = pServices->ResolveAbsolutePathAndFilename(ResourceDirectory, &fullPath); if(CPUTFAILED(result)) { return result; } // check existence of directory result = pServices->DoesDirectoryExist(fullPath); if(CPUTFAILED(result)) { return result; } // set the resource directory (absolute path) mResourceDirectory = fullPath; // tell the gui system where to look for it's resources // todo: do we want to force a flush/reload of all resources (i.e. change control graphics) result = CPUTGuiControllerDX11::GetController()->SetResourceDirectory(ResourceDirectory); return result; }
CPUTResult CPUTMeshDX11::ExtractVerticesandIndices() { CPUTResult result = CPUT_SUCCESS; int vertexSizeInBytes; result = GetByteSizeFromFormat((mpLayoutDescription + mNumberOfInputLayoutElements -1)->Format, vertexSizeInBytes); if(CPUTFAILED(result)) { return result; } vertexSizeInBytes += (mpLayoutDescription + mNumberOfInputLayoutElements -1)->AlignedByteOffset; mpRawVertices = (Vertex*)_aligned_malloc(sizeof(__m128) * mVertexCount, 32);//new Vertex[m_VertexCount]; char* vertexData = (char*)mpVertexData; for(unsigned int i = 0; i < mVertexCount; i++) { mpRawVertices[i].position.m128_f32[0] = *((float*)vertexData + 0); mpRawVertices[i].position.m128_f32[1] = *((float*)vertexData + 1); mpRawVertices[i].position.m128_f32[2] = *((float*)vertexData + 2); mpRawVertices[i].position.m128_f32[3] = 1.0f; vertexData = vertexData + vertexSizeInBytes; } mpRawIndices = new unsigned int[mIndexCount]; char* indexData = (char*)mpIndexData; for(unsigned int i = 0; i < mIndexCount; i++, indexData += mIndexElementByteSize) { mpRawIndices[i] = *((unsigned int*)indexData); } return result; }
//---------------------------------------------------------------- CPUTResult CPUTConfigFile::LoadFile(const cString &szFilename) { // Load the file cString szCurrLine; CPUTConfigBlock *pCurrBlock = NULL; FILE *pFile = NULL; int nCurrBlock = 0; CPUTResult result = CPUTOSServices::GetOSServices()->OpenFile(szFilename, &pFile); if(CPUTFAILED(result)) { return result; } _locale_t locale = _get_current_locale(); /* Determine file size */ fseek(pFile, 0, SEEK_END); int nBytes = ftell(pFile); // for text files, this is an overestimate fseek(pFile, 0, SEEK_SET); /* Read the whole thing */ char *pFileContents = new char[nBytes + 1]; nBytes = (int)fread(pFileContents, 1, nBytes, pFile); fclose(pFile); pFileContents[nBytes] = 0; // add 0-terminator /* Count the number of blocks */ const char *pCur = pFileContents; const char *pStart, *pEnd; while(ReadLine(&pStart, &pEnd, &pCur)) { const char *pOpen = FindFirst(pStart, pEnd, '['); const char *pClose = FindLast(pOpen + 1, pEnd, ']'); if (pOpen < pClose) { // This line is a valid block header mnBlockCount++; } } // For files that don't have any blocks, just add the entire file to one block if(mnBlockCount == 0) { mnBlockCount = 1; } pCur = pFileContents; mpBlocks = new CPUTConfigBlock[mnBlockCount]; pCurrBlock = mpBlocks; /* Find the first block first */ while(ReadLine(&pStart, &pEnd, &pCur)) { const char *pOpen = FindFirst(pStart, pEnd, '['); const char *pClose = FindLast(pOpen + 1, pEnd, ']'); if (pOpen < pClose) { // This line is a valid block header pCurrBlock = mpBlocks + nCurrBlock++; AssignStr(pCurrBlock->mszName, pOpen + 1, pClose, locale); std::transform(pCurrBlock->mszName.begin(), pCurrBlock->mszName.end(), pCurrBlock->mszName.begin(), ::tolower); } else if (pStart < pEnd) { // It's a value if (pCurrBlock == NULL) { continue; } const char *pEquals = FindFirst(pStart, pEnd, '='); if (pEquals == pEnd) { // No value, just a key, save it anyway // Optimistically, we assume it's new cString &name = pCurrBlock->mpValues[pCurrBlock->mnValueCount].szName; AssignStr(name, pStart, pEnd, locale); bool dup = false; for(int ii=0;ii<pCurrBlock->mnValueCount;++ii) { if(!pCurrBlock->mpValues[ii].szName.compare(name)) { dup = true; break; } } if(!dup) { pCurrBlock->mnValueCount++; } } else { const char *pNameStart = pStart; const char *pNameEnd = pEquals; const char *pValStart = pEquals + 1; const char *pValEnd = pEnd; RemoveWhitespace(pNameStart, pNameEnd); RemoveWhitespace(pValStart, pValEnd); // Optimistically assume the name is new cString &name = pCurrBlock->mpValues[pCurrBlock->mnValueCount].szName; AssignStr(name, pNameStart, pNameEnd, locale); std::transform(name.begin(), name.end(), name.begin(), ::tolower); bool dup = false; for(int ii=0;ii<pCurrBlock->mnValueCount;++ii) { if(!pCurrBlock->mpValues[ii].szName.compare(name)) { dup = true; break; } } if(!dup) { AssignStr(pCurrBlock->mpValues[pCurrBlock->mnValueCount].szValue, pValStart, pValEnd, locale); pCurrBlock->mnValueCount++; } } } } delete[] pFileContents; return CPUT_SUCCESS; }
void MySample::Create() { CPUTAssetLibrary *pAssetLibrary = CPUTAssetLibrary::GetAssetLibrary(); cString ExecutableDirectory; CPUTFileSystem::GetExecutableDirectory(&ExecutableDirectory); ExecutableDirectory.append(_L(ASSET_LOCATION)); pAssetLibrary->SetMediaDirectoryName(ExecutableDirectory); #ifdef ENABLE_GUI CPUTGuiControllerOGL *pGUI = (CPUTGuiControllerOGL*)CPUTGetGuiController(); std::string mediaDirectory = ws2s(pAssetLibrary->GetMediaDirectoryName()); std::string fontDirectory("Font/"); CPUTFont *pFont = CPUTFont::CreateFont(SYSTEM_LOCATION + fontDirectory, "arial_64.fnt"); pGUI->SetFont(pFont); // // Create some controls // CPUTDropdown *pDropdownMethod; pGUI->CreateText(_L("Test Font"), ID_IGNORE_CONTROL_ID, ID_MAIN_PANEL, &pTextMethod); pTextMethod->SetColor(1.0f, 1.0f, 1.0f, 1.0f); CreateInstancingControlButtons(); #endif CPUTFileSystem::GetExecutableDirectory(&ExecutableDirectory); ExecutableDirectory.append(_L(ASSET_LOCATION)); pAssetLibrary->SetMediaDirectoryName(ExecutableDirectory); int width, height; mpWindow->GetClientDimensions(&width, &height); DEBUG_PRINT(_L("Resize Window")); ResizeWindow(width, height); mpScene = new CPUTScene(); DEBUG_PRINT(_L("Load Scene")); // Load the scene if (CPUTFAILED(mpScene->LoadScene(SCENE_FILE))) { LOGI("Failed to Load Scene, try loading asset set individually"); CPUTAssetSet *pAssetSet = NULL; pAssetSet = pAssetLibrary->GetAssetSet( ASSET_SET_FILE ); mpScene->AddAssetSet(pAssetSet); pAssetSet->Release(); } LOGI("Loaded the scene"); // Get the camera. Get the first camera encountered in the scene or // if there are none, create a new one. unsigned int numAssets = mpScene->GetNumAssetSets(); for (unsigned int i = 0; i < numAssets; ++i) { CPUTAssetSet *pAssetSet = mpScene->GetAssetSet(i); if (pAssetSet->GetCameraCount() > 0) { mpCamera = pAssetSet->GetFirstCamera(); break; } } // Create the camera if (mpCamera == NULL) { mpCamera = new CPUTCamera(); pAssetLibrary->AddCamera( _L(""), _L("SampleStart Camera"), _L(""), mpCamera ); mpCamera->SetPosition( 0.0f, cameraY, 100.0f ); // Set the projection matrix for all of the cameras to match our window. // TODO: this should really be a viewport matrix. Otherwise, all cameras will have the same FOV and aspect ratio, etc instead of just viewport dimensions. mpCamera->SetAspectRatio(((float)width)/((float)height)); } mpCamera->SetFov(DegToRad(90.0)); // TODO: Fix converter's FOV bug (Maya generates cameras for which fbx reports garbage for fov) mpCamera->SetFarPlaneDistance(100000.0f); mpCamera->Update(); mpCameraController = new CPUTCameraControllerFPS(); mpCameraController->SetCamera(mpCamera); mpCameraController->SetLookSpeed(0.004f); mpCameraController->SetMoveSpeed(150.0f); // retrieve function pointer glDrawElementsInstancedEXT = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC) ( eglGetProcAddress( "glDrawElementsInstanced" ) ); if( glDrawElementsInstancedEXT == NULL ) { LOGE( "Failed to load extension pointer" ); } currentRowCount = NUM_ROWS / 1.5; currentColCount = NUM_COLUMNS; LOGI("Getting handles for materials"); // get handles to switch instancing / non instancing pAssetLibrary->PrintAssetLibrary(); supportMaterial = pAssetLibrary->GetMaterialByName("instanceV2/Material/concreteMultiMaterial.mtl"); techMaterial = pAssetLibrary->GetMaterialByName("instanceV2/Material/techALowMultiMataterial.mtl"); isInstanced = true; CPUTModel *pModel = pAssetLibrary->GetModelByName( _L( ".instangeGrptechALow" ) ); pModel->SetDrawModelCallBack((DrawModelCallBackFunc)drawCallback); pModel = pAssetLibrary->GetModelByName( _L( ".instangeGrpconcrete" ) ); pModel->SetDrawModelCallBack((DrawModelCallBackFunc)drawCallback); UINT supportCount = supportMaterial->GetMaterialEffectCount(); UINT techCount = techMaterial->GetMaterialEffectCount(); glFrontFace(GL_CW); UpdateMatrixBuffers(); }
//----------------------------------------------------------------------------- CPUTResult CPUTModel::LoadModelPayload(const cString &FileName) { CPUTResult result = CPUT_SUCCESS; CPUTFileSystem::CPUTOSifstream file(FileName, std::ios::in | std::ios::binary); ASSERT( !file.fail(), _L("CPUTModel::LoadModelPayload() - Could not find binary model file: ") + FileName ); // set up for mesh creation loop UINT meshIndex = 0; while(file.good() && !file.eof()) { // TODO: rearrange while() to avoid if(eof). Should perform only one branch per loop iteration, not two CPUTRawMeshData vertexFormatDesc; vertexFormatDesc.Read(file); if(file.eof()) { // TODO: Wtf? Why would we get here? We check eof at the top of loop. If it isn't eof there, why is it eof here? break; } ASSERT( meshIndex < mMeshCount, _L("Actual mesh count doesn't match stated mesh count")); // create the mesh. CPUTMesh *pMesh = mpMesh[meshIndex]; // always a triangle list (at this point) pMesh->SetMeshTopology(CPUT_TOPOLOGY_INDEXED_TRIANGLE_LIST); // get number of data blocks in the vertex element (pos,norm,uv,etc) CPUTBufferElementInfo *pVertexElementInfo = new CPUTBufferElementInfo[vertexFormatDesc.mFormatDescriptorCount]; // running count of each type of element int positionStreamCount=0; int normalStreamCount=0; int texCoordStreamCount=0; int tangentStreamCount=0; int binormalStreamCount=0; int colorStreamCount=0; int blendWeightStreamCount = 0; int blendIndexStreamCount = 0; int runningOffset = 0; for(UINT ii=0; ii<vertexFormatDesc.mFormatDescriptorCount; ii++) { // lookup the CPUT data type equivalent pVertexElementInfo[ii].mElementType = CPUT_FILE_ELEMENT_TYPE_TO_CPUT_TYPE_CONVERT(vertexFormatDesc.mpElements[ii].mVertexElementType); ASSERT((pVertexElementInfo[ii].mElementType !=CPUT_UNKNOWN ) , _L(".MDL file load error. This model file has an unknown data type in it's model data.")); // calculate the number of elements in this stream block (i.e. F32F32F32 = 3xF32) pVertexElementInfo[ii].mElementComponentCount = vertexFormatDesc.mpElements[ii].mElementSizeInBytes/CPUT_DATA_FORMAT_SIZE[pVertexElementInfo[ii].mElementType]; // store the size of each element type in bytes (i.e. 3xF32, each element = F32 = 4 bytes) pVertexElementInfo[ii].mElementSizeInBytes = vertexFormatDesc.mpElements[ii].mElementSizeInBytes; // store the number of elements (i.e. 3xF32, 3 elements) // calculate the offset from the first element of the stream - assumes all blocks appear in the vertex stream as the order that appears here pVertexElementInfo[ii].mOffset = runningOffset; runningOffset = runningOffset + pVertexElementInfo[ii].mElementSizeInBytes; // extract the name of stream pVertexElementInfo[ii].mpSemanticName = CPUT_VERTEX_ELEMENT_SEMANTIC_AS_STRING[ii]; //TODO: Calculate Opengl semantic index elsewhere switch(vertexFormatDesc.mpElements[ii].mVertexElementSemantic) { //FIXME - this isn't right, and needs to change for DX and OpenGL //Probably just need to move semantic bind point into OpenGL, or something. //Currently, TEXCOORD is the only semantic with multiples in common use. Adding //semantic index works provided addtional attributes (e.g. vertex color) are not //present case eCPUT_VERTEX_ELEMENT_SEMANTIC::CPUT_VERTEX_ELEMENT_POSITON: pVertexElementInfo[ii].mpSemanticName = "POSITION"; pVertexElementInfo[ii].mSemanticIndex = positionStreamCount++; pVertexElementInfo[ii].mBindPoint = CPUTSemanticBindPoint::POSITION; break; case eCPUT_VERTEX_ELEMENT_SEMANTIC::CPUT_VERTEX_ELEMENT_NORMAL: pVertexElementInfo[ii].mpSemanticName = "NORMAL"; pVertexElementInfo[ii].mSemanticIndex = normalStreamCount++; pVertexElementInfo[ii].mBindPoint = CPUTSemanticBindPoint::NORMAL; break; case eCPUT_VERTEX_ELEMENT_SEMANTIC::CPUT_VERTEX_ELEMENT_TEXTURECOORD: pVertexElementInfo[ii].mpSemanticName = "TEXCOORD"; pVertexElementInfo[ii].mSemanticIndex = texCoordStreamCount++; pVertexElementInfo[ii].mBindPoint = CPUTSemanticBindPoint::TEXCOORD + pVertexElementInfo[ii].mSemanticIndex; break; case eCPUT_VERTEX_ELEMENT_SEMANTIC::CPUT_VERTEX_ELEMENT_TANGENT: pVertexElementInfo[ii].mpSemanticName = "TANGENT"; pVertexElementInfo[ii].mSemanticIndex = tangentStreamCount++; pVertexElementInfo[ii].mBindPoint = CPUTSemanticBindPoint::TANGENT; break; case eCPUT_VERTEX_ELEMENT_SEMANTIC::CPUT_VERTEX_ELEMENT_BINORMAL: pVertexElementInfo[ii].mpSemanticName = "BINORMAL"; pVertexElementInfo[ii].mSemanticIndex = binormalStreamCount++; pVertexElementInfo[ii].mBindPoint = CPUTSemanticBindPoint::BINORMAL; break; case eCPUT_VERTEX_ELEMENT_SEMANTIC::CPUT_VERTEX_ELEMENT_VERTEXCOLOR: pVertexElementInfo[ii].mpSemanticName = "COLOR"; pVertexElementInfo[ii].mSemanticIndex = colorStreamCount++; pVertexElementInfo[ii].mBindPoint = CPUTSemanticBindPoint::COLOR; break; default: cString errorString = _L("Invalid vertex semantic in: '")+FileName+_L("'\n"); TRACE(errorString.c_str()); ASSERT(0, errorString); } } // Index buffer CPUTBufferElementInfo indexDataInfo; indexDataInfo.mElementType = (vertexFormatDesc.mIndexType == eCPUT_VERTEX_ELEMENT_TYPE::tUINT32) ? CPUT_U32 : CPUT_U16; indexDataInfo.mElementComponentCount = 1; indexDataInfo.mElementSizeInBytes = (vertexFormatDesc.mIndexType == eCPUT_VERTEX_ELEMENT_TYPE::tUINT32) ? sizeof(uint32_t) : sizeof(uint16_t); indexDataInfo.mOffset = 0; indexDataInfo.mSemanticIndex = 0; indexDataInfo.mpSemanticName = NULL; if( vertexFormatDesc.mVertexCount && vertexFormatDesc.mIndexCount ) { result = pMesh->CreateNativeResources( this, meshIndex, vertexFormatDesc.mFormatDescriptorCount, pVertexElementInfo, vertexFormatDesc.mVertexCount, (void*)vertexFormatDesc.mpVertices, &indexDataInfo, vertexFormatDesc.mIndexCount, vertexFormatDesc.mpIndices ); if(CPUTFAILED(result)) { return result; } } delete [] pVertexElementInfo; pVertexElementInfo = NULL; ++meshIndex; } ASSERT( file.eof(), _L("") ); // close file file.close(); return result; }
//---------------------------------------------------------------- CPUTResult CPUTConfigFile::LoadFile(const cString &szFilename) { // Load the file cString szCurrLine; CPUTConfigBlock *pCurrBlock = NULL; FILE *pFile = NULL; int nCurrBlock = 0; CPUTResult result = CPUTOSServices::GetOSServices()->OpenFile(szFilename, &pFile); if(CPUTFAILED(result)) { return result; } /* count the number of blocks */ while(1) { /* Find the block */ // Read lines until a '[' is found CPUTResult readResult = ReadLine(szCurrLine, pFile); if(readResult != CPUT_SUCCESS) break; size_t nOpenBracketIndex = szCurrLine.find_first_of(_L('[')); size_t nCloseBracketIndex = szCurrLine.find_last_of(_L(']')); if(nOpenBracketIndex != cString::npos && nCloseBracketIndex != cString::npos) { // This line is a valid block header mnBlockCount++; } }; /* Mtl files don't have headers, so we have to do some magic to support them */ if(mnBlockCount == 0) { mnBlockCount = 1; } fseek(pFile, 0, SEEK_SET); mpBlocks = new CPUTConfigBlock[mnBlockCount]; pCurrBlock = mpBlocks; /* Find the first block first */ while(1) { /* Find the block */ // Read lines until a '[' is found CPUTResult readResult = ReadLine(szCurrLine, pFile); if(readResult != CPUT_SUCCESS && szCurrLine == _L("")) { fclose(pFile); return CPUT_SUCCESS; } size_t nOpenBracketIndex = szCurrLine.find_first_of(_L('[')); size_t nCloseBracketIndex = szCurrLine.find_last_of(_L(']')); if(nOpenBracketIndex != cString::npos && nCloseBracketIndex != cString::npos) { // This line is a valid block header pCurrBlock = mpBlocks + nCurrBlock++; szCurrLine.erase(nCloseBracketIndex,1); pCurrBlock->mszName = szCurrLine.c_str()+1; /* size_t nSpaceIndex = szCurrLine.find_first_of(_L(' ')); cString szValue = szCurrLine.substr(nSpaceIndex+1); cString szName = szCurrLine.erase(nSpaceIndex, 1024); RemoveWhitespace(szValue); RemoveWhitespace(szName); pCurrBlock->mName.szName = szName; pCurrBlock->mName.szValue = szValue; */ std::transform(pCurrBlock->mszName.begin(), pCurrBlock->mszName.end(), pCurrBlock->mszName.begin(), ::tolower); } else if(szCurrLine != _L("")) { // It's a value if(pCurrBlock == NULL) { continue; } size_t nEqualsIndex = szCurrLine.find_first_of(_L('=')); if(nEqualsIndex == cString::npos) { bool dup = false; // No value, just a key, save it anyway for(int ii=0;ii<pCurrBlock->mnValueCount;++ii) { if(!pCurrBlock->mpValues[ii].szName.compare(szCurrLine)) { dup = true; break; } } if(!dup) { pCurrBlock->mpValues[pCurrBlock->mnValueCount].szName = szCurrLine; pCurrBlock->mnValueCount++; } } else { cString szValue = szCurrLine.substr(nEqualsIndex+1); cString szName = szCurrLine.erase(nEqualsIndex, 1024); RemoveWhitespace(szValue); RemoveWhitespace(szName); std::transform(szName.begin(), szName.end(), szName.begin(), ::tolower); bool dup = false; for(int ii=0;ii<pCurrBlock->mnValueCount;++ii) { if(!pCurrBlock->mpValues[ii].szName.compare(szName)) { dup = true; break; } } if(!dup) { pCurrBlock->mpValues[pCurrBlock->mnValueCount].szValue = szValue; pCurrBlock->mpValues[pCurrBlock->mnValueCount].szName = szName; pCurrBlock->mnValueCount++; } } } }; fclose(pFile); return CPUT_SUCCESS; }
//----------------------------------------------------------------------------- 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; }
// Register all shared resources //-------------------------------------------------------------------------------- CPUTResult CPUTButton::RegisterStaticResources(GLuint m_shaderID, GLuint modelViewMatrixID) { CPUTResult result; if(m_Registered) return CPUT_SUCCESS; // store shader ID and needed matrix ID's m_shaderProgram = m_shaderID; m_ModelViewMatrixID = glGetUniformLocation(m_shaderProgram, "ModelViewMatrix"); m_textureUniformLocation = glGetUniformLocation(m_shaderProgram, "diffuseTexture"); glUseProgram(m_shaderProgram); // load all the idle+active button images const int numberOfImages = CPUT_NUM_IMAGES_IN_BUTTON; cString pImageFilenames[numberOfImages] = { _L(".//controls//button//button-lt.png"), _L(".//controls//button//button-lm.png"), _L(".//controls//button//button-lb.png"), _L(".//controls//button//button-mt.png"), _L(".//controls//button//button-mm.png"), _L(".//controls//button//button-mb.png"), _L(".//controls//button//button-rt.png"), _L(".//controls//button//button-rm.png"), _L(".//controls//button//button-rb.png"), }; // load each of the 9 quadrants of a button CPUTOSServices* pServices = CPUTOSServices::GetOSServices(); // load each of the 9 quadrants of a button CPUTTextureLoader* pTextureLoader = CPUTTextureLoader::GetTextureLoader(); for(int i=0; i<numberOfImages; i++) { result = pTextureLoader->LoadAndRegisterTexture(pImageFilenames[i], m_pButtonIdleTextureList[i], (GLuint&)m_pButtonIdleImageSizeList[i].width, (GLuint&)m_pButtonIdleImageSizeList[i].height, true, CPUT_PATH_SEARCH_RESOURCE_DIRECTORY); if(CPUTFAILED(result)) { return result; } // calculate the 'border' sizes if(i<3) { if(m_SmallestLeftSizeIdle < m_pButtonIdleImageSizeList[i].width) { m_SmallestLeftSizeIdle = m_pButtonIdleImageSizeList[i].width; } } if(i>5) { if(m_SmallestRightSizeIdle < m_pButtonIdleImageSizeList[i].width) { m_SmallestRightSizeIdle = m_pButtonIdleImageSizeList[i].width; } } if( (0==i) || (3==i) || (6==i) ) { if(m_SmallestTopSizeIdle < m_pButtonIdleImageSizeList[i].height) { m_SmallestTopSizeIdle = m_pButtonIdleImageSizeList[i].height; } } if( (2==i) || (5==i) || (8==i) ) { if(m_SmallestBottomSizeIdle < m_pButtonIdleImageSizeList[i].height) { m_SmallestBottomSizeIdle = m_pButtonIdleImageSizeList[i].height; } } } // Load the 'pressed' button state images cString pPressedImageFilenames[numberOfImages] = { _L(".//controls//button//button-pressed-lt.png"), _L(".//controls//button//button-pressed-lm.png"), _L(".//controls//button//button-pressed-lb.png"), _L(".//controls//button//button-pressed-mt.png"), _L(".//controls//button//button-pressed-mm.png"), _L(".//controls//button//button-pressed-mb.png"), _L(".//controls//button//button-pressed-rt.png"), _L(".//controls//button//button-pressed-rm.png"), _L(".//controls//button//button-pressed-rb.png"), }; // load each of the 9 quadrants of button for(int i=0; i<numberOfImages; i++) { result = pTextureLoader->LoadAndRegisterTexture(pPressedImageFilenames[i], m_pButtonPressedTextureList[i], (GLuint&)m_pButtonPressedImageSizeList[i].width, (GLuint&)m_pButtonPressedImageSizeList[i].height, true, CPUT_PATH_SEARCH_RESOURCE_DIRECTORY); if(CPUTFAILED(result)) { return result; } // calculate the 'border' sizes if(i<3) { if(m_SmallestLeftSizePressed < m_pButtonPressedImageSizeList[i].width) { m_SmallestLeftSizePressed = m_pButtonPressedImageSizeList[i].width; } } if(i>5) { if(m_SmallestRightSizePressed < m_pButtonPressedImageSizeList[i].width) { m_SmallestRightSizePressed = m_pButtonPressedImageSizeList[i].width; } } if( (0==i) || (3==i) || (6==i) ) { if(m_SmallestTopSizePressed < m_pButtonPressedImageSizeList[i].height) { m_SmallestTopSizePressed = m_pButtonPressedImageSizeList[i].height; } } if( (2==i) || (5==i) || (8==i) ) { if(m_SmallestBottomSizePressed < m_pButtonPressedImageSizeList[i].height) { m_SmallestBottomSizePressed = m_pButtonPressedImageSizeList[i].height; } } } m_Registered = true; return CPUT_SUCCESS; }
// 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; }
// Load and register all the resources needed by the GUI system //----------------------------------------------------------------------------- CPUTResult CPUTGuiControllerOGL::RegisterGUIResources() { CPUTResult result = CPUT_SUCCESS; cString name = _L("$cbGUIValues"); mpConstantBufferVS = new CPUTBufferOGL(name); GLuint id = mpConstantBufferVS->GetBufferID(); GL_CHECK(glBindBuffer(GL_UNIFORM_BUFFER, mpConstantBufferVS->GetBufferID())); GL_CHECK(glBufferData(GL_UNIFORM_BUFFER, sizeof(GUIConstantBufferVS), NULL, GL_DYNAMIC_DRAW)); // NULL to just init buffer size GL_CHECK(glBindBuffer(GL_UNIFORM_BUFFER, 0)); DEBUG_PRINT(_L("bind gui constant buffers: %d\n"), id); // GL_CHECK(glBindBufferBase(GL_UNIFORM_BUFFER, mpConstantBufferVS->GetBufferID(), mpConstantBufferVS->GetBufferID())); DEBUG_PRINT(_L("completed bind gui constant buffers\n")); CPUTAssetLibrary::GetAssetLibrary()->AddConstantBuffer(_L(""), name, _L(""), mpConstantBufferVS); CPUTAssetLibraryOGL *pAssetLibrary = NULL; pAssetLibrary = (CPUTAssetLibraryOGL*)CPUTAssetLibraryOGL::GetAssetLibrary(); // Get the resource directory cString mediaDirectory; mediaDirectory = pAssetLibrary->GetMediaDirectoryName(); mpTextMaterial = pAssetLibrary->GetMaterial(_L("guimaterial_text")); mpControlMaterial = pAssetLibrary->GetMaterial(_L("guimaterial_control")); CPUTBufferElementInfo pGUIVertex[3] = { { "POSITION", 0, 0, CPUT_F32, 3, 3*sizeof(float), 0 }, { "TEXCOORD", 0, 1, CPUT_F32, 2, 2*sizeof(float), 3*sizeof(float)}, { "COLOR", 0, 2, CPUT_F32, 4, 4*sizeof(float), 5*sizeof(float)}, }; unsigned int maxSize = std::max(CPUT_GUI_BUFFER_STRING_SIZE, CPUT_GUI_BUFFER_SIZE); maxSize = std::max(maxSize, CPUT_GUI_VERTEX_BUFFER_SIZE); maxSize *= sizeof( CPUTGUIVertex ); mpUberBuffer = new CPUTMeshOGL(); mpUberBuffer->CreateNativeResources(NULL, 0, 3, pGUIVertex, CPUT_GUI_VERTEX_BUFFER_SIZE, mpMirrorBuffer, NULL, 0, NULL); mpTextUberBuffer = new CPUTMeshOGL(); mpTextUberBuffer->CreateNativeResources(NULL, 0, 3, pGUIVertex, CPUT_GUI_VERTEX_BUFFER_SIZE, NULL, NULL, 0, NULL); mpFocusedControlBuffer = new CPUTMeshOGL(); mpFocusedControlBuffer->CreateNativeResources(NULL, 0, 3, pGUIVertex, CPUT_GUI_VERTEX_BUFFER_SIZE, mpFocusedControlMirrorBuffer, NULL, 0, NULL); mpFocusedControlTextBuffer = new CPUTMeshOGL(); mpFocusedControlTextBuffer->CreateNativeResources(NULL, 0, 3, pGUIVertex, CPUT_GUI_VERTEX_BUFFER_SIZE, mpFocusedControlTextMirrorBuffer, NULL, 0, NULL); // 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; } DEBUG_PRINT(_L("Exit RegisterGUIResources()\n")); return CPUT_SUCCESS; }
// Create a window context //----------------------------------------------------------------------------- CPUTResult CPUT_OGL::CPUTCreateWindowAndContext(const cString WindowTitle, CPUTWindowCreationParams windowParams) { CPUTResult result = CPUT_SUCCESS; HEAPCHECK; // We shouldn't destroy old window if it already exist, // Framework user should do this by himself to be aware // of what he is doing. if( mpWindow ) { return CPUT_ERROR_WINDOW_ALREADY_EXISTS; } result = MakeWindow(WindowTitle, windowParams); if(CPUTFAILED(result)) { return result; } HEAPCHECK; // create the GL context result = CreateOGLContext(windowParams.deviceParams); if(CPUTFAILED(result)) { return result; } HEAPCHECK; result = CreateContext(); CPUTRenderStateBlock *pBlock = new CPUTRenderStateBlockOGL(); CPUTRenderStateBlock::SetDefaultRenderStateBlock( pBlock ); cString name = _L("$cbPerFrameValues"); mpPerFrameConstantBuffer = new CPUTBufferOGL(name); GLuint id = mpPerFrameConstantBuffer->GetBufferID(); #ifndef CPUT_FOR_OGLES2 GL_CHECK(glBindBuffer(GL_UNIFORM_BUFFER, mpPerFrameConstantBuffer->GetBufferID())); GL_CHECK(glBufferData(GL_UNIFORM_BUFFER, sizeof(CPUTFrameConstantBuffer), NULL, GL_DYNAMIC_DRAW)); // NULL to just init buffer size DEBUG_PRINT(_L("bind per frame buffer buffer %d\n"), id); //FIXME: constant buffer binding GL_CHECK(ES3_COMPAT(glBindBufferBase(GL_UNIFORM_BUFFER, id, id))); DEBUG_PRINT(_L("completed - bind buffer %d\n"), id); GL_CHECK(glBindBuffer(GL_UNIFORM_BUFFER, 0)); #else #warning "Need to do something with uniform buffers here" #endif CPUTAssetLibrary::GetAssetLibrary()->AddConstantBuffer(_L(""), name, _L(""), mpPerFrameConstantBuffer); name = _L("$cbPerModelValues"); mpPerModelConstantBuffer = new CPUTBufferOGL(name, GL_UNIFORM_BUFFER, GL_DYNAMIC_DRAW, sizeof(CPUTModelConstantBuffer), NULL); id = mpPerModelConstantBuffer->GetBufferID(); #ifndef CPUT_FOR_OGLES2 DEBUG_PRINT(_L("Bind per model values %d"), id); GL_CHECK(ES3_COMPAT(glBindBufferBase(GL_UNIFORM_BUFFER, id, id))); DEBUG_PRINT(_L("Completed bind per model values")); GL_CHECK(glBindBuffer(GL_UNIFORM_BUFFER, 0)); #else #warning "Need to do something with uniform buffers here" #endif CPUTAssetLibrary::GetAssetLibrary()->AddConstantBuffer(_L(""), name, _L(""), mpPerModelConstantBuffer); name = _L("$cbGUIConstants"); CPUTBuffer* pBuffer = new CPUTBufferOGL(name, GL_UNIFORM_BUFFER, GL_DYNAMIC_DRAW, sizeof(GUIConstants), NULL); CPUTAssetLibrary::GetAssetLibrary()->AddConstantBuffer(_L(""), name, _L(""), pBuffer); SAFE_RELEASE(pBuffer); // Add our programatic (and global) material parameters CPUTMaterial::mGlobalProperties.AddValue( _L("cbPerFrameValues"), _L("$cbPerFrameValues") ); CPUTMaterial::mGlobalProperties.AddValue( _L("cbPerModelValues"), _L("$cbPerModelValues") ); CPUTMaterial::mGlobalProperties.AddValue( _L("cbGUIValues"), _L("$cbGUIValues") ); HEAPCHECK; // Trigger a post-create user callback event Create(); HEAPCHECK; // // Start the timer after everything is initialized and assets have been loaded // mpTimer->StartTimer(); int x,y,width,height; mpWindow->GetClientDimensions(&x, &y, &width, &height); ResizeWindow(width,height); return result; }
// Register the buffer with OpenGL //----------------------------------------------------------------------------- CPUTResult CPUTMesh::Register(void** ppLayout) { CPUTResult result; result = UnRegister(); if(CPUTFAILED(result)) return result; int NumberOfVertexStreamsInThisMesh = GetVertexStreamCount(); int NumberOfTotalStreamsInThisMesh=NumberOfVertexStreamsInThisMesh; // if indexed, we need one additional vbo if(IsIndexedMesh()) NumberOfTotalStreamsInThisMesh++; // allocate the variables we'll need for this operation //m_ppDXBufferObjects = new ID3D11Buffer*[NumberOfVertexStreamsInThisMesh]; //D3D11_INPUT_ELEMENT_DESC* layout = new D3D11_INPUT_ELEMENT_DESC[ NumberOfVertexStreamsInThisMesh ]; //m_pStreamStrides = new UINT[NumberOfVertexStreamsInThisMesh]; //m_pStreamOffsets = new UINT[NumberOfVertexStreamsInThisMesh]; // generate 1 VAO (vertex array object) to hold all these streams glGenVertexArrays(1, &m_VertexArrayObjectID); // Bind VAO so you can glBindVertexArray(m_VertexArrayObjectID); // generate 'stream' slots m_pVertexBufferObjectIDs = new GLuint[NumberOfTotalStreamsInThisMesh]; glGenBuffers(NumberOfTotalStreamsInThisMesh, m_pVertexBufferObjectIDs); for(int j=0; j<NumberOfVertexStreamsInThisMesh; j++) { // register each stream of each mesh, storing it's DX object pointer CPUTMeshStream* stream = GetVertexStream(j); if(CPUT_STREAM_ELEMENT_LAYOUT_UNIFORM == stream->GetStreamElementLayoutType()) { // non-indexed CPUTMeshStreamUniform* uniformStream = (CPUTMeshStreamUniform*) stream; // deterimine the number of components per generic vertex attribute. Must be 1, 2, 3, or 4. // bind this stream's data GLenum glDataType; void* pData = NULL; glDataType = ConvertCPUTFormatToGL(uniformStream->GetDataFormatElementType()); glBindBuffer(GL_ARRAY_BUFFER, m_pVertexBufferObjectIDs[j]); uniformStream->Lock(&pData); glBufferData(GL_ARRAY_BUFFER, uniformStream->GetDataElementBlockSize() * uniformStream->GetNumberVerticies(), pData, GL_STATIC_DRAW); uniformStream->Unlock(); glVertexAttribPointer((GLuint)j, uniformStream->GetNumberDataFormatElements(), glDataType, GL_FALSE, 0, 0); glEnableVertexAttribArray(j); // slot number // Store the number of verticies // TODO: BUG - what if there diff number of elements/stream? m_NumberOfVerticies = uniformStream->GetNumberVerticies(); } else if(CPUT_STREAM_ELEMENT_LAYOUT_FLEXIBLE == stream->GetStreamElementLayoutType()) { // TODO: fill this out with flexible streams } else { // TODO: ERROR } } // register any index stream (if there is one) if(IsIndexedMesh()) { CPUTMeshStream* stream = GetIndexStream(); if(CPUT_STREAM_ELEMENT_LAYOUT_UNIFORM == stream->GetStreamElementLayoutType()) { void* pData = NULL; CPUTMeshStreamUniform* uniformStream = (CPUTMeshStreamUniform*) stream; // bind index stream and fill data // last m_pVertexBufferObjectID[] is always the Index buffer (if there is one) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_pVertexBufferObjectIDs[NumberOfTotalStreamsInThisMesh-1]); uniformStream->Lock(&pData); glBufferData(GL_ELEMENT_ARRAY_BUFFER, uniformStream->GetDataElementBlockSize() * uniformStream->GetNumberVerticies(), pData, GL_STATIC_DRAW); uniformStream->Unlock(); // this is an indexed mesh, so draw as such m_MeshDrawingType = CPUT_STREAM_TYPE_INDEX; m_NumberOfVerticies = uniformStream->GetNumberVerticies(); } } // unbind what we were doing // todo: would be better to restore the user's state instead of just blast over it with 0 glBindVertexArray(0); return CPUT_SUCCESS; }
// Force resize of the button to given dimensions //-------------------------------------------------------------------------------- CPUTResult CPUTButton::Resize(int width, int height) { CPUTResult result = CPUT_SUCCESS; int safeWidth, safeHeight; switch(m_ControlState) { case CPUT_CONTROL_ACTIVE: safeWidth = m_ButtonDimensions.x + m_SmallestLeftSizeIdle + m_SmallestRightSizeIdle + 1; safeHeight = m_ButtonDimensions.y + m_SmallestTopSizeIdle + m_SmallestBottomSizeIdle + 1; break; case CPUT_CONTROL_INACTIVE: assert(false); // todo: error! unknown state - using idle dimensions as a default safeWidth = m_ButtonDimensions.x + m_SmallestLeftSizeIdle + m_SmallestRightSizeIdle + 1; safeHeight = m_ButtonDimensions.y + m_SmallestTopSizeIdle + m_SmallestBottomSizeIdle + 1; break; case CPUT_CONTROL_PRESSED: safeWidth = m_ButtonDimensions.x + m_SmallestLeftSizePressed + m_SmallestRightSizePressed + 1; safeHeight = m_ButtonDimensions.y + m_SmallestTopSizePressed + m_SmallestBottomSizePressed + 1; break; default: assert(false); // todo: error! unknown state - using idle dimensions as a default safeWidth = m_ButtonDimensions.x + m_SmallestLeftSizeIdle + m_SmallestRightSizeIdle + 1; safeHeight = m_ButtonDimensions.y + m_SmallestTopSizeIdle + m_SmallestBottomSizeIdle + 1; } // if the user's dimensions are smaller than the smallest 'safe' dimensions of the button, // use the safe ones instead. if(safeWidth > width) width = safeWidth; if(safeHeight > height) height = safeHeight; // add some padding for nicety width += CPUT_BUTTON_TEXT_BORDER_PADDING_X; height += CPUT_BUTTON_TEXT_BORDER_PADDING_Y; if( (m_ButtonDimensions.width != width) || (m_ButtonDimensions.height != height) ) { // store the new dimensions m_ButtonDimensions.width = width; m_ButtonDimensions.height = height; // calculate the pieces we'll need to rebuild int middleWidth = width - m_SmallestLeftSizeIdle - m_SmallestRightSizeIdle; int middleHeight = height - m_SmallestTopSizeIdle - m_SmallestBottomSizeIdle; // create a new quads with the correct size // Idle button quads //glDeleteBuffers(2, m_pIdleVertexBufferObjectIDs[1*2]); //glDeleteVertexArrays(1, &m_pIdleVertexArrayObjectIDs[1]); result = RegisterQuad(m_pButtonIdleSizeList[1].width, middleHeight, m_pIdleVertexArrayObjectIDs[1], &m_pIdleVertexBufferObjectIDs[1*2]); m_pButtonIdleSizeList[1].height = middleHeight; if(CPUTFAILED(result)) return result; result = RegisterQuad(middleWidth, m_pButtonIdleSizeList[3].height, m_pIdleVertexArrayObjectIDs[3], &m_pIdleVertexBufferObjectIDs[3*2]); m_pButtonIdleSizeList[3].width = middleWidth; if(CPUTFAILED(result)) return result; result = RegisterQuad(middleWidth, middleHeight, m_pIdleVertexArrayObjectIDs[4], &m_pIdleVertexBufferObjectIDs[4*2]); m_pButtonIdleSizeList[4].width = middleWidth; m_pButtonIdleSizeList[4].height = middleHeight; if(CPUTFAILED(result)) return result; result = RegisterQuad(middleWidth, m_pButtonIdleSizeList[5].height, m_pIdleVertexArrayObjectIDs[5], &m_pIdleVertexBufferObjectIDs[5*2]); m_pButtonIdleSizeList[5].width = middleWidth; if(CPUTFAILED(result)) return result; result = RegisterQuad(m_pButtonIdleSizeList[7].width, middleHeight, m_pIdleVertexArrayObjectIDs[7], &m_pIdleVertexBufferObjectIDs[7*2]); m_pButtonIdleSizeList[7].height = middleHeight; if(CPUTFAILED(result)) return result; // Pressed button quads result = RegisterQuad(m_pButtonPressedSizeList[1].width, middleHeight, m_pPressedVertexArrayObjectIDs[1], &m_pPressedVertexBufferObjectIDs[1*2]); m_pButtonPressedSizeList[1].height = middleHeight; if(CPUTFAILED(result)) return result; result = RegisterQuad(middleWidth, m_pButtonPressedSizeList[3].height, m_pPressedVertexArrayObjectIDs[3], &m_pPressedVertexBufferObjectIDs[3*2]); m_pButtonPressedSizeList[3].width = middleWidth; if(CPUTFAILED(result)) return result; result = RegisterQuad(middleWidth, middleHeight, m_pPressedVertexArrayObjectIDs[4], &m_pPressedVertexBufferObjectIDs[4*2]); m_pButtonPressedSizeList[4].width = middleWidth; m_pButtonPressedSizeList[4].height = middleHeight; if(CPUTFAILED(result)) return result; result = RegisterQuad(middleWidth, m_pButtonPressedSizeList[5].height, m_pPressedVertexArrayObjectIDs[5], &m_pPressedVertexBufferObjectIDs[5*2]); m_pButtonPressedSizeList[5].width = middleWidth; if(CPUTFAILED(result)) return result; result = RegisterQuad(m_pButtonPressedSizeList[7].width, middleHeight, m_pPressedVertexArrayObjectIDs[7], &m_pPressedVertexBufferObjectIDs[7*2]); m_pButtonPressedSizeList[7].height = middleHeight; if(CPUTFAILED(result)) return result; } return result; }
//----------------------------------------------------------------------------- CPUTResult CPUTModel::LoadModelPayload(const cString &File) { CPUTResult result = CPUT_SUCCESS; std::ifstream file(File.c_str(), std::ios::in | std::ios::binary); ASSERT( !file.fail(), _L("CPUTModelDX11::LoadModelPayload() - Could not find binary model file: ") + File ); // set up for mesh creation loop UINT meshIndex = 0; while(file.good() && !file.eof()) { // TODO: rearrange while() to avoid if(eof). Should perform only one branch per loop iteration, not two CPUTRawMeshData vertexFormatDesc; vertexFormatDesc.Read(file); if(file.eof()) { // TODO: Wtf? Why would we get here? We check eof at the top of loop. If it isn't eof there, why is it eof here? break; } ASSERT( meshIndex < mMeshCount, _L("Actual mesh count doesn't match stated mesh count")); // create the mesh. CPUTMesh *pMesh = mpMesh[meshIndex]; // always a triangle list (at this point) pMesh->SetMeshTopology(CPUT_TOPOLOGY_INDEXED_TRIANGLE_LIST); // get number of data blocks in the vertex element (pos,norm,uv,etc) // YUCK! TODO: Use fixed-size array of elements CPUTBufferInfo *pVertexElementInfo = new CPUTBufferInfo[vertexFormatDesc.mFormatDescriptorCount]; // pMesh->SetBounds(vertexFormatDesc.mBboxCenter, vertexFormatDesc.mBboxHalf); // running count of each type of element int positionStreamCount=0; int normalStreamCount=0; int texCoordStreamCount=0; int tangentStreamCount=0; int binormalStreamCount=0; int colorStreamCount=0; int RunningOffset = 0; for(UINT ii=0; ii<vertexFormatDesc.mFormatDescriptorCount; ii++) { // lookup the CPUT data type equivalent pVertexElementInfo[ii].mElementType = CPUT_FILE_ELEMENT_TYPE_TO_CPUT_TYPE_CONVERT[vertexFormatDesc.mpElements[ii].mVertexElementType]; ASSERT((pVertexElementInfo[ii].mElementType !=CPUT_UNKNOWN ) , _L(".MDL file load error. This model file has an unknown data type in it's model data.")); // calculate the number of elements in this stream block (i.e. F32F32F32 = 3xF32) pVertexElementInfo[ii].mElementComponentCount = vertexFormatDesc.mpElements[ii].mElementSizeInBytes/CPUT_DATA_FORMAT_SIZE[pVertexElementInfo[ii].mElementType]; // store the size of each element type in bytes (i.e. 3xF32, each element = F32 = 4 bytes) pVertexElementInfo[ii].mElementSizeInBytes = vertexFormatDesc.mpElements[ii].mElementSizeInBytes; // store the number of elements (i.e. 3xF32, 3 elements) pVertexElementInfo[ii].mElementCount = vertexFormatDesc.mVertexCount; // calculate the offset from the first element of the stream - assumes all blocks appear in the vertex stream as the order that appears here pVertexElementInfo[ii].mOffset = RunningOffset; RunningOffset = RunningOffset + pVertexElementInfo[ii].mElementSizeInBytes; // extract the name of stream pVertexElementInfo[ii].mpSemanticName = CPUT_VERTEX_ELEMENT_SEMANTIC_AS_STRING[ii]; switch(vertexFormatDesc.mpElements[ii].mVertexElementSemantic) { case CPUT_VERTEX_ELEMENT_POSITON: pVertexElementInfo[ii].mpSemanticName = "POSITION"; pVertexElementInfo[ii].mSemanticIndex = positionStreamCount++; break; case CPUT_VERTEX_ELEMENT_NORMAL: pVertexElementInfo[ii].mpSemanticName = "NORMAL"; pVertexElementInfo[ii].mSemanticIndex = normalStreamCount++; break; case CPUT_VERTEX_ELEMENT_TEXTURECOORD: pVertexElementInfo[ii].mpSemanticName = "TEXCOORD"; pVertexElementInfo[ii].mSemanticIndex = texCoordStreamCount++; break; case CPUT_VERTEX_ELEMENT_TANGENT: pVertexElementInfo[ii].mpSemanticName = "TANGENT"; pVertexElementInfo[ii].mSemanticIndex = tangentStreamCount++; break; case CPUT_VERTEX_ELEMENT_BINORMAL: pVertexElementInfo[ii].mpSemanticName = "BINORMAL"; pVertexElementInfo[ii].mSemanticIndex = binormalStreamCount++; break; case CPUT_VERTEX_ELEMENT_VERTEXCOLOR: pVertexElementInfo[ii].mpSemanticName = "COLOR"; pVertexElementInfo[ii].mSemanticIndex = colorStreamCount++; break; default: cString errorString = _L("Invalid vertex semantic in: '")+File+_L("'\n"); TRACE(errorString.c_str()); ASSERT(0, errorString); } } // Index buffer CPUTBufferInfo indexDataInfo; indexDataInfo.mElementType = (vertexFormatDesc.mIndexType == tUINT32) ? CPUT_U32 : CPUT_U16; indexDataInfo.mElementComponentCount = 1; indexDataInfo.mElementSizeInBytes = (vertexFormatDesc.mIndexType == tUINT32) ? sizeof(UINT32) : sizeof(UINT16); indexDataInfo.mElementCount = vertexFormatDesc.mIndexCount; indexDataInfo.mOffset = 0; indexDataInfo.mSemanticIndex = 0; indexDataInfo.mpSemanticName = NULL; if( pVertexElementInfo->mElementCount && indexDataInfo.mElementCount ) { result = pMesh->CreateNativeResources( this, meshIndex, vertexFormatDesc.mFormatDescriptorCount, pVertexElementInfo, (void*)vertexFormatDesc.mpVertices, &indexDataInfo, &vertexFormatDesc.mpIndices[0] ); if(CPUTFAILED(result)) { return result; } // CC added result = pMesh->ExtractVerticesandIndices(); if(CPUTFAILED(result)) { return result; } // CC added ends } delete [] pVertexElementInfo; pVertexElementInfo = NULL; ++meshIndex; } ASSERT( file.eof(), _L("") ); // close file file.close(); return result; }
// 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 CPUTMaterialEffectOGL::LoadMaterialEffect( const cString &fileName, const CPUTModel *pModel, int meshIndex, const char **pShaderMacros, int externalCount, cString *pExternalName, float4 *pExternals, int *pExternalOffset, int *pExternalSize ){ CPUTResult result = CPUT_SUCCESS; CPUTConfigEntry *pValue; mMaterialName = fileName; mMaterialNameHash = CPUTComputeHash( mMaterialName ); // Open/parse the file CPUTConfigFile file; result = file.LoadFile(fileName); if(CPUTFAILED(result)) { return result; } // Make a local copy of all the parameters CPUTConfigBlock *pBlock = file.GetBlock(0); ASSERT( pBlock, _L("Error getting parameter block") ); if( !pBlock ) { return CPUT_ERROR_PARAMETER_BLOCK_NOT_FOUND; } mConfigBlock = *pBlock; // get necessary device and AssetLibrary pointers //ID3D11Device *pD3dDevice = CPUT_DX11::GetDevice(); CPUTAssetLibraryOGL *pAssetLibrary = (CPUTAssetLibraryOGL*)CPUTAssetLibrary::GetAssetLibrary(); { CPUTConfigEntry *pEntryPointName, *pProfileName; int numFiles = 0; cString pBase = _L("VertexShaderFileOGL_"); cString pName = pBase + to_cString(numFiles+1); std::vector<cString> filenames; while (mConfigBlock.GetValueByName(pName)->IsValid()) { filenames.push_back(mConfigBlock.GetValueByName(pName)->ValueAsString()); numFiles++; pName = pBase + to_cString(numFiles+1); } if(numFiles > 0) { pEntryPointName = mConfigBlock.GetValueByName(_L("VertexShaderMain")); pProfileName = mConfigBlock.GetValueByName(_L("VertexShaderProfile")); pAssetLibrary->GetVertexShader( filenames, /*pD3dDevice,*/ _L("VertexShaderMain"), pProfileName->ValueAsString(), &mpVertexShader, false, (CPUT_SHADER_MACRO*)pShaderMacros ); } } #ifdef CPUT_SUPPORT_TESSELLATION { int numFiles = 0; cString pBase = _L("ControlShaderFileOGL_"); cString pName = pBase + to_cString(numFiles+1); std::vector<cString> filenames; while (mConfigBlock.GetValueByName(pName)->IsValid()) { filenames.push_back(mConfigBlock.GetValueByName(pName)->ValueAsString()); numFiles++; pName = pBase + to_cString(numFiles+1); } if(numFiles > 0) { pAssetLibrary->GetHullShader( filenames, /* pD3dDevice,*/ _L("ControlShaderMain"), _L(""), &mpControlShader, false, (CPUT_SHADER_MACRO*)pShaderMacros ); } } { int numFiles = 0; cString pBase = _L("EvaluationShaderFileOGL_"); cString pName = pBase + to_cString(numFiles+1); std::vector<cString> filenames; while (mConfigBlock.GetValueByName(pName)->IsValid()) { filenames.push_back(mConfigBlock.GetValueByName(pName)->ValueAsString()); numFiles++; pName = pBase + to_cString(numFiles+1); } if(numFiles > 0) { pAssetLibrary->GetDomainShader( filenames, /* pD3dDevice,*/ _L("EvaluationShaderMain"), _L(""), &mpEvaluationShader, false, (CPUT_SHADER_MACRO*)pShaderMacros ); } } #endif { int numFiles = 0; cString pBase = _L("GeometryShaderFileOGL_"); cString pName = pBase + to_cString(numFiles+1); std::vector<cString> filenames; while (mConfigBlock.GetValueByName(pName)->IsValid()) { filenames.push_back(mConfigBlock.GetValueByName(pName)->ValueAsString()); numFiles++; pName = pBase + to_cString(numFiles+1); } if(numFiles > 0) { pAssetLibrary->GetGeometryShader( filenames, /* pD3dDevice,*/ _L("GeometryShaderMain"), _L(""), &mpGeometryShader, false, (CPUT_SHADER_MACRO*)pShaderMacros ); } } // load and store the pixel shader if it was specified { int numFiles = 0; cString pBase = _L("FragmentShaderFileOGL_"); cString pName = pBase + to_cString(numFiles+1); std::vector<cString> filenames; while (mConfigBlock.GetValueByName(pName)->IsValid()) { filenames.push_back(mConfigBlock.GetValueByName(pName)->ValueAsString()); numFiles++; pName = pBase + to_cString(numFiles+1); } if(numFiles > 0) { pAssetLibrary->GetPixelShader( filenames, /* pD3dDevice,*/ _L("FragmentShaderMain"), //mConfigBlock.GetValueByName(_L("FragmentShaderMain"))->ValueAsString(), mConfigBlock.GetValueByName(_L("FragmentShaderProfile"))->ValueAsString(), &mpFragmentShader, false, (CPUT_SHADER_MACRO*)pShaderMacros ); } } // load and store the render state file if it was specified pValue = mConfigBlock.GetValueByName(_L("RenderStateFile")); if( pValue->IsValid() ) { mpRenderStateBlock = pAssetLibrary->GetRenderStateBlock(pValue->ValueAsString()); } int IsLinked; char *shaderProgramInfoLog; int maxLength; mShaderProgram = glCreateProgram(); // Attach our shaders to our program // Attach our shaders to our program if (mpVertexShader) { GL_CHECK(glAttachShader(mShaderProgram, mpVertexShader->GetShaderID())); } if (mpFragmentShader) { GL_CHECK(glAttachShader(mShaderProgram, mpFragmentShader->GetShaderID())); } if (mpControlShader) { GL_CHECK(glAttachShader(mShaderProgram, mpControlShader->GetShaderID())); } if (mpEvaluationShader) { GL_CHECK(glAttachShader(mShaderProgram, mpEvaluationShader->GetShaderID())); } if (mpGeometryShader) { GL_CHECK(glAttachShader(mShaderProgram, mpGeometryShader->GetShaderID())); } /* GL_CHECK(glBindAttribLocation(mShaderProgram, 0, "in_Position")); GL_CHECK(glBindAttribLocation(mShaderProgram, 1, "inNormal")); GL_CHECK(glBindAttribLocation(mShaderProgram, 2, "inBinormal")); GL_CHECK(glBindAttribLocation(mShaderProgram, 3, "inTangent")); GL_CHECK(glBindAttribLocation(mShaderProgram, 4, "inTex")); */ // Link our program // At this stage, the vertex and fragment programs are inspected, optimized and a binary code is generated for the shader. // The binary code is uploaded to the GPU, if there is no error. GL_CHECK(glLinkProgram(mShaderProgram)); // Again, we must check and make sure that it linked. If it fails, it would mean either there is a mismatch between the vertex // and fragment shaders. It might be that you have surpassed your GPU's abilities. Perhaps too many ALU operations or // too many texel fetch instructions or too many interpolators or dynamic loops. GL_CHECK(glGetProgramiv(mShaderProgram, GL_LINK_STATUS, (int *)&IsLinked)); if(IsLinked == false) { // Noticed that glGetProgramiv is used to get the length for a shader program, not glGetShaderiv. glGetProgramiv(mShaderProgram, GL_INFO_LOG_LENGTH, &maxLength); // The maxLength includes the NULL character shaderProgramInfoLog = (char *)malloc(maxLength); // Notice that glGetProgramInfoLog, not glGetShaderInfoLog. glGetProgramInfoLog(mShaderProgram, maxLength, &maxLength, shaderProgramInfoLog); DEBUG_PRINT_ALWAYS((_L("Failed to link shader program:\n%s\n"), shaderProgramInfoLog)); ASSERT(false, _L("glLinkProgram failed")); // Handle the error in an appropriate way such as displaying a message or writing to a log file. // In this simple program, we'll just leave //DEBUG_PRINT_ALWAYS(("Failed to link shader program:\n%s\n", shaderProgramInfoLog)); free(shaderProgramInfoLog); } // Shader must be successfully linked before we can query uniform locations ReadShaderSamplersAndTextures( mShaderProgram, &mVertexShaderParameters ); glUseProgram(0); // For each of the shader stages, bind shaders and buffers // for( CPUTShaderParameters **pCur = mpShaderParametersList; *pCur; pCur++ ) // Bind textures and buffersfor each shader stage { BindTextures( mVertexShaderParameters, pModel, meshIndex ); //BindTextures( **pCur, pModel, meshIndex ); //BindBuffers( **pCur, pModel, meshIndex ); BindUAVs( mVertexShaderParameters, pModel, meshIndex ); BindConstantBuffers( mVertexShaderParameters, pModel, meshIndex ); } return result; }
// Create a window context //----------------------------------------------------------------------------- CPUTResult CPUT_DX11::CPUTCreateWindowAndContext(const cString WindowTitle, CPUTWindowCreationParams windowParams) { CPUTResult result = CPUT_SUCCESS; HEAPCHECK; // create the window result = MakeWindow(WindowTitle, windowParams.windowWidth, windowParams.windowHeight, windowParams.windowPositionX, windowParams.windowPositionY); if(CPUTFAILED(result)) { return result; } HEAPCHECK; // create the DX context result = CreateDXContext(windowParams.deviceParams); if(CPUTFAILED(result)) { return result; } CPUTModelDX11::CreateModelConstantBuffer(); HEAPCHECK; #define ENABLE_GUI #ifdef ENABLE_GUI // initialize the gui controller // Use the ResourceDirectory that was given during the Initialize() function // to locate the GUI+font resources CPUTGuiControllerDX11 *pGUIController = CPUTGuiControllerDX11::GetController(); cString ResourceDirectory = GetCPUTResourceDirectory(); result = pGUIController->Initialize(mpContext, ResourceDirectory); if(CPUTFAILED(result)) { return result; } // register the callback object for GUI events as our sample CPUTGuiControllerDX11::GetController()->SetCallback(this); #endif HEAPCHECK; DrawLoadingFrame(); HEAPCHECK; // warn the user they are using the software rasterizer if((D3D_DRIVER_TYPE_REFERENCE == mdriverType) || (D3D_DRIVER_TYPE_WARP == mdriverType)) { CPUTOSServices::GetOSServices()->OpenMessageBox(_L("Performance warning"), _L("Your graphics hardware does not support the DirectX features required by this sample. The sample is now running using the DirectX software rasterizer.")); } // trigger a post-create user callback event HEAPCHECK; Create(); HEAPCHECK; // // Start the timer after everything is initialized and assets have been loaded // mpTimer->StartTimer(); // if someone triggers the shutdown routine in on-create, exit if(mbShutdown) { return result; } // does user want to start in fullscreen mode? if(true == windowParams.startFullscreen) { result = CPUTToggleFullScreenMode(); if(CPUTFAILED(result)) { return result; } } // fill first frame with clear values so render order later is ok const float srgbClearColor[] = { 0.0993f, 0.0993f, 0.0993f, 1.0f }; mpContext->ClearRenderTargetView( mpBackBufferRTV, srgbClearColor ); mpContext->ClearDepthStencilView(mpDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 0.0f, 0); // trigger a 'resize' event int x,y,width,height; CPUTOSServices::GetOSServices()->GetClientDimensions(&x, &y, &width, &height); ResizeWindow(width,height); return result; }
//----------------------------------------------------------------------------- CPUTResult CPUTMaterial::LoadMaterial( const cString &fileName, const CPUTModel *pModel, int meshIndex, const char **pShaderMacros, int systemMaterialCount, cString *pSystemMaterialNames, int externalCount, cString *pExternalName, float4 *pExternals, int *pExternalOffset, int *pExternalSize ){ CPUTResult result = CPUT_SUCCESS; mMaterialName = fileName; mMaterialNameHash = CPUTComputeHash( mMaterialName ); // Open/parse the file CPUTConfigFile file; result = file.LoadFile(fileName); if(CPUTFAILED(result)) { return result; } // Make a local copy of all the parameters CPUTConfigBlock *pBlock = file.GetBlock(0); ASSERT( pBlock, _L("Error getting parameter block") ); if( !pBlock ) { return CPUT_ERROR_PARAMETER_BLOCK_NOT_FOUND; } mConfigBlock = *pBlock; CPUTAssetLibrary *pAssetLibrary = (CPUTAssetLibrary*)CPUTAssetLibrary::GetAssetLibrary(); mMaterialEffectCount = 0; if( mConfigBlock.GetValueByName( _L("MultiMaterial") )->ValueAsBool() ) { // Count materials; for(;;) { CPUTConfigEntry *pValue = mConfigBlock.GetValueByName( _L("Material") + itoc(mMaterialEffectCount) ); if( pValue->IsValid() ) { ++mMaterialEffectCount; } else { break; } } ASSERT(mMaterialEffectCount != 0, _L("MultiMaterial specified, but no sub materials given.") ); // Reserve space for "authored" materials plus system materials mpMaterialEffectNames = new cString[mMaterialEffectCount+systemMaterialCount]; int ii; for( ii=0; ii<mMaterialEffectCount; ii++ ) { CPUTConfigEntry *pValue = mConfigBlock.GetValueByName( _L("Material") + itoc(ii) ); mpMaterialEffectNames[ii] = pAssetLibrary->GetMaterialEffectPath(pValue->ValueAsString(), false); } } else { mMaterialEffectCount = 1; mpMaterialEffectNames = new cString[mMaterialEffectCount+systemMaterialCount]; mpMaterialEffectNames[0] = fileName; } CPUT_SHADER_MACRO *pFinalShaderMacros = (CPUT_SHADER_MACRO*)pShaderMacros; CPUT_SHADER_MACRO *pUserSpecifiedMacros = NULL; // The real material count includes the system material count mMaterialEffectCount += systemMaterialCount; for( int ii=0; ii<systemMaterialCount; ii++ ) { // Read additional macros from .mtl file cString macroBlockName = _L("defines") + itoc(ii); CPUTConfigBlock *pMacrosBlock = file.GetBlockByName(macroBlockName); int numUserSpecifiedMacros = 0; if( pMacrosBlock ) { ReadMacrosFromConfigBlock( pMacrosBlock, (CPUT_SHADER_MACRO*)pShaderMacros, &pUserSpecifiedMacros, &numUserSpecifiedMacros, &pFinalShaderMacros ); } // System materials "grow" from the end; the 1st system material is at the end of the list. mpMaterialEffectNames[mMaterialEffectCount-systemMaterialCount+ii] = pSystemMaterialNames[ii]; for( int kk=0; kk<numUserSpecifiedMacros; kk++ ) { // ReadMacrosFromConfigBlock allocates memory (ws2s does). Delete it here. SAFE_DELETE(pUserSpecifiedMacros[kk].Name); SAFE_DELETE(pUserSpecifiedMacros[kk].Definition); } SAFE_DELETE_ARRAY( pFinalShaderMacros ); SAFE_DELETE_ARRAY( pUserSpecifiedMacros ); } mpMaterialEffects = new CPUTMaterialEffect*[mMaterialEffectCount+1]; for( int ii=0; ii<mMaterialEffectCount; ii++ ) { mpMaterialEffects[ii] = pAssetLibrary->GetMaterialEffect( mpMaterialEffectNames[ii], true, pModel, meshIndex,(const char**)pFinalShaderMacros ); } mpMaterialEffects[mMaterialEffectCount] = NULL; return result; // This material is a multi-material, so we're done. }