☰
The Book of Shaders:运行 Fragment Shader 的完整工具链——glslCanvas、glslViewer、glslEditor 与主流框架集成实战
2026/10/15 20:43:46 网站建设 项目流程

【免费下载链接】thebookofshaders

Step-by-step guide through the abstract and complex universe of Fragment Shaders.

项目地址:https://gitcode.com/gh_mirrors/th/thebookofshaders
点击查看免费下载

本指南对应《The Book of Shaders》第 4 章(04/README-fr.md)的技术主线:如何把书中每一章编写的 Fragment Shader 真正"跑起来"。文章将带你走完作者为本书构建的完整工具生态(浏览器显示、命令行渲染、在线编辑、分享与画廊策展),并给出在 Three.js、Processing、openFrameworks、SFML 四大主流框架中接入这些 shader 的可运行代码,同时结合本仓库(04/ 示例目录 与 src/ 站点资源)的源码级证据进行印证。读完你即可拥有从"写一行 GLSL"到"在任意平台展示作品"的完整实战能力。

一、工具生态总览:显示、创建、分享、策展

这一章的核心是一套由作者(Patricio Gonzalez Vivo)为本书构建的 shader 工具生态系统,覆盖了 shader 工作流的四个环节:

环节工具典型用途
显示(Display)glslCanvas在浏览器<canvas>中直接渲染独立的 fragment shader,本书所有在线示例均由此驱动
命令行(Console)glslViewer在 bash 脚本或 Unix 管道中运行 shader,类似 ImageMagick 的用法,也是树莓派上编译 shader 的利器
创建(Create)glslEditor带辅助小部件(widgets)的 GLSL 编辑器,内嵌于本书示例,也可作为独立 Web 应用运行
分享(Share)glslEditor 在线版导出 shader 的唯一 URL,或直接导出到 openFrame.io 艺术展示平台
策展(Curate)glslGallery将多个 shader 组织成画廊,嵌入任意网站

这套工具最重要的特性是跨平台一致:同一份 shader 代码无需任何改动,即可在 Linux 桌面、macOS、Windows、Raspberry Pi 以及浏览器上以相同方式运行——这也是后续所有章节示例能够"复制即用"的前提。

二、在浏览器中显示:glslCanvas

glslCanvas 让"运行一个独立 shader"变得极其简单:只需要在 HTML 中放置一个带glslCanvas类的canvas元素,并通过data-fragment-url属性指向你的.frag文件即可:

<canvas class="glslCanvas">glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -E screenshot,yourOutputImage.png
  • yourShader.frag:要渲染的 fragment shader;
  • yourInputImage.png:可选输入纹理;
  • -w 500 -h 500:输出窗口/图像尺寸为 500×500;
  • -E screenshot,yourOutputImage.png:执行截图命令,把渲染结果保存为yourOutputImage.png。

小提示:不同翻译版本对该命令的写法略有差异,例如 04/README-ch.md 中使用的是-s 1 -o yourOutputImage.png的形式,含义同为"保存一帧输出图像",实际参数以你所安装的 glslViewer 版本帮助为准。

glslViewer 的另一大价值是树莓派:由于它能够在树莓派上直接编译并全屏显示 shader,openFrame.io 正是基于它来展示 shader 艺术作品。此外,如果你习惯离线使用 SublimeText 编写代码,可以安装 glslViewer 的 SublimeText 插件包,在编辑器内一键预览 shader(见下方 glslViewer 运行效果)。

四、编写与分享:glslEditor

为了降低 GLSL 编码的抽象感,作者开发了 glslEditor 编辑器:它内嵌在本书的实时示例中(参见 src/main.js 中.codeAndCanvas元素的解析逻辑,编辑器以 250px 画布跟随、右侧浮动、带导出按钮等选项初始化),提供一系列实用小部件,让代码编辑过程"看得见、摸得着"。你也可以在浏览器中将其作为独立 Web 应用打开使用。

分享能力:无论是内嵌版还是独立版,编辑器都提供导出按钮——你可以把 shader 保存到线上并获得一个唯一 URL 用于分享,甚至可以直接导出为 openFrame.io 兼容格式,让 shader 进入数字艺术展框(如下方导出流程动图所示)。

五、策展你的作品:glslGallery

分享代码只是把 shader 当作艺术作品分享的开始。glslGallery 是一个画廊工具,用于把多个 shader 组织成可嵌入任何网站的展示画廊,适合作品集或教学页面批量陈列。至此,从"编写 → 显示 → 分享 → 策展"的完整闭环打通。

六、贯穿全书的 uniform 命名约定

在进入框架集成之前,有必要先明确一个约定:本书所有 shader 统一使用以下 uniform 变量名(从仓库中的示例 shader 可以清楚看到这一规律):

  • uniform vec2 u_resolution;:画布/窗口分辨率(像素),用于把gl_FragCoord归一化到 0.0~1.0;
  • uniform float u_time;:运行以来的秒数,驱动动画;
  • uniform vec2 u_mouse;(或vec3):鼠标位置,驱动交互。

例如 04/processing/data/shader.frag 与 04/sfml/data/shader.frag 中的标准头部即为此约定,而主站源码 src/moon/moon.frag 甚至额外使用了u_tex0、u_tex0Resolution这类纹理 uniform。理解了这套命名,后续所有框架示例的对应关系就一目了然:框架侧只需负责在每一帧把这三个值喂给 GPU 即可。

七、在 Three.js 中运行

Three.js 是 WebGL 生态中最知名的框架之一。在浏览器中,你可以完全复用第二章学到的 shader 代码,把它粘贴到下面 HTML 中id="fragmentShader"的 script 标签里:

<body> <div id="container"></div> <script src="js/three.min.js"></script> <script id="vertexShader" type="x-shader/x-vertex"> void main() { gl_Position = vec4( position, 1.0 ); } </script> <script id="fragmentShader" type="x-shader/x-fragment"> uniform vec2 u_resolution; uniform float u_time; void main() { vec2 st = gl_FragCoord.xy/u_resolution.xy; gl_FragColor=vec4(st.x,st.y,0.0,1.0); } </script> <script> var container; var camera, scene, renderer, clock; var uniforms; init(); animate(); function init() { container = document.getElementById( 'container' ); camera = new THREE.Camera(); camera.position.z = 1; scene = new THREE.Scene(); clock = new THREE.Clock(); var geometry = new THREE.PlaneBufferGeometry( 2, 2 ); uniforms = { u_time: { type: "f", value: 1.0 }, u_resolution: { type: "v2", value: new THREE.Vector2() }, u_mouse: { type: "v2", value: new THREE.Vector2() } }; var material = new THREE.ShaderMaterial( { uniforms: uniforms, vertexShader: document.getElementById( 'vertexShader' ).textContent, fragmentShader: document.getElementById( 'fragmentShader' ).textContent } ); var mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); renderer = new THREE.WebGLRenderer(); renderer.setPixelRatio( window.devicePixelRatio ); container.appendChild( renderer.domElement ); onWindowResize(); window.addEventListener( 'resize', onWindowResize, false ); document.onmousemove = function(e){ uniforms.u_mouse.value.x = e.pageX uniforms.u_mouse.value.y = e.pageY } } function onWindowResize( event ) { renderer.setSize( window.innerWidth, window.innerHeight ); uniforms.u_resolution.value.x = renderer.domElement.width; uniforms.u_resolution.value.y = renderer.domElement.height; } function animate() { requestAnimationFrame( animate ); render(); } function render() { uniforms.u_time.value += clock.getDelta(); renderer.render( scene, camera ); } </script> </body>

要点拆解:

  1. 顶点着色器:示例给出的是一个最简顶点着色器,直接把顶点位置原样输出,渲染结果是一张覆盖屏幕的 2×2 平面;
  2. uniforms 容器:u_time(f类型)、u_resolution(v2)、u_mouse(v2)在 JS 侧以{ type, value }形式声明,与 GLSL 声明一一对应;
  3. 每帧更新:render()中通过clock.getDelta()累加u_time,onWindowResize()中刷新u_resolution,鼠标移动事件更新u_mouse——这正是第六节所述约定在 Three.js 中的落地方式。

仓库中的完整版本见 04/three_js/index.html,它在文档示例基础上额外预置了u_mouse的声明与鼠标事件处理,可直接打开运行。

八、在 Processing 中运行

Processing 会在 sketch 的data文件夹中查找名为"shader.frag"的 shader 文件,所以请把书中的示例代码复制进data目录并正确命名:

PShader shader; void setup() { size(640, 360, P2D); noStroke(); shader = loadShader("shader.frag"); } void draw() { shader.set("u_resolution", float(width), float(height)); shader.set("u_mouse", float(mouseX), float(mouseY)); shader.set("u_time", millis() / 1000.0); shader(shader); rect(0,0,width,height); }
  • loadShader("shader.frag"):加载并编译着色器;
  • shader.set(...):向 uniform 传值,注意u_time用millis() / 1000.0换算为秒;
  • shader(shader):用自定义着色器替换默认管线;
  • rect(0,0,width,height):绘制全屏矩形作为"广告牌",让每个像素都被 shader 处理。

兼容旧版本:在 Processing 2.1 之前的版本中运行,需要在 shader 开头加入一行#define PROCESSING_COLOR_SHADER,完整 shader 形如:

#ifdef GL_ES precision mediump float; #endif #define PROCESSING_COLOR_SHADER uniform vec2 u_resolution; uniform vec3 u_mouse; uniform float u_time; void main() { vec2 st = gl_FragCoord.st/u_resolution; gl_FragColor = vec4(st.x,st.y,0.0,1.0); }

注意此版本中u_mouse声明为vec3。仓库中的完整 sketch 见 04/processing/processing.pde,它额外实现了keyPressed()热重载——每次按键都会重新loadShader("shader.frag"),方便边改边看;配套的 shader 文件位于 04/processing/data/shader.frag。

九、在 openFrameworks 中运行

与 Processing 类似,openFrameworks 也会从data文件夹查找 shader 文件,因此需要把.frag文件复制进去,并在程序中指定文件名:

void ofApp::draw(){ ofShader shader; shader.load("","shader.frag"); shader.begin(); shader.setUniform1f("u_time", ofGetElapsedTimef()); shader.setUniform2f("u_resolution", ofGetWidth(), ofGetHeight()); ofRect(0,0,ofGetWidth(), ofGetHeight()); shader.end(); }
  • shader.load("", "shader.frag"):第一个参数是顶点着色器路径(留空表示用默认顶点着色器),第二个是 fragment shader;
  • shader.begin() / shader.end():在两者之间替换渲染管线;
  • setUniform1f / setUniform2f:分别设置float与vec2类型的 uniform。

仓库中的完整工程见 04/openFrameworks/src/ofApp.cpp(类声明在 ofApp.h):它不仅补全了u_mouse的传递(setUniform2f("u_mouse", mouseX, mouseY)),还在keyPressed()中实现了按键热重载(ofApp.cpp)。

如果希望以更简洁的方式使用 glslViewer/glslCanvas 规范中的全套 uniforms(多缓冲、材质 shader、热重载、以及树莓派上的 OpenGL ES 自动转换),文档推荐使用 ofxShader 插件,代码可以简化为 allocate + load + render 三步。

十、仓库补充:在 SFML 中运行(完整 CMake 工程)

除了文档正文的三个框架,本仓库还额外提供了一个 SFML(C++ 多媒体库)的完整可构建示例,位于 04/sfml/:

  • 04/sfml/src/main.cpp:创建 800×800 渲染窗口,通过shader.loadFromFile("data/shader.frag", sf::Shader::Fragment)加载片段着色器,在主循环中用shader.setUniform("u_resolution", ...)、shader.setUniform("u_mouse", ...)、shader.setUniform("u_time", ...)更新三个标准 uniform,最后window.draw(shape, &shader)以着色器渲染全屏矩形;
  • 04/sfml/CMakeLists.txt:要求 CMake ≥ 3.15、C++17,通过find_package(SFML 2.5 COMPONENTS graphics REQUIRED)查找依赖,并把data目录随目标一起安装;
  • 04/sfml/data/shader.frag:与 Processing 版完全相同的标准 shader 头。

由此可见,同一份 shader 文件可以在这些框架之间原样复用——这正是本章工具生态与 uniform 约定设计的直接收益。

十一、总结:从代码到作品的完整路径

本章建立了一套可复用的 shader 工作流:

  1. 写:用 glslEditor(网页版或内嵌版)编写调试,借助小部件实时观察输出;
  2. 跑:浏览器用 glslCanvas 一行<canvas>嵌入;命令行用 glslViewer 接入脚本/管道,甚至部署到树莓派或 openFrame.io;
  3. 接入:在 Three.js / Processing / openFrameworks / SFML 中,只需按u_resolution、u_time、u_mouse约定喂值,即可复用书中全部示例;
  4. 分享与策展:通过在线编辑器导出唯一 URL,或借助 glslGallery 构建可嵌入任意网站的作品画廊。

这套约定与工具链将贯穿全书后续所有章节——从 05 章"造型函数" 开始,你在每个章节学到的 shader,都可以用本章的方法立即运行、调试与分享。仓库中 04/ 目录下各框架的完整源码,是你对照学习的最佳起点。

【免费下载链接】thebookofshaders

Step-by-step guide through the abstract and complex universe of Fragment Shaders.

项目地址:https://gitcode.com/gh_mirrors/th/thebookofshaders
点击查看免费下载
上一篇:Windows 11绕过硬件限制的完整指南:让老电脑轻松升级的终极方案
下一篇:如何让老电脑也能安装Windows 11?3个简单技巧打破硬件限制

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询