Structures 结构体

 

As we showed in the first example shader, it is often convenient to

be able to define structures in HLSL shaders. For example, many

shader writers will define an output structure in their vertex

shader code and use this structure as the return type from their

vertex shader's main function. (It is less common to do this with a

pixel shader since most pixel shaders have only one float4 output.)

An example structure taken from the NPR Metallic shader

that we discuss later is shown below:

 

像我们在第一个例程着色器代码里所展示的,在HLSL里面定义

结构体是很方便的事情。例如,许多作者会在他们的代码中为

顶点着色器代码定义一个输出结构,然后使用这个结构作为他们

的顶点着色器的主函数的返回值。

 

struct VS_OUTPUT

{

float4 Pos : POSITION;

float3 View : TEXCOORD0;

float3 Normal: TEXCOORD1;

float3 Light1: TEXCOORD2;

float3 Light2: TEXCOORD3;

float3 Light3: TEXCOORD4;

};

 

Structures may be declared for general use in an HLSL shader as

well. They follow the type casting rules outlined above.

 

结构体也可以被声明在代码中作为通常的应用。他们遵循上面

提到的类型转换规则。

 

 

Samplers 采样器

 

For each different texture map that you plan to sample in a pixel

shader, you must declare a sampler. Recall the hlsl_rings() shader

described earlier:

 

为了在像素着色器中对每种不同的纹理映射类型进行采样,必须

声明一个采样器(sampler)。回顾早些时候声明的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);

}

 

In this shader, we declared a sampler called PulseTrainSampler at

global scope and passed it as the first parameter to the tex1D()

intrinsic function (we discuss intrinsics in the next section). An

HLSL sampler has a very direct mapping to the API concept of a

sampler and, in turn, to the actual silicon in the 3D graphics processor,

which is responsible for addressing and filtering textures.

A sampler must be defined for every texture map that you plan to

access in a given shader, but you may use a given sampler multiple

times in a shader. This usage is very common in image

processing applications, as discussed in ShaderX2: Shader Programming

Tips & Tricks with DirectX 9, since the input image is

often sampled multiple times with different texture coordinates to

provide data to a filter kernel expressed in shader code. For example,

the following shader uses the rasterizer to convert a height

map to a normal map with a pair of Sobel filters:

 

在这个shader里面,我们在全局域中声明了一个叫做PulseTrainSampler

采样器,然后把它作为第一个参数传递给tex1D()内置函数(我们将会在下一节讨论内置函数)。

一个HLSL采样器和一个API概念上的采样器是直接映射的,依次又映射到3维图形处理器

的晶片单元,后者负责纹理的采样和过滤。为了在指定的着色器中存取纹理贴图,必须先

定义采样器。如在《ShaderX2: Shader Programming Tips & Tricks with DirectX 9

中所讨论的,这种用法在图像处理程序中很常见,因为输入的图像经常需要用多个不同的纹理

坐标进行多次采样,为着色器中的核心过滤代码提供数据。例如,下面的着色器使用带有

两个Sobel 过滤器的光栅化器将一张高度贴图转换成为一张法线贴图:

 

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;

}

 

This shader uses only one sampler, InputImage, but samples from

it eight times using the tex2D() intrinsic function.

 

这个着色器仅仅使用了一个采样器InputImage,但是使用内置函数

tex2D()从输入的图像进行了8次采样。