.. _channels: ======== 通道 ======== 通道用于声明顶点着色器将从顶点缓冲区获取的数据。 通道必须通过以下语法在 ``shader{...}`` 代码块中定义: .. code-block:: c channel (type) (usage_dst) = (usage_src) [ modifier ]; **数据类型** 使用 ``channel`` 关键字的数据类型与 :ref:`data-types` 中描述的本地 DSHL 类型不同。 这些类型被认为是 **可转换的**,这意味着当它们被移植到 ``hlsl{...}`` 块中的变量时,总是会被转换为本地 HLSL 数据类型。 即使源 DSHL 类型不是 4 分量类型,也会将其转换为某种基本标量类型的 4 分量向量。 例如,具有 ``(x, y)`` 分量的 ``float2`` 类型通过规则 ``(x, y, 0, 1)`` 被转换为 4 分量的float向量。 下面的列表描述了这些 **可转换** 类型及其向 4D 向量的转换。 - ``float1`` -- 1D float ``(x, 0, 0, 1)`` - ``float2`` -- 2D float ``(x, y, 0, 1)`` - ``float3`` -- 3D float ``(x, y, z, 1)`` - ``float4`` -- 4D float ``(x, y, z, w)`` - ``short2`` -- 2D signed short ``(x, y, 0, 1)`` - ``short4`` -- 4D signed short ``(x, y, z, w)`` - ``ubyte4`` -- 4D uint8_t ``(x, y, z, w)`` - ``color8`` -- 4-byte ``(R, G, B, A)`` color in ``[0..1]`` range - ``half2`` -- 2D 16-bit float ``(x, y, 0, 1)`` - ``half4`` -- 4D 16-bit float ``(x, y, z, w)`` - ``short2n`` -- 2D signed short normalized ``(x/32767.0, y/32767.0 , 0, 1)`` - ``short4n`` -- 4D signed short normalized ``(x/32767.0, y/32767.0 , z/32767.0, w/32767.0)`` - ``ushort2n`` -- 2D unsigned short normalized ``(x/32767.0, y/32767.0 , 0, 1)`` - ``ushort4n`` -- 4D unsigned short normalized ``(x/32767.0, y/32767.0 , z/32767.0, w/32767.0)`` - ``udec3`` -- 3D unsigned 10-bit float ``(x, y, z, 1)`` - ``dec3n`` -- 3D signed 10-bit float normalized ``(x/511.0, y/511.0, z/511.0, 1)`` **数据用法** 着色器资源生成器需要知道从给定网格中提取哪些数据发送给着色器。 这就是为什么需要指定通道的 **用途**。 - ``pos`` -- 位置 - ``norm`` -- 法线 - ``vcol`` -- 顶点颜色 - ``tc`` -- 纹理坐标 - ``lightmap`` -- 光照贴图,已弃用(使用光照贴图时代的遗留物) - ``extra`` -- 额外的,只能用作 ``usage_src``(用于为顶点提供额外信息) 通常, ``usage_src`` 和 ``usage_dst`` 是匹配的。但有时,例如当 ``extra`` 频道被用作 ``usage_src`` 时,必须将其重新映射到其他预期的 ``usage_dst``。 **数据修改器** 在某些情况下,数据修改器可能很有用,因为通道中的数据需要重新缩放或乘以某个常数。 - ``signed_pack`` -- 将数据从 ``[0..1]`` 范围转换到 ``[-1..1]`` 范围 - ``unsigned_pack`` -- 将数据从 ``[-1..1]`` 范围转换到 ``[0..1]`` 范围 - ``bounding_pack`` -- 将数据从 ``[min..max]`` 重新缩放到 ``[0..1]``(如果 ``usage_dst`` 是无符号的)或 ``[-1..1]`` (如果是有符号的) - ``mul_1k`` -- 将数据乘以 ``1024`` - ``mul_2k`` -- 将数据乘以 ``2048`` - ``mul_4k`` -- 将数据乘以 ``4096`` - ``mul_8k`` -- 将数据乘以 ``8192`` - ``mul_16k`` -- 将数据乘以 ``16384`` - ``mul_32767`` -- 将数据乘以 ``32767`` 并将其夹在 ``[-32767..32767]`` 范围内 下面是一个简单的使用示例: .. code-block:: c shader some_shader { /* 在此,我们为顶点着色器声明通道,着色器编译器将使用这些通道为该特定着色器生成适当的顶点着色器声明。 */ channel float3 pos=pos; // 顶点位置 channel color8 vcol=vcol; // 顶点颜色 channel float3 tc[0] = tc[0]; // 顶点纹理坐标 channel float3 tc[1] = tc[1]; // 其他顶点纹理坐标 hlsl(vs) { /* 此 VsInput 结构以 HLSL 风格声明顶点信息。 请注意,对于上面声明的每个 DSHL 通道,都应该有与所声明通道相匹配的相应 HLSL 语义。 */ struct VsInput { float4 pos : POSITION; // 顶点位置 float4 color : COLOR0; // 顶点颜色 float3 texcoord : TEXCOORD0; // 顶点纹理坐标 float3 another_texcoord : TEXCOORD1; // 其他顶点纹理坐标 }; } hlsl(vs) { VsOutput some_vs(VsInput input) { // ... } } }