在HLSL中,我必须使用语义将信息从顶点着色器传递到片段着色器.在GLSL中,不需要语义.语义的客观利益是什么?
示例:GLSL
顶点着色器
varying vec4 foo
varying vec4 bar;
void main() {
...
foo = ...
bar = ...
}
Run Code Online (Sandbox Code Playgroud)
片段着色器
varying vec4 foo
varying vec4 bar;
void main() {
gl_FragColor = foo * bar;
}
Run Code Online (Sandbox Code Playgroud)
示例:HLSL
顶点着色器
struct VS_OUTPUT
{
float4 foo : TEXCOORD3;
float4 bar : COLOR2;
}
VS_OUTPUT whatever()
{
VS_OUTPUT out;
out.foo = ...
out.bar = ...
return out;
}
Run Code Online (Sandbox Code Playgroud)
像素着色器
void main(float4 foo : TEXCOORD3,
float4 bar : COLOR2) : COLOR
{
return foo * bar;
}
Run Code Online (Sandbox Code Playgroud)
我看到如何foo以及bar在片段着色器中VS_OUTPUT连接到foo和bar中main.我没有得到的是为什么我手动选择语义来携带数据.为什么像GLSL一样,DirectX只能找出放置数据的位置并在连接着色器时连接它?
是否有一些更具体的优势来手动指定语义,还是只是从汇编语言着色器时代遗留下来?选择说TEXCOORD4而不是COLOR2或BINORMAL1有一些速度优势吗?
我认为语义可以暗示意义,没有任何意义foo或者bar它们也可以模糊意义只要foo不是TEXCOORD并且bar不是颜色就好了.我们没有将语义放在C#或C++或JavaScript变量上,为什么HLSL需要它们呢?
cat*_*ier 13
简单地说,(旧)glsl使用这种变量来命名变量(请注意,现在已经弃用了变量).
语义的一个明显好处是,您不需要在各阶段之间使用相同的变量名称,因此DirectX管道通过语义而不是变量名称进行匹配,并且只要您具有兼容的布局,就会重新排列数据.
如果您通过foo2重命名foo,则需要在可能的所有着色器(以及最终的着色器)中替换此名称.使用语义,您不需要这个.
此外,由于您不需要精确匹配,因此可以更轻松地分离着色器阶段.
例如:
你可以有一个像这样的顶点着色器:
struct vsInput
{
float4 PosO : POSITION;
float3 Norm: NORMAL;
float4 TexCd : TEXCOORD0;
};
struct vsOut
{
float4 PosWVP : SV_POSITION;
float4 TexCd : TEXCOORD0;
float3 NormView : NORMAL;
};
vsOut VS(vsInput input)
{
//Do you processing here
}
Run Code Online (Sandbox Code Playgroud)
像这样的像素着色器:
struct psInput
{
float4 PosWVP: SV_POSITION;
float4 TexCd: TEXCOORD0;
};
Run Code Online (Sandbox Code Playgroud)
由于顶点着色器输出提供了像素着色器所需的所有输入,因此这是完全有效的.法线将被忽略,不会提供给像素着色器.
但是,您可以交换到可能需要法线的新像素着色器,而无需另外使用Vertex Shader.您也可以仅交换PixelShader,从而节省一些API调用(Separate Shader Objects扩展是OpenGL的等价物).
因此,在某些方面,语义为您提供了一种在阶段之间封装输入/输出的方法,并且由于您引用了其他语言,这将等同于使用属性/设置器/指针地址...
速度方面根据命名没有区别(你可以用你想要的任何方式命名语义,当然除了系统之外).不同的布局位置确实意味着一个打击(管道将为您重新组织,但也会发出警告,至少在DirectX中).
OpenGL还提供了大致相同的布局限定符(它在技术上有点不同,但遵循或多或少相同的概念).
希望有所帮助.
| 归档时间: |
|
| 查看次数: |
4712 次 |
| 最近记录: |