//----------------------------------------------------------------------------- bool CPUTShaderDX11::ShaderRequiresPerModelPayload( CPUTConfigBlock &properties ) { ID3D11ShaderReflection *pReflector = NULL; D3DReflect( mpBlob->GetBufferPointer(), mpBlob->GetBufferSize(), IID_ID3D11ShaderReflection, (void**)&pReflector); // Walk through the shader input bind descriptors. // If any of them begin with '@', then we need a unique material per model (i.e., we need to clone the material). int ii=0; D3D11_SHADER_INPUT_BIND_DESC desc; HRESULT hr = pReflector->GetResourceBindingDesc( ii++, &desc ); while( SUCCEEDED(hr) ) { cString tagName = s2ws(desc.Name); CPUTConfigEntry *pValue = properties.GetValueByName(tagName); if( !pValue->IsValid() ) { // We didn't find our property in the file. Is it in the global config block? pValue = CPUTMaterial::mGlobalProperties.GetValueByName(tagName); } cString boundName = pValue->ValueAsString(); if( (boundName.length() > 0) && ((boundName[0] == '@') || (boundName[0] == '#')) ) { return true; } hr = pReflector->GetResourceBindingDesc( ii++, &desc ); } return false; }
//----------------------------------------------------------------------------- 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 ReadMacrosFromConfigBlock( CPUTConfigBlock *pMacrosBlock, CPUT_SHADER_MACRO *pShaderMacros, CPUT_SHADER_MACRO **pUserSpecifiedMacros, int *pNumUserSpecifiedMacros, CPUT_SHADER_MACRO **pFinalShaderMacros ){ *pNumUserSpecifiedMacros = pMacrosBlock->ValueCount(); // Count the number of macros passed in CPUT_SHADER_MACRO *pMacro = (CPUT_SHADER_MACRO*)pShaderMacros; int numPassedInMacros = 0; if( pMacro ) { while( pMacro->Name ) { ++numPassedInMacros; ++pMacro; } } // Allocate an array of macro pointer large enough to contain the passed-in macros plus those specified in the .mtl file. *pFinalShaderMacros = new CPUT_SHADER_MACRO[*pNumUserSpecifiedMacros + numPassedInMacros + 1]; // Copy the passed-in macro pointers to the final array int jj; for( jj=0; jj<numPassedInMacros; jj++ ) { (*pFinalShaderMacros)[jj] = *(CPUT_SHADER_MACRO*)&pShaderMacros[jj]; } // Create a CPUT_SHADER_MACRO for each of the macros specified in the .mtl file. // And, add their pointers to the final array *pUserSpecifiedMacros = new CPUT_SHADER_MACRO[*pNumUserSpecifiedMacros]; for( int kk=0; kk<*pNumUserSpecifiedMacros; kk++, jj++ ) { CPUTConfigEntry *pValue = pMacrosBlock->GetValue(kk); (*pUserSpecifiedMacros)[kk].Name = ws2s(pValue->NameAsString()); (*pUserSpecifiedMacros)[kk].Definition = ws2s(pValue->ValueAsString()); (*pFinalShaderMacros)[jj] = (*pUserSpecifiedMacros)[kk]; } (*pFinalShaderMacros)[jj].Name = NULL; (*pFinalShaderMacros)[jj].Definition = NULL; }
//----------------------------------------------------------------------------- void CPUTMaterialEffectOGL::BindConstantBuffers( CPUTShaderParameters ¶ms, const CPUTModel *pModel, int meshIndex ) { CPUTAssetLibraryOGL *pAssetLibrary = (CPUTAssetLibraryOGL*)CPUTAssetLibrary::GetAssetLibrary(); for(params.mConstantBufferCount=0; params.mConstantBufferCount < params.mConstantBufferParameterCount; params.mConstantBufferCount++) { cString constantBufferName; UINT constantBufferCount = params.mConstantBufferCount; // Dirty fix - you should work on std::string in all OS'es ! Why WSTRING ? Whyyyyyyy #ifndef CPUT_OS_WINDOWS cString tagName = params.mConstantBufferParameterNames[constantBufferCount]; #else cString tagName = s2ws(params.mConstantBufferParameterNames[constantBufferCount].c_str()); #endif 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 = CPUTMaterial::mGlobalProperties.GetValueByName(tagName); } ASSERT( pValue->IsValid(), L"Can't find constant buffer '" + tagName + L"'." ); // TODO: fix message constantBufferName = pValue->ValueAsString(); UINT bindPoint = params.mConstantBufferBindPoints[constantBufferCount]; ASSERT( bindPoint < CPUT_MATERIAL_MAX_CONSTANT_BUFFER_SLOTS, _L("Constant buffer bind point out of range.") ); params.mBindConstantBufferMin = std::min( params.mBindConstantBufferMin, bindPoint ); params.mBindConstantBufferMax = std::max( params.mBindConstantBufferMax, bindPoint ); if( constantBufferName[0] == '@' ) { constantBufferName += ptoc(pModel) + itoc(meshIndex); } else if( constantBufferName[0] == '#' ) { constantBufferName += ptoc(pModel); } if( !params.mpConstantBuffer[constantBufferCount] ) { params.mpConstantBuffer[constantBufferCount] = pAssetLibrary->GetConstantBuffer( constantBufferName ); ASSERT( params.mpConstantBuffer[constantBufferCount], _L("Failed getting constant buffer ") + constantBufferName); } #ifndef CPUT_FOR_OGLES2 ES3_COMPAT(glUniformBlockBinding(mShaderProgram, bindPoint, bindPoint)); // just use the index as the binding point #else #warning "Need to do something with uniform buffers here" #endif // If has constant buffer, then add to mppBindConstantBuffer // params.mppBindConstantBuffers[bindPoint] = ((CPUTBufferOGL*)mpConstantBuffer[constantBufferCount])->GetNativeBuffer(); // if( params.mppBindConstantBuffers[bindPoint] ) { // params.mppBindConstantBuffers[bindPoint]->AddRef(); // } } DEBUG_PRINT(_L("Exit BindConstantBuffers")); }
void CPUTMaterialEffectOGL::BindUAVs( CPUTShaderParameters ¶ms, const CPUTModel *pModel, int meshIndex ) { #ifdef CPUT_SUPPORT_IMAGE_STORE CPUTAssetLibraryOGL *pAssetLibrary = (CPUTAssetLibraryOGL*)CPUTAssetLibrary::GetAssetLibrary(); for(params.mUAVCount=0; params.mUAVCount < params.mUAVParameterCount; params.mUAVCount++) { cString UAVName; unsigned int UAVCount = params.mUAVCount; // Dirty fix #ifndef CPUT_OS_WINDOWS cString tagName = params.mpUAVParameterNames[UAVCount]; #else cString tagName = s2ws(params.mpUAVParameterNames[UAVCount].c_str()); #endif 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 = CPUTMaterial::mGlobalProperties.GetValueByName(tagName); } ASSERT( pValue->IsValid(), L"Can't find UAV '" + tagName + L"'." ); // TODO: fix message UAVName = pValue->ValueAsString(); // If the UAV name not specified. Load default.dds instead if( 0 == UAVName.length() ) { UAVName = _L("default.dds"); } UINT bindPoint = params.mUAVCount;//params.mpUAVParameterBindPoints[UAVCount]; params.mpUAVParameterBindPoints.push_back(bindPoint); // UINT bindPoint = params.mpUAVParameterBindPoint[UAVCount]; mpUAVParameterBindPoints ASSERT( bindPoint < CPUT_MATERIAL_MAX_UAV_SLOTS, _L("UAV bind point out of range.") ); params.mBindViewMin = std::min( params.mBindViewMin, bindPoint ); params.mBindViewMax = std::max( params.mBindViewMax, bindPoint ); if( UAVName[0] == '@' ) { // This is a per-mesh value. Add to per-mesh list. UAVName += ptoc(pModel) + itoc(meshIndex); } else if( UAVName[0] == '#' ) { // This is a per-mesh value. Add to per-mesh list. UAVName += ptoc(pModel); } // Get the sRGB flag (default to true) //#ifndef CPUT_OS_WINDOWS cString SRGBName = tagName + _L("sRGB"); //#else // cString SRGBName = tagName + L"sRGB"; //#endif CPUTConfigEntry *pSRGBValue = mConfigBlock.GetValueByName(SRGBName); bool loadAsSRGB = pSRGBValue->IsValid() ? loadAsSRGB = pSRGBValue->ValueAsBool() : true; if( !params.mpUAV[UAVCount] ) { params.mpUAV[UAVCount] = pAssetLibrary->GetTexture( UAVName, false, loadAsSRGB ); ASSERT( params.mpUAV[UAVCount], _L("Failed getting UAV ") + UAVName); } cString ReadName = tagName + _L("READ"); CPUTConfigEntry *pRead = mConfigBlock.GetValueByName(ReadName); bool read = pRead->IsValid() ? pRead->ValueAsBool() : true; cString WriteName = tagName + _L("WRITE"); CPUTConfigEntry *pWrite = mConfigBlock.GetValueByName(WriteName); bool write = pWrite->IsValid() ? pWrite ->ValueAsBool() : true; if(write && read) params.mpUAVMode[UAVCount] = GL_READ_WRITE; else if(read) params.mpUAVMode[UAVCount] = GL_READ_ONLY; else params.mpUAVMode[UAVCount] = GL_WRITE_ONLY; // The shader file (e.g. .fx) can specify the UAV bind point (e.g., t0). Those specifications // might not be contiguous, and there might be gaps (bind points without assigned UAVs) // TODO: Warn about missing bind points? // params.mppBindViews[bindPoint] = ((CPUTTextureOGL*)mpTexture[textureCount])->GetShaderResourceView(); // params.mppBindViews[bindPoint]->AddRef(); // // Match up the UAV name in any UAV samplers given in the renderstate file. If there wasn't // one specified for a particular UAV then it just uses the default sampler. // CPUTRenderStateOGL *pRenderState; pRenderState = ((CPUTRenderStateBlockOGL*)mpRenderStateBlock)->GetState(); mSamplerIDs[UAVCount] = pRenderState->DefaultSamplerID; for (int renderStateIDX = 0; renderStateIDX < NUM_SAMPLERS_PER_RENDERSTATE; renderStateIDX++) { if(renderStateIDX<((CPUTRenderStateBlockOGL*)mpRenderStateBlock)->GetNumSamplers()) { mSamplerIDs[UAVCount] = pRenderState->SamplerIDs[renderStateIDX]; } } } #endif }
CPUTResult CPUTMaterialEffectOGL::LoadMaterialEffect( const cString &fileName, const CPUTModel *pModel, int meshIndex, const char **pShaderMacros, int externalCount, cString *pExternalName, float4 *pExternals, int *pExternalOffset, int *pExternalSize ){ CPUTResult result = CPUT_SUCCESS; CPUTConfigEntry *pValue; mMaterialName = fileName; mMaterialNameHash = CPUTComputeHash( mMaterialName ); // Open/parse the file CPUTConfigFile file; result = file.LoadFile(fileName); if(CPUTFAILED(result)) { return result; } // Make a local copy of all the parameters CPUTConfigBlock *pBlock = file.GetBlock(0); ASSERT( pBlock, _L("Error getting parameter block") ); if( !pBlock ) { return CPUT_ERROR_PARAMETER_BLOCK_NOT_FOUND; } mConfigBlock = *pBlock; // get necessary device and AssetLibrary pointers //ID3D11Device *pD3dDevice = CPUT_DX11::GetDevice(); CPUTAssetLibraryOGL *pAssetLibrary = (CPUTAssetLibraryOGL*)CPUTAssetLibrary::GetAssetLibrary(); { CPUTConfigEntry *pEntryPointName, *pProfileName; int numFiles = 0; cString pBase = _L("VertexShaderFileOGL_"); cString pName = pBase + to_cString(numFiles+1); std::vector<cString> filenames; while (mConfigBlock.GetValueByName(pName)->IsValid()) { filenames.push_back(mConfigBlock.GetValueByName(pName)->ValueAsString()); numFiles++; pName = pBase + to_cString(numFiles+1); } if(numFiles > 0) { pEntryPointName = mConfigBlock.GetValueByName(_L("VertexShaderMain")); pProfileName = mConfigBlock.GetValueByName(_L("VertexShaderProfile")); pAssetLibrary->GetVertexShader( filenames, /*pD3dDevice,*/ _L("VertexShaderMain"), pProfileName->ValueAsString(), &mpVertexShader, false, (CPUT_SHADER_MACRO*)pShaderMacros ); } } #ifdef CPUT_SUPPORT_TESSELLATION { int numFiles = 0; cString pBase = _L("ControlShaderFileOGL_"); cString pName = pBase + to_cString(numFiles+1); std::vector<cString> filenames; while (mConfigBlock.GetValueByName(pName)->IsValid()) { filenames.push_back(mConfigBlock.GetValueByName(pName)->ValueAsString()); numFiles++; pName = pBase + to_cString(numFiles+1); } if(numFiles > 0) { pAssetLibrary->GetHullShader( filenames, /* pD3dDevice,*/ _L("ControlShaderMain"), _L(""), &mpControlShader, false, (CPUT_SHADER_MACRO*)pShaderMacros ); } } { int numFiles = 0; cString pBase = _L("EvaluationShaderFileOGL_"); cString pName = pBase + to_cString(numFiles+1); std::vector<cString> filenames; while (mConfigBlock.GetValueByName(pName)->IsValid()) { filenames.push_back(mConfigBlock.GetValueByName(pName)->ValueAsString()); numFiles++; pName = pBase + to_cString(numFiles+1); } if(numFiles > 0) { pAssetLibrary->GetDomainShader( filenames, /* pD3dDevice,*/ _L("EvaluationShaderMain"), _L(""), &mpEvaluationShader, false, (CPUT_SHADER_MACRO*)pShaderMacros ); } } #endif { int numFiles = 0; cString pBase = _L("GeometryShaderFileOGL_"); cString pName = pBase + to_cString(numFiles+1); std::vector<cString> filenames; while (mConfigBlock.GetValueByName(pName)->IsValid()) { filenames.push_back(mConfigBlock.GetValueByName(pName)->ValueAsString()); numFiles++; pName = pBase + to_cString(numFiles+1); } if(numFiles > 0) { pAssetLibrary->GetGeometryShader( filenames, /* pD3dDevice,*/ _L("GeometryShaderMain"), _L(""), &mpGeometryShader, false, (CPUT_SHADER_MACRO*)pShaderMacros ); } } // load and store the pixel shader if it was specified { int numFiles = 0; cString pBase = _L("FragmentShaderFileOGL_"); cString pName = pBase + to_cString(numFiles+1); std::vector<cString> filenames; while (mConfigBlock.GetValueByName(pName)->IsValid()) { filenames.push_back(mConfigBlock.GetValueByName(pName)->ValueAsString()); numFiles++; pName = pBase + to_cString(numFiles+1); } if(numFiles > 0) { pAssetLibrary->GetPixelShader( filenames, /* pD3dDevice,*/ _L("FragmentShaderMain"), //mConfigBlock.GetValueByName(_L("FragmentShaderMain"))->ValueAsString(), mConfigBlock.GetValueByName(_L("FragmentShaderProfile"))->ValueAsString(), &mpFragmentShader, false, (CPUT_SHADER_MACRO*)pShaderMacros ); } } // load and store the render state file if it was specified pValue = mConfigBlock.GetValueByName(_L("RenderStateFile")); if( pValue->IsValid() ) { mpRenderStateBlock = pAssetLibrary->GetRenderStateBlock(pValue->ValueAsString()); } int IsLinked; char *shaderProgramInfoLog; int maxLength; mShaderProgram = glCreateProgram(); // Attach our shaders to our program // Attach our shaders to our program if (mpVertexShader) { GL_CHECK(glAttachShader(mShaderProgram, mpVertexShader->GetShaderID())); } if (mpFragmentShader) { GL_CHECK(glAttachShader(mShaderProgram, mpFragmentShader->GetShaderID())); } if (mpControlShader) { GL_CHECK(glAttachShader(mShaderProgram, mpControlShader->GetShaderID())); } if (mpEvaluationShader) { GL_CHECK(glAttachShader(mShaderProgram, mpEvaluationShader->GetShaderID())); } if (mpGeometryShader) { GL_CHECK(glAttachShader(mShaderProgram, mpGeometryShader->GetShaderID())); } /* GL_CHECK(glBindAttribLocation(mShaderProgram, 0, "in_Position")); GL_CHECK(glBindAttribLocation(mShaderProgram, 1, "inNormal")); GL_CHECK(glBindAttribLocation(mShaderProgram, 2, "inBinormal")); GL_CHECK(glBindAttribLocation(mShaderProgram, 3, "inTangent")); GL_CHECK(glBindAttribLocation(mShaderProgram, 4, "inTex")); */ // Link our program // At this stage, the vertex and fragment programs are inspected, optimized and a binary code is generated for the shader. // The binary code is uploaded to the GPU, if there is no error. GL_CHECK(glLinkProgram(mShaderProgram)); // Again, we must check and make sure that it linked. If it fails, it would mean either there is a mismatch between the vertex // and fragment shaders. It might be that you have surpassed your GPU's abilities. Perhaps too many ALU operations or // too many texel fetch instructions or too many interpolators or dynamic loops. GL_CHECK(glGetProgramiv(mShaderProgram, GL_LINK_STATUS, (int *)&IsLinked)); if(IsLinked == false) { // Noticed that glGetProgramiv is used to get the length for a shader program, not glGetShaderiv. glGetProgramiv(mShaderProgram, GL_INFO_LOG_LENGTH, &maxLength); // The maxLength includes the NULL character shaderProgramInfoLog = (char *)malloc(maxLength); // Notice that glGetProgramInfoLog, not glGetShaderInfoLog. glGetProgramInfoLog(mShaderProgram, maxLength, &maxLength, shaderProgramInfoLog); DEBUG_PRINT_ALWAYS((_L("Failed to link shader program:\n%s\n"), shaderProgramInfoLog)); ASSERT(false, _L("glLinkProgram failed")); // Handle the error in an appropriate way such as displaying a message or writing to a log file. // In this simple program, we'll just leave //DEBUG_PRINT_ALWAYS(("Failed to link shader program:\n%s\n", shaderProgramInfoLog)); free(shaderProgramInfoLog); } // Shader must be successfully linked before we can query uniform locations ReadShaderSamplersAndTextures( mShaderProgram, &mVertexShaderParameters ); glUseProgram(0); // For each of the shader stages, bind shaders and buffers // for( CPUTShaderParameters **pCur = mpShaderParametersList; *pCur; pCur++ ) // Bind textures and buffersfor each shader stage { BindTextures( mVertexShaderParameters, pModel, meshIndex ); //BindTextures( **pCur, pModel, meshIndex ); //BindBuffers( **pCur, pModel, meshIndex ); BindUAVs( mVertexShaderParameters, pModel, meshIndex ); BindConstantBuffers( mVertexShaderParameters, pModel, meshIndex ); } return result; }
//----------------------------------------------------------------------------- CPUTResult CPUTAssetSet::LoadAssetSet(std::string name, int numSystemMaterials, std::string *pSystemMaterialNames) { CPUTResult result = CPUT_SUCCESS; // if not found, load the set file CPUTConfigFile ConfigFile; result = ConfigFile.LoadFile(name); if( !CPUTSUCCESS(result) ) { return result; } // ASSERT( CPUTSUCCESS(result), "Failed loading set file '" + name + "'." ); mAssetCount = ConfigFile.BlockCount() + 1; // Add one for the implied root node mppAssetList = new CPUTRenderNode*[mAssetCount]; mppAssetList[0] = mpRootNode; mpRootNode->AddRef(); CPUTAssetLibrary *pAssetLibrary = (CPUTAssetLibrary*)CPUTAssetLibrary::GetAssetLibrary(); CPUTAnimation *pDefaultAnimation = NULL; for(UINT ii=0; ii<mAssetCount-1; ii++) // Note: -1 because we added one for the root node (we don't load it) { CPUTConfigBlock *pBlock = ConfigFile.GetBlock(ii); ASSERT(pBlock != NULL, "Cannot find block"); if( !pBlock ) { return CPUT_ERROR_PARAMETER_BLOCK_NOT_FOUND; } std::string nodeType = pBlock->GetValueByName("type")->ValueAsString(); CPUTRenderNode *pParentNode = NULL; // TODO: use Get*() instead of Load*() ? std::string name = pBlock->GetValueByName("name")->ValueAsString(); int parentIndex; CPUTRenderNode *pNode = NULL; if(0==nodeType.compare("null")) { pNode = pNode = CPUTNullNode::Create(); result = ((CPUTNullNode*)pNode)->LoadNullNode(pBlock, &parentIndex); pParentNode = mppAssetList[parentIndex+1]; std::string &parentPrefix = pParentNode->GetPrefix(); std::string prefix = parentPrefix; prefix.append("."); prefix.append(name); pNode->SetPrefix(prefix); // pNode->SetPrefix( parentPrefix + "." + name ); pAssetLibrary->AddNullNode("", parentPrefix + name, "", (CPUTNullNode*)pNode); // Add this null's name to our prefix // Append this null's name to our parent's prefix pNode->SetParent( pParentNode ); pParentNode->AddChild( pNode ); } else if(0==nodeType.compare("model")) { CPUTConfigEntry *pValue = pBlock->GetValueByName( "instance" ); CPUTModel *pModel = CPUTModel::Create(); if( pValue == &CPUTConfigEntry::sNullConfigValue ) { // Not found. So, not an instance. pModel->LoadModel(pBlock, &parentIndex, NULL, numSystemMaterials, pSystemMaterialNames); } else { int instance = pValue->ValueAsInt(); // If the current node is an instance of itself then it has no "master" model if(ii == instance) { // TODO: create instance model object pModel->LoadModel(pBlock, &parentIndex, NULL, numSystemMaterials, pSystemMaterialNames); } else { pModel->LoadModel(pBlock, &parentIndex, (CPUTModel*)mppAssetList[instance+1], numSystemMaterials, pSystemMaterialNames); } } pParentNode = mppAssetList[parentIndex+1]; pModel->SetParent( pParentNode ); pParentNode->AddChild( pModel ); std::string &parentPrefix = pParentNode->GetPrefix(); pModel->SetPrefix( parentPrefix ); pAssetLibrary->AddModel(name, parentPrefix, "", pModel); pModel->UpdateBoundsWorldSpace(); #ifdef SUPPORT_DRAWING_BOUNDING_BOXES // Create a mesh for rendering the bounding box // TODO: There is definitely a better way to do this. But, want to see the bounding boxes! pModel->CreateBoundingBoxMesh(); #endif pNode = pModel; } else if(0==nodeType.compare("light")) { pNode = CPUTLight::Create(); ((CPUTLight*)pNode)->LoadLight(pBlock, &parentIndex); pParentNode = mppAssetList[parentIndex+1]; // +1 because we added a root node to the start pNode->SetParent( pParentNode ); pParentNode->AddChild( pNode ); std::string &parentPrefix = pParentNode->GetPrefix(); pNode->SetPrefix( parentPrefix ); pAssetLibrary->AddLight(name, parentPrefix, "", (CPUTLight*)pNode); } else if(0==nodeType.compare("camera")) { pNode = CPUTCamera::Create(CPUT_PERSPECTIVE); ((CPUTCamera*)pNode)->LoadCamera(pBlock, &parentIndex); pParentNode = mppAssetList[parentIndex+1]; // +1 because we added a root node to the start pNode->SetParent( pParentNode ); pParentNode->AddChild( pNode ); std::string &parentPrefix = pParentNode->GetPrefix(); pNode->SetPrefix( parentPrefix ); pAssetLibrary->AddCamera(name, parentPrefix, "", (CPUTCamera*)pNode); if( !mpFirstCamera ) { mpFirstCamera = (CPUTCamera*)pNode; mpFirstCamera->AddRef();} ++mCameraCount; } else { ASSERT(0,"Unsupported node type '" + nodeType + "'."); } CPUTConfigEntry *pAnimValue = pBlock->GetValueByName( "Animation0" ); //int autoPlayAnimationIndex = pBlock->GetValueByName( "DefaultAnimation" ); for(int i = 1; pAnimValue != &CPUTConfigEntry::sNullConfigValue; ++i ) { CPUTAnimation *pCurrentAnimation = pAssetLibrary->GetAnimation(pAnimValue->ValueAsString()); //First Animation will be default for now if(pCurrentAnimation != NULL && i == 1 /*autoPlayAnimationIndex*/) { pDefaultAnimation = pCurrentAnimation ; pCurrentAnimation->AddRef(); } std::stringstream animName; animName << "Animation" << i; pAnimValue = pBlock->GetValueByName(animName.str()); pNode->mAnimationList.push_back(pCurrentAnimation); } // Add the node to our asset list (i.e., the linear list, not the hierarchical) mppAssetList[ii+1] = pNode; // Don't AddRef.Creating it set the refcount to 1. We add it to the list, and then we're done with it. // Net effect is 0 (+1 to add to list, and -1 because we're done with it) // pNode->AddRef(); } //Set the default animation to the current Asset Set if(pDefaultAnimation != NULL && mAssetCount > 1) { //Apply Animation to root of the setfile mppAssetList[1]->SetAnimation(pDefaultAnimation); } SAFE_RELEASE(pDefaultAnimation); return result; }
bool CPUTGUIElement::Load(CPUTConfigBlock* pBlock, int* pParent) { CPUTConfigEntry* pEntry = NULL; pEntry = pBlock->GetValueByName(NAME); if (pEntry->IsValid()) mName= pEntry->ValueAsString(); pEntry = pBlock->GetValueByName(PARENT); if(pEntry->IsValid()) *pParent = pEntry->ValueAsInt(); pEntry = pBlock->GetValueByName(WIDTH); if(pEntry->IsValid()) mWidth = pEntry->ValueAsInt(); pEntry = pBlock->GetValueByName(HEIGHT); if(pEntry->IsValid()) mHeight = pEntry->ValueAsInt(); pEntry = pBlock->GetValueByName(POS_X); if(pEntry->IsValid()) mRelX = pEntry->ValueAsInt(); pEntry = pBlock->GetValueByName(POS_Y); if(pEntry->IsValid()) mRelY = pEntry->ValueAsInt(); pEntry = pBlock->GetValueByName(PARENT_RELATIVE); if(pEntry->IsValid()) mParentRelative = pEntry->ValueAsBool(); pEntry = pBlock->GetValueByName(VISIBLE); if(pEntry->IsValid()) mVisible = pEntry->ValueAsBool(); pEntry = pBlock->GetValueByName(FOREGROUND_COLOR); if(pEntry->IsValid()) { pEntry->ValueAsFloatArray((float*)&mForegroundColor, 4); mForegroundHighlightColor = mForegroundColor; } pEntry = pBlock->GetValueByName(BACKGROUND_COLOR); if(pEntry->IsValid()) { pEntry->ValueAsFloatArray((float*)&mBackgroundColor, 4); mBackgroundHighlightColor = mBackgroundColor; } pEntry = pBlock->GetValueByName(FOREGROUND_HIGHLIGHT_COLOR); if(pEntry->IsValid()) pEntry->ValueAsFloatArray((float*)&mForegroundHighlightColor, 4); pEntry = pBlock->GetValueByName(BACKGROUND_HIGHLIGHT_COLOR); if(pEntry->IsValid()) pEntry->ValueAsFloatArray((float*)&mBackgroundHighlightColor, 4); pEntry = pBlock->GetValueByName(MATERIAL); if(pEntry->IsValid()) { cString materialName = pEntry->ValueAsString(); mpSprite = CPUTSprite::CreateSprite(0.0, 0.0, 1.0, 1.0, materialName); } pEntry = pBlock->GetValueByName(TEXT_MATERIAL); if(pEntry->IsValid()) { cString materialName = pEntry->ValueAsString(); mpTextMaterial = CPUTAssetLibrary::GetAssetLibrary()->GetMaterial(materialName); } const cString FONT = _L("font"); pEntry = pBlock->GetValueByName(FONT); if(pEntry->IsValid()) { cString fontName; pEntry->ValueAsString(&fontName); mpFont = (CPUTFont*)CPUTAssetLibrary::GetAssetLibrary()->GetFontByName(fontName); if(mpFont == NULL) { DEBUG_PRINT(_L("Failed to load font: %s"), fontName.c_str()); } } pEntry = pBlock->GetValueByName(TEXT); cString string; if(pEntry->IsValid()) { pEntry->ValueAsString(&string); SetText(string); } pEntry = pBlock->GetValueByName(HIGHLIGHT); if(pEntry->IsValid()) { mHighlighted = pEntry->ValueAsBool(); } pEntry = pBlock->GetValueByName(MOUSE_CLICK); if(pEntry->IsValid()) { pEntry->ValueAsString(&mClick.key); mEventHandler = true; } pEntry = pBlock->GetValueByName(MOUSE_UP); if(pEntry->IsValid()) { pEntry->ValueAsString(&mUp.key); mEventHandler = true; } pEntry = pBlock->GetValueByName(MOUSE_DOWN); if(pEntry->IsValid()) { pEntry->ValueAsString(&mDown.key); mEventHandler = true; } pEntry = pBlock->GetValueByName(MOUSE_OUT); if(pEntry->IsValid()) { pEntry->ValueAsString(&mOut.key); mEventHandler = true; } pEntry = pBlock->GetValueByName(MOUSE_IN); if(pEntry->IsValid()) { pEntry->ValueAsString(&mIn.key); mEventHandler = true; } pEntry = pBlock->GetValueByName(HOTKEY); if(pEntry->IsValid()) { cString key; pEntry->ValueAsString(&key); mHotkey = MapKey(key); mEventHandler = true; } pEntry = pBlock->GetValueByName(HOTKEY_UP); if(pEntry->IsValid()) { pEntry->ValueAsString(&mKeyUp.key); mEventHandler = true; } pEntry = pBlock->GetValueByName(HOTKEY_DOWN); if(pEntry->IsValid()) { pEntry->ValueAsString(&mKeyDown.key); mEventHandler = true; } mParentMatrix = float4x4Translation((float)mPosX, (float)mPosY, 0.0); return true; }
//----------------------------------------------------------------------------- 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. }