DirectX 9高层着色语言介绍4——语言基础(3)

原创 2004年10月13日 22:36:00

强制类型转换

为了有助于着色器的编写和所产生代码的效率,最好熟悉一下HLSL的强制类型转换机制。强制类型转换常用于扩展或缩减选定的变量以匹配要赋值的变量。例如,在下列例子中,初始化vResult时把float型常量0.0f强制转换为float4型{0.0f , 0.0f , 0.0f , 0.0f }。

float4   vResult = 0.0f;

当把一个高维数据类型如向量或矩阵类型赋值给一个低维数据类型时就会发生类似的强制转换。这些情况下,额外数据都被有效省略。例如,编写下列代码:

float3   vLight;
float    fFinal, fColor;
fFinal = vLight * fColor;

这个例子中,只是把float类型的标量fColor与vLight中的第一个成员相乘,从而把vLight强制转换为float类型。fFinal等于vLight.x * fColor。

最好先熟悉一下表4,HLSL的强制类型转换规则:

表6. HLSL的强制类型转换规则

Scalar-to-scalar 一直有效。当布尔型被强制转换为整数或浮点型,false变为0,true变为1。当整数或浮点型被强制转换为布尔型,0变为false,非0变为true。当浮点型被强制转换为整数类型,值被向0舍入,这与C语言的一样截断机制一样。
Scalar-to-vector 一直有效 该强制转换操作通过复制标量并填充到向量。
Scalar-to-matrix 一直有效 该强制转换操作通过复制标量并填充到矩阵。
Scalar-to-structure 该强制转换操作通过复制标量并填充到结构体。
Vector-to-scalar 一直有效 选择向量的第一部分。
Vector-to-vector 目标向量必须不大于资源向量。该强制转换操作是通过保留最左边的值,去掉多余值。这样做的目的是可以把行矩阵,列矩阵和数字结构看成向量。
Vector-to-matrix 向量大小必须与矩阵大小相等。
Vector-to-structure 结构体不大于向量,且结构体各部分均为数字则有效。
Matrix-to-scalar 一直有效 选择了矩阵的左上部分。
Matrix-to-vector 矩阵大小必须与向量大小相等。
Matrix-to-matrix 目标矩阵在任何一维都不大于源矩阵,该强制转换操作是通过保持左上值,去掉多余值。
Matrix-to-structure 结构体的大小等于矩阵的大小,结构体的所有成员都是数字。
Structure-to-scalar 结构体必须包含至少一个数字型成员
Structure-to-vector 结构体必须至少与向量的大小一样,第一个成员必须是数字,一直到向量的大小。(译者注:即成员数量与向量大小一样)
Structure-to-matrix 结构体必须至少与矩阵的大小一样。第一个成员必须是数字,一直到矩阵的大小。(译者注:即成员数量与矩阵大小一样)
Structure-to-object 结构体至少包含一个对象的成员。该成员的类型必须和对象类型完全相同。
Structure-to-structure 目标结构必须不大于源结构。一个有效的强制转换必定存在于所有相应的源成员与目的成员之间。

结构体

正如上边第一个着色器示例显示的,在HLSL着色器中定义一个结构体常常带来方便。例如,许多着色器编写者在他们的顶点着色器代码中会定义一个输出的结构体,使用该结构体作为他们的顶点着色器主函数的返回类型。(对于像素着色器很少这样做因为大多数像素着色器只有一个float4输出。)一个结构体的例子如下,来自于NPR Metallic着色器,我们将在后边讨论该着色器。(译者注:NPR(non-photo reality),是一种独特的二w维效果)

struct VS_OUTPUT
{
   float4 Pos   : POSITION;
   float3 View  : TEXCOORD0;
   float3 Normal: TEXCOORD1;
   float3 Light1: TEXCOORD2;
   float3 Light2: TEXCOORD3;
   float3 Light3: TEXCOORD4;
};

在HLSL着色器中也可以声明结构体作为普通使用。同样遵循上边所概括的强制类型转换规则。

取样器

要是想在像素着色器中对于每一个不同的纹理贴图进行取样,必须声明一个取样器。再调用一下前边描述的着色器中的hlsl_rings():

float4 lightWood; // xyz == Light Wood Color
float4 darkWood;  // xyz == Dark Wood Color
float  ringFreq;  // ring frequency

sampler PulseTrainSampler;

float4 hlsl_rings (float4 Pshade : TEXCOORD0) : COLOR
{
    float scaledDistFromZAxis = sqrt(dot(Pshade.xy, Pshade.xy)) * ringFreq;

    float blendFactor = tex1D (PulseTrainSampler, scaledDistFromZAxis);
 
    return lerp (darkWood, lightWood, blendFactor);
}

在这个着色器中,我们在全局范围声明了一个被称为PulseTrainSampler的取样器并把它作为第一个参数传递给内部函数tex1D()(将在下一部分讨论内部函数)。HLSL取样器 有一个非常直接的映射——在基于取样器概念的API与实际硅(在负责寻址纹理和过滤纹理的3D图形处理器中)之间轮换。在一个着色器中必须为每一个你计划访问的纹理贴图定义一个取样器,不过你可以在一个着色器中多次使用给定的取样器。这种处理方法在图像处理程序中非常普遍(在ShaderX2 - Shader Tips & Tricks的"Advanced Image Processing with DirectX 9 Pixel Shaders"章节有讨论),为了给由着色器代码表示的一个内部过滤器提供数据,输入的图像被以不同的纹理坐标多次取样。例如,下面的着色器使用光栅化引擎(rasterizer)通过一对Sobel滤波器把一个高度贴图(height map)转换为一个法线贴图(normal map)。

sampler InputImage;

float4 main( float2 topLeft    : TEXCOORD0, float2 left        : TEXCOORD1,
             float2 bottomLeft : TEXCOORD2, float2 top         : TEXCOORD3,
             float2 bottom     : TEXCOORD4, float2 topRight    : TEXCOORD5,
             float2 right      : TEXCOORD6, float2 bottomRight : TEXCOORD7): COLOR
{
   // Take all eight taps
   float4 tl = tex2D (InputImage, topLeft);
   float4  l = tex2D (InputImage, left);
   float4 bl = tex2D (InputImage, bottomLeft);
   float4  t = tex2D (InputImage, top);
   float4  b = tex2D (InputImage, bottom);
   float4 tr = tex2D (InputImage, topRight);
   float4  r = tex2D (InputImage, right);
   float4 br = tex2D (InputImage, bottomRight);

   // Compute dx using Sobel operator:
   //
   //           -1 0 1 
   //           -2 0 2
   //           -1 0 1
   float dX = -tl.a - 2.0f*l.a - bl.a + tr.a + 2.0f*r.a + br.a;

   // Compute dy using Sobel operator:
   //
   //           -1 -2 -1 
   //            0  0  0
   //            1  2  1
   float dY = -tl.a - 2.0f*t.a - tr.a + bl.a + 2.0f*b.a + br.a;

   // Compute cross-product and renormalize
   float4 N = float4(normalize(float3(-dX, -dY, 1)), tl.a);

   // Convert signed values from -1..1 to 0..1 range and return
   return N * 0.5f + 0.5f;
}

该着色器只使用了一个取样器:InputImage,不过示例中八次调用了内部函数tex2D()。

DirectX 9高层着色语言介绍3 —— 语言基础(2)

强制类型转换  为了有助于着色器的编写和所产生代码的效率,最好熟悉一下HLSL的强制类型转换机制。强制类型转换常用于扩展或缩减选定的变量以匹配要赋值的变量。例如,在下列例子中,初始化vResult时把...
  • chenbuaa
  • chenbuaa
  • 2004年10月28日 16:05
  • 1011

DirectX 9高层着色语言介绍3——语言基础(2)

类型修饰符在你的着色器中打算使用的HLSL中有几个可选的类型修饰符。通常把不想被着色器的代码修改的量设为const(常量)类型修饰符。在赋值符号左边使用常量(例如作为一个lval)会产生一个编译错误。...
  • starflash2003
  • starflash2003
  • 2004年10月12日 00:13
  • 2069

DirectX 9高层着色语言介绍

引言高层着色语言(HLSL)是DirectX® 9最为强力的新组件之一。使用这种标准的高级语言, 在进行着色时编写者可以专注于算法而不用再去理会诸如寄存器的分配,寄存器读端口限制, 并行处理指令等等硬...
  • pizi0475
  • pizi0475
  • 2010年04月07日 13:07
  • 1033

DirectX 9高层着色语言介绍2 —— 语言基础(1)

语言基础  现在你已经对什么是HLSL顶点和像素着色器以及他们如何与低层汇编着色器相互作用有了了解,我们将讨论一些语言本身的细节。关键字  关键字是HLSL语言保留的预定义标识符,不能在你的程序中作为...
  • chenbuaa
  • chenbuaa
  • 2004年10月28日 16:03
  • 880

DirectX 9高层着色语言介绍2——语言基础(1)

  语言基础现在你已经对什么是HLSL顶点和像素着色器以及他们如何与低层汇编着色器相互作用有了了解,我们将讨论一些语言本身的细节。关键字关键字是HLSL语言保留的预定义标识符,不能在你的程序中作为标识...
  • starflash2003
  • starflash2003
  • 2004年10月09日 23:22
  • 1526

DirectX (7) 着色方式

引言              在前面,我们已经讲解了多个
  • i_dovelemon
  • i_dovelemon
  • 2014年05月29日 15:01
  • 1845

DirectX学习笔记(五):利用平面着色和Gouraud着色模式绘制具有颜色的三角形

完整代码: #include #include #include IDirect3DDevice9* Device = 0; // 一个C++对象,代表了我们用来显示3D图形的物理硬件设...
  • lishuzhai
  • lishuzhai
  • 2016年09月14日 14:37
  • 2648

DirectX11 图形流水线历史以及着色器简介

图形流水线历史Direct3D要求使用着色器来渲染几何图形,因此我们会在深入讨论着色器之前就会遇到它们。为了了解着色器的由来,我们首先要了解下图形流水线的历史。 图形流水线是什么? 图形流水线是G...
  • sinat_24229853
  • sinat_24229853
  • 2015年07月18日 13:07
  • 1032

DirectX 9高层着色语言介绍1——引言、简单例子、汇编语言和编译对象

引言高层着色语言(HLSL)是DirectX® 9最为强力的新组件之一。使用这种标准的高级语言, 在进行着色时编写者可以专注于算法而不用再去理会诸如寄存器的分配,寄存器读端口限制, 并行处理指令等等硬...
  • starflash2003
  • starflash2003
  • 2004年10月08日 23:49
  • 2827

DirectX 9高层着色语言介绍1 —— 引言、简单例子、汇编语言和编译对象

引言  高层着色语言(HLSL)是DirectX® 9最为强力的新组件之一。使用这种标准的高级语言, 在进行着色时编写者可以专注于算法而不用再去理会诸如寄存器的分配,寄存器读端口限制, 并行处理指令等...
  • chenbuaa
  • chenbuaa
  • 2004年10月28日 16:01
  • 1161
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:DirectX 9高层着色语言介绍4——语言基础(3)
举报原因:
原因补充:

(最多只允许输入30个字)