glsl

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

GLSL Shader Programming Skill

GLSL着色器编程技能

File Organization: This skill uses split structure. See
references/
for advanced shader patterns.
文件结构:本技能采用拆分式结构。高级着色器模式请查看
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 基本原则

  1. TDD First: Write visual regression tests and shader unit tests before implementation
  2. Performance Aware: Profile GPU performance, optimize for 60 FPS target
  3. Precision Matters: Use appropriate precision qualifiers for performance
  4. Avoid Branching: Minimize conditionals in shaders for GPU efficiency
  5. Optimize Math: Use built-in functions, avoid expensive operations
  6. Uniform Safety: Validate uniform inputs before sending to GPU
  7. Loop Bounds: Always use constant loop bounds to prevent GPU hangs
  8. Memory Access: Optimize texture lookups and varying interpolation
  1. 先做测试驱动开发(TDD):在实现前编写视觉回归测试和着色器单元测试
  2. 关注性能:分析GPU性能,以60 FPS为优化目标
  3. 精度重要:使用合适的精度限定词以提升性能
  4. 避免分支:尽量减少着色器中的条件判断以提高GPU效率
  5. 优化数学运算:使用内置函数,避免昂贵的运算
  6. Uniform安全性:在发送到GPU前验证Uniform输入
  7. 循环边界:始终使用常量循环边界以防止GPU挂起
  8. 内存访问:优化纹理查找和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
undefined
bash
undefined

Run 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
undefined
npm run test:webgl-compat
undefined

4. Technology Stack & Versions

4. 技术栈与版本

4.1 GLSL Versions

4.1 GLSL版本

VersionContextFeatures
GLSL ES 3.00WebGL 2.0Modern features, better precision
GLSL ES 1.00WebGL 1.0Legacy support
版本上下文特性
GLSL ES 3.00WebGL 2.0现代特性,更高精度
GLSL ES 1.00WebGL 1.0遗留支持

4.2 Shader Setup

4.2 着色器设置

glsl
#version 300 es
precision highp float;
precision highp int;

// WebGL 2.0 shader header
glsl
#version 300 es
precision highp float;
precision highp int;

// WebGL 2.0 shader header

5. 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 values
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范围,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安全

RiskMitigation
Infinite loopsAlways use constant loop bounds
GPU hangsTest shaders with small datasets first
Memory exhaustionLimit 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:
  1. TDD First: Write tests before shaders - compilation, uniforms, visual regression
  2. Performance: Use branchless patterns, texture atlases, LOD, precision optimization
  3. Safety: Constant loop bounds, guard divisions
  4. Testing: Verify across target browsers, benchmark GPU performance
Remember: Shaders run on GPU - a single bad shader can freeze the entire system.

References:
  • references/advanced-patterns.md
    - Complex shader techniques
GLSL着色器为JARVIS HUD的视觉效果提供动力:
  1. 先做TDD:在编写着色器前先编写测试——编译测试、Uniform测试、视觉回归测试
  2. 性能优化:使用无分支模式、纹理图集、LOD、精度优化
  3. 安全保障:使用常量循环边界、防护除法运算
  4. 测试验证:在目标浏览器上验证,基准测试GPU性能
注意:着色器运行在GPU上——一个有问题的着色器可能导致整个系统冻结。

参考资料:
  • references/advanced-patterns.md
    - 复杂着色器技术