Contents

純粋なConi LispでWebGLシェーダーを書く!

前回の記事では、80,000パーティクルのWebGLマトリックスをオーケストレーションすることで、Coni WASMの生み出すパワーを紹介しました。しかし、WebGLのパイプラインには常に一つの厄介な問題が残っていました。それはシェーダーそのものです。

WebGLコードを書いたことがある人なら、その面倒さを知っているはずです。頂点シェーダーとフラグメントシェーダーを、コードベース全体に連結された巨大で厄介な文字列リテラルとして書くことになります。構文のハイライトもフォーマットも失われ、さらにLispハッカーにとって最も悲劇的なことに、構造的編集(Paredit/Slurp/Barf)も失われてしまいます。

本日、新しいlibs/webgl/src/glsl.coniライブラリにより、私たちがその最後のフロンティアを征服したことを発表できることを嬉しく思います。

GLSLシェーダーをConiのネイティブLisp構文で完全に記述できるようになりました。

defshaderの登場

Coniの強力なAST(抽象構文木)とマクロシステムを活用することで、私たちはdefshaderを構築しました。これは標準的なLispのフォーム、型、数学的演算を受け取り、それらがGPUに到達する前に自動的に厳密なGLSLへとトランスパイルします。

私たちのAmplifocusパーティクルエンジンのために、このフラグメントシェーダーがいかに美しく書かれているかを見てください:

(require "libs/webgl/src/glsl.coni" :all)

(defshader fs-src
  (precision mediump float)
  (varying vec4 v_color)
  
  (defn void main []
    ;; ネイティブの数学と座標マッピング!
    (set vec2 coord (- gl_PointCoord (vec2 0.5 0.5)))
    (set float dist (length coord))
    
    (if (> dist 0.5)
      (discard))
    
    ;; LispのS式を使った発光(グロー)の計算
    (set float glow (- 1.0 (* dist 2.0)))
    (set vec4 final_color (* v_color glow))
    (set gl_FragColor final_color)))

なぜこれがゲームチェンジャーなのか?

  1. 文字列リテラルからの解放: シェーダーはファーストクラスのコードになります。アプリケーションの他の部分と完全にフォーマットが統一されます。
  2. ASTレベルの検証: Coniコンパイラは、ブラウザでWebGLプログラムをコンパイルしようとする前に、シェーダーの構造をパースして検証できます。
  3. 構造的編集: 標準的なLispの構造的編集ツールを使用して、複雑なGPU計算をスラープ、バーフ、そして操作することができます。CスタイルのGLSL文字列でそれをやろうとしてみてください!
  4. シームレスな統合: 使用可能なWebGLシェーダーへのコンパイルは、core-gl/gl-shader関数を呼び出すだけというシンプルさです:(core-gl/gl-shader gl (.-FRAGMENT_SHADER gl) fs-src)

ブラウザのためのフルスタックLisp

このアップデートにより、パイプラインは完成しました。reframeによるDOM操作から、WebAudioの合成、WASMのFloatバッファ、そして今や実際のGPU頂点変換に至るまで、100% Coniで実現できます。

生のJavaScriptは不要です。生のGLSLも不要です。ただ、驚異的な速度で実行される純粋なLispがあるだけです。

私たちはすでに、これらの新しいLispシェーダーをdeep-focus-webglアプリにデプロイしています。ブラウザで高性能なインタラクティブ体験を構築しているなら、ぜひConiを試す時が来ました!