Ejemplo n.º 1
0
//-----------------------------------------------------------------------
bool FFPTransform::createCpuSubPrograms(ProgramSet* programSet)
{
    //! [param_resolve]
    Program* vsProgram = programSet->getCpuVertexProgram();
    Function* vsEntry = vsProgram->getEntryPointFunction();
    
    // Resolve World View Projection Matrix.
    UniformParameterPtr wvpMatrix = vsProgram->resolveAutoParameterInt(GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX, 0);
        
    // Resolve input position parameter.
    ParameterPtr positionIn = vsEntry->resolveInputParameter(Parameter::SPS_POSITION, 0, Parameter::SPC_POSITION_OBJECT_SPACE, GCT_FLOAT4); 
    
    // Resolve output position parameter.
    ParameterPtr positionOut = vsEntry->resolveOutputParameter(Parameter::SPS_POSITION, 0, Parameter::SPC_POSITION_PROJECTIVE_SPACE, GCT_FLOAT4);

    if (!wvpMatrix || !positionIn || !positionOut)
    {
        OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, 
                "Not all parameters could be constructed for the sub-render state.",
                "FFPTransform::createCpuSubPrograms" );
    }
    //! [param_resolve]
    // Add dependency.
    vsProgram->addDependency(FFP_LIB_TRANSFORM);

    FunctionInvocation* transformFunc = OGRE_NEW FunctionInvocation(FFP_FUNC_TRANSFORM,  FFP_VS_TRANSFORM, 0); 

    transformFunc->pushOperand(wvpMatrix, Operand::OPS_IN);
    transformFunc->pushOperand(positionIn, Operand::OPS_IN);
    transformFunc->pushOperand(positionOut, Operand::OPS_OUT);

    vsEntry->addAtomInstance(transformFunc);

    return true;
}
Ejemplo n.º 2
0
bool FunctionInvocation::FunctionInvocationLessThan::operator ()(FunctionInvocation const& lhs, FunctionInvocation const& rhs) const
{
    // Check the function names first
    if (lhs.getFunctionName() < rhs.getFunctionName())
        return true;

    // Next check the return type
    if (lhs.getReturnType() < rhs.getReturnType())
        return true;

    // Check the number of operands
    if (lhs.mOperands.size() < rhs.mOperands.size())
        return true;

    // Now that we've gotten past the two quick tests, iterate over operands
    // Check the semantic and type.  The operands must be in the same order as well.
    OperandVector::const_iterator itLHSOps = lhs.mOperands.begin();
    OperandVector::const_iterator itRHSOps = rhs.mOperands.begin();

    for ( ; itLHSOps != lhs.mOperands.end(), itRHSOps != rhs.mOperands.end(); ++itLHSOps, ++itRHSOps)
    {
        if (itLHSOps->getSemantic() < itRHSOps->getSemantic())
            return true;

        if (itLHSOps->getParameter()->getType() < itRHSOps->getParameter()->getType())
            return true;
    }

    return false;
}
Ejemplo n.º 3
0
//-----------------------------------------------------------------------------
void ProgramProcessor::buildParameterReferenceMap(FunctionAtomInstanceList& funcAtomList, ParameterOperandMap& paramsRefMap)
{
	
	FunctionAtomInstanceIterator it    = funcAtomList.begin();
	FunctionAtomInstanceIterator itEnd = funcAtomList.end();

	for (; it != itEnd; ++it)
	{
		FunctionAtom* curAtom = *it;

		// Deal only with function invocations.
		if (curAtom->getFunctionAtomType() == FunctionInvocation::Type)
		{
			FunctionInvocation* curFuncInvocation = static_cast<FunctionInvocation*>(curAtom);
			FunctionInvocation::OperandVector& funcOperands = curFuncInvocation->getOperandList();

			for (unsigned int op=0; op < funcOperands.size(); ++op)
			{
				Operand& curOperand = funcOperands[op];

				paramsRefMap[curOperand.getParameter().get()].push_back(&curOperand);
			}
		}
	}
}
Ejemplo n.º 4
0
ArrayVariable*
ArrayVariable::rnd_mutate(void)
{
	assert(0 && "invalid call to rnd_mutate");
	bool use_existing = rnd_flipcoin(20);
	ERROR_GUARD(NULL);
	size_t i;
	if (use_existing) {
		vector<Variable*> ok_vars;
		for (i=0; i<parent->local_vars.size(); i++) {
			if (is_variant(parent->local_vars[i])) {
				ok_vars.push_back(parent->local_vars[i]);
			}
		}
		Variable* v = VariableSelector::choose_ok_var(ok_vars);
		ERROR_GUARD(NULL);
		if (v) {
			ArrayVariable* av = dynamic_cast<ArrayVariable*>(v);
			return av;
		}
	}
	vector<const Expression*> new_indices;
	vector<bool> mutate_flags;
	bool no_mutate = true;
	for (i=0; i<get_dimension(); i++) {
		bool mutate = rnd_flipcoin(10);
		ERROR_GUARD(0);
		mutate_flags.push_back(mutate);
		if (mutate) {
			no_mutate = false;
		}
	}
	// if no mutation, return self
	if (no_mutate) {
		return this;
	}
	for (i=0; i<get_dimension(); i++) {
		if (mutate_flags[i]) {
			const Expression* e = indices[i];
			assert(e->term_type == eVariable);
			const ExpressionVariable* ev = dynamic_cast<const ExpressionVariable*>(e);
			// create a mutated index from the original by adding an constant offset
			FunctionInvocation* fi = new FunctionInvocationBinary(eAdd, 0);
        	fi->add_operand(new ExpressionVariable(*(ev->get_var())));
			int offset = rnd_upto(sizes[i]);
			if (offset == 0) offset = 1;	// give offset 1 more chance
			ERROR_GUARD(NULL);
			ostringstream oss;
			oss << offset;
        	fi->add_operand(new Constant(get_int_type(), oss.str()));
        	Expression* mutated_e = new ExpressionFuncall(*fi);
			new_indices.push_back(mutated_e);
		}
		else {
			new_indices.push_back(indices[i]->clone());
		}
	}
	// if index of at least one dimension mutated, return the new variable
	return VariableSelector::create_mutated_array_var(this, new_indices);
}
Ejemplo n.º 5
0
bool FunctionInvocation::FunctionInvocationCompare::operator ()(FunctionInvocation const& lhs, FunctionInvocation const& rhs) const
{
    // Check the function names first
    if (lhs.getFunctionName() != rhs.getFunctionName())
        return false;

    // Next check the return type
    if (lhs.getReturnType() != rhs.getReturnType())
        return false;

    // Check the number of operands
    if (lhs.mOperands.size() != rhs.mOperands.size())
        return false;

    // Now that we've gotten past the two quick tests, iterate over operands
    // Check the semantic and type.  The operands must be in the same order as well.
    OperandVector::const_iterator itLHSOps = lhs.mOperands.begin();
    OperandVector::const_iterator itRHSOps = rhs.mOperands.begin();
    for ( ; ((itLHSOps != lhs.mOperands.end()) && (itRHSOps != rhs.mOperands.end())); ++itLHSOps, ++itRHSOps)
    {
        if (itLHSOps->getSemantic() != itRHSOps->getSemantic())
            return false;

        GpuConstantType leftType    = itLHSOps->getParameter()->getType();
        GpuConstantType rightType   = itRHSOps->getParameter()->getType();
        
        if (Ogre::Root::getSingletonPtr()->getRenderSystem()->getName().find("OpenGL ES 2") != String::npos)
        {
            if (leftType == GCT_SAMPLER1D)
                leftType = GCT_SAMPLER2D;

            if (rightType == GCT_SAMPLER1D)
                rightType = GCT_SAMPLER2D;
        }

        // If a swizzle mask is being applied to the parameter, generate the GpuConstantType to
        // perform the parameter type comparison the way that the compiler will see it.
        if ((itLHSOps->getFloatCount(itLHSOps->getMask()) > 0) ||
           (itRHSOps->getFloatCount(itRHSOps->getMask()) > 0))
        {
            if (itLHSOps->getFloatCount(itLHSOps->getMask()) > 0)
            {
                leftType = (GpuConstantType)((itLHSOps->getParameter()->getType() - itLHSOps->getParameter()->getType()) +
                                             itLHSOps->getFloatCount(itLHSOps->getMask()));
            }
            if (itRHSOps->getFloatCount(itRHSOps->getMask()) > 0)
            {
                rightType = (GpuConstantType)((itRHSOps->getParameter()->getType() - itRHSOps->getParameter()->getType()) +
                                             itRHSOps->getFloatCount(itRHSOps->getMask()));
            }
        }

        if (leftType != rightType)
            return false;
    }

    // Passed all tests, they are the same
    return true;
}
//-----------------------------------------------------------------------
void DualQuaternionSkinning::addIndexedPositionWeight(Function* vsMain, int index,
								ParameterPtr& pWorldMatrix, ParameterPtr& pPositionTempParameter,
								ParameterPtr& pPositionRelatedOutputParam, int& funcCounter)
{
	Operand::OpMask indexMask = indexToMask(index);
	FunctionInvocation* curFuncInvocation;

	//multiply position with world matrix and put into temporary param
	curFuncInvocation = OGRE_NEW FunctionInvocation(SGX_FUNC_BLEND_WEIGHT, FFP_VS_TRANSFORM, funcCounter++);
	curFuncInvocation->pushOperand(mParamInWeights, Operand::OPS_IN, indexMask);
	curFuncInvocation->pushOperand(pWorldMatrix, Operand::OPS_IN);
	curFuncInvocation->pushOperand(pPositionTempParameter, Operand::OPS_OUT);
	vsMain->addAtomInstance(curFuncInvocation);

	//check if on first iteration
	if (index == 0)
	{
		//set the local param as the value of the world param
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, FFP_VS_TRANSFORM, funcCounter++);
		curFuncInvocation->pushOperand(pPositionTempParameter, Operand::OPS_IN);
		curFuncInvocation->pushOperand(pPositionRelatedOutputParam, Operand::OPS_OUT);
		vsMain->addAtomInstance(curFuncInvocation);
	}
	else
	{
		//add the local param as the value of the world param
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ADD, FFP_VS_TRANSFORM, funcCounter++);
		curFuncInvocation->pushOperand(pPositionTempParameter, Operand::OPS_IN);
		curFuncInvocation->pushOperand(pPositionRelatedOutputParam, Operand::OPS_IN);
		curFuncInvocation->pushOperand(pPositionRelatedOutputParam, Operand::OPS_OUT);
		vsMain->addAtomInstance(curFuncInvocation);
	}
}
Ejemplo n.º 7
0
bool FunctionInvocation::FunctionInvocationLessThan::operator ()(FunctionInvocation const& lhs, FunctionInvocation const& rhs) const
{
    // Check the function names first
    // Adding an exception to std::string sorting.  I feel that functions beginning with an underscore should be placed before
    // functions beginning with an alphanumeric character.  By default strings are sorted based on the ASCII value of each character.
    // Underscores have an ASCII value in between capital and lowercase characters.  This is why the exception is needed.
    if (lhs.getFunctionName() < rhs.getFunctionName())
    {
        if(rhs.getFunctionName().at(0) == '_')
            return false;
        else
            return true;
    }
    if (lhs.getFunctionName() > rhs.getFunctionName())
    {
        if(lhs.getFunctionName().at(0) == '_')
            return true;
        else
            return false;
    }

    // Next check the return type
    if (lhs.getReturnType() < rhs.getReturnType())
        return true;
    if (lhs.getReturnType() > rhs.getReturnType())
        return false;

    // Check the number of operands
    if (lhs.mOperands.size() < rhs.mOperands.size())
        return true;
    if (lhs.mOperands.size() > rhs.mOperands.size())
        return false;

    // Now that we've gotten past the two quick tests, iterate over operands
    // Check the semantic and type.  The operands must be in the same order as well.
    OperandVector::const_iterator itLHSOps = lhs.mOperands.begin();
    OperandVector::const_iterator itRHSOps = rhs.mOperands.begin();

    for ( ; itLHSOps != lhs.mOperands.end(), itRHSOps != rhs.mOperands.end(); ++itLHSOps, ++itRHSOps)
    {
        if (itLHSOps->getSemantic() < itRHSOps->getSemantic())
            return true;
        if (itLHSOps->getSemantic() > itRHSOps->getSemantic())
            return false;

        if (itLHSOps->getParameter()->getType() < itRHSOps->getParameter()->getType())
            return true;
        if (itLHSOps->getParameter()->getType() > itRHSOps->getParameter()->getType())
            return false;
    }

    return true;
}
//-----------------------------------------------------------------------
void LayeredBlending::addPSBlendInvocations(Function* psMain, 
                                         ParameterPtr arg1,
                                         ParameterPtr arg2,
                                         ParameterPtr texel,
                                         int samplerIndex,
                                         const LayerBlendModeEx& blendMode,
                                         const int groupOrder, 
                                         int& internalCounter,
                                         int targetChannels)
{
    //
    // Add the modifier invocation
    //

    addPSModifierInvocation(psMain, samplerIndex, arg1, arg2, groupOrder, internalCounter, targetChannels);

    //
    // Add the blending function invocations
    //

    BlendMode mode = getBlendMode(samplerIndex);
    
    if ((LB_FFPBlend == mode) || (LB_Invalid == mode))
    {
        FFPTexturing::addPSBlendInvocations(psMain, arg1, arg2, texel, samplerIndex, blendMode, groupOrder, internalCounter, targetChannels);
    }
    else 
    {
        //find the function name for the blend mode
        String funcName;
        for(int i = 0 ; i < (int)LayeredBlending::LB_MaxBlendModes ; ++i)
        {
            if (_blendModes[i].type == mode)
            {
                funcName = _blendModes[i].funcName;
                break;
            }
        }

        //add the function of the blend mode
        if (funcName.empty() == false)
        {
            FunctionInvocation* curFuncInvocation = OGRE_NEW FunctionInvocation(funcName, groupOrder, internalCounter++);
            curFuncInvocation->pushOperand(arg1, Operand::OPS_IN, targetChannels);
            curFuncInvocation->pushOperand(arg2, Operand::OPS_IN, targetChannels);
            curFuncInvocation->pushOperand(mPSOutDiffuse, Operand::OPS_OUT, targetChannels);        
            psMain->addAtomInstance(curFuncInvocation); 
        }
    }
}
//-----------------------------------------------------------------------
bool ShaderExInstancedViewports::addPSInvocations( Function* psMain, const int groupOrder )
{
	FunctionInvocation* funcInvocation = NULL;
	int internalCounter = 0;

	funcInvocation = OGRE_NEW FunctionInvocation(SGX_FUNC_INSTANCED_VIEWPORTS_DISCARD_OUT_OF_BOUNDS, groupOrder, internalCounter++);
	funcInvocation->pushOperand(mPSInMonitorsCount, Operand::OPS_IN);
	funcInvocation->pushOperand(mPSInMonitorIndex, Operand::OPS_IN);
	funcInvocation->pushOperand(mPSInPositionProjectiveSpace, Operand::OPS_IN);
	
	psMain->addAtomInstance(funcInvocation);

	return true;
}
//-----------------------------------------------------------------------
void LayeredBlending::addPSModifierInvocation(Function* psMain, 
                                         int samplerIndex, 
                                         ParameterPtr arg1,
                                         ParameterPtr arg2,
                                         const int groupOrder, 
                                         int& internalCounter,
                                         int targetChannels)
{
    SourceModifier modType;
    int customNum;
    if (getSourceModifier(samplerIndex, modType, customNum) == true)
    {
        ParameterPtr modifiedParam;
        String funcName;
        switch (modType)
        {
        case SM_Source1Modulate: 
            funcName = "SGX_src_mod_modulate";
            modifiedParam = arg1;
            break;
        case SM_Source2Modulate:
            funcName = "SGX_src_mod_modulate";
            modifiedParam = arg2;
            break;
        case SM_Source1InvModulate:
            funcName = "SGX_src_mod_inv_modulate";
            modifiedParam = arg1;
            break;
        case SM_Source2InvModulate:
            funcName = "SGX_src_mod_inv_modulate";
            modifiedParam = arg2;
            break;
        default:
            break;
        }

        //add the function of the blend mode
        if (funcName.empty() == false)
        {
            ParameterPtr& controlParam = mTextureBlends[samplerIndex].modControlParam;

            FunctionInvocation* curFuncInvocation = OGRE_NEW FunctionInvocation(funcName, groupOrder, internalCounter++);
            curFuncInvocation->pushOperand(modifiedParam, Operand::OPS_IN, targetChannels);
            curFuncInvocation->pushOperand(controlParam, Operand::OPS_IN, targetChannels);
            curFuncInvocation->pushOperand(modifiedParam, Operand::OPS_OUT, targetChannels);        
            psMain->addAtomInstance(curFuncInvocation); 
        }
    }
}
Ejemplo n.º 11
0
//-----------------------------------------------------------------------
void FFPTexturing::addPSSampleTexelInvocation(TextureUnitParams* textureUnitParams, Function* psMain, 
											  const ParameterPtr& texel, int groupOrder, int& internalCounter)
{
	FunctionInvocation* curFuncInvocation = NULL;

	if (textureUnitParams->mTexCoordCalcMethod == TEXCALC_PROJECTIVE_TEXTURE)
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_SAMPLE_TEXTURE_PROJ, groupOrder, internalCounter++);
	else	
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_SAMPLE_TEXTURE, groupOrder, internalCounter++);

	curFuncInvocation->pushOperand(textureUnitParams->mTextureSampler, Operand::OPS_IN);
	curFuncInvocation->pushOperand(textureUnitParams->mPSInputTexCoord, Operand::OPS_IN);
	curFuncInvocation->pushOperand(texel, Operand::OPS_OUT);
	psMain->addAtomInstance(curFuncInvocation);
}
Ejemplo n.º 12
0
		bool FFPAlphaTest::addFunctionInvocations( ProgramSet* programSet )
		{
			Program* psProgram = programSet->getCpuFragmentProgram();
			Function* psMain = psProgram->getEntryPointFunction();

			FunctionInvocation *curFuncInvocation;

			//Fragment shader invocations
			curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ALPHA_TEST, FFP_PS_ALPHA_TEST, 0);
			curFuncInvocation->pushOperand(mPSAlphaFunc, Operand::OPS_IN);
			curFuncInvocation->pushOperand(mPSAlphaRef, Operand::OPS_IN);
			curFuncInvocation->pushOperand(mPSOutDiffuse, Operand::OPS_IN);

			psMain->addAtomInstance(curFuncInvocation);	

			return true;
		}
//-----------------------------------------------------------------------
bool RTShaderSRSSegmentedLights::addVSInvocation(Function* vsMain, const int groupOrder, int& internalCounter)
{
    FunctionInvocation* curFuncInvocation = NULL;

    if (mVSInNormal.get() != NULL)
    {
        // Transform normal in world space.
        curFuncInvocation = OGRE_NEW FunctionInvocation(SL_FUNC_TRANSFORMNORMAL, groupOrder, internalCounter++); 
        curFuncInvocation->pushOperand(mWorldITMatrix, Operand::OPS_IN);
        curFuncInvocation->pushOperand(mVSInNormal, Operand::OPS_IN);
        curFuncInvocation->pushOperand(mVSOutNormal, Operand::OPS_OUT); 
        vsMain->addAtomInstance(curFuncInvocation);
    }

    // Transform world space position if need to.
    if (mVSOutWorldPos.get() != NULL)
    {
        curFuncInvocation = OGRE_NEW FunctionInvocation(SL_FUNC_TRANSFORMPOSITION, groupOrder, internalCounter++); 
        curFuncInvocation->pushOperand(mWorldMatrix, Operand::OPS_IN);
        curFuncInvocation->pushOperand(mVSInPosition, Operand::OPS_IN);
        curFuncInvocation->pushOperand(mVSOutWorldPos, Operand::OPS_OUT);   
        vsMain->addAtomInstance(curFuncInvocation);
    }


    return true;
}
//-----------------------------------------------------------------------
bool IntegratedPSSM3::addVSInvocation(Function* vsMain, const int groupOrder, int& internalCounter)
{
    FunctionInvocation* curFuncInvocation;

    // Output the vertex depth in camera space.
    curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, groupOrder, internalCounter++);                                
    curFuncInvocation->pushOperand(mVSOutPos, Operand::OPS_IN, Operand::OPM_Z); 
    curFuncInvocation->pushOperand(mVSOutDepth, Operand::OPS_OUT);  
    vsMain->addAtomInstance(curFuncInvocation); 


    // Compute world space position.    
    ShadowTextureParamsIterator it = mShadowTextureParamsList.begin();

    while(it != mShadowTextureParamsList.end())
    {
        curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_TRANSFORM, groupOrder, internalCounter++);                                 
        curFuncInvocation->pushOperand(it->mWorldViewProjMatrix, Operand::OPS_IN);  
        curFuncInvocation->pushOperand(mVSInPos, Operand::OPS_IN);
        curFuncInvocation->pushOperand(it->mVSOutLightPosition, Operand::OPS_OUT);  
        vsMain->addAtomInstance(curFuncInvocation); 

        ++it;
    }

    return true;
}
//-----------------------------------------------------------------------
void HardwareSkinning::addNormalRelatedCalculations(Function* vsMain,
								ParameterPtr& pNormalRelatedParam, 
								ParameterPtr& pNormalWorldRelatedParam, 
								int& funcCounter)
{
	FunctionInvocation* curFuncInvocation;
	
	if (mDoBoneCalculations == true)
	{
		//set functions to calculate world normal
		for(int i = 0 ; i < getWeightCount() ; ++i)
		{
			addIndexedNormalRelatedWeight(vsMain, pNormalRelatedParam, pNormalWorldRelatedParam, i, funcCounter);
		}

		//update back the original position relative to the object
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_TRANSFORM, FFP_VS_TRANSFORM, funcCounter++); 								
		curFuncInvocation->pushOperand(mParamInInvWorldMatrix, Operand::OPS_IN);
		curFuncInvocation->pushOperand(pNormalWorldRelatedParam, Operand::OPS_IN);
		curFuncInvocation->pushOperand(pNormalRelatedParam, Operand::OPS_OUT);
		vsMain->addAtomInstance(curFuncInvocation);	
	}
	else
	{
		//update from object to world space
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_TRANSFORM, FFP_VS_TRANSFORM, funcCounter++); 								
		curFuncInvocation->pushOperand(mParamInWorldMatrix, Operand::OPS_IN);
		curFuncInvocation->pushOperand(pNormalRelatedParam, Operand::OPS_IN);
		curFuncInvocation->pushOperand(pNormalWorldRelatedParam, Operand::OPS_OUT);
		vsMain->addAtomInstance(curFuncInvocation);	
	}

}
Ejemplo n.º 16
0
//-----------------------------------------------------------------------
bool FFPTransform::createCpuSubPrograms(ProgramSet* programSet)
{
	Program* vsProgram = programSet->getCpuVertexProgram();
	
	// Resolve World View Projection Matrix.
	UniformParameterPtr wvpMatrix = vsProgram->resolveAutoParameterInt(GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX, 0);
	if (wvpMatrix.get() == NULL)
		return false;
		
	Function* vsEntry = vsProgram->getEntryPointFunction();
	assert(vsEntry != NULL);

	// Resolve input position parameter.
	ParameterPtr positionIn = vsEntry->resolveInputParameter(Parameter::SPS_POSITION, 0, Parameter::SPC_POSITION_OBJECT_SPACE, GCT_FLOAT4);	
	if (positionIn.get() == NULL)
		return false;
	

	// Resolve output position parameter.
	ParameterPtr positionOut = vsEntry->resolveOutputParameter(Parameter::SPS_POSITION, 0, Parameter::SPC_POSITION_PROJECTIVE_SPACE, GCT_FLOAT4);
	if (positionOut.get() == NULL)
		return false;
	

	// Add dependency.
	vsProgram->addDependency(FFP_LIB_TRANSFORM);

	FunctionInvocation* transformFunc = OGRE_NEW FunctionInvocation(FFP_FUNC_TRANSFORM,  FFP_VS_TRANSFORM, 0); 

	transformFunc->pushOperand(wvpMatrix, Operand::OPS_IN);
	transformFunc->pushOperand(positionIn, Operand::OPS_IN);
	transformFunc->pushOperand(positionOut, Operand::OPS_OUT);

	vsEntry->addAtomInstace(transformFunc);

	return true;
}
Ejemplo n.º 17
0
//-----------------------------------------------------------------------
bool ShaderExReflectionMap::addPSInvocations( Function* psMain, const int groupOrder )
{
	FunctionInvocation* funcInvoaction = NULL;
	int internalCounter = 0;

	funcInvoaction = OGRE_NEW FunctionInvocation(SGX_FUNC_APPLY_REFLECTION_MAP, groupOrder, internalCounter++);
	funcInvoaction->pushOperand(mMaskMapSampler, Operand::OPS_IN);
	funcInvoaction->pushOperand(mPSInMaskTexcoord, Operand::OPS_IN);
	funcInvoaction->pushOperand(mReflectionMapSampler, Operand::OPS_IN);
	funcInvoaction->pushOperand(mPSInReflectionTexcoord, Operand::OPS_IN);	
	funcInvoaction->pushOperand(mPSOutDiffuse, Operand::OPS_IN,(Operand::OPM_X | Operand::OPM_Y | Operand::OPM_Z));
	funcInvoaction->pushOperand(mReflectionPower, Operand::OPS_IN);
	funcInvoaction->pushOperand(mPSOutDiffuse, Operand::OPS_OUT,(Operand::OPM_X | Operand::OPM_Y | Operand::OPM_Z));
	
	psMain->addAtomInstace(funcInvoaction);

	return true;
}
Ejemplo n.º 18
0
//-----------------------------------------------------------------------------
void ProgramProcessor::generateLocalSplitParameters(Function* func, GpuProgramType progType,
												   MergeParameterList& mergedParams, 
												   ShaderParameterList& splitParams, LocalParameterMap& localParamsMap)
{
	// No split params created.
	if (splitParams.size() == 0)	
		return;	

	// Create the local parameters + map from source to local.
	for (unsigned int i=0; i < splitParams.size(); ++i)
	{
		ParameterPtr srcParameter   = splitParams[i];
		ParameterPtr localParameter = func->resolveLocalParameter(srcParameter->getSemantic(), srcParameter->getIndex(), "lsplit_" + srcParameter->getName(), srcParameter->getType());

		localParamsMap[srcParameter.get()] = localParameter;		
	}	

	int invocationCounter = 0;

	// Establish link between the local parameter to the merged parameter.
	for (unsigned int i=0; i < mergedParams.size(); ++i)
	{
		MergeParameter& curMergeParameter = mergedParams[i];

		for (unsigned int p=0; p < curMergeParameter.getSourceParameterCount(); ++p)
		{
			ParameterPtr srcMergedParameter    = curMergeParameter.getSourceParameter(p);
			LocalParameterMap::iterator itFind = localParamsMap.find(srcMergedParameter.get());

			// Case the source parameter is split parameter.
			if (itFind != localParamsMap.end())
			{
				// Case it is the vertex shader -> assign the local parameter to the output merged parameter.
				if (progType == GPT_VERTEX_PROGRAM)
				{
					FunctionInvocation* curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, FFP_VS_POST_PROCESS, invocationCounter++);
					
					curFuncInvocation->pushOperand(itFind->second, Operand::OPS_IN, curMergeParameter.getSourceParameterMask(p));
					curFuncInvocation->pushOperand(curMergeParameter.getDestinationParameter(Operand::OPS_OUT, i), Operand::OPS_OUT, curMergeParameter.getDestinationParameterMask(p));		
					func->addAtomInstance(curFuncInvocation);		
				}
				else if (progType == GPT_FRAGMENT_PROGRAM)
				{
					FunctionInvocation* curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, FFP_PS_PRE_PROCESS, invocationCounter++);
					
					curFuncInvocation->pushOperand(curMergeParameter.getDestinationParameter(Operand::OPS_IN, i), Operand::OPS_IN, curMergeParameter.getDestinationParameterMask(p));		
					curFuncInvocation->pushOperand(itFind->second, Operand::OPS_OUT, curMergeParameter.getSourceParameterMask(p));
					func->addAtomInstance(curFuncInvocation);		
				}
			}
		}
	}				
}
//-----------------------------------------------------------------------
bool RTShaderSRSSegmentedLights::addPSFinalAssignmentInvocation( Function* psMain, const int groupOrder, int& internalCounter )
{
    FunctionInvocation* curFuncInvocation;

    curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, FFP_PS_COLOUR_BEGIN + 1, internalCounter++);                               
    curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_IN);  
    curFuncInvocation->pushOperand(mPSDiffuse, Operand::OPS_OUT);   
    psMain->addAtomInstance(curFuncInvocation); 

    curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, FFP_PS_COLOUR_BEGIN + 1, internalCounter++);                               
    curFuncInvocation->pushOperand(mPSDiffuse, Operand::OPS_IN);    
    curFuncInvocation->pushOperand(mPSOutDiffuse, Operand::OPS_OUT);    
    psMain->addAtomInstance(curFuncInvocation);

    if (mSpecularEnable)
    {
        curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, FFP_PS_COLOUR_BEGIN + 1, internalCounter++); 
        curFuncInvocation->pushOperand(mPSTempSpecularColour, Operand::OPS_IN);
        curFuncInvocation->pushOperand(mPSSpecular, Operand::OPS_OUT);          
        psMain->addAtomInstance(curFuncInvocation); 
    }

    return true;
}
//-----------------------------------------------------------------------
void DualQuaternionSkinning::adjustForCorrectAntipodality(Function* vsMain,
								int index, int& funcCounter, const ParameterPtr& pTempWorldMatrix)
{
	FunctionInvocation* curFuncInvocation;
	
	//Antipodality doesn't need to be adjusted for dq0 on itself (used as the basis of antipodality calculations)
	if(index > 0)
	{
		curFuncInvocation = OGRE_NEW FunctionInvocation(SGX_FUNC_ANTIPODALITY_ADJUSTMENT, FFP_VS_TRANSFORM, funcCounter++);
		//This is the base dual quaternion dq0, which the antipodality calculations are based on
		curFuncInvocation->pushOperand(mParamInitialDQ, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mParamTempFloat2x4, Operand::OPS_IN);
		curFuncInvocation->pushOperand(pTempWorldMatrix, Operand::OPS_OUT);
		vsMain->addAtomInstance(curFuncInvocation);
	}
	else if(index == 0)
	{	
		//Set the first dual quaternion as the initial dq
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, FFP_VS_TRANSFORM, funcCounter++);
		curFuncInvocation->pushOperand(mParamTempFloat2x4, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mParamInitialDQ, Operand::OPS_OUT);
		vsMain->addAtomInstance(curFuncInvocation);
	}
}
//-----------------------------------------------------------------------
bool FFPFog::addFunctionInvocations(ProgramSet* programSet)
{
	if (mFogMode == FOG_NONE)
		return true;

	Program* vsProgram = programSet->getCpuVertexProgram();
	Program* psProgram = programSet->getCpuFragmentProgram();
	Function* vsMain = vsProgram->getEntryPointFunction();
	Function* psMain = psProgram->getEntryPointFunction();
	FunctionInvocation* curFuncInvocation = NULL;	
	int internalCounter;


	// Per pixel fog.
	if (mCalcMode == CM_PER_PIXEL)
	{
		internalCounter = 0;
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_PIXELFOG_DEPTH, FFP_VS_FOG, internalCounter++);
		curFuncInvocation->pushOperand(mWorldViewProjMatrix, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mVSInPos, Operand::OPS_IN);	
		curFuncInvocation->pushOperand(mVSOutDepth, Operand::OPS_OUT);	
		vsMain->addAtomInstace(curFuncInvocation);		

		internalCounter = 0;
		switch (mFogMode)
		{
		case FOG_LINEAR:
			curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_PIXELFOG_LINEAR, FFP_PS_FOG, internalCounter++);
			break;
		case FOG_EXP:
			curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_PIXELFOG_EXP, FFP_PS_FOG, internalCounter++);
			break;
		case FOG_EXP2:
			curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_PIXELFOG_EXP2, FFP_PS_FOG, internalCounter++);
			break;
        case FOG_NONE:
        default:
            break;
		}

		curFuncInvocation->pushOperand(mPSInDepth, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mFogParams, Operand::OPS_IN);	
		curFuncInvocation->pushOperand(mFogColour, Operand::OPS_IN);		
		curFuncInvocation->pushOperand(mPSOutDiffuse, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mPSOutDiffuse, Operand::OPS_OUT);
		psMain->addAtomInstace(curFuncInvocation);	
		
	}

	// Per vertex fog.
	else
	{
		internalCounter = 0;

		switch (mFogMode)
		{
		case FOG_LINEAR:
			curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_VERTEXFOG_LINEAR, FFP_VS_FOG, internalCounter++);
			break;
		case FOG_EXP:
			curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_VERTEXFOG_EXP, FFP_VS_FOG, internalCounter++);
			break;
		case FOG_EXP2:
			curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_VERTEXFOG_EXP2, FFP_VS_FOG, internalCounter++);
			break;
        case FOG_NONE:
        default:
            break;
		}
			
		curFuncInvocation->pushOperand(mWorldViewProjMatrix, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mVSInPos, Operand::OPS_IN);		
		curFuncInvocation->pushOperand(mFogParams, Operand::OPS_IN);		
		curFuncInvocation->pushOperand(mVSOutFogFactor, Operand::OPS_OUT);
		vsMain->addAtomInstace(curFuncInvocation);		


		internalCounter = 0;

		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_LERP, FFP_PS_FOG, internalCounter++);
		curFuncInvocation->pushOperand(mFogColour, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mPSOutDiffuse, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mPSInFogFactor, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mPSOutDiffuse, Operand::OPS_OUT);
		psMain->addAtomInstace(curFuncInvocation);	
	}



	return true;
}
//-----------------------------------------------------------------------
bool ShaderExInstancedViewports::addVSInvocations( Function* vsMain, const int groupOrder )
{
	FunctionInvocation* funcInvocation = NULL;
	int internalCounter = 0;
	
    funcInvocation = OGRE_NEW FunctionInvocation(SGX_FUNC_INSTANCED_VIEWPORTS_TRANSFORM, groupOrder, internalCounter++);
    funcInvocation->pushOperand(mVSInPosition, Operand::OPS_IN);
    funcInvocation->pushOperand(mWorldViewMatrix, Operand::OPS_IN);
    funcInvocation->pushOperand(mProjectionMatrix, Operand::OPS_IN);
    funcInvocation->pushOperand(mVSInViewportOffsetMatrixR0, Operand::OPS_IN);
    funcInvocation->pushOperand(mVSInViewportOffsetMatrixR1, Operand::OPS_IN);
    funcInvocation->pushOperand(mVSInViewportOffsetMatrixR2, Operand::OPS_IN);
    funcInvocation->pushOperand(mVSInViewportOffsetMatrixR3, Operand::OPS_IN);
    funcInvocation->pushOperand(mVSInMonitorsCount, Operand::OPS_IN);
    funcInvocation->pushOperand(mVSInMonitorIndex, Operand::OPS_IN);
    funcInvocation->pushOperand(mVSOriginalOutPositionProjectiveSpace, Operand::OPS_OUT);
    vsMain->addAtomInstance(funcInvocation);

	// Output position in projective space.
    funcInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN,  groupOrder, internalCounter++); 
    funcInvocation->pushOperand(mVSOriginalOutPositionProjectiveSpace, Operand::OPS_IN);
    funcInvocation->pushOperand(mVSOutPositionProjectiveSpace, Operand::OPS_OUT);
    vsMain->addAtomInstance(funcInvocation);

	// Output monitor index.
    funcInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN,  groupOrder, internalCounter++); 
    funcInvocation->pushOperand(mVSInMonitorIndex, Operand::OPS_IN);
    funcInvocation->pushOperand(mVSOutMonitorIndex, Operand::OPS_OUT);
    vsMain->addAtomInstance(funcInvocation);

	return true;
}
//-----------------------------------------------------------------------
void GLSLProgramWriter::writeSourceCode(std::ostream& os, Program* program)
{
	GpuProgramType gpuType = program->getType();
	if(gpuType == GPT_GEOMETRY_PROGRAM)
	{
		OGRE_EXCEPT( Exception::ERR_NOT_IMPLEMENTED, 
			"Geometry Program not supported in GLSL writer ", 
			"GLSLProgramWriter::writeSourceCode" );	
	}

	// Clear out old input params
	mFragInputParams.clear();

	const ShaderFunctionList& functionList = program->getFunctions();
	ShaderFunctionConstIterator itFunction;

	const UniformParameterList& parameterList = program->getParameters();
	UniformParameterConstIterator itUniformParam = parameterList.begin();
	
	// Write the current version (this force the driver to more fulfill the glsl standard)
	os << "#version "<< mGLSLVersion << std::endl;

	// Generate source code header.
	writeProgramTitle(os, program);
	os<< std::endl;

	// Write forward declarations
	writeForwardDeclarations(os, program);
	os<< std::endl;
	
	// Generate global variable code.
	writeUniformParametersTitle(os, program);
	os << std::endl;

	// Write the uniforms 
	for (itUniformParam = parameterList.begin();  itUniformParam != parameterList.end(); ++itUniformParam)
	{
		ParameterPtr pUniformParam = *itUniformParam;

		os << "uniform\t"; 
		os << mGpuConstTypeMap[pUniformParam->getType()];
		os << "\t";	
		os << pUniformParam->getName();
		if (pUniformParam->isArray() == true)
		{
			os << "[" << pUniformParam->getSize() << "]";	
		}
		os << ";" << std::endl;		
	}
	os << std::endl;			

	// Write program function(s).
	for (itFunction=functionList.begin(); itFunction != functionList.end(); ++itFunction)
	{
		Function* curFunction = *itFunction;

		writeFunctionTitle(os, curFunction);
		
		// Clear output mapping this map is used when we use
		// glsl built in types like gl_Color for example
		mInputToGLStatesMap.clear();

		// Write inout params and fill mInputToGLStatesMap
		writeInputParameters(os, curFunction, gpuType);
		writeOutParameters(os, curFunction, gpuType);
					
		// The function name must always main.
		os << "void main(void) {" << std::endl;

		// Write local parameters.
		const ShaderParameterList& localParams = curFunction->getLocalParameters();
		ShaderParameterConstIterator itParam = localParams.begin();
		ShaderParameterConstIterator itParamEnd = localParams.end();

		for (; itParam != itParamEnd; ++itParam)
		{
			os << "\t";
			writeLocalParameter(os, *itParam);			
			os << ";" << std::endl;						
		}
		os << std::endl;			

		// Sort function atoms.
		curFunction->sortAtomInstances();
		
		const FunctionAtomInstanceList& atomInstances = curFunction->getAtomInstances();
		FunctionAtomInstanceConstIterator itAtom = atomInstances.begin();
		FunctionAtomInstanceConstIterator itAtomEnd = atomInstances.end();

		for (; itAtom != itAtomEnd; ++itAtom)
		{		
			FunctionInvocation*  pFuncInvoc = (FunctionInvocation*)*itAtom;
			FunctionInvocation::OperandVector::iterator itOperand = pFuncInvoc->getOperandList().begin();
			FunctionInvocation::OperandVector::iterator itOperandEnd = pFuncInvoc->getOperandList().end();

			// Local string stream
			StringStream localOs;

			// Write function name			
			localOs << "\t" << pFuncInvoc->getFunctionName() << "(";

			ushort curIndLevel = 0;

			for (; itOperand != itOperandEnd; )
			{
				Operand op = *itOperand;
				Operand::OpSemantic opSemantic = op.getSemantic();
				String paramName = op.getParameter()->getName();
				Parameter::Content content = op.getParameter()->getContent();

				if (opSemantic == Operand::OPS_OUT || opSemantic == Operand::OPS_INOUT)
				{
					// Is the written parameter a varying 
					bool isVarying = false;

					// Check if we write to an varying because the are only readable in fragment programs 
					if (gpuType == GPT_FRAGMENT_PROGRAM)
					{	
						StringVector::iterator itFound = std::find(mFragInputParams.begin(), mFragInputParams.end(), paramName);	
						if(itFound != mFragInputParams.end())
						{						
							// Declare the copy variable
							String newVar = "local_" + paramName;
							String tempVar = paramName;
							isVarying = true;

							// We stored the original values in the mFragInputParams thats why we have to replace the first var with o
							// because all vertex output vars are prefixed with o in glsl the name has to match in the fragment program.
							tempVar.replace(tempVar.begin(), tempVar.begin() + 1, "o");

							// Declare the copy variable and assign the original
							os << "\t" << mGpuConstTypeMap[op.getParameter()->getType()] << " " << newVar << " = " << tempVar << ";\n" << std::endl;	

							// From now on we replace it automatic 
							mInputToGLStatesMap[paramName] = newVar;

							// Remove the param because now it is replaced automatic with the local variable
							// (which could be written).
							mFragInputParams.erase(itFound++);
						}
					}
					
					// If its not a varying param check if a uniform is written
					if(!isVarying)
					{
						UniformParameterList::const_iterator itFound = std::find_if( parameterList.begin(), parameterList.end(), std::bind2nd( CompareUniformByName(), paramName ) );
						if(itFound != parameterList.end())
						{	
							// Declare the copy variable
							String newVar = "local_" + paramName;

							// now we check if we already declared a uniform redirector var
							if(mInputToGLStatesMap.find(newVar) == mInputToGLStatesMap.end())
							{
								// Declare the copy variable and assign the original
								os << "\t" << mGpuConstTypeMap[itFound->get()->getType()] << " " << newVar << " = " << paramName << ";\n" << std::endl;	

								// From now on we replace it automatic 
								mInputToGLStatesMap[paramName] = newVar;
							}
						}
					}
				}

				if(mInputToGLStatesMap.find(paramName) != mInputToGLStatesMap.end())
				{
					int mask = op.getMask(); // our swizzle mask

					// Here we insert the renamed param name
					localOs << mInputToGLStatesMap[paramName];

					if(mask != Operand::OPM_ALL)
					{
						localOs << "." << Operand::getMaskAsString(mask);
					}	
					// Now that every texcoord is a vec4 (passed as vertex attributes) we
					// have to swizzle them according the desired type.
					else if(gpuType == GPT_VERTEX_PROGRAM &&
							(content == Parameter::SPC_TEXTURE_COORDINATE0 ||
							content == Parameter::SPC_TEXTURE_COORDINATE1 ||
							content == Parameter::SPC_TEXTURE_COORDINATE2 ||
							content == Parameter::SPC_TEXTURE_COORDINATE3 ||
							content == Parameter::SPC_TEXTURE_COORDINATE4 ||
							content == Parameter::SPC_TEXTURE_COORDINATE5 ||
							content == Parameter::SPC_TEXTURE_COORDINATE6 ||
							content == Parameter::SPC_TEXTURE_COORDINATE7) )
					{
						// Now generate the swizzel mask according
						// the type.
						switch(op.getParameter()->getType())
						{
						case GCT_FLOAT1:
							localOs << ".x";
							break;
						case GCT_FLOAT2:
							localOs << ".xy";
							break;
						case GCT_FLOAT3:
							localOs << ".xyz";
							break;
						case GCT_FLOAT4:
							localOs << ".xyzw";
							break;

						default:
							break;
						}
					}						
				}
				else
				{
					localOs << op.toString();
				}
				
				++itOperand;

				// Prepare for the next operand
				ushort opIndLevel = 0;
				if (itOperand != itOperandEnd)
				{
					opIndLevel = itOperand->getIndirectionLevel();
				}

				if (curIndLevel != 0)
				{
					localOs << ")";
				}

				if (curIndLevel < opIndLevel)
				{
					while (curIndLevel < opIndLevel)
					{
						++curIndLevel;
						localOs << "[";
					}
				}
				else //if (curIndLevel >= opIndLevel)
				{
					while (curIndLevel > opIndLevel)
					{
						--curIndLevel;
						localOs << "]";
					}
					if (opIndLevel != 0)
					{
						localOs << "][";
					}
					else if (itOperand != itOperandEnd)
					{
						localOs << ", ";
					}
				}
				if (curIndLevel != 0)
				{
					localOs << "int(";
				}
			}

			// Write function call closer.
			localOs << ");" << std::endl;
			localOs << std::endl;
			os << localOs.str();
		}
		os << "}" << std::endl;
	}
	os << std::endl;
}
//-----------------------------------------------------------------------
bool RTShaderSRSSegmentedLights::addPSIlluminationInvocation(LightParams* curLightParams, Function* psMain, const int groupOrder, int& internalCounter)
{   
    FunctionInvocation* curFuncInvocation = NULL;   

    
    switch (curLightParams->mType)
    {

    case Light::LT_DIRECTIONAL:         
        if (mSpecularEnable)
        {               
            curFuncInvocation = OGRE_NEW FunctionInvocation(SL_FUNC_LIGHT_DIRECTIONAL_DIFFUSESPECULAR, groupOrder, internalCounter++); 
            curFuncInvocation->pushOperand(mPSLocalNormal, Operand::OPS_IN);
            curFuncInvocation->pushOperand(mPSInWorldPos, Operand::OPS_IN);         
            curFuncInvocation->pushOperand(curLightParams->mDirection, Operand::OPS_IN);
            curFuncInvocation->pushOperand(curLightParams->mDiffuseColour, Operand::OPS_IN);            
            curFuncInvocation->pushOperand(curLightParams->mSpecularColour, Operand::OPS_IN);           
            curFuncInvocation->pushOperand(mSurfaceShininess, Operand::OPS_IN);
            curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_IN, Operand::OPM_XYZ);    
            curFuncInvocation->pushOperand(mPSTempSpecularColour, Operand::OPS_IN, Operand::OPM_XYZ);
            curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_OUT, Operand::OPM_XYZ);   
            curFuncInvocation->pushOperand(mPSTempSpecularColour, Operand::OPS_OUT, Operand::OPM_XYZ);  
            psMain->addAtomInstance(curFuncInvocation);
        }

        else
        {
            curFuncInvocation = OGRE_NEW FunctionInvocation(SL_FUNC_LIGHT_DIRECTIONAL_DIFFUSE, groupOrder, internalCounter++);          
            curFuncInvocation->pushOperand(mPSLocalNormal, Operand::OPS_IN);
            curFuncInvocation->pushOperand(curLightParams->mDirection, Operand::OPS_IN);
            curFuncInvocation->pushOperand(curLightParams->mDiffuseColour, Operand::OPS_IN);                    
            curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_IN, Operand::OPM_XYZ);    
            curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_OUT, Operand::OPM_XYZ);   
            psMain->addAtomInstance(curFuncInvocation); 
        }   
        break;

    case Light::LT_POINT:   
    case Light::LT_SPOTLIGHT:
        {
            curFuncInvocation = OGRE_NEW FunctionInvocation(SL_FUNC_LIGHT_AMBIENT_DIFFUSE, groupOrder, internalCounter++);                      
            curFuncInvocation->pushOperand(mPSLocalNormal, Operand::OPS_IN);
            curFuncInvocation->pushOperand(mPSInWorldPos, Operand::OPS_IN);
            curFuncInvocation->pushOperand(curLightParams->mPosition, Operand::OPS_IN);
            curFuncInvocation->pushOperand(curLightParams->mDirection, Operand::OPS_IN);
            curFuncInvocation->pushOperand(curLightParams->mSpotParams, Operand::OPS_IN);
            curFuncInvocation->pushOperand(curLightParams->mDiffuseColour, Operand::OPS_IN);                    
            curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_INOUT, Operand::OPM_XYZ); 
            psMain->addAtomInstance(curFuncInvocation); 
        }
        break;
    }

    return true;
}
//-----------------------------------------------------------------------
bool RTShaderSRSSegmentedLights::addPSGlobalIlluminationInvocationEnd(Function* psMain, const int groupOrder, int& internalCounter)
{
    FunctionInvocation* curFuncInvocation = NULL;   

    // Merge diffuse colour with vertex colour if need to.
    if (mTrackVertexColourType & TVC_DIFFUSE)           
    {
        curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_MODULATE, groupOrder, internalCounter++); 
        curFuncInvocation->pushOperand(mPSDiffuse, Operand::OPS_IN, Operand::OPM_XYZ);  
        curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_IN, Operand::OPM_XYZ);
        curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_OUT, Operand::OPM_XYZ);
        psMain->addAtomInstance(curFuncInvocation);
    }

    // Merge specular colour with vertex colour if need to.
    if ((mSpecularEnable == true) && (mTrackVertexColourType & TVC_SPECULAR))
    {                           
        curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_MODULATE, groupOrder, internalCounter++); 
        curFuncInvocation->pushOperand(mPSDiffuse, Operand::OPS_IN, Operand::OPM_XYZ);  
        curFuncInvocation->pushOperand(mPSTempSpecularColour, Operand::OPS_IN, Operand::OPM_XYZ);
        curFuncInvocation->pushOperand(mPSTempSpecularColour, Operand::OPS_OUT, Operand::OPM_XYZ);
        psMain->addAtomInstance(curFuncInvocation);
    }


    if ((mTrackVertexColourType & TVC_AMBIENT) == 0 && 
        (mTrackVertexColourType & TVC_EMISSIVE) == 0)
    {
        curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ADD, groupOrder, internalCounter++); 
        curFuncInvocation->pushOperand(mDerivedSceneColour, Operand::OPS_IN, (Operand::OPM_XYZ));
        curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_IN, (Operand::OPM_XYZ));  
        curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_OUT, Operand::OPM_XYZ);   
        psMain->addAtomInstance(curFuncInvocation);     
    }
    else
    {
        if (mTrackVertexColourType & TVC_AMBIENT)
        {
            curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_MODULATE, groupOrder, internalCounter++); 
            curFuncInvocation->pushOperand(mPSDiffuse, Operand::OPS_IN, Operand::OPM_XYZ);          
            curFuncInvocation->pushOperand(mLightAmbientColour, Operand::OPS_IN, Operand::OPM_XYZ);
            curFuncInvocation->pushOperand(mLightAmbientColour, Operand::OPS_OUT, Operand::OPM_XYZ);    
            psMain->addAtomInstance(curFuncInvocation);
        
            curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ADD, groupOrder, internalCounter++); 
            curFuncInvocation->pushOperand(mLightAmbientColour, Operand::OPS_IN, Operand::OPM_XYZ);
            curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_IN, Operand::OPM_XYZ);            
            curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_OUT, Operand::OPM_XYZ);   
            psMain->addAtomInstance(curFuncInvocation);
        }
        else
        {
            curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ADD, groupOrder, internalCounter++); 
            curFuncInvocation->pushOperand(mDerivedAmbientLightColour, Operand::OPS_IN, Operand::OPM_XYZ);  
            curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_IN, Operand::OPM_XYZ);    
            curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_OUT, Operand::OPM_XYZ);   
            psMain->addAtomInstance(curFuncInvocation);
        }

        if (mTrackVertexColourType & TVC_EMISSIVE)
        {
            curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ADD, groupOrder, internalCounter++); 
            curFuncInvocation->pushOperand(mPSDiffuse, Operand::OPS_IN, Operand::OPM_XYZ);
            curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_IN, Operand::OPM_XYZ);
            curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_OUT, Operand::OPM_XYZ);   
            psMain->addAtomInstance(curFuncInvocation);
        }
        else
        {
            curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ADD, groupOrder, internalCounter++); 
            curFuncInvocation->pushOperand(mSurfaceEmissiveColour, Operand::OPS_IN, Operand::OPM_XYZ);
            curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_IN, Operand::OPM_XYZ);
            curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_OUT, Operand::OPM_XYZ);   
            psMain->addAtomInstance(curFuncInvocation);
        }       
    }

    if (mSpecularEnable)
    {
        curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ADD, groupOrder, internalCounter++); 
        curFuncInvocation->pushOperand(mPSSpecular, Operand::OPS_IN);
        curFuncInvocation->pushOperand(mPSTempSpecularColour, Operand::OPS_IN); 
        curFuncInvocation->pushOperand(mPSTempSpecularColour, Operand::OPS_OUT);    
        psMain->addAtomInstance(curFuncInvocation); 
    }

    return true;
}
Ejemplo n.º 26
0
StatementAssign *
StatementAssign::make_possible_compound_assign(CGContext &cg_context, 
				 const Lhs &l,
				 eAssignOps op,
				 const Expression &e)
{
	eBinaryOps bop = compound_to_binary_ops(op);
	const Expression *rhs = NULL;
	SafeOpFlags *fs = NULL;
	std::string tmp1;
	std::string tmp2;

	if (bop != MAX_BINARY_OP) {
		//SafeOpFlags *local_fs = SafeOpFlags::make_random(sOpAssign, true);
		SafeOpFlags *local_fs  = NULL;
		FunctionInvocation* fi = NULL;
		if (safe_assign(op)) {
			local_fs = SafeOpFlags::make_dummy_flags();
			fi = new FunctionInvocationBinary(bop, local_fs);
		}
		else {
			local_fs = SafeOpFlags::make_random(sOpAssign);
			
			fi = FunctionInvocationBinary::CreateFunctionInvocationBinary(cg_context, bop, local_fs);
			tmp1 = dynamic_cast<FunctionInvocationBinary*>(fi)->get_tmp_var1();
			tmp2 = dynamic_cast<FunctionInvocationBinary*>(fi)->get_tmp_var2();			
		}
		fs = local_fs->clone();
        	fi->add_operand(new ExpressionVariable(*(l.get_var()), &l.get_type()));
        	fi->add_operand(e.clone());
        	rhs = new ExpressionFuncall(*fi);
        }
	else {
		rhs = &e;
#if 0
		if (e.term_type == eFunction) {
			const ExpressionFuncall* func = dynamic_cast<const ExpressionFuncall*>(&e);
			if (!func->get_invoke().safe_invocation()) {
				fs = SafeOpFlags::make_dummy_flags();
				fs = NULL;
			}
		}
#endif
		if (op != eSimpleAssign) {
			fs = SafeOpFlags::make_random(sOpAssign);
			bool op1 = fs->get_op1_sign();
			bool op2 = fs->get_op2_sign();
			enum SafeOpSize size = fs->get_op_size();

			eSimpleType type1 = SafeOpFlags::flags_to_type(op1, size);
			eSimpleType type2 = SafeOpFlags::flags_to_type(op2, size);

			const Block *blk = cg_context.get_current_block();
			assert(blk);

			tmp1 = blk->create_new_tmp_var(type1);
			tmp2 = blk->create_new_tmp_var(type2);
			
		}
	}
	StatementAssign *sa = new StatementAssign(cg_context.get_current_block(), l, op, e, rhs, fs, tmp1, tmp2);
	return sa;
}
Ejemplo n.º 27
0
bool FunctionInvocation::FunctionInvocationLessThan::operator ()(FunctionInvocation const& lhs, FunctionInvocation const& rhs) const
{
    // Check the function names first
    // Adding an exception to std::string sorting.  I feel that functions beginning with an underscore should be placed before
    // functions beginning with an alphanumeric character.  By default strings are sorted based on the ASCII value of each character.
    // Underscores have an ASCII value in between capital and lowercase characters.  This is why the exception is needed.
    if (lhs.getFunctionName() < rhs.getFunctionName())
    {
        if(rhs.getFunctionName().at(0) == '_')
            return false;
        else
            return true;
    }
    if (lhs.getFunctionName() > rhs.getFunctionName())
    {
        if(lhs.getFunctionName().at(0) == '_')
            return true;
        else
            return false;
    }

    // Next check the return type
    if (lhs.getReturnType() < rhs.getReturnType())
        return true;
    if (lhs.getReturnType() > rhs.getReturnType())
        return false;

    // Check the number of operands
    if (lhs.mOperands.size() < rhs.mOperands.size())
        return true;
    if (lhs.mOperands.size() > rhs.mOperands.size())
        return false;

    // Now that we've gotten past the two quick tests, iterate over operands
    // Check the semantic and type.  The operands must be in the same order as well.
    OperandVector::const_iterator itLHSOps = lhs.mOperands.begin();
    OperandVector::const_iterator itRHSOps = rhs.mOperands.begin();

    for ( ; ((itLHSOps != lhs.mOperands.end()) && (itRHSOps != rhs.mOperands.end())); ++itLHSOps, ++itRHSOps)
    {
        if (itLHSOps->getSemantic() < itRHSOps->getSemantic())
            return true;
        if (itLHSOps->getSemantic() > itRHSOps->getSemantic())
            return false;

        GpuConstantType leftType    = itLHSOps->getParameter()->getType();
        GpuConstantType rightType   = itRHSOps->getParameter()->getType();
        
        if (Ogre::Root::getSingletonPtr()->getRenderSystem()->getName().find("OpenGL ES 2") != String::npos)
        {
            if (leftType == GCT_SAMPLER1D)
                leftType = GCT_SAMPLER2D;

            if (rightType == GCT_SAMPLER1D)
                rightType = GCT_SAMPLER2D;
        }

        // If a swizzle mask is being applied to the parameter, generate the GpuConstantType to
        // perform the parameter type comparison the way that the compiler will see it.
        if ((itLHSOps->getFloatCount(itLHSOps->getMask()) > 0) ||
           (itRHSOps->getFloatCount(itRHSOps->getMask()) > 0))
        {
            if (itLHSOps->getFloatCount(itLHSOps->getMask()) > 0)
            {
                leftType = (GpuConstantType)((itLHSOps->getParameter()->getType() - itLHSOps->getParameter()->getType()) +
                                             itLHSOps->getFloatCount(itLHSOps->getMask()));
            }
            if (itRHSOps->getFloatCount(itRHSOps->getMask()) > 0)
            {
                rightType = (GpuConstantType)((itRHSOps->getParameter()->getType() - itRHSOps->getParameter()->getType()) +
                                             itRHSOps->getFloatCount(itRHSOps->getMask()));
            }
        }

        if (leftType < rightType)
            return true;
        if (leftType > rightType)
            return false;
    }

    return false;
}
//-----------------------------------------------------------------------
void GLSLProgramWriter::writeForwardDeclarations(std::ostream& os, Program* program)
{
	os << "//-----------------------------------------------------------------------------" << std::endl;
	os << "//                         FORWARD DECLARATIONS" << std::endl;
	os << "//-----------------------------------------------------------------------------" << std::endl;

	StringVector forwardDecl; // holds all generated function declarations 
	const ShaderFunctionList& functionList = program->getFunctions();
	ShaderFunctionConstIterator itFunction;

	// Iterate over all functions in the current program (in our case this is always the main() function)
	for ( itFunction = functionList.begin(); itFunction != functionList.end(); ++itFunction)
	{
		Function* curFunction = *itFunction;
		const FunctionAtomInstanceList& atomInstances = curFunction->getAtomInstances();
		FunctionAtomInstanceConstIterator itAtom = atomInstances.begin();
		FunctionAtomInstanceConstIterator itAtomEnd = atomInstances.end();

		// Now iterate over all function atoms
		for ( ; itAtom != itAtomEnd; ++itAtom)
		{	
			// Skip non function invocation atoms.
			if ((*itAtom)->getFunctionAtomType() != FunctionInvocation::Type)
				continue;

			FunctionInvocation* pFuncInvoc = static_cast<FunctionInvocation*>(*itAtom);			
			FunctionInvocation::OperandVector::iterator itOperator = pFuncInvoc->getOperandList().begin();
			FunctionInvocation::OperandVector::iterator itOperatorEnd = pFuncInvoc->getOperandList().end();

			// Start with function declaration 
			String funcDecl = pFuncInvoc->getReturnType() + " " + pFuncInvoc->getFunctionName() + "(";

			// Now iterate overall operands
			for (; itOperator != itOperatorEnd; )
			{
				ParameterPtr pParam = (*itOperator).getParameter();				
				Operand::OpSemantic opSemantic = (*itOperator).getSemantic();
				int opMask = (*itOperator).getMask();
				GpuConstantType gpuType = GCT_UNKNOWN;

				// Write the semantic in, out, inout
				switch(opSemantic)
				{
				case Operand::OPS_IN:
					funcDecl += "in ";
					break;

				case Operand::OPS_OUT:
					funcDecl += "out ";
					break;

				case Operand::OPS_INOUT:
					funcDecl += "inout ";
					break;

				default:
					break;
				}				
				
				//  Swizzle masks are only defined for types like vec2, vec3, vec4.
				if (opMask == Operand::OPM_ALL)
				{
					gpuType = pParam->getType();
				}
				else 
				{
					// Now we have to convert the mask to operator
					gpuType = Operand::getGpuConstantType(opMask);
				}

				// We need a valid type otherwise glsl compilation will not work
				if (gpuType == GCT_UNKNOWN)
				{
					OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, 
						"Can not convert Operand::OpMask to GpuConstantType", 
						"GLSLProgramWriter::writeForwardDeclarations" );	
				}

				// Write the operand type.
				funcDecl += mGpuConstTypeMap[gpuType];

				++itOperator;
				//move over all operators with indirection
				while ((itOperator != itOperatorEnd) && (itOperator->getIndirectionLevel() != 0)) 
				{
					++itOperator;
				}

				// Prepare for the next operand
				if (itOperator != itOperatorEnd)
				{
					funcDecl += ", ";
				}
			}
			// Write function call closer.
			funcDecl += ");\n";

			// Push the generated declaration into the vector
			// duplicate declarations will be removed later.
			forwardDecl.push_back(funcDecl);
		}
	}

	// Now remove duplicate declaration, first we have to sort the vector.
	std::sort(forwardDecl.begin(), forwardDecl.end());
	StringVector::iterator endIt = std::unique(forwardDecl.begin(), forwardDecl.end()); 

	// Finally write all function declarations to the shader file
	for (StringVector::iterator it = forwardDecl.begin(); it != endIt; it++)
	{
		os << *it;
	}
}
bool RTShaderSRSSegmentedLights::addPSSegmentedTextureLightInvocation(Function* psMain, const int groupOrder, int& internalCounter)
{
    float invWidth = 1.0f / (float)SegmentedDynamicLightManager::getSingleton().getTextureWidth();
    float invHeight = 1.0f / (float)SegmentedDynamicLightManager::getSingleton().getTextureHeight();
    ParameterPtr paramInvWidth = ParameterFactory::createConstParamFloat(invWidth);
    ParameterPtr paramInvHeight = ParameterFactory::createConstParamFloat(invHeight);

    FunctionInvocation* curFuncInvocation = NULL;   
    curFuncInvocation = OGRE_NEW FunctionInvocation(SL_FUNC_LIGHT_SEGMENT_TEXTURE_AMBIENT_DIFFUSE, groupOrder, internalCounter++);                      
    curFuncInvocation->pushOperand(mPSLocalNormal, Operand::OPS_IN);
    curFuncInvocation->pushOperand(mPSInWorldPos, Operand::OPS_IN);
    curFuncInvocation->pushOperand(mPSSegmentedLightTexture, Operand::OPS_IN);
    curFuncInvocation->pushOperand(mPSLightTextureIndexLimit, Operand::OPS_IN);
    curFuncInvocation->pushOperand(mPSLightTextureLightBounds, Operand::OPS_IN);
    curFuncInvocation->pushOperand(paramInvWidth, Operand::OPS_IN);
    curFuncInvocation->pushOperand(paramInvHeight, Operand::OPS_IN);                    
    curFuncInvocation->pushOperand(mPSTempDiffuseColour, Operand::OPS_INOUT, Operand::OPM_XYZ); 
    psMain->addAtomInstance(curFuncInvocation); 

    if (SegmentedDynamicLightManager::getSingleton().isDebugMode())
    {
        ParameterPtr psOutColor = psMain->resolveOutputParameter(Parameter::SPS_COLOR, -1, Parameter::SPC_COLOR_DIFFUSE, GCT_FLOAT4);

        FunctionInvocation* curDebugFuncInvocation = NULL;
        curDebugFuncInvocation = OGRE_NEW FunctionInvocation(SL_FUNC_LIGHT_SEGMENT_DEBUG, FFP_PS_COLOUR_END + 1, internalCounter++);                        
        curDebugFuncInvocation->pushOperand(mPSLocalNormal, Operand::OPS_IN);
        curDebugFuncInvocation->pushOperand(mPSInWorldPos, Operand::OPS_IN);
        curDebugFuncInvocation->pushOperand(mPSSegmentedLightTexture, Operand::OPS_IN);
        curDebugFuncInvocation->pushOperand(mPSLightTextureIndexLimit, Operand::OPS_IN);
        curDebugFuncInvocation->pushOperand(mPSLightTextureLightBounds, Operand::OPS_IN);
        curDebugFuncInvocation->pushOperand(paramInvWidth, Operand::OPS_IN);
        curDebugFuncInvocation->pushOperand(paramInvHeight, Operand::OPS_IN);   

        curDebugFuncInvocation->pushOperand(psOutColor, Operand::OPS_INOUT, Operand::OPM_XYZ);  
        psMain->addAtomInstance(curDebugFuncInvocation);    
    }

    return true;
}
Ejemplo n.º 30
0
//-----------------------------------------------------------------------
bool FFPColour::addFunctionInvocations(ProgramSet* programSet)
{
	Program* vsProgram = programSet->getCpuVertexProgram();
	Program* psProgram = programSet->getCpuFragmentProgram();
	Function* vsMain   = vsProgram->getEntryPointFunction();
	Function* psMain   = psProgram->getEntryPointFunction();	
	FunctionInvocation* curFuncInvocation = NULL;	
	int internalCounter;

	
	// Create vertex shader colour invocations.
	ParameterPtr vsDiffuse;
	ParameterPtr vsSpecular;
	internalCounter = 0;	
	if (mVSInputDiffuse.get() != NULL)
	{
		vsDiffuse = mVSInputDiffuse;
	}
	else
	{
		vsDiffuse = vsMain->resolveLocalParameter(Parameter::SPS_COLOR, 0, Parameter::SPC_COLOR_DIFFUSE, GCT_FLOAT4);
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_CONSTRUCT, FFP_VS_COLOUR, internalCounter++);
		curFuncInvocation->pushOperand(ParameterFactory::createConstParamFloat(1.0), Operand::OPS_IN);
		curFuncInvocation->pushOperand(ParameterFactory::createConstParamFloat(1.0), Operand::OPS_IN);
		curFuncInvocation->pushOperand(ParameterFactory::createConstParamFloat(1.0), Operand::OPS_IN);
		curFuncInvocation->pushOperand(ParameterFactory::createConstParamFloat(1.0), Operand::OPS_IN);
		curFuncInvocation->pushOperand(vsDiffuse, Operand::OPS_OUT);
		vsMain->addAtomInstace(curFuncInvocation);
	}

	if (mVSOutputDiffuse.get() != NULL)
	{
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, FFP_VS_COLOUR, internalCounter++);
		curFuncInvocation->pushOperand(vsDiffuse, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mVSOutputDiffuse, Operand::OPS_OUT);
		vsMain->addAtomInstace(curFuncInvocation);
	}
	
	if (mVSInputSpecular.get() != NULL)
	{
		vsSpecular = mVSInputSpecular;		
	}
	else
	{
		vsSpecular = vsMain->resolveLocalParameter(Parameter::SPS_COLOR, 1, Parameter::SPC_COLOR_SPECULAR, GCT_FLOAT4);

		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_CONSTRUCT, FFP_VS_COLOUR, internalCounter++);
		curFuncInvocation->pushOperand(ParameterFactory::createConstParamFloat(0.0), Operand::OPS_IN);
		curFuncInvocation->pushOperand(ParameterFactory::createConstParamFloat(0.0), Operand::OPS_IN);
		curFuncInvocation->pushOperand(ParameterFactory::createConstParamFloat(0.0), Operand::OPS_IN);
		curFuncInvocation->pushOperand(ParameterFactory::createConstParamFloat(0.0), Operand::OPS_IN);
		curFuncInvocation->pushOperand(vsSpecular, Operand::OPS_OUT);
		vsMain->addAtomInstace(curFuncInvocation);
	}

	if (mVSOutputSpecular.get() != NULL)
	{
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, FFP_VS_COLOUR, internalCounter++);
		curFuncInvocation->pushOperand(vsSpecular, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mVSOutputSpecular, Operand::OPS_OUT);
		vsMain->addAtomInstace(curFuncInvocation);
	}
	
	

	// Create fragment shader colour invocations.
	ParameterPtr psDiffuse;
	ParameterPtr psSpecular;
	internalCounter = 0;
	
	// Handle diffuse colour.
	if (mPSInputDiffuse.get() != NULL)
	{
		psDiffuse = mPSInputDiffuse;				
	}
	else
	{
		psDiffuse = psMain->resolveLocalParameter(Parameter::SPS_COLOR, 0, Parameter::SPC_COLOR_DIFFUSE, GCT_FLOAT4);
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_CONSTRUCT, FFP_PS_COLOUR_BEGIN, internalCounter++);
		curFuncInvocation->pushOperand(ParameterFactory::createConstParamFloat(1.0), Operand::OPS_IN);
		curFuncInvocation->pushOperand(ParameterFactory::createConstParamFloat(1.0), Operand::OPS_IN);
		curFuncInvocation->pushOperand(ParameterFactory::createConstParamFloat(1.0), Operand::OPS_IN);
		curFuncInvocation->pushOperand(ParameterFactory::createConstParamFloat(1.0), Operand::OPS_IN);
		curFuncInvocation->pushOperand(psDiffuse, Operand::OPS_OUT);
		psMain->addAtomInstace(curFuncInvocation);
	}

	// Handle specular colour.
	if (mPSInputSpecular.get() != NULL)
	{
		psSpecular = mPSInputSpecular;		
	}
	else
	{
		psSpecular = psMain->resolveLocalParameter(Parameter::SPS_COLOR, 1, Parameter::SPC_COLOR_SPECULAR, GCT_FLOAT4);
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_CONSTRUCT, FFP_PS_COLOUR_BEGIN, internalCounter++);
		curFuncInvocation->pushOperand(ParameterFactory::createConstParamFloat(0.0), Operand::OPS_IN);
		curFuncInvocation->pushOperand(ParameterFactory::createConstParamFloat(0.0), Operand::OPS_IN);
		curFuncInvocation->pushOperand(ParameterFactory::createConstParamFloat(0.0), Operand::OPS_IN);
		curFuncInvocation->pushOperand(ParameterFactory::createConstParamFloat(0.0), Operand::OPS_IN);
		curFuncInvocation->pushOperand(psSpecular, Operand::OPS_OUT);
		psMain->addAtomInstace(curFuncInvocation);
	}

	// Assign diffuse colour.
	if (mPSOutputDiffuse.get() != NULL)
	{	
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, FFP_PS_COLOUR_BEGIN, internalCounter++);
		curFuncInvocation->pushOperand(psDiffuse, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mPSOutputDiffuse, Operand::OPS_OUT);		
		psMain->addAtomInstace(curFuncInvocation);
	}

	// Assign specular colour.
	if (mPSOutputSpecular.get() != NULL)
	{
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, FFP_PS_COLOUR_BEGIN, internalCounter++);
		curFuncInvocation->pushOperand(psSpecular, Operand::OPS_IN);
		curFuncInvocation->pushOperand(mPSOutputSpecular, Operand::OPS_OUT);		
		psMain->addAtomInstace(curFuncInvocation);
	}

	// Add specular to out colour.
	internalCounter = 0;
	if (mPSOutputDiffuse.get() != NULL && psSpecular.get() != NULL)
	{
		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ADD, FFP_PS_COLOUR_END, internalCounter++);
		curFuncInvocation->pushOperand(mPSOutputDiffuse, Operand::OPS_IN,(Operand::OPM_X | Operand::OPM_Y | Operand::OPM_Z));
		curFuncInvocation->pushOperand(psSpecular, Operand::OPS_IN,(Operand::OPM_X | Operand::OPM_Y | Operand::OPM_Z));
		curFuncInvocation->pushOperand(mPSOutputDiffuse, Operand::OPS_OUT,(Operand::OPM_X | Operand::OPM_Y | Operand::OPM_Z));
		psMain->addAtomInstace(curFuncInvocation);
	}	

	return true;
}