Contents

用纯Coni Lisp编写WebGL着色器!

在上一篇文章中,我们通过编排一个由80,000个粒子组成的WebGL矩阵展示了Coni WASM的原始威力。但在WebGL流水线中,始终存在一个挥之不去的烦恼:着色器本身

如果您写过WebGL代码,您一定深有体会。您最终会将顶点着色器和片段着色器写成庞大、混乱的字符串字面量,散布在整个代码库中。您失去了语法高亮、格式化,而且——对于Lisp黑客来说最悲惨的是——您失去了结构化编辑(Paredit/Slurp/Barf)。

今天,我们非常高兴地宣布,我们通过新的 libs/webgl/src/glsl.coni 库征服了最后的这个前沿阵地。

您现在完全可以使用Coni的原生Lisp语法编写您的GLSL着色器了。

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-表达式进行发光(Glow)计算
    (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结构化编辑工具来slurp、barf和操作复杂的GPU数学计算。试着用C风格的GLSL字符串做这些试试!
  4. 无缝集成: 将其编译成可用的WebGL着色器极其简单,只需调用我们的 core-gl/gl-shader 函数即可:(core-gl/gl-shader gl (.-FRAGMENT_SHADER gl) fs-src)

专为浏览器打造的全栈Lisp

有了这次更新,整个流水线终于完整了。从使用 reframe 的DOM操作,到WebAudio合成,到WASM浮点缓冲,再到现在实际的GPU顶点变换——100%都是Coni。

无需原生JavaScript。无需原生GLSL。只有纯粹的、以惊人速度运行的Lisp。

我们已经将这些全新的Lisp着色器部署到了我们的 deep-focus-webgl 应用中。如果您正在浏览器中构建高性能的交互式体验,是时候试试Coni了!