着色器输出
顶点和像素着色器提供的数据供其后的图形管线使用.输出关联用于指定着色器产生的数据如何链接给下一阶段的输入.举例来说,顶点着色器的输出关联将顶点着色程序运算得到的结果链接到像素着色器的输入关联上.
顶点着色器输出关联用于将着色器连接到像素着色器和光栅阶段.POSITION输出是每个顶点必须输出给光栅器而不暴露给像素着色器的数据,
TEXCOORDn和COLORn表示输出用于像素着色器进行插值.
像素着色器输出关联将其输出颜色绑定给正确的渲染目标.颜色输出被连接到alpha混合阶段.DEPTH输出关联用于改变当前光栅化位置的目标深度值.输出关联语义同输入关联的声明相同.
下面是顶点着色器的输出关联
关联符 描述
POSITION 位置
PSIZE 点大小
FOG 顶点雾
COLORn 颜色
TEXCOORDn 纹理坐标
下面是像素着色器输出关联
关联符 描述
COLORn 渲染目标n的颜色
DEPTH 深度值
例:
//声明具有关联绑定的输出结构
struct OutStruct
{
float2 Tex2 : TEXCOORD2
};
//声明Tex为输出参数,其包含文理坐标数据
float4 main(out float2 Tex0: TEXCOORD0, out OutStruct Out) : POSITON
{
Tex0 = float2(1.0, 0.0);
out.Tex2 = float2(0.1, 0.2);
return float4(0.5, 0.5, 0.5, 1);
}
//声明包含颜色插值的Col变量
float4 mainPS(out float4 Col1 : COLOR1) : COLOR
{
Col1 = float4(0.0, 0.0, 0.0, 0.0);
return float4(1.0, 0.9722, 0.3333334, 0);
}
struct PS_OUT
{
float4 Color:COLOR;
float4 Depth:DEPTH;
};
//三种方法从像素着色器输出
PSOUT PSFunc1(){...}
void PSFunc2(out float4 Color:COLOR,out float Depth:DEPTH){...}
void PDFunc3(out PS_OUT Out)
{...}
一个着色器例子
float4x4 view_proj_matrix;
float4 view_position;
float4 light0;
float4 light1;
float4 light2;
struct VS_OUTPUT
{
float4 Pos :POSITION;
float3 view :TEXCOORD0;
float3 Normal :TEXCOORD1;
float3 Light1 :TEXCOORD2;
float3 Light2 :TEXCOORD3;
float3 Light3 :TEXCOORD4;
};
VS_OUTPUT main(float4 inPos:POSITION, float3 inNorm:NORMAL)
{
VS_OUTPUT out = (VS_OUTPUT) 0;
out.Pos = mul(view_proj_matrix, inPos);
out.Normal = inNorm;
out.View = normalize(view_position - inPos);
out.Light1 = normalize(light0 - inPos);
out.Light2 = normalize(light1 - inPos);
out.Light3 = normalize(light2 - inPos);
return out;
}
这个顶点着色器在开头声明几个全局域的变量,他们都隐式的声明为uniform,因此他们可以被API和着色器访问.接着我们看到一个VS_OUTPUT结构体,由结构体定义可知顶点着色器除了除数一个4D位置信息,还将输出5个3D纹理坐标信息.现在来看main函数,由一个4D向量作为位置输入,一个3D向量作为法向量输入.inPos通过mul函数操作,但是inNorm并没有被使用.最后,经过干函数运算的数据将会在多边形中进行插值.
下面我来着手编译下这个文件.首先,我们将上面代码复制进一个文本文件并重命名为NPRMetallic.vhl.然后在命令行输入如下命令:
"fxc -nologo -T vs_1_1 -Fc -Vd NPRMetallic.vhl".
因为这个顶点着色器不要求流控制,我们选用vs_1_1编译目标.
输出如下:
//
// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
//
// fxc -nologo -T vs_1_1 -Fc -Vd j:/NPRMetallic.vhl
//
//
// Parameters:
//
// float4 light0;
// float4 light1;
// float4 light2;
// float4 view_position;
// float4x4 view_proj_matrix;
//
//
// Registers:
//
// Name Reg Size
// ---------------- ----- ----
// view_proj_matrix c0 4
// view_position c4 1
// light0 c5 1
// light1 c6 1
// light2 c7 1
//
vs_1_1
dcl_position v0
dcl_normal v1
mul r0, v0.y, c1
mad r0, c0, v0.x, r0
mad r0, c2, v0.z, r0
mad oPos, c3, v0.w, r0
add r0, -v0, c4
dp4 r0.w, r0, r0
rsq r0.w, r0.w
mul oT0.xyz, r0.w, r0
add r0, -v0, c5
dp4 r0.w, r0, r0
rsq r0.w, r0.w
mul oT2.xyz, r0.w, r0
add r0, -v0, c6
dp4 r0.w, r0, r0
rsq r0.w, r0.w
mul oT3.xyz, r0.w, r0
add r0, -v0, c7
dp4 r0.w, r0, r0
rsq r0.w, r0.w
mul oT4.xyz, r0.w, r0
mov oT1.xyz, v1
// approximately 21 instruction slots used
代码上方是顶点着色器的输入参数,这些参数需要通过API来设定以使着色器正常工作.下面一个部分是硬件寄存器的分配.租后是汇编指令,一共21条.现在不必要从头读到尾,但应该注意dcl_position,dcl_normal两个语句,他们代表这main函数的两个参数.另外注意输出结果放在oPos,oT0~4这些输出寄存器中.
现在我们需要使用顶点着色器把几何体变换到剪裁空间并定义那些将会在多边形插值用用到的值.下面我们来进行像素着色:
float4 Material;
sampler Outline;
float4 main(float3 View:TEXCOORD0, float3 Normal:TEXCOORD1, float3 Light1:TEXCOORD2, float3 Light2:TEXCOORD3,float3 Light3:TEXCOORD4):COLOR
{
//标准化输入向量
float3 norm = normalize(Normal);
float4 outline = tex1D(Outline, 1 - dot(norm, normalize(View)));
float lighting = (dot (normalize(Light1), norm)*0.5 + 0.5) +
(dot (normalize(Light2), norm)*0.5 + 0.5) +
(dot (normalize(Light3), norm)*0.5 + 0.5) ;
return outline*Material*lighting;
}
使用“fxc -nologo -T ps_2_0 -Fc -Vd NPRMetallic.phl”编译
产生的代码如下:
//
// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
//
// fxc -nologo -T ps_2_0 -Fc -Vd J:/shader/NPRMetallic.phl
//
//
// Parameters:
//
// float4 Material;
// sampler2D Outline;
//
//
// Registers:
//
// Name Reg Size
// ------------ ----- ----
// Material c0 1
// Outline s0 1
//
ps_2_0
def c1, 1, 0.5, 0, 0
dcl t0.xyz
dcl t1.xyz
dcl t2.xyz
dcl t3.xyz
dcl t4.xyz
dcl_2d s0
nrm r0.xyz, t2
nrm r1.xyz, t1
dp3 r1.w, r0, r1
mad r1.w, r1.w, c1.y, c1.y
nrm r0.xyz, t3
dp3 r0.x, r0, r1
mad r1.w, r0.x, c1.y, r1.w
add r1.w, r1.w, c1.y
nrm r0.xyz, t4
dp3 r0.x, r0, r1
mad r1.w, r0.x, c1.y, r1.w
add r1.w, r1.w, c1.y
nrm r0.xyz, t0
dp3 r0.x, r1, r0
add r0.xy, -r0.x, c1.x
texld r0, r0, s0
mul r0, r0, c0
mul r0, r1.w, r0
mov oC0, r0
// approximately 29 instruction slots used (1 texture, 28 arithmetic)