More IL examples
IL is now fully multi-threaded. A new thread is started with:
thread( f, arg1, arg2, ...) where f
is the name of a function string and arg1,
arg2, etc. are the arguments that
function is started with in the new thread. thread(
.. ) returns an integer identification of the thread. The boolean status of a
thread t is returned by isready(
t ).When a thread is finished, You can call end(
t ), which also returns the result of the associated function.. threads()
returns a list of integers indicating active threads.
String and Diferential operatorsRecently I extended the functionality of the String function. It is of course the function linked to the Stringtyp, converting any coercible type to a String. Now it can also be applied to any map, returning a string, which, when executed as a function, again generates that map.
} m = exp(m3()'0)
exp( ( m3() ' 0 ) )
To improve readability, there is a mode xyzuvt which, when set, replaces the domain components by , surprise, x, y, z, u, v, and t.
exp( x )
error 127: identifier unknown x
Of course when calling this string as a function, x has to be defined. Initially doing read( "xyz" )takes care of all of this:
xyz = m3();
x = xyz'0;
y = xyz'1;
z = xyz'2;
uv = m2();
u = uv'0;
v = uv'1;
t = m1();
xyzuvt( T );
have even more fun with this, I introduced differential operators. Each
domain has it's own, and they are generated by functions: D1, D2, D3. They are applied by multiplication.
For maps representing a scalar function (Real valued), they can be regarded as gradient. For a vector field (for instance Real3 valued), they are the divergence. http://en.wikipedia.org/wiki/Del
To apply them as curl, use cross product notation: **.
} ma = exp(x) / log(y*z)
} dma = D3()*ma
( ( exp( x ) * log( ( y * z ) ) ) / sqr( log( ( y * z ) ) ) ), ( exp( x
) / sqr( log( ( y * z ) ) ) ), ( exp( x ) / sqr( log( ( y * z ) )
) ) )
} mb = real3( x^2, sin(y), tan(z) )
} dmb = D3()*mb
( ( 2 * x ) + ( cos( y ) + ( 1 + sqr( tan( z ) ) ) ) )
} mc = real3( log( y * sin(z) ) , exp(z) / cos( x), tan( x*y ) )
} String( D3()**mc )
real3( ( ( x * ( 1 + sqr( tan( ( x * y ) ) ) ) ) - ( ( exp( z ) * cos( x ) ) / sqr( cos( x ) ) ) ), ( ( ( y * cos( z ) ) / ( y * sin( z ) ) ) - ( y * ( 1 + sqr( tan( ( x * y ) ) ) ) ) ), ( ( exp( z ) / sqr( cos( x ) ) ) - ( sin( z ) / ( y * sin( z ) ) ) ) )
OpenGL bindingOpenGL is integrated in the language. It works by linking a list of lists to a window. Every list is one of:
A shader program is created by glslprogram(), followed by setshader and linkshader calls.
- a shader program to use, followed by a list of uniform definition pairs.
- a drawable followed by its model transform
framebuffer to render to, which will be used as a texture when
switching back to normal window rendering (by a list with a single 0)
Look at glalphatest.il for instance.
glrendertotex.il is a framebuffer example. Also notice here how easy it is to do a simple animation by just using a m1 (time) based map in a transform expression.
Other files you can try are: glalphatestI.il for simple mouse interaction, glcubmap(I).il, glcubemap_refract(I).il, gldiscardI.il and gledge.il.
All these examples are based on the book "OpenGL 4.0 Shading Language Cookbook" by David Wolff.
Dual number magicLook here about dual numbers. In IL
they are pretty much implemented analogous to complex numbers. When you
have an expression calculating dual numbers and you apply that to dual( x, 1 ),
the real part of the result is the value as if that expression simply
was applied to the real value, but the dual part of the result is the
value of the derivative at x.
} f = "( log( %1 ) + sin( %1 ) ) / tan( %1 )"
( log( %1 ) + sin( %1 ) ) / tan( %1 )
} f( 5 )
-0.19243 - 0.85051 e
} m = f( t )
} evalmap( D1() * m )
Random ConstructorsIn il.il several random constructor functions are defined:
vr = "real3( normrand(), normrand(), normrand() )";
zr := "cmplx( normrand(), normrand() )";
nzr := "norm( zr() )";
dr = "dual( normrand(), normrand() )";
qr := "quat( normrand(), normrand(), normrand(), normrand() )";
nqr := "norm( qr() )";
nor := "norm( or() )";
dqr = "dualquat( qr(), qr() )";
ndqr = "norm( dqr() )";
Dual QuaternionsLook here for an introduction. For construction, dualquat takes 2 quaternions or 4 duals. Q0 and Qe give back the 2 quaternion parts.There are two versions of the conjugate:
} dq = ndqr()
A dual quaternion is equivalent to a rigid transformation:
0.87237 -0.4422 0.20841 -0.18378
0.00538 -0.41762 -0.9086 0.15325
0.48882 0.79376 -0.36194 0.33735
} tt = rotate( 0.5*pi, lx ) * translate( 1,2,3 )
0.0 0.0 -1.0 -3.0
} DualQuat( tt )
In il.il a function is defined how to transform with a dual quaternion:
dqtrf = "im( Qe( %1 * DualQuat( %2 ) * conj( dconj( %1 ) ) ) )";
} dq = ndqr()
} w = vr()
} Transform(dq) * w