官术网_书友最值得收藏!

Using packed arrays

Loosely speaking, the code inside a shader has to be executed for at least every pixel in your screen. This is the reason why GPUs are highly optimized for parallel computing. This philosophy is also evident in the standard type of variables and operators available in Cg. Understanding them is essential not just to use shaders correctly, but also to write highly optimized ones.

How to do it...

There are two types of variables in Cg: single values and packed arrays. The latter can be identified because their type ends with a number such as float3 or int4. As their names suggest, these types of variables are similar to structs, which means that they each contain several single values. Cg calls them packed arrays, though they are not exactly arrays in the traditional sense.

The elements of a packed array can be accessed as a normal struct. They are typically called x, y, z, and w. However, Cg also provides you with another alias for them, that is, r, g, b, and a. Despite there being no difference between using x or r, it can make a huge difference for the readers. Shader coding, in fact, often involves calculation with positions and colors. You might have seen this in the Standard Shaders:

o.Alpha = _Color.a;

Here, o was a struct and _Color was a packed array. This is also why Cg prohibits the mixed usage of these two syntaxes: you cannot use _Color.xgz.

There is also another important feature of packed arrays that has no equivalent in C#: swizzling. Cg allows addressing and reordering elements within packed arrays in just a single line. Once again, this appears in the Standard Shader:

o.Albedo = _Color.rgb;

Albedo is fixed3, which means that it contains three values of the fixed type. However, _Color is defined as fixed4. A direct assignment would result in a compiler error as _Color is bigger than Albedo. The C# way of doing this would be as follows:

o.Albedo.r = _Color.r;
o.Albedo.g = _Color.g;
o.Albedo.b = _Color.b;

However, it can be compressed in Cg:

o.Albedo = _Color.rgb;

Cg also allows reordering elements, for instance, using _Color.bgr to swap the red and blue channels.

Lastly, when a single value is assigned to a packed array, it is copied to all of its fields:

o.Albedo = 0; // Black =(0,0,0)
o.Albedo = 1; // White =(1,1,1)

This is referred to as smearing.

Swizzling can also be used on the left-hand side of an expression, allowing only certain components of a packed array to be overwritten:

o.Albedo.rg = _Color.rg;

In which case, it is called masking.

Packed matrices

Where swizzling really shows its full potential is when applied to packed matrices. Cg allows types such as float4x4, which represents a matrix of floats with four rows and four columns. You can access a single element of the matrix using the _mRC notation, where R is the row and C is the column:

float4x4 matrix;
// ...
float first = matrix._m00;
float last = matrix._m33;

The _mRC notation can also be chained:

float4 diagonal = matrix._m00_m11_m22_m33;

An entire row can be selected using squared brackets:

float4 firstRow = matrix[0];
// Equivalent to
float4 firstRow = matrix._m00_m01_m02_m03;

See also

Packed arrays are one of the nicest features of Cg. You can discover more about them here:

http://http.developer.nvidia.com/CgTutorial/cg_tutorial_chapter02.html

主站蜘蛛池模板: 玉龙| 贡嘎县| 吴川市| 枣阳市| 莲花县| 曲周县| 梁河县| 道孚县| 安吉县| 岳普湖县| 合水县| 莱阳市| 南平市| 类乌齐县| 梁平县| 西昌市| 克什克腾旗| 大竹县| 曲麻莱县| 安化县| 西乡县| 广平县| 长春市| 靖安县| 兴安县| 巴塘县| 景泰县| 上虞市| 五河县| 湘乡市| 宁晋县| 灯塔市| 宝应县| 嘉定区| 鹤壁市| 宁津县| 涡阳县| 德惠市| 台南县| 米泉市| 韶山市|