shader-programming-glsl
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseShader Programming GLSL
GLSL着色器编程
Overview
概述
A comprehensive guide to writing GPU shaders using GLSL (OpenGL Shading Language). Learn syntax, uniforms, varying variables, and key mathematical concepts like swizzling and vector operations for visual effects.
这是一份使用GLSL(OpenGL着色语言)编写GPU着色器的全面指南。您将学习语法、uniforms、varying变量,以及用于视觉效果的关键数学概念,如分量重组(swizzling)和向量运算。
When to Use This Skill
适用场景
- Use when creating custom visual effects in WebGL, Three.js, or game engines.
- Use when optimizing graphics rendering performance.
- Use when implementing post-processing effects (blur, bloom, color correction).
- Use when procedurally generating textures or geometry on the GPU.
- 在WebGL、Three.js或游戏引擎中创建自定义视觉效果时使用。
- 优化图形渲染性能时使用。
- 实现后期处理效果(模糊、bloom、色彩校正)时使用。
- 在GPU上程序化生成纹理或几何体时使用。
Step-by-Step Guide
分步指南
1. Structure: Vertex vs. Fragment
1. 结构:Vertex Shader vs Fragment Shader
Understand the pipeline:
- Vertex Shader: Transforms 3D coordinates to 2D screen space ().
gl_Position - Fragment Shader: Colors individual pixels ().
gl_FragColor
glsl
// Vertex Shader (basic)
attribute vec3 position;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}glsl
// Fragment Shader (basic)
uniform vec3 color;
void main() {
gl_FragColor = vec4(color, 1.0);
}理解渲染管线:
- Vertex Shader(顶点着色器):将3D坐标转换为2D屏幕空间()。
gl_Position - Fragment Shader(片段着色器):为单个像素上色()。
gl_FragColor
glsl
// Vertex Shader (basic)
attribute vec3 position;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}glsl
// Fragment Shader (basic)
uniform vec3 color;
void main() {
gl_FragColor = vec4(color, 1.0);
}2. Uniforms and Varyings
2. Uniforms与Varying变量
- : Data constant for all vertices/fragments (passed from CPU).
uniform - : Data interpolated from vertex to fragment shader.
varying
glsl
// Passing UV coordinates
varying vec2 vUv;
// In Vertex Shader
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
// In Fragment Shader
void main() {
// Gradient based on UV
gl_FragColor = vec4(vUv.x, vUv.y, 1.0, 1.0);
}- :所有顶点/片段共享的常量数据(从CPU传入)。
uniform - :从顶点着色器插值传递到片段着色器的数据。
varying
glsl
// Passing UV coordinates
varying vec2 vUv;
// In Vertex Shader
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
// In Fragment Shader
void main() {
// Gradient based on UV
gl_FragColor = vec4(vUv.x, vUv.y, 1.0, 1.0);
}3. Swizzling & Vector Math
3. 分量重组(Swizzling)与向量运算
Access vector components freely:
vec4 color = vec4(1.0, 0.5, 0.0, 1.0);- ->
color.rgbvec3(1.0, 0.5, 0.0) - ->
color.zyx(reordering)vec3(0.0, 0.5, 1.0)
可自由访问向量分量:
vec4 color = vec4(1.0, 0.5, 0.0, 1.0);- ->
color.rgbvec3(1.0, 0.5, 0.0) - ->
color.zyx(重新排序)vec3(0.0, 0.5, 1.0)
Examples
示例
Example 1: Simple Raymarching (SDF Sphere)
示例1:简单光线步进(SDF球体)
glsl
float sdSphere(vec3 p, float s) {
return length(p) - s;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
vec3 ro = vec3(0.0, 0.0, -3.0); // Ray Origin
vec3 rd = normalize(vec3(uv, 1.0)); // Ray Direction
float t = 0.0;
for(int i = 0; i < 64; i++) {
vec3 p = ro + rd * t;
float d = sdSphere(p, 1.0); // Sphere radius 1.0
if(d < 0.001) break;
t += d;
}
vec3 col = vec3(0.0);
if(t < 10.0) {
vec3 p = ro + rd * t;
vec3 normal = normalize(p);
col = normal * 0.5 + 0.5; // Color by normal
}
fragColor = vec4(col, 1.0);
}glsl
float sdSphere(vec3 p, float s) {
return length(p) - s;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
vec3 ro = vec3(0.0, 0.0, -3.0); // Ray Origin
vec3 rd = normalize(vec3(uv, 1.0)); // Ray Direction
float t = 0.0;
for(int i = 0; i < 64; i++) {
vec3 p = ro + rd * t;
float d = sdSphere(p, 1.0); // Sphere radius 1.0
if(d < 0.001) break;
t += d;
}
vec3 col = vec3(0.0);
if(t < 10.0) {
vec3 p = ro + rd * t;
vec3 normal = normalize(p);
col = normal * 0.5 + 0.5; // Color by normal
}
fragColor = vec4(col, 1.0);
}Best Practices
最佳实践
- ✅ Do: Use for linear interpolation instead of manual math.
mix() - ✅ Do: Use and
step()for thresholding and soft edges (avoidsmoothstep()branches).if - ✅ Do: Pack data into vectors () to minimize memory access.
vec4 - ❌ Don't: Use heavy branching () inside loops if possible; it hurts GPU parallelism.
if-else - ❌ Don't: Calculate constant values inside the shader; pre-calculate them on the CPU (uniforms).
- ✅ 建议:使用进行线性插值,而非手动计算。
mix() - ✅ 建议:使用和
step()实现阈值处理和柔化边缘(避免smoothstep()分支)。if - ✅ 建议:将数据打包到向量()中,以减少内存访问。
vec4 - ❌ 避免:尽可能不要在循环内使用大量分支(),这会影响GPU并行性。
if-else - ❌ 避免:不要在着色器内计算常量值;在CPU上预先计算(作为uniforms传入)。
Troubleshooting
故障排除
Problem: Shader compiles but screen is black.
Solution: Check if is correct (usually 1.0). Check if uniforms are actually being set from the host application. Verify UV coordinates are within [0, 1].
gl_Position.w问题:着色器编译成功但屏幕显示黑色。
解决方案:检查是否正确(通常为1.0)。检查宿主应用是否正确设置了uniforms。验证UV坐标是否在[0, 1]范围内。
gl_Position.wLimitations
局限性
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.
- 仅当任务与上述描述的范围完全匹配时使用本技能。
- 不要将输出结果视为特定环境下验证、测试或专家评审的替代品。
- 如果缺少必要的输入、权限、安全边界或成功标准,请暂停并要求澄清。