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

WebGL 中的着色器(Shader)是什么?顶点着色器和片段着色器有什么区别?

3月6日 21:57

WebGL 着色器概述

着色器(Shader)是在 GPU 上运行的小程序,用于处理图形渲染的各个阶段。WebGL 使用 GLSL(OpenGL Shading Language)编写着色器代码。

着色器的类型

WebGL 主要有两种着色器:

  1. 顶点着色器(Vertex Shader)
  2. 片段着色器(Fragment Shader)

顶点着色器(Vertex Shader)

功能

  • 处理每个顶点的数据
  • 负责坐标变换
  • 将 3D 坐标转换为裁剪空间坐标

输入

  • attribute:顶点属性(位置、颜色、法线、纹理坐标等)
  • uniform:统一变量(变换矩阵、光照参数等)

输出

  • gl_Position:裁剪空间中的顶点位置(必需)
  • varying:传递给片段着色器的插值数据

代码示例

glsl
// 顶点着色器 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() { // 坐标变换:模型空间 → 世界空间 → 相机空间 → 裁剪空间 mat4 mvp = u_projectionMatrix * u_viewMatrix * u_modelMatrix; gl_Position = mvp * vec4(a_position, 1.0); // 传递数据给片段着色器 v_color = a_color; v_texCoord = a_texCoord; }

片段着色器(Fragment Shader)

功能

  • 处理每个片段(潜在的像素)
  • 计算最终像素颜色
  • 执行纹理采样、光照计算等

输入

  • varying:从顶点着色器插值而来的数据
  • uniform:统一变量(纹理、材质参数等)

输出

  • gl_FragColor:最终像素颜色(WebGL 1.0)
  • out vec4 fragColor:输出变量(WebGL 2.0)

代码示例

glsl
// 片段着色器 precision mediump float; varying vec3 v_color; varying vec2 v_texCoord; uniform sampler2D u_texture; uniform float u_opacity; void main() { // 纹理采样 vec4 texColor = texture2D(u_texture, v_texCoord); // 混合顶点颜色和纹理颜色 vec3 finalColor = v_color * texColor.rgb; // 设置最终颜色 gl_FragColor = vec4(finalColor, texColor.a * u_opacity); }

顶点着色器 vs 片段着色器对比

特性顶点着色器片段着色器
执行频率每个顶点执行一次每个片段执行一次
主要任务坐标变换颜色计算
必需输出gl_Positiongl_FragColor
典型操作矩阵乘法、顶点光照纹理采样、像素级光照
性能影响顶点数量少时影响小通常对性能影响更大
精度要求通常使用 highp常用 mediump 优化性能

着色器变量类型

attribute(顶点着色器专用)

glsl
attribute vec3 a_position; // 顶点位置 attribute vec2 a_texCoord; // 纹理坐标 attribute vec3 a_normal; // 法线向量

uniform(两种着色器都可用)

glsl
uniform mat4 u_matrix; // 变换矩阵 uniform sampler2D u_texture; // 纹理采样器 uniform vec3 u_lightColor; // 光照颜色

varying(顶点→片段传递数据)

glsl
// 顶点着色器 varying vec2 v_texCoord; // 片段着色器 varying vec2 v_texCoord; // 同名变量接收插值数据

着色器编译和链接流程

javascript
// 1. 创建着色器对象 const vertexShader = gl.createShader(gl.VERTEX_SHADER); const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); // 2. 设置源码 gl.shaderSource(vertexShader, vertexSource); gl.shaderSource(fragmentShader, fragmentSource); // 3. 编译着色器 gl.compileShader(vertexShader); gl.compileShader(fragmentShader); // 4. 创建程序对象 const program = gl.createProgram(); // 5. 附加着色器 gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); // 6. 链接着色器程序 gl.linkProgram(program); // 7. 使用程序 gl.useProgram(program);

性能优化建议

  1. 减少 varying 变量数量:减少顶点与片段着色器间的数据传输
  2. 在顶点着色器中计算:尽可能在顶点级别而非片段级别计算
  3. 使用适当精度:移动端使用 mediumplowp
  4. 避免分支语句:GPU 不擅长处理条件分支
  5. 预计算常量:将 uniforms 而非反复计算
标签:WebGL