几个关键类解析:
// 存储当前编译的Shader代码的上下文信息. class Context : public NiMemObject { public: // 正在编译shade tree的Owner,可以理解为ShaderTree的根 NiMaterialConfiguratorPtr m_spConfigurator; // 保存所有静态变量的指针 NiMaterialResourceProducerNodePtr m_spStatics; // 保存所有uniform变量的指针. NiMaterialResourceProducerNodePtr m_spUniforms; // 保存所有 input变量的指针. NiMaterialResourceProducerNodePtr m_spInputs; // 保存所有output变量的指针. NiMaterialResourceConsumerNodePtr m_spOutputs; // shade-tree的栈上的变量. 只有resources 从节点添加到shader tree的变量才存储到这里 NiTPrimitiveArray<NiMaterialResource*> m_akVariables; };
在shader里面注册一个全局的变量g_dyeingColor:
NiShaderFactory::RegisterGlobalShaderConstant(
"g_dyeingColor", NiShaderAttributeDesc::ATTRIB_TYPE_POINT3,
sizeof(NiColor), &dyeingColor);
往当前材质shader里面添加这个全局的变量
NiMaterialResource* dyeingColor = AddOutputGlobal(kContext.m_spUniforms,
"g_dyeingColor", NiShaderAttributeDesc::ATTRIB_TYPE_POINT3, 1);
例子,一个VS的代码:
static bool Saturate = false; // NiMaterialResourceProducerNodePtr m_spStatics; float4x4 g_World; float4x4 g_View; float4x4 g_Proj; //m_spUniforms NiMaterialResourceProducerNodePtr m_spUniforms
struct Input { float3 Position : POSITION0; float3 Normal : NORMAL0; float2 UVSet0 : TEXCOORD0; }; //--------------------------------------------------------------------------- // Output: //--------------------------------------------------------------------------- struct Output { float4 PosProjected : POSITION0; float4 DiffuseAccum : TEXCOORD0; float FogOut : FOG0; };
关于Context的Input 和Output
VS里面输出projected position
kContext.m_spOutputs->AddInputResource("float4", "Position", "World",
"PosProjected");
添加一个 projected position输出,要输出的值(即输出值的输入AddInputResource)是PosProjected
PS里面接受projected position输入
kContext.m_spInputs->AddOutputResource("float4", "Position",
"World", "PosProjected");
添加一个PosProjected Position的输入,这个值可以输出值(即输出AddOutputResource)是PosProjected
关于方法参数的绑定,例子:
//shader代码
void CompositeFinalRGBColor(float3 DiffuseColor,
float3 SpecularColor,
out float3 OutputColor)
{
OutputColor.rgb = DiffuseColor.rgb + SpecularColor.rgb;
}
NiMaterialResource* pkFinalColor = NULL;
//首先得到当前材质Shader方法的Node
NiMaterialNode* pkNode = GetAttachableNodeFromLibrary(
"CompositeFinalRGBColor");
//把得到的Node加入到上下文m_spConfigurator里面
kContext.m_spConfigurator->AddNode(pkNode);
//pkNode的需要输入DiffuseColor,现在把NiMaterialResource* pkDiffuseAccum作为其输入。
kContext.m_spConfigurator->AddBinding(pkDiffuseAccum,
"DiffuseColor", pkNode);
//pkNode的需要输入SpecularColor,现在把NiMaterialResource* pkSpecularAccum作为其输入。
kContext.m_spConfigurator->AddBinding(pkSpecularAccum,
"SpecularColor", pkNode);
bool AddBinding(const NiFixedString& kOutputVar,
NiMaterialNode* pkOutputNode,
const NiFixedString& kInputVar,
NiMaterialNode* pkInputNode);
1、从前面的输出pkOutputNode找到名字为kOutputVar的变量。
2、pkInputNode需要名字为kInputVar的输入。
3、把kOutputVar输出到kInputVar去,即完成一次参数传递
pkFinalColor = pkNode->GetOutputResourceByVariableName("OutputColor");
前面的方法会返回一个最终的颜色,以此方法获得此结果。