JavaScript EditorFree JavaScript Editor     Ajax Editor 



Main Page
Previous Page
Next Page

3.7. Operations

Table 3.1 includes the operators, in order of precedence, available in the OpenGL Shading Language. The precedence and associativity are consistent with C.

Table 3.1. Operators, in order of precedence

Operator

Description

[ ]

Index

.

Member selection and swizzle

++ --

Postfix increment/decrement

++ --

Prefix increment/decrement

- !

Unary negation and logical not

* /

Multiply and divide

+ -

Add and subtract

< > <= >=

Relational

== !=

Equality

&&

Logical and

^^

Logical exclusive or

||

Logical inclusive or

?:

Selection

= += -= *= /=

Assignment

,

Sequence


3.7.1. Indexing

Vectors, matrices, and arrays can be indexed with the index operator ([ ]). All indexing is zero based; the first element is at index 0. Indexing an array operates just as in C.

Indexing a vector returns scalar components. This allows giving components numerical names of 0, 1, . . . and also enables variable selection of vector components, should that be needed. For example,

vec4 v = vec4(1.0, 2.0, 3.0, 4.0);
float f = v[2];  // f takes the value 3.0

Here, v[2] is the floating-point scalar 3.0, which is then assigned into f.

Indexing a matrix returns columns of the matrix as vectors. For example,

mat4 m = mat4(3.0);  // initializes the diagonal to all 3.0
vec4 v;
v = m[1];   // places the vector (0.0, 3.0, 0.0, 0.0) into v

Here, the second column of m, m[1] is treated as a vector that is copied into v.

Behavior is undefined if an array, vector, or matrix is accessed with an index that is less than zero or greater than or equal to the size of the object.

3.7.2. Swizzling

The normal structure-member selector (.) is also used to SWIZZLE components of a vectorthat is, select or rearrange components by listing their names after the swizzle operator (.). Examples:

vec4 v4;
v4.rgba;   // is a vec4 and the same as just using v4,
v4.rgb;    // is a vec3,
v4.b;      // is a float,
v4.xy;     // is a vec2,
v4.xgba;   // is illegal - the component names do not come from
           // the same set.

The component names can be out of order to rearrange the components, or they can be replicated to duplicate the components:

vec4 pos = vec4(1.0, 2.0, 3.0, 4.0);
vec4 swiz = pos.wzyx; // swiz = (4.0, 3.0, 2.0, 1.0)
vec4 dup = pos.xxyy; // dup = (1.0, 1.0, 2.0, 2.0)

At most, four component names can be listed in a swizzle; otherwise, they would result in a nonexistent type. The rules for swizzling are slightly different for R-VALUES (expressions that are read from) and L-VALUES (expressions that say where to write to). R-values can have any combination and repetition of components. L-values must not have any repetition. For example:

vec4 pos = vec4(1.0, 2.0, 3.0, 4.0);
pos.xw = vec2(5.0, 6.0); // pos = (5.0, 2.0, 3.0, 6.0)
pos.wx = vec2(7.0, 8.0); // pos = (8.0, 2.0, 3.0, 7.0)
pos.xx = vec2(3.0, 4.0); // illegal - 'x' used twice

For R-values, this syntax can be used on any expression whose resultant type is a vector. For example, getting a two-component vector from a texture lookup can be done as

vec2 v = texture1D(sampler, coord).xy;

where the built-in function texture1D returns a vec4.

3.7.3. Component-wise Operation

With a few important exceptions, when an operator is applied to a vector, it behaves as if it were applied independently to each component of the vector. We refer to this behavior as component-wise for short.

For example,

vec3 v, u;
float f;
v = u + f;

is equivalent to

v.x = u.x + f;
v.y = u.y + f;
v.z = u.z + f;

And

vec3 v, u, w;
w = v + u;

is equivalent to

w.x = v.x + u.x;
w.y = v.y + u.y;
w.z = v.z + u.z;

If a binary operation operates on a vector and a scalar, the scalar is applied to each component of the vector. If two vectors are operated on, their sizes must match.

Exceptions are multiplication of a vector times a matrix and a matrix times a matrix, which perform standard linear-algebraic multiplies, not component-wise multiplies.

Increment and decrement operators (++ and --) and unary negation (-) behave as in C. When applied to a vector or matrix, they increment or decrement each component. They operate on integer and floating-point-based types.

Arithmetic operators of addition (+), subtraction (-), multiplication (*), and division (/) behave as in C, or component-wise, with the previously described exception of using linear-algebraic multiplication on vectors and matrices:

vec4 v, u;
mat4 m;
v * u;  // This is a component-wise multiply
v * m;  // This is a linear-algebraic row-vector times matrix multiply
m * v;  // This is a linear-algebraic matrix times column-vector multiply
m * m;  // This is a linear-algebraic matrix times matrix multiply

All other operations are performed component by component.

Logical not (!), logical and (&&), logical or (||), and logical inclusive or (^^) operate only on expressions that are typed as scalar Booleans, and they result in a Boolean. These cannot operate on vectors. A built-in function, not, computes the component-wise logical not of a vector of Booleans.

Relational operations (<, >, <=, and >=) operate only on floating-point and integer scalars and result in a scalar Boolean. Certain built-in functions, for instance, lessThanEqual, compute a Boolean vector result of component-wise comparisons of two vectors.

The equality operators (== and !=) operate on all types except arrays. They compare every component or structure member across the operands. This results in a scalar Boolean, indicating whether the two operands were equal. For two operands to be equal, their types must match, and each of their components or members must be equal. To compare two vectors in a component-wise fashion, call the built-in functions equal and notEqual.

Scalar Booleans are produced by the operators equal (==), not equal (!=), relational (<, >, <=, and >=), and logical not (!) because flow-control constructs (if, for, etc.) require a scalar Boolean. If built-in functions like equal are called to compute a vector of Booleans, such a vector can be turned into a scalar Boolean with the built-in functions any or all. For example, to do something if any component of a vector is less than the corresponding component of another vector, the code would be

vec4 u, v;
. . .
if (any(lessThan(u, v)))
    . . .

Assignment (=) requires exact type match between the left- and right-hand side. Any type, except for arrays, can be assigned. Other assignment operators (+=, -=, *=, and /=) are similar to C but must make semantic sense when expanded, as in

a *= b    a = a * b

where the expression a * b must be semantically valid, and the type of the expression a * b must be the same as the type of a. The other assignment operators behave similarly.

The ternary selection operator (?:) operates on three expressions: exp1 ? exp2 : exp3. This operator evaluates the first expression, which must result in a scalar Boolean. If the result is true, the operator selects to evaluate the second expression; otherwise, it selects to evaluate the third expression. Only one of the second and third expressions will appear to be evaluated. The second and third expressions must be the same type, but they can be of any type other than an array. The resulting type is the same as the type of the second and third expressions.

The sequence operator (,) operates on expressions by returning the type and value of the rightmost expression in a comma-separated list of expressions. All expressions are evaluated, in order, from left to right.


Previous Page
Next Page




JavaScript EditorAjax Editor     JavaScript Editor