glsl
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGLSL Shader Programming Skill
GLSL着色器编程技能
File Organization: This skill uses split structure. Seefor advanced shader patterns.references/
文件结构:本技能采用拆分式结构。高级着色器模式请查看目录。references/
1. Overview
1. 概述
This skill provides GLSL shader expertise for creating holographic visual effects in the JARVIS AI Assistant HUD. It focuses on efficient GPU programming for real-time rendering.
Risk Level: LOW - GPU-side code with limited attack surface, but can cause performance issues
Primary Use Cases:
- Holographic panel effects with scanlines
- Animated energy fields and particle systems
- Data visualization with custom rendering
- Post-processing effects (bloom, glitch, chromatic aberration)
本技能提供用于在JARVIS AI助手HUD中创建全息视觉效果的GLSL着色器专业知识,专注于实时渲染的高效GPU编程。
风险等级:低 - GPU端代码攻击面有限,但可能导致性能问题
主要用例:
- 带扫描线的全息面板效果
- 动画能量场和粒子系统
- 自定义渲染的数据可视化
- 后期处理效果(bloom、故障效果、色差)
2. Core Responsibilities
2. 核心职责
2.1 Fundamental Principles
2.1 基本原则
- TDD First: Write visual regression tests and shader unit tests before implementation
- Performance Aware: Profile GPU performance, optimize for 60 FPS target
- Precision Matters: Use appropriate precision qualifiers for performance
- Avoid Branching: Minimize conditionals in shaders for GPU efficiency
- Optimize Math: Use built-in functions, avoid expensive operations
- Uniform Safety: Validate uniform inputs before sending to GPU
- Loop Bounds: Always use constant loop bounds to prevent GPU hangs
- Memory Access: Optimize texture lookups and varying interpolation
- 先做测试驱动开发(TDD):在实现前编写视觉回归测试和着色器单元测试
- 关注性能:分析GPU性能,以60 FPS为优化目标
- 精度重要:使用合适的精度限定词以提升性能
- 避免分支:尽量减少着色器中的条件判断以提高GPU效率
- 优化数学运算:使用内置函数,避免昂贵的运算
- Uniform安全性:在发送到GPU前验证Uniform输入
- 循环边界:始终使用常量循环边界以防止GPU挂起
- 内存访问:优化纹理查找和varying插值
3. Implementation Workflow (TDD)
3. 实现工作流(TDD)
3.1 Step 1: Write Failing Test First
3.1 步骤1:先编写失败的测试
typescript
// tests/shaders/holographic-panel.test.ts
import { describe, it, expect, beforeEach } from 'vitest'
import { WebGLTestContext, captureFramebuffer, compareImages } from '../utils/webgl-test'
describe('HolographicPanelShader', () => {
let ctx: WebGLTestContext
beforeEach(() => {
ctx = new WebGLTestContext(256, 256)
})
// Unit test: Shader compiles
it('should compile without errors', () => {
const shader = ctx.compileShader(holoFragSource, ctx.gl.FRAGMENT_SHADER)
expect(shader).not.toBeNull()
expect(ctx.getShaderErrors()).toEqual([])
})
// Unit test: Uniforms are accessible
it('should have required uniforms', () => {
const program = ctx.createProgram(vertSource, holoFragSource)
expect(ctx.getUniformLocation(program, 'uTime')).not.toBeNull()
expect(ctx.getUniformLocation(program, 'uColor')).not.toBeNull()
expect(ctx.getUniformLocation(program, 'uOpacity')).not.toBeNull()
})
// Visual regression test
it('should render scanlines correctly', async () => {
ctx.renderShader(holoFragSource, { uTime: 0, uColor: [0, 0.5, 1], uOpacity: 1 })
const result = captureFramebuffer(ctx)
const baseline = await loadBaseline('holographic-scanlines.png')
expect(compareImages(result, baseline, { threshold: 0.01 })).toBeLessThan(0.01)
})
// Edge case test
it('should handle extreme UV values', () => {
const testCases = [
{ uv: [0, 0], expected: 'no crash' },
{ uv: [1, 1], expected: 'no crash' },
{ uv: [0.5, 0.5], expected: 'no crash' }
]
testCases.forEach(({ uv }) => {
expect(() => ctx.renderAtUV(holoFragSource, uv)).not.toThrow()
})
})
})typescript
// tests/shaders/holographic-panel.test.ts
import { describe, it, expect, beforeEach } from 'vitest'
import { WebGLTestContext, captureFramebuffer, compareImages } from '../utils/webgl-test'
describe('HolographicPanelShader', () => {
let ctx: WebGLTestContext
beforeEach(() => {
ctx = new WebGLTestContext(256, 256)
})
// Unit test: Shader compiles
it('should compile without errors', () => {
const shader = ctx.compileShader(holoFragSource, ctx.gl.FRAGMENT_SHADER)
expect(shader).not.toBeNull()
expect(ctx.getShaderErrors()).toEqual([])
})
// Unit test: Uniforms are accessible
it('should have required uniforms', () => {
const program = ctx.createProgram(vertSource, holoFragSource)
expect(ctx.getUniformLocation(program, 'uTime')).not.toBeNull()
expect(ctx.getUniformLocation(program, 'uColor')).not.toBeNull()
expect(ctx.getUniformLocation(program, 'uOpacity')).not.toBeNull()
})
// Visual regression test
it('should render scanlines correctly', async () => {
ctx.renderShader(holoFragSource, { uTime: 0, uColor: [0, 0.5, 1], uOpacity: 1 })
const result = captureFramebuffer(ctx)
const baseline = await loadBaseline('holographic-scanlines.png')
expect(compareImages(result, baseline, { threshold: 0.01 })).toBeLessThan(0.01)
})
// Edge case test
it('should handle extreme UV values', () => {
const testCases = [
{ uv: [0, 0], expected: 'no crash' },
{ uv: [1, 1], expected: 'no crash' },
{ uv: [0.5, 0.5], expected: 'no crash' }
]
testCases.forEach(({ uv }) => {
expect(() => ctx.renderAtUV(holoFragSource, uv)).not.toThrow()
})
})
})3.2 Step 2: Implement Minimum to Pass
3.2 步骤2:实现最小可通过版本
glsl
// Start with minimal shader that passes tests
#version 300 es
precision highp float;
uniform float uTime;
uniform vec3 uColor;
uniform float uOpacity;
in vec2 vUv;
out vec4 fragColor;
void main() {
// Minimal implementation to pass compilation test
fragColor = vec4(uColor, uOpacity);
}glsl
// Start with minimal shader that passes tests
#version 300 es
precision highp float;
uniform float uTime;
uniform vec3 uColor;
uniform float uOpacity;
in vec2 vUv;
out vec4 fragColor;
void main() {
// Minimal implementation to pass compilation test
fragColor = vec4(uColor, uOpacity);
}3.3 Step 3: Refactor with Full Implementation
3.3 步骤3:重构为完整实现
glsl
// Expand to full implementation after tests pass
void main() {
vec2 uv = vUv;
float scanline = sin(uv.y * 100.0) * 0.1 + 0.9;
float pulse = sin(uTime * 2.0) * 0.1 + 0.9;
vec3 color = uColor * scanline * pulse;
fragColor = vec4(color, uOpacity);
}glsl
// Expand to full implementation after tests pass
void main() {
vec2 uv = vUv;
float scanline = sin(uv.y * 100.0) * 0.1 + 0.9;
float pulse = sin(uTime * 2.0) * 0.1 + 0.9;
vec3 color = uColor * scanline * pulse;
fragColor = vec4(color, uOpacity);
}3.4 Step 4: Run Full Verification
3.4 步骤4:运行完整验证
bash
undefinedbash
undefinedRun all shader tests
Run all shader tests
npm run test:shaders
npm run test:shaders
Visual regression tests
Visual regression tests
npm run test:visual -- --update-snapshots # First time only
npm run test:visual
npm run test:visual -- --update-snapshots # First time only
npm run test:visual
Performance benchmark
Performance benchmark
npm run bench:shaders
npm run bench:shaders
Cross-browser compilation check
Cross-browser compilation check
npm run test:webgl-compat
undefinednpm run test:webgl-compat
undefined4. Technology Stack & Versions
4. 技术栈与版本
4.1 GLSL Versions
4.1 GLSL版本
| Version | Context | Features |
|---|---|---|
| GLSL ES 3.00 | WebGL 2.0 | Modern features, better precision |
| GLSL ES 1.00 | WebGL 1.0 | Legacy support |
| 版本 | 上下文 | 特性 |
|---|---|---|
| GLSL ES 3.00 | WebGL 2.0 | 现代特性,更高精度 |
| GLSL ES 1.00 | WebGL 1.0 | 遗留支持 |
4.2 Shader Setup
4.2 着色器设置
glsl
#version 300 es
precision highp float;
precision highp int;
// WebGL 2.0 shader headerglsl
#version 300 es
precision highp float;
precision highp int;
// WebGL 2.0 shader header5. Performance Patterns
5. 性能优化模式
5.1 Avoid Branching - Use Mix/Step
5.1 避免分支 - 使用Mix/Step
glsl
// ❌ BAD - GPU branch divergence
vec3 getColor(float value) {
if (value < 0.3) {
return vec3(1.0, 0.0, 0.0); // Red
} else if (value < 0.7) {
return vec3(1.0, 1.0, 0.0); // Yellow
} else {
return vec3(0.0, 1.0, 0.0); // Green
}
}
// ✅ GOOD - Branchless with mix/step
vec3 getColor(float value) {
vec3 red = vec3(1.0, 0.0, 0.0);
vec3 yellow = vec3(1.0, 1.0, 0.0);
vec3 green = vec3(0.0, 1.0, 0.0);
vec3 color = mix(red, yellow, smoothstep(0.3, 0.31, value));
color = mix(color, green, smoothstep(0.7, 0.71, value));
return color;
}glsl
// ❌ BAD - GPU branch divergence
vec3 getColor(float value) {
if (value < 0.3) {
return vec3(1.0, 0.0, 0.0); // Red
} else if (value < 0.7) {
return vec3(1.0, 1.0, 0.0); // Yellow
} else {
return vec3(0.0, 1.0, 0.0); // Green
}
}
// ✅ GOOD - Branchless with mix/step
vec3 getColor(float value) {
vec3 red = vec3(1.0, 0.0, 0.0);
vec3 yellow = vec3(1.0, 1.0, 0.0);
vec3 green = vec3(0.0, 1.0, 0.0);
vec3 color = mix(red, yellow, smoothstep(0.3, 0.31, value));
color = mix(color, green, smoothstep(0.7, 0.71, value));
return color;
}5.2 Texture Atlases - Reduce Draw Calls
5.2 纹理图集 - 减少绘制调用
glsl
// ❌ BAD - Multiple texture bindings
uniform sampler2D uIcon1;
uniform sampler2D uIcon2;
uniform sampler2D uIcon3;
vec4 getIcon(int id) {
if (id == 0) return texture(uIcon1, vUv);
if (id == 1) return texture(uIcon2, vUv);
return texture(uIcon3, vUv);
}
// ✅ GOOD - Single atlas texture
uniform sampler2D uIconAtlas;
uniform vec4 uAtlasOffsets[3]; // [x, y, width, height] for each icon
vec4 getIcon(int id) {
vec4 offset = uAtlasOffsets[id];
vec2 atlasUV = offset.xy + vUv * offset.zw;
return texture(uIconAtlas, atlasUV);
}glsl
// ❌ BAD - Multiple texture bindings
uniform sampler2D uIcon1;
uniform sampler2D uIcon2;
uniform sampler2D uIcon3;
vec4 getIcon(int id) {
if (id == 0) return texture(uIcon1, vUv);
if (id == 1) return texture(uIcon2, vUv);
return texture(uIcon3, vUv);
}
// ✅ GOOD - Single atlas texture
uniform sampler2D uIconAtlas;
uniform vec4 uAtlasOffsets[3]; // [x, y, width, height] for each icon
vec4 getIcon(int id) {
vec4 offset = uAtlasOffsets[id];
vec2 atlasUV = offset.xy + vUv * offset.zw;
return texture(uIconAtlas, atlasUV);
}5.3 Level of Detail (LOD) - Distance-Based Quality
5.3 细节层次(LOD)- 基于距离的质量调整
glsl
// ❌ BAD - Same quality regardless of distance
const int NOISE_OCTAVES = 8;
float noise(vec3 p) {
float result = 0.0;
for (int i = 0; i < NOISE_OCTAVES; i++) {
result += snoise(p * pow(2.0, float(i)));
}
return result;
}
// ✅ GOOD - Reduce octaves based on distance
uniform float uCameraDistance;
float noise(vec3 p) {
// Fewer octaves when far away (detail not visible)
int octaves = int(mix(2.0, 8.0, 1.0 - smoothstep(10.0, 100.0, uCameraDistance)));
float result = 0.0;
for (int i = 0; i < 8; i++) {
if (i >= octaves) break;
result += snoise(p * pow(2.0, float(i)));
}
return result;
}glsl
// ❌ BAD - Same quality regardless of distance
const int NOISE_OCTAVES = 8;
float noise(vec3 p) {
float result = 0.0;
for (int i = 0; i < NOISE_OCTAVES; i++) {
result += snoise(p * pow(2.0, float(i)));
}
return result;
}
// ✅ GOOD - Reduce octaves based on distance
uniform float uCameraDistance;
float noise(vec3 p) {
// Fewer octaves when far away (detail not visible)
int octaves = int(mix(2.0, 8.0, 1.0 - smoothstep(10.0, 100.0, uCameraDistance)));
float result = 0.0;
for (int i = 0; i < 8; i++) {
if (i >= octaves) break;
result += snoise(p * pow(2.0, float(i)));
}
return result;
}5.4 Uniform Batching - Minimize CPU-GPU Transfers
5.4 Uniform批处理 - 最小化CPU-GPU传输
glsl
// ❌ BAD - Many individual uniforms
uniform float uPosX;
uniform float uPosY;
uniform float uPosZ;
uniform float uRotX;
uniform float uRotY;
uniform float uRotZ;
uniform float uScaleX;
uniform float uScaleY;
uniform float uScaleZ;
// ✅ GOOD - Packed into vectors/matrices
uniform vec3 uPosition;
uniform vec3 uRotation;
uniform vec3 uScale;
// Or even better:
uniform mat4 uTransform;glsl
// ❌ BAD - Many individual uniforms
uniform float uPosX;
uniform float uPosY;
uniform float uPosZ;
uniform float uRotX;
uniform float uRotY;
uniform float uRotZ;
uniform float uScaleX;
uniform float uScaleY;
uniform float uScaleZ;
// ✅ GOOD - Packed into vectors/matrices
uniform vec3 uPosition;
uniform vec3 uRotation;
uniform vec3 uScale;
// Or even better:
uniform mat4 uTransform;5.5 Precision Optimization - Use Appropriate Precision
5.5 精度优化 - 使用合适的精度
glsl
// ❌ BAD - Everything highp (wastes GPU cycles)
precision highp float;
highp vec3 color;
highp float alpha;
highp vec2 uv;
// ✅ GOOD - Match precision to data needs
precision highp float; // Default for calculations
mediump vec3 color; // 0-1 range, mediump sufficient
mediump float alpha; // 0-1 range
highp vec2 uv; // Need precision for texture coords
lowp int flags; // Boolean-like valuesglsl
// ❌ BAD - Everything highp (wastes GPU cycles)
precision highp float;
highp vec3 color;
highp float alpha;
highp vec2 uv;
// ✅ GOOD - Match precision to data needs
precision highp float; // Default for calculations
mediump vec3 color; // 0-1范围,mediump足够
mediump float alpha; // 0-1范围
highp vec2 uv; // 纹理坐标需要高精度
lowp int flags; // 类布尔值5.6 Cache Texture Lookups
5.6 缓存纹理查找结果
glsl
// ❌ BAD - Redundant texture fetches
void main() {
vec3 diffuse = texture(uTexture, vUv).rgb;
// ... some code ...
float alpha = texture(uTexture, vUv).a; // Same lookup!
// ... more code ...
vec3 doubled = texture(uTexture, vUv).rgb * 2.0; // Again!
}
// ✅ GOOD - Cache the result
void main() {
vec4 texSample = texture(uTexture, vUv);
vec3 diffuse = texSample.rgb;
float alpha = texSample.a;
vec3 doubled = texSample.rgb * 2.0;
}glsl
// ❌ BAD - Redundant texture fetches
void main() {
vec3 diffuse = texture(uTexture, vUv).rgb;
// ... some code ...
float alpha = texture(uTexture, vUv).a; // Same lookup!
// ... more code ...
vec3 doubled = texture(uTexture, vUv).rgb * 2.0; // Again!
}
// ✅ GOOD - Cache the result
void main() {
vec4 texSample = texture(uTexture, vUv);
vec3 diffuse = texSample.rgb;
float alpha = texSample.a;
vec3 doubled = texSample.rgb * 2.0;
}6. Implementation Patterns
6. 实现模式
6.1 Holographic Panel Shader
6.1 全息面板着色器
glsl
// shaders/holographic-panel.frag
#version 300 es
precision highp float;
uniform float uTime;
uniform vec3 uColor;
uniform float uOpacity;
uniform vec2 uResolution;
in vec2 vUv;
out vec4 fragColor;
const int SCANLINE_COUNT = 50;
void main() {
vec2 uv = vUv;
// Scanline effect
float scanline = 0.0;
for (int i = 0; i < SCANLINE_COUNT; i++) {
float y = float(i) / float(SCANLINE_COUNT);
scanline += smoothstep(0.0, 0.002, abs(uv.y - y));
}
scanline = 1.0 - scanline * 0.3;
// Edge glow
float edge = 1.0 - smoothstep(0.0, 0.05, min(
min(uv.x, 1.0 - uv.x),
min(uv.y, 1.0 - uv.y)
));
// Animated pulse
float pulse = sin(uTime * 2.0) * 0.1 + 0.9;
vec3 color = uColor * scanline * pulse;
color += vec3(0.0, 0.5, 1.0) * edge * 0.5;
fragColor = vec4(color, uOpacity);
}glsl
// shaders/holographic-panel.frag
#version 300 es
precision highp float;
uniform float uTime;
uniform vec3 uColor;
uniform float uOpacity;
uniform vec2 uResolution;
in vec2 vUv;
out vec4 fragColor;
const int SCANLINE_COUNT = 50;
void main() {
vec2 uv = vUv;
// Scanline effect
float scanline = 0.0;
for (int i = 0; i < SCANLINE_COUNT; i++) {
float y = float(i) / float(SCANLINE_COUNT);
scanline += smoothstep(0.0, 0.002, abs(uv.y - y));
}
scanline = 1.0 - scanline * 0.3;
// Edge glow
float edge = 1.0 - smoothstep(0.0, 0.05, min(
min(uv.x, 1.0 - uv.x),
min(uv.y, 1.0 - uv.y)
));
// Animated pulse
float pulse = sin(uTime * 2.0) * 0.1 + 0.9;
vec3 color = uColor * scanline * pulse;
color += vec3(0.0, 0.5, 1.0) * edge * 0.5;
fragColor = vec4(color, uOpacity);
}6.2 Energy Field Shader
6.2 能量场着色器
glsl
// shaders/energy-field.frag
#version 300 es
precision highp float;
uniform float uTime;
uniform vec3 uColor;
in vec2 vUv;
in vec3 vNormal;
in vec3 vViewPosition;
out vec4 fragColor;
float snoise(vec3 v) {
return fract(sin(dot(v, vec3(12.9898, 78.233, 45.543))) * 43758.5453);
}
void main() {
vec3 viewDir = normalize(-vViewPosition);
float fresnel = pow(1.0 - abs(dot(viewDir, vNormal)), 3.0);
float noise = snoise(vec3(vUv * 5.0, uTime * 0.5));
vec3 color = uColor * fresnel;
color += uColor * noise * 0.2;
float alpha = fresnel * 0.8 + noise * 0.1;
fragColor = vec4(color, alpha);
}glsl
// shaders/energy-field.frag
#version 300 es
precision highp float;
uniform float uTime;
uniform vec3 uColor;
in vec2 vUv;
in vec3 vNormal;
in vec3 vViewPosition;
out vec4 fragColor;
float snoise(vec3 v) {
return fract(sin(dot(v, vec3(12.9898, 78.233, 45.543))) * 43758.5453);
}
void main() {
vec3 viewDir = normalize(-vViewPosition);
float fresnel = pow(1.0 - abs(dot(viewDir, vNormal)), 3.0);
float noise = snoise(vec3(vUv * 5.0, uTime * 0.5));
vec3 color = uColor * fresnel;
color += uColor * noise * 0.2;
float alpha = fresnel * 0.8 + noise * 0.1;
fragColor = vec4(color, alpha);
}6.3 Data Visualization Shader
6.3 数据可视化着色器
glsl
// shaders/data-bar.frag
#version 300 es
precision highp float;
uniform float uValue;
uniform float uThreshold;
uniform vec3 uColorLow;
uniform vec3 uColorHigh;
uniform vec3 uColorWarning;
in vec2 vUv;
out vec4 fragColor;
void main() {
float fill = step(vUv.x, uValue);
vec3 color = mix(uColorLow, uColorHigh, uValue);
color = mix(color, uColorWarning, step(uThreshold, uValue));
float gradient = vUv.y * 0.3 + 0.7;
fragColor = vec4(color * gradient * fill, fill);
}glsl
// shaders/data-bar.frag
#version 300 es
precision highp float;
uniform float uValue;
uniform float uThreshold;
uniform vec3 uColorLow;
uniform vec3 uColorHigh;
uniform vec3 uColorWarning;
in vec2 vUv;
out vec4 fragColor;
void main() {
float fill = step(vUv.x, uValue);
vec3 color = mix(uColorLow, uColorHigh, uValue);
color = mix(color, uColorWarning, step(uThreshold, uValue));
float gradient = vUv.y * 0.3 + 0.7;
fragColor = vec4(color * gradient * fill, fill);
}7. Security & Performance Standards
7. 安全与性能标准
7.1 GPU Safety
7.1 GPU安全
| Risk | Mitigation |
|---|---|
| Infinite loops | Always use constant loop bounds |
| GPU hangs | Test shaders with small datasets first |
| Memory exhaustion | Limit texture sizes |
| 风险 | 缓解措施 |
|---|---|
| 无限循环 | 始终使用常量循环边界 |
| GPU挂起 | 先使用小数据集测试着色器 |
| 内存耗尽 | 限制纹理尺寸 |
7.2 Loop Safety Pattern
7.2 循环安全模式
glsl
// ❌ BAD - Dynamic loop bound
for (int i = 0; i < int(uCount); i++) { }
// ✅ GOOD - Constant loop bound
const int MAX_ITERATIONS = 100;
for (int i = 0; i < MAX_ITERATIONS; i++) {
if (i >= int(uCount)) break;
}glsl
// ❌ BAD - Dynamic loop bound
for (int i = 0; i < int(uCount); i++) { }
// ✅ GOOD - Constant loop bound
const int MAX_ITERATIONS = 100;
for (int i = 0; i < MAX_ITERATIONS; i++) {
if (i >= int(uCount)) break;
}8. Common Mistakes & Anti-Patterns
8. 常见错误与反模式
8.1 Never: Use Dynamic Loop Bounds
8.1 切勿:使用动态循环边界
glsl
// ❌ DANGEROUS - May cause GPU hang
for (int i = 0; i < uniformValue; i++) { }
// ✅ SAFE - Constant bound with early exit
const int MAX = 100;
for (int i = 0; i < MAX; i++) {
if (i >= uniformValue) break;
}glsl
// ❌ DANGEROUS - May cause GPU hang
for (int i = 0; i < uniformValue; i++) { }
// ✅ SAFE - Constant bound with early exit
const int MAX = 100;
for (int i = 0; i < MAX; i++) {
if (i >= uniformValue) break;
}8.2 Never: Divide Without Checking Zero
8.2 切勿:未检查零就进行除法
glsl
// ❌ DANGEROUS - Division by zero
float result = value / divisor;
// ✅ SAFE - Guard against zero
float result = value / max(divisor, 0.0001);glsl
// ❌ DANGEROUS - Division by zero
float result = value / divisor;
// ✅ SAFE - Guard against zero
float result = value / max(divisor, 0.0001);9. Pre-Implementation Checklist
9. 预实现检查清单
Phase 1: Before Writing Code
阶段1:编写代码前
- Write shader compilation test
- Write uniform accessibility test
- Create baseline images for visual regression tests
- Define performance targets (FPS, draw calls)
- Review existing shaders for reusable patterns
- 编写着色器编译测试
- 编写Uniform可访问性测试
- 创建视觉回归测试的基准图像
- 定义性能目标(FPS、绘制调用数)
- 审查现有着色器以寻找可复用模式
Phase 2: During Implementation
阶段2:实现过程中
- All loops have constant bounds
- No division by zero possible
- Using branchless patterns (mix/step)
- Appropriate precision qualifiers
- Texture lookups cached
- Uniforms batched into vectors/matrices
- 所有循环都有常量边界
- 不会出现除零情况
- 使用无分支模式(mix/step)
- 使用合适的精度限定词
- 缓存纹理查找结果
- Uniform批处理为向量/矩阵
Phase 3: Before Committing
阶段3:提交前
- All shader tests pass:
npm run test:shaders - Visual regression tests pass:
npm run test:visual - Performance benchmark meets targets:
npm run bench:shaders - Cross-browser compatibility verified
- No artifacts at edge cases (UV 0,0 and 1,1)
- Smooth animation timing verified
- 所有着色器测试通过:
npm run test:shaders - 视觉回归测试通过:
npm run test:visual - 性能基准测试达到目标:
npm run bench:shaders - 跨浏览器兼容性验证通过
- 边缘情况(UV 0,0和1,1)无渲染异常
- 动画时序平滑性验证通过
10. Summary
10. 总结
GLSL shaders power the visual effects in JARVIS HUD:
- TDD First: Write tests before shaders - compilation, uniforms, visual regression
- Performance: Use branchless patterns, texture atlases, LOD, precision optimization
- Safety: Constant loop bounds, guard divisions
- Testing: Verify across target browsers, benchmark GPU performance
Remember: Shaders run on GPU - a single bad shader can freeze the entire system.
References:
- - Complex shader techniques
references/advanced-patterns.md
GLSL着色器为JARVIS HUD的视觉效果提供动力:
- 先做TDD:在编写着色器前先编写测试——编译测试、Uniform测试、视觉回归测试
- 性能优化:使用无分支模式、纹理图集、LOD、精度优化
- 安全保障:使用常量循环边界、防护除法运算
- 测试验证:在目标浏览器上验证,基准测试GPU性能
注意:着色器运行在GPU上——一个有问题的着色器可能导致整个系统冻结。
参考资料:
- - 复杂着色器技术
references/advanced-patterns.md