web-shaders
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseWeb Shaders
Web Shader
You are writing shaders that run in a browser. Get the platform and language right first, then the technique, then verify visually.
你正在编写运行于浏览器的 shader。先确定正确的平台和语言,然后选择技术,最后进行视觉验证。
1. Establish the target before writing a line
1. 确定目标,再写第一行代码
Ask (or infer from the codebase) which of these you are in — the boilerplate and language differ:
| Target | Language | Notes |
|---|---|---|
| Raw WebGL 2 | GLSL ES 3.00 ( | You declare everything. |
| Raw WebGL 1 | GLSL ES 1.00 | |
| WebGPU (raw) | WGSL | |
Three.js | GLSL ES 1.00 by default | Three injects camera/model matrices and attributes (see §2). Set |
Three.js | whatever you declare | No injected uniforms/attributes or |
| Three.js TSL (WebGPURenderer) | JavaScript nodes | Author with |
| React Three Fiber | GLSL via drei | Wraps |
If the project uses , prefer TSL over raw WGSL strings — it is the supported path and cross-compiles.
WebGPURenderer询问目标,或从代码库中推断当前使用的技术——不同目标所需的模板代码和语言各不相同:
| 目标 | 语言 | 说明 |
|---|---|---|
| 原生 WebGL 2 | GLSL ES 3.00 ( | 全部内容都由你声明。使用 |
| 原生 WebGL 1 | GLSL ES 1.00 | 使用 |
| WebGPU(原生) | WGSL | 使用 |
Three.js | 默认使用 GLSL ES 1.00 | Three.js 会自动注入相机、模型矩阵和 attributes(见 §2)。使用 GLSL 3 时设置 |
Three.js | 由你自行声明 | 不注入任何 uniforms、attributes 或 |
| Three.js TSL(WebGPURenderer) | JavaScript nodes | 使用 |
| React Three Fiber | 通过 drei | 封装 |
如果项目使用 ,应优先采用 TSL,而不是原始 WGSL 字符串——这是受支持的实现路径,并且支持跨语言编译。
WebGPURenderer2. Three.js ShaderMaterial: what is already provided
2. Three.js ShaderMaterial:已经提供的内容
ShaderMaterialRawShaderMaterial- Vertex attributes: ,
position,normal.uv - Uniforms: ,
modelMatrix,modelViewMatrix,projectionMatrix,viewMatrix,normalMatrix.cameraPosition - is set for you.
precision
A minimal correct pair:
glsl
// vertex
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}glsl
// fragment
varying vec2 vUv;
uniform float uTime;
void main() {
gl_FragColor = vec4(vUv, 0.5 + 0.5 * sin(uTime), 1.0);
}For GLSL 3 (): replace →, →, and declare instead of .
glslVersion: THREE.GLSL3varyingin/outtexture2Dtextureout vec4 fragColor;gl_FragColorIn R3F, prefer drei's + , then drive uniforms from a ref, not React state (avoid re-renders).
shaderMaterial(uniforms, vertex, fragment)extenduseFrameShaderMaterialRawShaderMaterial- 顶点 attributes:、
position、normal。uv - Uniforms:、
modelMatrix、modelViewMatrix、projectionMatrix、viewMatrix、normalMatrix。cameraPosition - 已自动设置。
precision
一组最小且正确的代码:
glsl
// vertex
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}glsl
// fragment
varying vec2 vUv;
uniform float uTime;
void main() {
gl_FragColor = vec4(vUv, 0.5 + 0.5 * sin(uTime), 1.0);
}对于 GLSL 3():将 替换为 ,将 替换为 ,并声明 来代替 。
glslVersion: THREE.GLSL3varyingin/outtexture2Dtextureout vec4 fragColor;gl_FragColor在 R3F 中,优先使用 drei 的 配合 ,然后通过 ref 驱动 uniforms,而不是使用 React state(避免重新渲染)。
shaderMaterial(uniforms, vertex, fragment)extenduseFrame3. WGSL essentials (WebGPU)
3. WGSL 核心要点(WebGPU)
- Entry points: and
@vertex fn vs(...) -> @builtin(position) vec4f.@fragment fn fs(...) -> @location(0) vec4f - Uniforms live in a bound via
struct— respect std140-like alignment (a@group(g) @binding(b) var<uniform> u: U;occupies 16 bytes; pad explicitly).vec3<f32> - No implicit conversions: is
1,i32is1.0,f32is1u. Be explicit.u32 - Texture sampling: in fragment stage only.
textureSample(tex, samp, uv)
- 入口点:和
@vertex fn vs(...) -> @builtin(position) vec4f。@fragment fn fs(...) -> @location(0) vec4f - Uniforms 放在一个 中,并通过
struct绑定——必须遵守类似 std140 的对齐规则(一个@group(g) @binding(b) var<uniform> u: U;占用 16 字节;需要显式填充)。vec3<f32> - 不存在隐式类型转换:是
1,i32是1.0,f32是1u。应明确指定类型。u32 - 纹理采样:仅可在 fragment stage 中使用 。
textureSample(tex, samp, uv)
4. Coordinate and color correctness (the usual bugs)
4. 坐标与颜色正确性(常见问题)
- UV origin: GL textures are bottom-left origin. Three sets by default for images; for render targets it is false. Flip
texture.flipY = trueif the image is upside down.vUv.y - Aspect ratio: correct with (or
uv.x *= resolution.x / resolution.y) or circles become ellipses.uv = (uv - .5) * vec2(aspect, 1.) + .5 - NDC vs UV: is clip space;
gl_Positionis in pixels — divide by resolution for 0..1.gl_FragCoord.xy - Color space: three renders linear then converts on output (). Sample color textures as sRGB (
renderer.outputColorSpace = SRGBColorSpace); keep data textures (normals, roughness) linear. Do lighting math in linear space.texture.colorSpace = SRGBColorSpace - Tone mapping: if is set, raw emissive colors get remapped — account for it.
renderer.toneMapping - Premultiplied alpha / blending: set and the right
transparent: truemode; unmultiplied vs premultiplied changes edges.blending
- UV 原点:GL 纹理以左下角为原点。Three.js 默认对图像设置 ,对 render target 则为 false。如果图像上下颠倒,请翻转
texture.flipY = true。vUv.y - 宽高比:使用 进行校正(或使用
uv.x *= resolution.x / resolution.y),否则圆形会变成椭圆形。uv = (uv - .5) * vec2(aspect, 1.) + .5 - NDC 与 UV:位于裁剪空间;
gl_Position使用像素坐标——除以 resolution 可归一化到 0..1。gl_FragCoord.xy - 色彩空间:Three.js 先在线性空间中渲染,再在输出时转换()。颜色纹理应按 sRGB 采样(
renderer.outputColorSpace = SRGBColorSpace);数据纹理(法线、粗糙度)应保持线性。光照计算应在线性空间中进行。texture.colorSpace = SRGBColorSpace - Tone mapping:如果设置了 ,原始 emissive colors 会被重新映射——需要考虑这一影响。
renderer.toneMapping - Premultiplied alpha / blending:设置 和正确的
transparent: true模式;unmultiplied 与 premultiplied 的差异会影响边缘效果。blending
5. Portability pitfalls that fail silently on some GPUs
5. 在部分 GPU 上静默失败的可移植性问题
- Always set in
precision highp float;/raw WebGL; testRawShaderMaterialbehavior for mobile (banding, precision loss).mediump - WebGL 1 GLSL: no dynamic (non-constant) array indexing, no /non-constant loop bounds; unroll or use textures.
while - and
mod(x, y)differ for negatives;%is undefined — clamp/abs first.pow(negative, y) - Integer division truncates; write , not
1.0/3.0.1/3 - Derivatives (/
dFdx,dFdy) needfwidthin WebGL 1 (built in for WebGL 2 / GLSL 3).#extension GL_OES_standard_derivatives : enable - Avoid heavy branching in fragment shaders; prefer /
mix/step. Both branches of a divergentsmoothstepmay execute.if - Never a possibly-zero vector without guarding.
normalize()
- 在 /原生 WebGL 中始终设置
RawShaderMaterial;针对移动端测试precision highp float;下的表现(色带、精度损失)。mediump - WebGL 1 GLSL:不支持动态(非恒定)数组索引,也不支持 /非恒定循环边界;应展开循环或改用 textures。
while - 与
mod(x, y)对负数的处理不同;对负数使用%属于未定义行为——应先执行 clamp/abs。pow(negative, y) - 整数除法会截断小数;应编写 ,而不是
1.0/3.0。1/3 - WebGL 1 中的 derivatives(/
dFdx、dFdy)需要fwidth;WebGL 2 / GLSL 3 已内置支持。#extension GL_OES_standard_derivatives : enable - 避免在 fragment shader 中使用复杂分支;优先采用 /
mix/step。发生分支发散的smoothstep,其两个分支都可能会执行。if - 对可能为零的向量调用 前,必须进行保护。
normalize()
6. Technique quick-reference
6. 技术快速参考
- Shaping: ,
step,smoothstep,mix,clamp,fract— the vocabulary of procedural graphics.mod - SDF / raymarching: distance functions + sphere tracing. Reach for Inigo Quilez's primitives and the raymarching loop; use for ready functions.
Lygia - Noise: gradient/simplex (,
glsl-noise,webgl-noise). Value noise for cheap, simplex for smooth.lygia - Post-processing: render to a target, sample in a fullscreen pass; in three use or
pmndrs/postprocessing.EffectComposer - GPGPU: encode state in float textures, ping-pong render targets (three ), or WebGPU compute shaders.
GPUComputationRenderer
Pull ready-made functions from Lygia (cross-language GLSL/WGSL) instead of reimplementing noise, easing, SDFs, and color conversions.
- 塑形:、
step、smoothstep、mix、clamp、fract——这些是程序化图形的基础工具。mod - SDF / raymarching:距离函数 + sphere tracing。可以直接采用 Inigo Quilez 的图元和 raymarching 循环;也可以使用 Lygia 提供的现成函数。
- 噪声:gradient/simplex(、
glsl-noise、webgl-noise)。Value noise 成本较低,simplex noise 更平滑。lygia - Post-processing:渲染到 target,再在全屏 pass 中采样;在 Three.js 中可使用 或
pmndrs/postprocessing。EffectComposer - GPGPU:将状态编码到 float textures 中,使用 ping-pong render targets(Three.js 中的 ),或者使用 WebGPU compute shaders。
GPUComputationRenderer
直接从 Lygia(跨语言 GLSL/WGSL)获取现成函数,无需重复实现噪声、easing、SDF 和颜色转换。
7. Debugging workflow
7. 调试工作流
- Isolate: output a known value () to confirm the pass runs and UVs are sane.
gl_FragColor = vec4(vUv, 0, 1) - Visualize the variable: pipe any intermediate to color () rather than guessing.
vec4(vec3(d), 1.0) - Check the console for shader compile/link errors — WebGL reports the exact line; WebGPU logs validation errors. Read them.
- Confirm uniforms are actually set (typos in uniform names fail silently — the value stays 0).
- Use Spector.js (WebGL) or the WebGPU Inspector to capture the draw call, uniforms, and compiled shader.
- 隔离问题:输出一个已知值(),确认 pass 正在运行且 UV 正常。
gl_FragColor = vec4(vUv, 0, 1) - 可视化变量:将任意中间值输出到颜色通道(),而不是依靠猜测。
vec4(vec3(d), 1.0) - 检查控制台:查看 shader 编译或链接错误——WebGL 会报告具体行号;WebGPU 会记录 validation errors。务必阅读这些错误。
- 确认 uniforms 已正确设置(uniform 名称拼写错误会静默失败,值将始终为 0)。
- 使用 Spector.js(WebGL)或 WebGPU Inspector 捕获 draw call、uniforms 和编译后的 shader。
8. Authoritative sources to consult
8. 应查阅的权威资料
When unsure of an API, consult these rather than guessing (many are LLM-ingestible ):
llms.txt- Three.js: https://threejs.org/docs/llms.txt (incl. WebGPURenderer + TSL)
- React Three Fiber: https://r3f.docs.pmnd.rs/llms.txt · drei: https://drei.docs.pmnd.rs/llms.txt
- WGSL spec: https://www.w3.org/TR/WGSL/ · WebGPU: https://www.w3.org/TR/webgpu/
- WebGL/WebGPU Fundamentals: https://webgl2fundamentals.org · https://webgpufundamentals.org
- SDFs & raymarching: https://iquilezles.org/articles/
- Lygia (reusable functions): https://lygia.xyz
不确定某个 API 时,应查阅以下资料,而不是依靠猜测(其中许多都提供适合 LLM 读取的 ):
llms.txt- Three.js:https://threejs.org/docs/llms.txt(包括 WebGPURenderer 和 TSL)
- React Three Fiber:https://r3f.docs.pmnd.rs/llms.txt;drei:https://drei.docs.pmnd.rs/llms.txt
- WGSL 规范:https://www.w3.org/TR/WGSL/;WebGPU:https://www.w3.org/TR/webgpu/
- WebGL/WebGPU 基础:https://webgl2fundamentals.org;https://webgpufundamentals.org
- SDF 与 raymarching:https://iquilezles.org/articles/
- Lygia(可复用函数):https://lygia.xyz
9. Before you finish
9. 完成前检查
- State the target you assumed (WebGL2/WebGPU, Three.js material type) if it was ambiguous.
- Verify it compiles (no console errors) and describe or screenshot the visual result — a shader that compiles can still render black.
- Keep uniforms named consistently between JS and GLSL; a mismatch is the most common "nothing happens" bug.
- 如果目标不明确,请说明你所假设的目标(WebGL2/WebGPU、Three.js material type)。
- 确认 shader 能够编译(控制台中没有错误),并描述或截图展示视觉结果——shader 即使编译成功,也可能渲染为黑色。
- 确保 JS 和 GLSL 中的 uniforms 名称保持一致;名称不匹配是导致“什么都没有发生”的最常见 bug。