WebGL Shaders

Custom shader implementation for advanced molecular visualization effects.

Shader Types

Vertex Shaders

Transform vertex positions and calculate lighting

Fragment Shaders

Calculate final pixel colors and effects

Shader Configuration

interface ShaderConfig {
  vertexShader: string;           // Vertex shader source code
  fragmentShader: string;         // Fragment shader source code
  uniforms?: {                    // Shader uniforms
    [key: string]: {
      type: string;               // Uniform type
      value: any;                 // Uniform value
    };
  };
  attributes?: {                  // Vertex attributes
    [key: string]: {
      size: number;               // Attribute size
      type: string;               // Attribute type
      normalized?: boolean;       // Normalize attribute values
    };
  };
}

Built-in Shaders

Phong Shader

Classic Phong lighting model

// Vertex shader
varying vec3 vNormal;
varying vec3 vPosition;

void main() {
  vNormal = normalize(normalMatrix * normal);
  vPosition = position;
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

// Fragment shader
uniform vec3 color;
uniform float shininess;
varying vec3 vNormal;
varying vec3 vPosition;

void main() {
  vec3 light = normalize(vec3(1.0, 1.0, 1.0));
  float diff = max(dot(vNormal, light), 0.0);
  vec3 viewDir = normalize(cameraPosition - vPosition);
  vec3 reflectDir = reflect(-light, vNormal);
  float spec = pow(max(dot(viewDir, reflectDir), 0.0), shininess);
  gl_FragColor = vec4(color * (diff + spec), 1.0);
}

Toon Shader

Cel-shading effect

// Vertex shader
varying vec3 vNormal;
varying vec3 vPosition;

void main() {
  vNormal = normalize(normalMatrix * normal);
  vPosition = position;
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

// Fragment shader
uniform vec3 color;
uniform float levels;
varying vec3 vNormal;
varying vec3 vPosition;

void main() {
  vec3 light = normalize(vec3(1.0, 1.0, 1.0));
  float diff = max(dot(vNormal, light), 0.0);
  float level = floor(diff * levels) / levels;
  gl_FragColor = vec4(color * level, 1.0);
}

Wireframe Shader

Edge detection and wireframe rendering

// Vertex shader
varying vec3 vBarycentric;

void main() {
  vBarycentric = barycentric;
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

// Fragment shader
uniform vec3 color;
uniform float lineWidth;
varying vec3 vBarycentric;

void main() {
  vec3 d = fwidth(vBarycentric);
  vec3 a3 = smoothstep(vec3(0.0), d * lineWidth, vBarycentric);
  float edge = min(min(a3.x, a3.y), a3.z);
  gl_FragColor = vec4(color, 1.0 - edge);
}

Example

// Create custom shader
const shader = new GLShader({
  vertexShader: `
    varying vec3 vNormal;
    varying vec3 vPosition;
    
    void main() {
      vNormal = normalize(normalMatrix * normal);
      vPosition = position;
      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }
  `,
  fragmentShader: `
    uniform vec3 color;
    uniform float time;
    varying vec3 vNormal;
    varying vec3 vPosition;
    
    void main() {
      vec3 light = normalize(vec3(1.0, 1.0, 1.0));
      float diff = max(dot(vNormal, light), 0.0);
      float pulse = sin(time * 2.0) * 0.5 + 0.5;
      gl_FragColor = vec4(color * (diff + pulse), 1.0);
    }
  `,
  uniforms: {
    color: { type: 'vec3', value: new THREE.Color(0xff0000) },
    time: { type: 'float', value: 0 }
  }
});

// Update shader uniforms
function animate() {
  shader.uniforms.time.value += 0.016;
  requestAnimationFrame(animate);
}
animate();

Related Topics

Learn more about WebGL implementation: