探索 glslViewer:实时 GLSL 着色器预览利器
如果你是一名图形程序员、技术艺术家,或者仅仅是对生成艺术(Generative Art)感兴趣的爱好者,那么你一定知道编写 GLSL(OpenGL Shading Language)时最痛苦的事情:为了看到一行代码的修改结果,你不得不重启整个 C++ 渲染框架或刷新网页。
glslViewer 正是为了解决这个痛点而生的。它是一个轻量级的、开源的 C/C++ 工具,旨在提供一个极简的实时预览环境,让你能够直接运行 .frag 或 .vert 文件,并在修改代码保存的瞬间,立即在屏幕上看到视觉效果。
1. 什么是 glslViewer?
glslViewer 是一个基于 OpenGL 的命令行工具。它并不要求你构建一个完整的 OpenGL 应用程序(无需处理复杂的 GLFW 窗口初始化、着色器编译链或缓冲区管理),而是将这些底层工作全部封装。
你只需要提供一个着色器文件,glslViewer 就会为你创建一个窗口,加载该着色器,并提供一套标准的 Uniform 变量(如时间、分辨率、鼠标位置),让你能够快速构建动态的视觉效果。
核心特性:
- 实时热重载 (Hot Reloading):保存文件,画面立即更新。
- 交互式控制:支持通过命令行或配置文件传递参数。
- 轻量级:无需庞大的 IDE,一个终端命令即可启动。
- 跨平台:支持 Windows, macOS, Linux。
- 支持多种输入:支持顶点着色器、片段着色器以及简单的 3D 模型加载。
2. 快速上手指南
安装
根据你的操作系统,可以通过以下方式安装:
- macOS: brew install glslviewer
- Linux/Windows: 从 GitHub Releases 下载预编译二进制文件,或通过 CMake 源码编译。
运行第一个着色器
创建一个名为 test.frag 的文件,粘贴以下简单的渐变代码:
precision mediump float;
uniform float u_time;
uniform vec2 u_resolution;
void main() {
vec2 uv = gl_FragCoord.xy / u_resolution.xy;
vec3 color = 0.5 + 0.5 * cos(u_time + uv.xyx + vec3(0, 2, 4));
gl_FragCoord = vec4(color, 1.0); // 注意:在某些版本中应为 gl_FragColor
}
注:在 glslViewer 中,通常使用 gl_FragColor 输出颜色。
在终端执行:
glslViewer test.frag
此时,你会看到一个随时间流逝而变换颜色的动态渐变屏幕。
3. 核心 Uniform 变量详解
为了让你的着色器“动”起来,glslViewer 默认注入了几个关键的 Uniform 变量,你可以在代码中直接使用:
| 变量名 | 类型 | 说明 |
|---|---|---|
u_time |
float |
程序运行的总时间(秒),用于创建动画。 |
u_resolution |
vec2 |
窗口的宽度和高度,用于计算归一化的 UV 坐标。 |
u_mouse |
vec2 |
鼠标在窗口中的当前坐标。 |
u_window_size |
vec2 |
窗口大小(与 resolution 类似)。 |
4. 进阶实战实例
实例 A:交互式 SDF 圆形(学习鼠标交互)
这个实例将展示如何利用 u_mouse 创建一个跟随鼠标移动的发光圆环。
precision mediump float;
uniform float u_time;
uniform vec2 u_resolution;
uniform vec2 u_mouse;
void main() {
// 归一化坐标 (0.0 到 1.0)
vec2 uv = gl_FragCoord.xy / u_resolution.xy;
// 归一化鼠标坐标
vec2 mouse = u_mouse / u_resolution.xy;
// 计算当前像素点到鼠标点的距离
float dist = distance(uv, mouse);
// 创建一个带边缘模糊的圆环
float ring = smoothstep(0.1, 0.11, dist) - smoothstep(0.12, 0.13, dist);
// 颜色随时间变化
vec3 color = 0.5 + 0.5 * cos(u_time + vec3(0, 2, 4));
gl_FragColor = vec4(color * ring, 1.0);
}
实例 B:简单的 Raymarching 场景(3D 效果)
glslViewer 非常适合测试 Raymarching 算法。以下是一个简单的 3D 球体渲染:
precision mediump float;
uniform float u_time;
uniform vec2 u_resolution;
float sdSphere(vec3 p, float s) {
return length(p) - s;
}
void main() {
vec2 uv = (gl_FragCoord.xy - 0.5 * u_resolution.xy) / u_resolution.y;
vec3 ro = vec3(0, 0, -3); // 摄像机位置
vec3 rd = normalize(vec3(uv, 1)); // 射线方向
float t = 0.0;
for(int i = 0; i < 64; i++) {
vec3 p = ro + t * rd;
float d = sdSphere(p, 1.0); // 渲染一个半径为 1 的球
if(d < 0.001) break;
t += d;
if(t > 10.0) break;
}
vec3 col = (t < 10.0) ? vec3(0.2, 0.6, 1.0) : vec3(0.1);
gl_FragColor = vec4(col, 1.0);
}
5. 高级用法:加载模型与自定义参数
glslViewer 不仅仅能跑片段着色器,它还支持加载 3D 模型(如 .obj 文件)并为其编写自定义着色器。
加载 3D 模型
如果你有一个模型文件 mesh.obj 和一个着色器 shader.frag,你可以运行:
glslViewer mesh.obj shader.frag
在这种模式下,glslViewer 会处理顶点数据的传递,你可以在 shader.frag 中通过 v_normal 或 v_texcoord 等内置变量来处理光照和贴图。
使用配置文件 (.json)
如果你有大量的 Uniform 变量需要调整,而不想每次都修改代码,你可以创建一个 JSON 配置文件:
{
"uniforms": {
"u_brightness": { "type": "float", "value": 1.5 },
"u_color": { "type": "vec3", "value": [1.0, 0.0, 0.0] }
}
}
然后运行:
glslViewer test.frag -c config.json
6. 为什么选择 glslViewer 而不是 Shadertoy?
虽然 Shadertoy 是目前最流行的 GLSL 平台,但 glslViewer 在以下场景中具有绝对优势:
- 本地开发:无需上传代码,直接在本地编辑器(如 VS Code + GLSL 插件)中编写,保存即生效。
- 加载本地资源:可以加载本地的
.obj模型、纹理图片,而 Shadertoy 依赖于其内置的资源库。 - 性能调试:直接运行在本地显卡驱动上,方便使用 RenderDoc 等工具进行帧分析。
- 集成工作流:可以轻松地将编写



还没有评论,来说两句吧...