We will talk about poetry. The minimalism of the programming
language Forth and the beauty of the images of the
demoscene pushed the programmer Brad Nelson to the idea of
Forth Haiku . Imitating the Japanese haiku, Brad wrote his first three-line programs, which consisted of five, seven, and again five words. But unlike the traditional Japanese genre, poetry in the Forth language produced pictures not in the reader’s imagination, but visibly, on a computer screen. This idea could remain a fad of a lonely fan of computer retro (Forth is strongly associated with the good old seventies), if Brad had not embodied it on the modern platform (WebGL) and would not have made the online editor publicly available.
Here is an example of the Forth Haiku code and the image that this code creates: “Light Drop” by Brad Nelson.
: iii xyz* Sin ; x 5 * xy - iii exp y iii

')
Ahead of us are waiting for a lot of amazing (including "live") pictures, but first - a little theory.
Basic concepts
Safety . Apparently, no one has time to finish reading the paragraph of “Warning”, instead they immediately go to the online editor and try to do something. The consequences are sad: the server was inundated, the base of work was blocked by non-performing haiku. Please scroll down a bit and read the rules of behavior on the water before embarking on an independent voyage. Thank!
Forth is a stack programming language. To perform operations on multiple numbers, you must first load them onto the stack. This is done by simply listing the numbers separated by spaces. Then indicate the action to be performed on the numbers from the stack. Commands are also separated by spaces and can go along with the numbers in any order necessary for the calculation. Ordinary arithmetic operations remove operands from the top of the stack and place the result instead.
1 2 3 + /
Example 1: we load the numbers 1, 2 and 3 onto the stack, then we add the two upper numbers (the stack becomes 1, 5) and then divide one number by another. As a result, the stack contains the answer: the number 0.2
1 2 + 3 /
Example 2: a different procedure. We load the numbers 1 and 2 onto the stack; The result is the number 3 stack. We load another number 3 onto the stack and perform a division. Answer: the number 1 on top of the stack.
Shader - here we will talk about pixel shaders, otherwise called fragmentary. This is a program executed by a video card for
each texture point, and in our case for each point of a square window of 256x256. Thus, the canvas on which we draw our pictures consists of 65536 points, and the shader program will be executed exactly this time. At the exit, it should produce a color point. It would seem that if the same program is executed for all points, then these points should look the same - we get Malevich’s large square (black, red, any other). It's like that. But fortunately, the shader program can recognize the
x and
y coordinates of the point that it is currently drawing. And that changes everything.
Coordinate system
At the end of the work, our shader program (Forth Haiku) should leave three numbers on the stack: the red component of the color, the green component and the blue one. It is very convenient that the brightness of the RGB components is measured on the same scale as the geometric dimensions of the window. Simply by putting
x or
y on the stack (it’s different for each point, right?), We’ll get a smooth color transition from black to bright through our entire canvas.
TimeIn addition to
x and
y , another global variable
t is available to us - time. True, in browsers lacking WebGL support, it is always zero. The countdown began in immemorial times, by now an inconceivable number of seconds had already hit, so the practical use for us is, perhaps, only the fractional part of the variable
t and the periodic function of the type sin (
t ), since it gives values ​​in the range from -1 to + one.

x y t sin 1 + 2 /
An example of the simplest animation. Put the
x coordinate on the stack and leave it unchanged - it will reflect the red component of the color. We put the green component on the second place in the stack, it will be
y (so the green will be raised from the bottom up). We put time
t as the blue component. And now we perform a series of operations on the last number. First, take a sine from it. Then we add 1 and divide by 2. Everything. We had a sine in the range [-1,1], and became [0,1] - as it should be a component of the color. And so a pleasant ripple went over the blue component, and now more points shone, shaded by the red and green component - beauty!
For comparison, here is
the same GLSL shader:
void main(void) { vec2 uv = gl_FragCoord.xy / iResolution.xy; gl_FragColor = vec4(uv,0.5+0.5*sin(iGlobalTime),1.0); }
To whom as, and to me, the Forth code seems simpler and clearer, it offers a very low threshold for entering the topic. See
what kind of animation my 9-year-old son did (from scratch) just by watching a couple of days of my experiments with Forth Haiku. I think this is an indicator.
Time forward!
Well, the theory is finished, we proceed to practice. The
Forth Programming Salon Gallery is full of
easel paintings of beautiful still images. But we are more interested in animation.
Warning (safety): when you start picking someone else's work (“Create a derived work”) or creating new ones (“Create a Haiku”, “Haiku Editor”), your hand will reach for the “Submit” button. In no case do not press it, because it
does not what you thought! You can view your program by clicking another button - “Update”. And the “Submit” button will publish into your general gallery your buried unfinished program, and with the username “Anonymus”. We don’t need such hockey, the base is already spammed with broken scraps of programs and clones (Brad Nelson promised to clean the base and improve the interface). So just "
Update ". Inhale-exhale, 15-minute break for gymnastics, take a fresh look at our program, and only if 146% are confident in it - then we give it a name, enter the author and - “Submit”.

Click on the pictures. It moves there! (in Chrome, Firefox, IE11 browsers)
My programs, of course, are terribly unreadable. First, only recently (thanks to the little son who picked up the JavaScript of this Forth-translator) I learned about the existence of an undocumented possibility to enter comments into the program (in parentheses, which must be separated by a space from the comment text itself). Secondly -
and this is the main thing - I tried to reduce the size of the program. There is such a sport - optimization, very
popular in the demoscene . 256 bytes smog? Well done! Now let's put it in 128. Therefore, the first thing I do is override the commands of the Forth language.
: q dup * ;
A colon is such an operator of the Forth language (in fact, among Fort programmers, it is customary to say “word” instead of “operator” and “dictionary” instead of “set of commands and functions”, but we will not complicate it). The colon operator is akin to defining a function. Following the colon (separated by a space, as usual) comes the name of the new operator, in this example it is “q” (from the word “square”). After the name, a small program is written through the space, which makes up the body of our newly-made operator “q”. The last statement is “semicolon”, the end of the definition (in fact, it takes out the return address from the special stack of returns and rearranges the command counter there, but again - let's not complicate it).
It often makes sense to use frequently used sequences of commands in separate new operators,
even if there is no physical sense in it . Let's say I write rey-tracing with a traditional programming approach. For me, vectors are inextricably linked sets of three numbers, the normalization function for me is a separate formula that has a specific physical meaning, and so on. But it costs me purely mechanically, without thinking about the “deep inner meaning”, to start optimizing the program at Forth, how multiplication by constants evaporates, some functions break in the middle and stick together with tails with other functions, but in the end ... As a result, I get a completely different structured program having its own special beauty. Not to mention the fact that she became shorter. For example:
x ' r / z * lx m y ' r / z * ly m
Here
x and
y are global constants, everything else is defined by the programmer. The operator "stroke" takes us to another coordinate system, the operator "r" calculates the length of the vector, the operator z calculates the normal, "lx" and "ly" give the coordinates of the light source, "m" normalizes the vector (more precisely, one of its coordinates). If it pleases us, we can add the multiplication after “z” into the body of the operator “z” itself (we will save a couple of bytes). And the division before “z” can be added to it (or to the previous operator “r”). When optimizing, all these intermediate actions crawl into the dictionary, and in the body of the program only the bare essence remains:
x, y, t .
It is beautiful. But after a week is completely unreadable, of course.
Do you want an example of a simple program that you can understand with the help
of the Forth Haiku dictionary ? This dictionary is much poorer than the dictionary of the classic Forth, and it is done on purpose. Click on the operator itself and read more about it.

: r dup y 12 ** * t + sin swap x * cos + 1 mod ; 18 r 25 r dup 12 r /
In the first line, we define the operator “r” (from the word “render”), which swallows the number from the top of the stack, chews carefully, snacking on
X and
players , and then spits out the result in the range [0, 1]. Operator "r" three times feed different numbers, and the output we get three components of RGB. For color correction, we duplicate the green component and divide it by the blue one. Now we have a new blue component, so that the overall picture turned out caramel.
"1 mod" is getting the fractional part of a number. True, it does not work everywhere (Forth Haiku, in fact, is drawn in the absence of WebGL, in pure JavaScript, but with a number of restrictions). Instead of "1 mod" it is better to use "dup floor -". But when you go after a size smaller than 128 bytes, you have to sacrifice compatibility in favor of brevity.
For fans of hardcore - drawing sprites in the absence of binary operations and a little more of all:

Conclusion
Forth Haiku is very simple and very limited. If you wish, you can squeeze out quite a lot of it, but there is no talk of any competition with GLSL. Not the goal. The Forth program is beautiful in itself. The thought flow of a person programming at Forth, and programming pixel shaders as well, is interesting in itself. A wonderful way to distract yourself and have fun, a great exercise for children. I would introduce a Forth Haiku course at school, honestly. At least one-fourth to push the children think different - it's great.
Links
Brad Nelson Forth
Projects .
Haiku dump - “back door” to the gallery of works.