//-----------------------------------------------------------------------------
void GLSLProgramProcessor::bindSubShaders(Program* program, GpuProgramPtr pGpuProgram)
{
	if (program->getDependencyCount() > 0)
	{
		// Get all attached shaders so we do not attach shaders twice.
		// maybe GLSLProgram should take care of that ( prevent add duplicate shaders )
		String attachedShaders = pGpuProgram->getParameter("attach");
		String subShaderDef = "";

		for (unsigned int i=0; i < program->getDependencyCount(); ++i)
		{
			// Here we append _VS and _FS to the library shaders (so max each lib shader
			// is compiled twice once as vertex and once as fragment shader)
			String subShaderName = program->getDependency(i);
			if (program->getType() == GPT_VERTEX_PROGRAM)
			{
				subShaderName += "_VS";
			}
			else
			{
				subShaderName += "_FS";
			}					

			// Check if the library shader already compiled
			if(!HighLevelGpuProgramManager::getSingleton().resourceExists(subShaderName))
			{
				// Create the library shader
				HighLevelGpuProgramPtr pSubGpuProgram = HighLevelGpuProgramManager::getSingleton().createProgram(subShaderName,
					ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TargetLanguage, program->getType());

				// Set the source name
				String sourceName = program->getDependency(i) + "." + TargetLanguage;
				pSubGpuProgram->setSourceFile(sourceName);
                pSubGpuProgram->load();

                // Prepend the current GLSL version
                String versionLine = "#version " + StringConverter::toString(Root::getSingleton().getRenderSystem()->getNativeShadingLanguageVersion()) + "\n";
                pSubGpuProgram->setSource(versionLine + pSubGpuProgram->getSource());

				// If we have compile errors than stop processing
				if (pSubGpuProgram->hasCompileError())
				{
					OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, 
						"Could not compile shader library from the source file: " + sourceName, 
						"GLSLProgramProcessor::bindSubShaders" );	
				}

				mLibraryPrograms.push_back(subShaderName);
			}

			// Check if the lib shader already attached to this shader
			if (attachedShaders.find(subShaderName) == String::npos)
			{
				// Append the shader name to subShaders
				subShaderDef += subShaderName + " ";
			}
		}

		// Check if we have something to attach
		if (subShaderDef.length() > 0)
		{
			pGpuProgram->setParameter("attach", subShaderDef);
		}
	}
	
}
//-----------------------------------------------------------------------------
GpuProgramPtr ProgramManager::createGpuProgram(Program* shaderProgram, 
											   ProgramWriter* programWriter,
											   const String& language,
											   const String& profiles,
											   const StringVector& profilesList,
											   const String& cachePath)
{

	
#if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
	Ogre::StringSerialiser sourceCodeStringStream;
#else
	std::stringstream sourceCodeStringStream;
#endif
	_StringHash stringHash;
	uint32 programHashCode;
	String programName;

	// Generate source code.
	programWriter->writeSourceCode(sourceCodeStringStream, shaderProgram);

	// Generate program hash code.
	programHashCode = static_cast<uint32>(stringHash(sourceCodeStringStream.str()));

	// Generate program name.
	programName = StringConverter::toString(programHashCode);
	
	if (shaderProgram->getType() == GPT_VERTEX_PROGRAM)
	{
		programName += "_VS";
	}
	else if (shaderProgram->getType() == GPT_FRAGMENT_PROGRAM)
	{
		programName += "_FS";
	}

	HighLevelGpuProgramPtr pGpuProgram;

	// Try to get program by name.
	pGpuProgram = HighLevelGpuProgramManager::getSingleton().getByName(programName);

	// Case the program doesn't exist yet.
	if (pGpuProgram.isNull())
	{
		// Create new GPU program.
		pGpuProgram = HighLevelGpuProgramManager::getSingleton().createProgram(programName,
			ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, language, shaderProgram->getType());

		// Case cache directory specified -> create program from file.
		if (cachePath.empty() == false)
		{
			const String  programFullName = programName + "." + language;
			const String  programFileName = cachePath + programFullName;	
			std::ifstream programFile;
			bool		  writeFile = true;


			// Check if program file already exist.
			programFile.open(programFileName.c_str());

			// Case no matching file found -> we have to write it.
			if (!programFile)
			{			
				writeFile = true;
			}
			else
			{
				writeFile = false;
				programFile.close();
			}

			// Case we have to write the program to a file.
			if (writeFile)
			{
				std::ofstream outFile(programFileName.c_str());

				if (!outFile)
					return GpuProgramPtr();

				outFile << sourceCodeStringStream.str();
				outFile.close();
			}

			pGpuProgram->setSourceFile(programFullName);
		}

		// No cache directory specified -> create program from system memory.
		else
		{
			pGpuProgram->setSource(sourceCodeStringStream.str());
		}
		
		
		pGpuProgram->setParameter("entry_point", shaderProgram->getEntryPointFunction()->getName());

		// HLSL program requires specific target profile settings - we have to split the profile string.
		if (language == "hlsl")
		{
			StringVector::const_iterator it = profilesList.begin();
			StringVector::const_iterator itEnd = profilesList.end();
			
			for (; it != itEnd; ++it)
			{
				if (GpuProgramManager::getSingleton().isSyntaxSupported(*it))
				{
					pGpuProgram->setParameter("target", *it);
					break;
				}
			}
		}
		
		pGpuProgram->setParameter("profiles", profiles);
		pGpuProgram->load();
	
		// Case an error occurred.
		if (pGpuProgram->hasCompileError())
		{
			pGpuProgram.setNull();
			return GpuProgramPtr(pGpuProgram);
		}

		// Add the created GPU program to local cache.
		if (pGpuProgram->getType() == GPT_VERTEX_PROGRAM)
		{
			mVertexShaderMap[programName] = pGpuProgram;			
		}
		else if (pGpuProgram->getType() == GPT_FRAGMENT_PROGRAM)
		{
			mFragmentShaderMap[programName] = pGpuProgram;	
		}				
	}
	
	return GpuProgramPtr(pGpuProgram);
}
Exemplo n.º 3
0
void Shader::prepare()
{
    // determining shader level and generating a part of the level string 
    std::string levelString = "_basic";
    if (shaderLevel == LEVEL_INTERMEDIATE) {
        levelString = "_intermediate";
    } else if (shaderLevel == LEVEL_ADVANCED) {
        levelString = "_advanced";
    }

    std::string vertexString;
    std::string geometryString;
    std::string fragmentString;

    // trying to use actual shader level, choosing basic as default/backup
    if (ResourceGroupManager::getSingleton()
            .resourceExistsInAnyGroup(shaderName + levelString + ".vert")) {
        vertexString = shaderName + levelString + ".vert";
    } else {
        vertexString = shaderName + "_basic.vert";
    }

    if (ResourceGroupManager::getSingleton()
            .resourceExistsInAnyGroup(shaderName + levelString + ".geom")) {
        geometryString = shaderName + levelString + ".geom";
    } else {
        geometryString = shaderName + "_basic.geom";
    }

    if (ResourceGroupManager::getSingleton()
            .resourceExistsInAnyGroup(shaderName + levelString + ".frag")) {
        fragmentString = shaderName + levelString + ".frag";
    } else {
        fragmentString = shaderName + "_basic.frag";
    }

    // creating new material
    material = MaterialManager::getSingletonPtr()->create(materialName + shaderName,
            ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);

    pass = material->getTechnique(0)->getPass(0);

    // with dynamic lighting only geometry with normals will be displayed
    pass->setLightingEnabled(true);
    material->setReceiveShadows(true);

    // loading vertex shader if there is one
    if (ResourceGroupManager::getSingleton()
            .resourceExistsInAnyGroup(vertexString)) {
        HighLevelGpuProgramPtr vertex =
                HighLevelGpuProgramManager::getSingletonPtr()->createProgram(
                shaderName + "_v",
                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
                "glsl", GpuProgramType::GPT_VERTEX_PROGRAM);
        vertex->setSourceFile(vertexString);
        pass->setVertexProgram(vertex->getName());
    }

    // loading geometry shader if there is one
    if (ResourceGroupManager::getSingleton()
            .resourceExistsInAnyGroup(geometryString)) {
        geometry = HighLevelGpuProgramManager::getSingletonPtr()->createProgram(
                shaderName + "_g",
                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "glsl",
                GpuProgramType::GPT_GEOMETRY_PROGRAM);
        geometry->setSourceFile(geometryString);
        pass->setGeometryProgram(geometry->getName());
    }

    // loading fragment shader if there is one
    if (ResourceGroupManager::getSingleton()
            .resourceExistsInAnyGroup(fragmentString)) {
        HighLevelGpuProgramPtr fragment =
                HighLevelGpuProgramManager::
                getSingletonPtr()->createProgram(shaderName + "_f",
                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
                "glsl", GpuProgramType::GPT_FRAGMENT_PROGRAM);
        fragment->setSourceFile(fragmentString);
        pass->setFragmentProgram(fragment->getName());
    }
    entity->getOgreEntity()->setMaterialName(material->getName());
}