顶点着色器和像素着色器比早期着色器版本大大简化。 如果在硬件中实现着色器,则不能将vs_3_0或ps_3_0与任何其他着色器版本一起使用,并且不能将任一着色器类型与固定函数管道一起使用。 这些更改使简化驱动程序和运行时成为可能。 唯一的例外是,仅软件vs_3_0着色器可与任何像素着色器版本一起使用。 此外,如果将仅软件vs_3_0着色器与以前的像素着色器版本一起使用,则顶点着色器只能使用与灵活顶点格式 (FVF) 代码兼容的输出语义。

必须在像素着色器输入上使用顶点着色器输出上使用的语义。 语义用于将顶点着色器输出映射到像素着色器输入,类似于将顶点声明映射到顶点着色器输入寄存器和以前的着色器模型的方式。 请参阅 vs 3.0 和 ps 3.0 着色器上的匹配语义。

添加了其他环绕模式呈现状态,以覆盖此新方案中其他纹理坐标的可能性。 设置相应的D3DRS_WRAP * 时,D3DDECLUSAGE_TEXCOORD和使用索引从 0 到 15 的属性在换行模式下内插。

  • 顶点着色器模型 3 功能
  • 像素着色器模型 3 功能
  • 匹配vs_3_0和ps_3_0着色器的语义
  • 迷雾、深度和底纹模式更改
  • 浮点和整数转换
  • 指定完全或部分精度
  • 软件顶点和像素着色器
  • 顶点着色器模型 3 功能

    顶点着色器输出寄存器类型已折叠为十二个寄存器 (请参阅 输出寄存器 ) 。 使用的每个寄存器都需要使用 dcl 指令和语义 ((例如,dcl_color0 o0.xyzw) )进行声明。

    3_0 顶点着色器模型 (vs_3_0) 扩展vs_2_0的功能,具有更强大的寄存器索引、一组简化的输出寄存器、在顶点着色器中采样纹理的能力,以及控制着色器输入初始化速率的功能。

    为任何寄存器编制索引

    可以使用 循环计数器 寄存器) 的所有寄存器 ( 输入寄存器 输出寄存器 编制索引, (在早期版本中只能为常量寄存器编制索引。)

    在为输入和输出寄存器编制索引之前,必须声明它们。 但是,不能为已使用位置或点大小语义声明的任何输出寄存器编制索引。 事实上,如果使用索引,则必须分别在 o0 和 o1 寄存器中声明位置和 psize 语义。

    只能为连续范围的寄存器编制索引;也就是说,不能跨尚未声明的寄存器编制索引。 虽然此限制可能不方便,但它允许进行硬件优化。 尝试跨非连续寄存器编制索引将产生未定义的结果。 着色器验证不强制实施此限制。

    简化输出寄存器

    所有各种类型的输出寄存器都已折叠为 12 个输出寄存器:1 个用于位置,2 表示颜色,8 表示纹理,1 表示雾或点大小。 这些寄存器将内插它们包含的像素着色器的任何数据。 输出寄存器声明是必需的,语义将分配给每个寄存器。

    寄存器可以按如下方式细分:

  • 必须至少将一个寄存器声明为四分量位置寄存器。 这是唯一必需的顶点着色器寄存器。
  • 着色器使用的前十个寄存器可能最多使用四个分量, (xyzw) 最大值。
  • 最后一个 (或第十二个) 寄存器只能包含标量 (,例如点大小) 。
  • 有关寄存器的列表,请参阅 Registers - vs_3_0

    顶点着色器中的纹理示例

    顶点着色器 3_0 支持使用 texldl - vs . 的顶点着色器中的纹理查找

    像素着色器模型 3 功能

    像素着色器颜色寄存器和纹理寄存器已折叠为十个输入寄存器 (请参阅 输入寄存器类型 ) 。 人脸寄存器是浮点标量寄存器。 只有此寄存器的符号有效。 如果符号为负数,则基元为背面。 例如,这可以在像素着色器内用于实现双面照明。 位置寄存器引用当前 (x,y) 像素。

    可以使用以下方法设置着色器常量寄存器:

  • SetPixelShaderConstantB
  • SetPixelShaderConstantI
  • SetPixelShaderConstantF
  • 匹配vs_3_0和ps_3_0着色器的语义

    vs_3_0和ps_3_0的语义使用存在一些限制。 通常,使用与着色器输出上使用的语义匹配的着色器输入时,需要小心谨慎。

    例如,此像素着色器将多个名称打包到一个寄存器中:

    ps_3_0 
    dcl_texcoord0 v0.x 
    dcl_texcoord1 v0.yz // Valid to pack multiple names into one register 
    dcl_texcoord2_centroid v1.w
    

    每个寄存器都有不同的语义。 请注意,由于使用了写入掩码,还可以使用不同的 (多个) 语义命名 v0.x 和 v0.yz。

    给定像素着色器后,以下vs_3_0着色器不能与其配对:

    vs_3_0 
    dcl_texcoord0 o5.x 
    dcl_texcoord1 o6.yzw 
    

    这两个着色器与它们对 D3DDECLUSAGE_TEXCOORD0 and D3DDECLUSAGE_TEXCOORD1 语义的使用冲突。

    重写顶点着色器,如下所示,以避免语义冲突:

    vs_3_0 
    dcl_texcoord2 o3 
    dcl_texcoord3 o9 
    

    同样,像素着色器) 中的不同输入寄存器上声明 (v0 和 v1 的语义名称不能在此顶点着色器的单个输出寄存器中使用。 例如,此顶点着色器不能与像素着色器配对,因为D3DDECLUSAGE_TEXCOORD1用于像素着色器输入寄存器 (v0、v1) 和顶点着色器输出寄存器 o3。

    vs_3_0 
    dcl_texcoord0 o3.x 
    dcl_texcoord1 o3.yz 
    dcl_texcoord2 o3.w // BAD! Would be valid if this were not o3 
    dcl_texcoord3 o9 ... 
    

    另一方面,此顶点着色器不能与像素着色器配对,因为具有给定语义的参数的输出掩码不提供像素着色器请求的数据:

    vs_3_0 
    dcl_texcoord0 o5.x 
    dcl_texcoord1 o5.yzw 
    dcl_texcoord2 o7.yz // BAD! Would be valid if w were included 
    dcl_texcoord3 o9 
    

    此顶点着色器不提供具有像素着色器请求的语义名称之一的输出,因此着色器配对无效:

    vs_3_0 
    dcl_texcoord0 o5.x 
    dcl_texcoord1 o5.yzw 
    dcl_texcoord3 o9 
    // The pixel shader wants texcoord2, with a w component, 
    // but it isn't output by this vertex shader at all! 
    

    迷雾、深度和底纹模式更改

    在剪裁和三角形光栅化期间为平面着色设置D3DRS_SHADEMODE时,具有D3DDECLUSAGE_COLOR的属性将内插为平面着色。 如果使用颜色语义声明寄存器的任何组件,但为同一寄存器的其他组件提供不同的语义,则将在该寄存器中没有颜色语义的组件上定义平面着色内插 (线性与平面) 。

    如果需要雾渲染,vs_3_0和ps_3_0着色器必须实现迷雾。 着色器之外不会执行雾计算。 vs_3_0中没有雾寄存器,D3DDECLUSAGE_FOG (每个顶点计算的雾混合因子的其他语义) 和D3DDECLUSAGE_DEPTH (,用于将深度值传递给像素着色器以计算雾混合因子) 已添加。

    使用像素着色器 3.0 时,将忽略纹理阶段状态D3DTSS_TEXCOORDINDEX。

    添加了以下值以适应这些更改:

    // Fog and Depth usages
    D3DDECLUSAGE_FOG 
    D3DDECLUSAGE_DEPTH 
    // Additional wrap states for vs_3_0 attributes with D3DDECLUSAGE_TEXCOORD 
    D3DRS_WRAP8 
    D3DRS_WRAP9 
    D3DRS_WRAP10 
    D3DRS_WRAP11 
    D3DRS_WRAP12 
    D3DRS_WRAP13 
    D3DRS_WRAP14 
    D3DRS_WRAP15
    

    浮点和整数转换

    浮点数学以不同的精度和范围发生, (管道的不同部分的 16 位、24 位和 32 位) 。 一个大于进入该管道的管道的动态范围的值 (例如,32 位浮点纹理贴图被采样到 24 位浮点管道中,ps_2_0) 创建未定义的结果。 对于可预测的行为,应将此类值限制为最大动态范围。

    从浮点值到整数的转换发生在多个位置,例如:

  • 遇到 mova - vs 指令时。
  • 在纹理寻址期间。
  • 写出到非浮点呈现目标时。
  • 指定完全或部分精度

    ps_3_0和ps_2_x都支持两个级别的精度:

    ps_3_0 ps_2_0 Precision

    ps_3_0支持的精度比ps_2_0高。 默认情况下,所有操作都以全精度级别进行。

    部分精度 (请参阅 像素着色器寄存器修饰符) 请求,方法是将_pp修饰符添加到着色器代码 (前提是基础实现) 支持它。 实现始终可以自由地忽略 修饰符,并完全精确执行受影响的操作。

    _pp修饰符可以在两个上下文中出现:

  • 在纹理坐标声明中,将部分精度纹理坐标传递给像素着色器。 当纹理坐标将颜色数据中继到像素着色器时,可以使用此方法,在部分精度下可能比某些实现中的全精度更快。
  • 在任何指令上请求使用部分精度,包括纹理加载指令。 这表示允许实现以部分精度执行指令并存储部分精度结果。 在没有显式修饰符的情况下,无论输入操作数) 的精度如何,都必须以全精度 (执行指令。
  • 应用程序可能会故意选择权衡精度的性能。 有几种类型的着色器输入数据是部分精度处理的自然候选项:

  • 颜色迭代器由部分精度值很好地表示。
  • 大多数格式的纹理值可以通过部分精度值来准确表示, (从 32 位浮点格式纹理采样的值是) 一个明显的例外。
  • 常量可由适合着色器的部分精度表示形式表示。
  • 在所有这些情况下,开发人员可以选择指定部分精度来处理数据,因为知道不会丢失任何输入数据精度。 在某些情况下,着色器可能要求以全精度执行计算的内部步骤,即使输入和输出值没有超过部分精度。

    软件顶点和像素着色器

    软件实现 (运行时和顶点着色器的引用和像素着色器的引用) 版本 2_0 及更高版本的验证有所放宽。 这对于调试和原型制作非常有用。 应用程序向运行时/汇编程序指示,它需要使用汇编程序 (中的_sw标志放宽某些验证,例如,vs_2_sw) 。 软件着色器不适用于硬件。

    vs_2_sw是放松到最大上限vs_2_x:同样,ps_2_sw是放宽到最大上限ps_2_x。 具体而言,以下验证是宽松的:

    着色器模型 vs_2_sw、vs_3_sw、ps_2_sw、ps_3_sw 循环开始/步骤/计数 代表和循环指令的迭代开始和迭代步骤大小是 32 位有符号整数。 计数最多可以为 MAX_INT/64。 vs_2_sw、vs_3_sw、ps_2_sw、ps_3_sw 放宽了所有寄存器文件的端口限制。 vs_3_sw vs_3_sw中的 16 个输出寄存器。 ps_3_sw 14 (16-2) ps_3_sw 输入寄存器。