# hxsl - Haxe 着色器语言

```var input : { pos : Float3, uv : Float2 };
var tuv : Float2;
function vertex( mpos : Matrix, mproj : Matrix ) {
out = pos.xyzw * mpos * mproj;
tuv = uv;
}
function fragment( t : Texture ) {
out = t.get(tuv,wrap);
}```

• 一个 "input" 对象，声明要保存到顶点缓存(Vertex buffer)数据
• 一个带参数(要处理顶点)的顶点着色器函数
• 一个带参数(要处理像素)的片段着色器函数

• `Float` : a single scalar value
• `Float2`, `Float3`, `Float4` : a set of 2,3,4 floats
• `Matrix` or `M44` : a 4x4 floats matrix
• `M33`, `M43` and `M34` : the corresponding matrix
• `Texture` : a 2D texture
• `CubeTexture` : a cubic texture (6 faces)

# 局部变量 Local variables

```function vertex(...) {
var tpos = pos.xyzw * mpos;
out = tpos * mproj;
}```

```function vertex(...) {
var tpos : Float4;
tpos = pos.xyzw * mpos;
out = tpos * mproj;
}```

# Constants

Constants can be a single scalar value or a group of constant values declared as an Haxe array :

```0.5         // Float
[0.5,1.5]   // Float2
[1,2,3]     // Float3
[1,2,3,4.5] // Float4```

# Operations

Here's the list of operations allowed in HxSL. FloatX means that this can apply to `Float`, `Float2`, `Float3` and `Float4` values, as soon as they are all of the same type.

All operations can be used in two ways :

```// standard C-like way :
// Object-Oriented way :

• `add` (or `+`) : add two values components
`function add( a : FloatX, b : FloatX ) : FloatX;`
• `sub` (or `-`) : subtract two values components
`function sub( a : FloatX, b : FloatX ) : FloatX;`
• `mul` (or `*`) : multiply two values components, or project a vector, or multiply two matrix :
```function mul( a : FloatX, b : FloatX ) : FloatX;
function mul( a : Float4, m : Matrix ) : Float4;
function mul( a : Matrix, b : Matrix ) : Matrix;```
• `div` (or `/`) : divide two values components
`function div( a : FloatX, b : FloatX ) : FloatX;`
• `pow` : calculate a^b for two values components
`function pow( a : FloatX, b : FloatX ) : FloatX;`
• `min` : calculate the minimum for two values components
`function min( a : FloatX, b : FloatX ) : FloatX;`
• `max` : calculate the maximum for two values components
`function max( a : FloatX, b : FloatX ) : FloatX;`
• `dot` (or `dp`, `dp3`, `dp4`) : calculate the dot product of two vectors
```function dot( a : Float3, b : Float3 ) : Float;
function dot( a : Float4, b : Float4 ) : Float;```
• `cross` (or `crs`) : calculate the cross product of two vectors
`function cross( a : Float3, b : Float3 ) : Float3;`
• `neg` (or unary `-`) : calculate the negative of one value components
`function neg( v : FloatX ) : FloatX;`
• `inv` (or `rcp`, or `1 / x`) : calculate the inverse of one value components
`function inv( v : FloatX ) : FloatX;`
• `sqrt` (or `sqt`) : calculate the square root of one value components
`function sqrt( v : FloatX ) : FloatX;`
• `rsqrt` (or `rsq`, or `1 / sqrt(x)`) : calculate the inverse square root of one value components
`function rsqrt( v : FloatX ) : FloatX;`
• `log` : calculate the logarithm of one value components
`function log( v : FloatX ) : FloatX;`
• `exp` : calculate the exponent of one value components
`function exp( v : FloatX ) : FloatX;`
• `length` (or `len`) : calculate the length of one value components
`function length( v : FloatX ) : Float;`
• `normalize` (or `norm`, or `nrm`') : return the normalized vector of one value components
`function normalize( v : FloatX ) : Float3;`
• `sin` : calculate the sinus of one value components
`function sin( v : FloatX ) : FloatX;`
• `cos` : calculate the cosine of one value components
`function cos( v : FloatX ) : FloatX;`
• `abs` : calculate the absolute of one value components
`function abs( v : FloatX ) : FloatX;`
• `saturate` (or `sat`) : calculate `min(1,max(v,0))` of one value components
`function saturate( v : FloatX ) : FloatX;`
• `fract` (or `frc`) : calculate the fractional portion of one value components
`function fract( v : FloatX ) : FloatX;`
• `int` : calculate the integer portion of one value components
`function int( v : FloatX ) : FloatX;`
• `lt` (or `<`) : return (a < b) ? 1 : 0 for each value components
`function lt( v : FloatX ) : FloatX;`
• `lte` (or `<=`) : return (a <= b) ? 1 : 0 for each value components
`function lte( v : FloatX ) : FloatX;`
• `gt` (or `>`) : return (a > b) ? 1 : 0 for each value components
`function gt( v : FloatX ) : FloatX;`
• `gte` (or `>=`) : return (a >= b) ? 1 : 0 for each value components
`function gte( v : FloatX ) : FloatX;`
• `kill` : only available in fragment shader. Skip a pixel write if the value is < 0
`function kill( v : Float ) : Void;`
• `get` : access a texture color value using a given texture coordinates
The following texture flags are allowed :
• `wrap` : wrap around the texture borders
• `clamp` : stick to the texture borders
• `nearest` : round-to-nearest pixel read
• `linear` : bilinear pixel read
• `mm_no` : disable mipmapping
• `mm_nearest` : round-to-nearest mipmapping
• `mm_linear` : linear mipmapping
• `centroid` : centroid sample
`function get( t : Texture, v : Float4, ....flags ) : Float4;`
• `transpose` : transpose a matrix components
`function transpose( m : MXY ) : MYX;`

It is possible to read only a part of a value components, or to rearrange the elements of a value by using swizzling. For example :

```var tmp : Float4 = [1,2,3,4];
out.x = tmp.x; // copy 1 into x
out.xz = tmp.yz; // copy 2 into x and 3 into z
out = tmp.xxww; // copy 1 into x and y and 4 into z and w```

The fact of only writing some parts of a value is called masking.

You can only swizzle on components which are accessible, for instance you cannot read the `z` value of a `Float2` variable. The only exception is for input and variables (not temporary ones) which all 4 components can be read since they are always filled with 0 if not written.

## Auto-Scalar Swizzling

When some operations take two `FloatX` values, if you use a single `Float` as one of two values, HxSL will automatically swizzle on all the components. For instance :

```var tmp : Float4 = [1,2,3,4];
out = tmp * 0.5; // will multiply all components by 0.5```

This also works for any single Float value :

```var half : Float = 0.5;
out = half * tmp; // same as writing half.xxxx```

# If / Else

If/Else can be inside a value-expression this way :

`color = if( red < 0 ) 1 else 0.2;`

This will actually compile to the code corresponding to the following :

`color = (red < 0) * 1 + (red >= 0) * 0.2;`

You can only use comparison operators inside a if/else value expression.

If/Else statements are not supported so far, but might be added in next HxSL version.

# For Loops

It is also possible to use for loops in HxSL, as long as they operate on constant values :

```// make the sum of 3x3 textures samples
var color = [0,0,0];
for( x in -1...2 )
for( y in -1...2 )
color += tex.get(uv + [x,y]);```

For-loops will be unrolled so the shader will be the same as if you would have written the corresponding 9 lines for each of the (x,y) possible values.

# Matrix Transposition

In order to perform operations such as vector projection or matrix multiplication, it is necessary to have the right matrix transposed (that is to be able to read its columns instead of its lines). This is because a Matrix consists in actually 4 Float4 values, which can represent either the matrix lines (by default) or its columns (transposed mode).

HxSL performs what is called matrix transposition inference. It infers from the operation you are using in which mode (either transposed or not) the matrix should be.

For instance when projecting a vector :

```function vertext( mpos : Matrix ) {
var tpos = pos * mpos;
...
}```

The will force the matrix `mpos` to be transposed. Any further operation using `mpos` in a not-transposed way will cause an error.

## Row Access

You can access a matrix row vector with `m[3]`, this will for example return the 4th row of the matrix.

# 在Flash11中使用 HxSL

```class Shader extends format.hxsl.Shader {
static var SRC = {
var input : { pos : Float3, uv : Float2 };
var tuv : Float2;
function vertex( mpos : Matrix, mproj : Matrix ) {
out = pos.xyzw * mpos * mproj;
tuv = uv;
}
function fragment( t : Texture ) {
out = t.get(tuv,wrap);
}
}
}

（以下为旧的写法，已经淘汰，放这里供对比参考）
var input : { pos : Float3, uv : Float2 };
var tuv : Float2;
function vertex( mpos : Matrix, mproj : Matrix ) {
out = pos.xyzw * mpos * mproj;
tuv = uv;
}
function fragment( t : Texture ) {
out = t.get(tuv,wrap);
}
})