乐闻世界logo
搜索文章和话题

What are shaders in WebGL? What is the difference between vertex and fragment shaders?

3月6日 21:57

WebGL Shaders Overview

Shaders are small programs that run on the GPU to process various stages of graphics rendering. WebGL uses GLSL (OpenGL Shading Language) to write shader code.

Types of Shaders

WebGL primarily has two types of shaders:

  1. Vertex Shader
  2. Fragment Shader

Vertex Shader

Function

  • Processes data for each vertex
  • Responsible for coordinate transformations
  • Converts 3D coordinates to clip space coordinates

Inputs

  • attribute: Vertex attributes (position, color, normal, texture coordinates, etc.)
  • uniform: Uniform variables (transformation matrices, lighting parameters, etc.)

Outputs

  • gl_Position: Vertex position in clip space (required)
  • varying: Interpolated data passed to the fragment shader

Code Example

glsl
// Vertex shader attribute vec3 a_position; attribute vec3 a_color; attribute vec2 a_texCoord; uniform mat4 u_modelMatrix; uniform mat4 u_viewMatrix; uniform mat4 u_projectionMatrix; varying vec3 v_color; varying vec2 v_texCoord; void main() { // Coordinate transformation: Model space → World space → Camera space → Clip space mat4 mvp = u_projectionMatrix * u_viewMatrix * u_modelMatrix; gl_Position = mvp * vec4(a_position, 1.0); // Pass data to fragment shader v_color = a_color; v_texCoord = a_texCoord; }

Fragment Shader

Function

  • Processes each fragment (potential pixel)
  • Calculates final pixel color
  • Performs texture sampling, lighting calculations, etc.

Inputs

  • varying: Interpolated data from vertex shader
  • uniform: Uniform variables (textures, material parameters, etc.)

Outputs

  • gl_FragColor: Final pixel color (WebGL 1.0)
  • out vec4 fragColor: Output variable (WebGL 2.0)

Code Example

glsl
// Fragment shader precision mediump float; varying vec3 v_color; varying vec2 v_texCoord; uniform sampler2D u_texture; uniform float u_opacity; void main() { // Texture sampling vec4 texColor = texture2D(u_texture, v_texCoord); // Blend vertex color with texture color vec3 finalColor = v_color * texColor.rgb; // Set final color gl_FragColor = vec4(finalColor, texColor.a * u_opacity); }

Vertex Shader vs Fragment Shader Comparison

FeatureVertex ShaderFragment Shader
Execution FrequencyExecuted once per vertexExecuted once per fragment
Primary TaskCoordinate transformationColor calculation
Required Outputgl_Positiongl_FragColor
Typical OperationsMatrix multiplication, vertex lightingTexture sampling, pixel-level lighting
Performance ImpactLess impact when few verticesUsually has greater performance impact
Precision RequirementsTypically uses highpOften uses mediump for optimization

Shader Variable Types

attribute (Vertex shader only)

glsl
attribute vec3 a_position; // Vertex position attribute vec2 a_texCoord; // Texture coordinates attribute vec3 a_normal; // Normal vector

uniform (Available in both shaders)

glsl
uniform mat4 u_matrix; // Transformation matrix uniform sampler2D u_texture; // Texture sampler uniform vec3 u_lightColor; // Light color

varying (Passing data from vertex to fragment)

glsl
// Vertex shader varying vec2 v_texCoord; // Fragment shader varying vec2 v_texCoord; // Same name variable receives interpolated data

Shader Compilation and Linking Process

javascript
// 1. Create shader objects const vertexShader = gl.createShader(gl.VERTEX_SHADER); const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); // 2. Set source code gl.shaderSource(vertexShader, vertexSource); gl.shaderSource(fragmentShader, fragmentSource); // 3. Compile shaders gl.compileShader(vertexShader); gl.compileShader(fragmentShader); // 4. Create program object const program = gl.createProgram(); // 5. Attach shaders gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); // 6. Link shader program gl.linkProgram(program); // 7. Use program gl.useProgram(program);

Performance Optimization Tips

  1. Reduce varying variables: Minimize data transfer between vertex and fragment shaders
  2. Calculate in vertex shader: Compute at vertex level rather than fragment level when possible
  3. Use appropriate precision: Use mediump or lowp on mobile devices
  4. Avoid branching: GPUs are not good at handling conditional branches
  5. Precompute constants: Use uniforms instead of repeated calculations
标签:WebGL