フォースとシェーダー

私たちは詩について話している。 Forthプログラミング言語のミニマリズムとデモシーンの画像の美しさにより、プログラマーのBrad NelsonはForth Haikuのアイデアを思いつきました。 日本語の俳句を模倣して、ブラッドは最初の3行のプログラムを書きました。5行、7行、そして再び5行で構成されていました。 しかし、日本の伝統的なジャンルとは異なり、フォース語の詩は、読者の想像ではなく、視覚的にコンピューター画面に絵画を生み出しました。 Bradが最新のプラットフォーム(WebGL)でそれを具体化せず、オンラインエディターを公開した場合、このアイデアはコンピューターレトロの孤独なファンの風変わりのままです(Forthは古き良き70年代に強く関連付けられています)。



Forth Haikuコードの例と、このコードが作成する画像を次に示します。BradNelsonによる「Light Drop」。



: iii xyz* Sin ; x 5 * xy - iii exp y iii
      
      





BradNによるライトドロップ



私たちの先には、多くの素晴らしい(「ライブ」を含む)絵画が待っていますが、まずは-少しの理論です。



基本的な概念



安全上の注意事項 。 どうやら、「警告」の段落の前に誰も読む時間がありません。代わりに、彼らはすぐにオンラインエディタに行き、何かをしようとします。 結果は悲しいものです。サーバーが殺到し、作業のベースがアイドル俳句で記録されました。 少し下にスクロールして、水上での行動規則を読んでから、自己水泳に乗り出してください。 よろしくお願いします!



Forthはスタック型プログラミング言語です。 複数の番号に対してアクションを実行するには、最初にそれらをスタックにロードする必要があります。 これは、スペースで区切られた数字を単にリストすることで行われます。 次に、スタックの数値に対して実行するアクションを指定します。 また、チームはスペースで区切られており、計算に必要な任意の順序で数字と混ぜることができます。 通常の算術演算は、スタックの最上部からオペランドを取得し、代わりに結果を配置します。

1 2 3 + /





例1:番号1、2、および3をスタックにロードし、2つの上位番号を追加し(スタックは1、5の形式をとります)、1つの番号を別の番号に分割します。 その結果、スタックには答えが含まれています:数値0.2

1 2 + 3 /





例2:別の手順。 スタックに数値1と2をロードし、それらを追加します。 結果はスタックの3番で、スタックに3番をロードして除算を実行します。 回答:スタックの一番上にある番号1。



シェーダー -ここでは、ピクセルシェーダー、あるいはフラグメントシェーダーと呼ばれるものに焦点を当てます。 これは、テクスチャのポイント、およびこの場合は256x256サイズの正方形ウィンドウのポイントに対してビデオカードによって実行されるプログラムです。 したがって、ペイントを描画するキャンバスは65,536ポイントで構成され、シェーダープログラムが実行される回数になります。 出力では、ポイントの色が表示されます。 すべてのポイントに対して同じプログラムを実行すると、これらのポイントは同じように見えるはずです-大きなMalevich正方形(黒、赤、その他)が得られます。 それだけです しかし幸いなことに、シェーダープログラムは、現在描画しているポイントのx座標とy座標を認識できます。 そして、すべてが変わります。



座標系

Forth Haiku座標系

作業の最後に、シェーダープログラム(Forth Haiku)は、スタックに3つの数字を残します:色の赤のコンポーネント、緑のコンポーネント、青。 RGBコンポーネントの明るさは、ウィンドウの幾何学的寸法と同じスケールで測定されると非常に便利です。 xまたはyをスタックに置くだけで(各ポイントで異なりますよね?)、キャンバス全体で黒から明るい色へのスムーズな移行が得られます。



時間

xyに加えて、別のグローバル変数tが利用可能です-時間。 確かに、WebGLがサポートされていないブラウザーでは、常にゼロです。 カウントダウンは太古の時代に始まり、考えられない秒数が今ややってきたので、変数tの分数部分と型sin( t )の周期関数のみが、-1から+の範囲の値を与えるので、実用的です。 1。



最小限のアニメーション

 x y t sin 1 + 2 /
      
      





最も単純なアニメーションの例x座標をスタックに配置し、変更しないままにします。これは、色の赤成分を反映します。 スタックの2番目の場所に緑のコンポーネントを配置します。これはyになります(したがって、緑は下から上に移動します)。 青いコンポーネントとして、時間tを入れます。 そして、最後のセット番号に対して一連の操作を実行します。 まず、サインを取ります。 次に、1を追加して2で除算します。 それだけです 範囲が[-1,1]のサインがあり、[0,1]になりました-色の成分であるはずです。 そして、心地よい波紋が青のコンポーネントに沿って進み、今では赤と緑のコンポーネントで覆われた前のポイントよりも明るく照らされました-美!

比較のために、 同じ GLSLシェーダーを次に示します。

 void main(void) { vec2 uv = gl_FragCoord.xy / iResolution.xy; gl_FragColor = vec4(uv,0.5+0.5*sin(iGlobalTime),1.0); }
      
      





誰にも思えますが、Forthコードのほうが簡単でわかりやすいように思われます。トピックを入力するためのしきい値が非常に低くなっています。 Forth Haikuでの実験を数日間見て、9歳の息子がどのようなアニメーションを作成したか(最初から)確認してください。 これは指標だと思います。



どうぞ!



さて、理論は終わりました。実践に移りましょう。 フォースプログラミングサロンギャラリーには美しい静止画のイーゼルペイントがいっぱいです。 しかし、アニメーションにもっと興味があります。

警告 (安全上の注意):他の人の作品の選択(「派生作品の作成」)または新しい作品の作成(「俳句の作成」、「俳句編集者」)を開始すると、「送信」ボタンに手が届きます。 決してあなたが思ったようにはしないので、それを押さないでください ! 別のボタン-[更新]をクリックすると、プログラムを表示できます。 [送信]ボタンをクリックすると、タグ付けされた未完成のプログラムが公開され、ユーザー名が「匿名」であっても共通ギャラリーに公開されます。 このようなホッケーは必要ありません。ベースには既に壊れたプログラムスニペットとクローンがスパムされています(Brad Nelsonはベースをクリーンにし、インターフェースを改善することを約束しました)。 したがって、「 更新 」のみ。 体操の15分間の休憩である吸気-呼気は、プログラムをもう一度見て、146%の確信がある場合にのみ、名前を付けて著者を入力し、「送信」します。



マンウェによるゴールデンバンプ マンウェのコーヒー パックマンbyマンウェ

写真をクリックしてください。 そこに移動します! (ブラウザでChrome、Firefox、IE11)



もちろん、私のプログラムはひどく読めません。 まず、ごく最近(このForth翻訳者のJavaScriptを選んだ幼い息子のおかげで)プログラムにコメントを入力するための文書化されていない機能の存在について学びました(コメントテキスト自体からスペースで区切る必要があります)。 第二に- そしてこれが主なことです -私はプログラムのサイズを小さくしようとしました。 そのようなスポーツがあります-最適化、それはデモシーンで非常に人気があります 。 256バイトでしたか? よくやった! さて、128にしましょう。最初にやることは、Forth言語コマンドを再定義することです。

 : q dup * ;
      
      





コロンはそのようなForth言語の演算子です(実際、Fortプログラマーでは、「演算子」の代わりに「単語」、「コマンドと関数のセット」の代わりに「辞書」と言うのが慣習ですが、複雑にしません)。 コロン文は関数定義に似ています。 コロン(通常どおり、スペースで区切られた)がnew演算子の名前の後、この例では「q」です(単語「square」から)。 名前の後に、小さなプログラムがスペースで書き込まれます。これは、新しく作成された演算子「q」の本体です。 最後の演算子はセミコロン、定義の最後です(実際、特別なリターンスタックからリターンアドレスを取り出し、そこに命令カウンターを再配置しますが、ここでも複雑にしません)。

多くの場合、使用されるコマンドシーケンスは、物理的な意味がない場合でも 、個別の新しい演算子で意味を持ちます。 私が伝統的なプログラミング手法でレイトレーシングを書いているとしましょう。 私にとってのベクトルは、3つの数字の密接にリンクされたセットであり、正規化関数は、特定の物理的意味を持つ個別の式などです。 しかし、純粋に機械的に、「深い内部の意味」を考えずに、Forthプログラムの最適化を開始し、定数の乗算が蒸発し、一部の関数が途中で壊れて他の関数と結合し、最終的に...完全に異なる構造化プログラムを取得する場合独自の特別な美しさを持っています。 それが短くなったという事実は言うまでもありません。 例:

 x ' r / z * lx m y ' r / z * ly m
      
      





ここで、 xyはグローバル定数であり、他のすべてはプログラマーによって決定されます。 「ストローク」演算子は別の座標系に移動し、「r」演算子はベクトルの長さを計算し、z演算子は法線を計算し、「lx」と「ly」は光源の座標を、「m」はベクトル(より正確には、その座標の1つ)を正規化します。 必要に応じて、「z」演算子の本体に「z」の後に乗算を追加できます(数バイトを節約します)。 そして、「z」の前の除算を(または前の演算子「r」に)追加できます。 最適化中に、これらの中間アクションはすべて辞書に忍び込み、プログラムの本体には最低限の本質、x、y、tのみが残ります。

綺麗です。 しかし、1週間後、もちろん完全に読めなくなりました。



Forth Haiku辞書を使用して理解できる簡単なプログラムの例が必要ですか? この辞書は、古典的なForth辞書よりもずっと貧弱で、これは意図的なものです。 演算子をクリックして、それについて詳しく読んでください。

マンウェのキャンディ滝

 : r dup y 12 ** * t + sin swap x * cos + 1 mod ; 18 r 25 r dup 12 r /
      
      





最初の行では、演算子「r」(単語「render」から)を定義します。これは、スタックの最上部から数字を飲み込み、慎重にかみ、 Xgamesで噛み、その後、スタックの範囲[0,1]に結果を吐き出します。 演算子「r」には異なる数が3回入力され、出力では3つのRGBコンポーネントが取得されます。 色補正のために、緑のコンポーネントを複製し、青に分割します。 これで新しい青いコンポーネントができたので、全体像はキャラメルになります。

「1 mod」は、数値の小数部分を取得しています。 確かに、それはどこでも動作しません(実際、Forth HaikuはWebGLがない場合、純粋なJavaScriptで描画されますが、いくつかの制限があります)。 「1 mod」の代わりに「dup floor-」を使用することをお勧めします。 ただし、128バイトより小さいサイズを追跡する場合は、簡潔さを優先して互換性を犠牲にする必要があります。



筋金入りのファンのために-バイナリ操作などがなくてもスプライトを描く:

PONG by Manwe マンウェによる侵略者 Trisomie21とManweの溶岩ランプ



おわりに



Forth Haikuは非常にシンプルで非常に限られています。 必要に応じて、多くを絞り出すことができますが、GLSLとの競合の問題はありません。 目標ではありません。 Forthプログラム自体は美しいです。 Forthでプログラミングしている人、さらにはピクセルシェーダーをプログラミングしている人の思考の流れ自体も興味深いものです。 気を散らし、自分自身を楽しませる素晴らしい方法、子供たちのための素晴らしいエクササイズ。 正直、学校での第4回俳句コースを紹介します。 少なくとも4分の1の子供たちに違う考え方をさせるのは素晴らしいことです。



参照資料



ブラッドネルソンのフォースプロジェクト

ハイクダンプ -作品ギャラリーへの「裏口」。



All Articles