Table of Contents

组合

入门 程序员

除了继承系统之外,SDSL 还引入了**组合(Composition)**的概念。组合是一个类型为另一个着色器类的成员。它的定义方式与变量相同。

你可以用期望的着色器类的实例进行组合,也可以用继承自该类的着色器类的实例进行组合。

示例代码

shader CompositionBase
{
	float4 Compute()
	{
		return float4(0.0);
	}
};
 
shader CompositionShaderA : CompositionBase
{
	float4 myColor;
 
	override float4 Compute()
	{
		return myColor;
	}
};
 
shader CompositionShaderB : CompositionBase
{
	float4 myColor;

	override float4 Compute()
	{
		return 0.5 * myColor;
	}
};
 
shader BaseShader
{
	CompositionBase Comp0;
	CompositionBase Comp1;
 
	float4 GetColor()
	{
		return Comp0.Compute() + Comp1.Compute();
	}
};

组合在其自身的上下文中编译,这意味着非 stage 变量只能在该组合内部访问。组合内部也可以再包含组合。

示例代码:访问根上下文

如果你想访问根编译上下文,可以使用以下格式:

shader CompositionShaderC : CompositionBase
{
	BaseShader rootShader = stage;
 
	float4 GetColor()
	{
		return rootShader.GetColor();
	}
};

这很容易出错,因为 CompositionShaderC 期望根上下文中存在 BaseShader。

示例代码:组合数组

你也可以像使用值数组一样创建组合数组。由于无法事先知道有多少个组合,你应该使用 foreach 语句进行迭代。

shader BaseShaderArray
{
	CompositionBase Comps[];
	
	float4 GetColor()
	{
		float4 resultColor = float4(0.0);
 
		foreach (var comp in Comps)
		{
			resultColor += comp.Compute();
		}
 
		return resultColor;
	}
};

示例代码:stage 行为

stage 关键字的行为很直观:变量或方法只会产生一个实例。

shader BaseShader
{
	stage float BaseStageValue;
	float NonStageValue;
};
 
shader TestShader : BaseShader
{
	BaseShader comp0;
	BaseShader comp1;
};
 
// 生成的着色器(表示形式)
shader TestShader
{
	float BaseStageValue;
	float NonStageValue;
	float comp0_NonStageValue;
	float comp1_NonStageValue;
};

示例代码:stage 成员行为

shader BaseShader
{
	stage float BaseStageMethod()
	{
		return 1.0;
	}

	float NonStageMethod()
	{
		return 2.0;
	}
};
 
shader TestShader : BaseShader
{
	BaseShader comp0;
	BaseShader comp1;
};
 
// 生成的着色器(表示形式)
shader TestClass
{
	float BaseStageMethod()
	{
		return 1.0;
	}

	float NonStageMethod()
	{
		return 2.0;
	}
	float comp0_NonStageMethod()
	{
		return 2.0;
	}
	float comp1_NonStageMethod()
	{
		return 2.0;
	}
};

请记住,即使在组合中,你也可以调用基方法、重写它们等等。重写发生的顺序与组合的顺序相同。

当你需要在多个组合中使用某个值但只需计算一次时(例如视图空间中的法线),这种行为非常有用。

Clone 行为

clone 关键字的行为则没那么简单。它会阻止 stage 关键字生成唯一的方法。

shader BaseShader
{
	stage float BaseStageMethod()
	{
		return 1.0;
	}
 
	stage float BaseStageMethodNotCloned()
	{
		return 1.0;
	}
};
 
shader CompShader : BaseShader
{
	override clone float BaseStageMethod()
	{
		return 1.0 + base.BaseStageMethod();
	}
 
	override float BaseStageMethodNotCloned()
	{
		return 1.0f + base.BaseStageMethodNotCloned();
	}
};
 
shader TestShader : BaseShader
{
	CompShader comp0;
	CompShadercomp1;
};
 
// 生成的着色器(表示形式)
shader TestShader
{
	// 被克隆的方法
	float base_BaseStageMethod()
	{
		return 1.0;
	}
 
	float comp0_BaseStageMethod()
	{
		return 1.0 + base_BaseStageMethod();
	}
 
	float BaseStageMethod() // 实际上是 comp1_BaseStageMethod
	{
		return 1.0 + comp0_BaseStageMethod; // 3.0f
	}
 
	// 未被克隆的方法
	float base_BaseStageMethodNotCloned()
	{
		return 1.0f;
	}
 
	float BaseStageMethodNotCloned()
	{
		return 1.0f + base_BaseStageMethodNotCloned(); // 2.0f
	}
};

当你想用不同的参数重复一个简单函数时(例如在另一种颜色之上叠加颜色),这种行为很有用。

另请参阅