webgl2 方法解析: shaderSource()

0 阅读3分钟

在 WebGL 2 中,shaderSource() 是一个非常重要的方法,用于向 WebGL 程序的着色器对象中加载着色器代码。以下是关于 shaderSource() 的详细说明:

1. 方法定义

shaderSource() 是 WebGL 2 API 的一部分,用于将着色器代码(通常是用 GLSL 编写的)加载到着色器对象中。它是一个 WebGLRenderingContext 的方法。

2. 语法

void gl.shaderSource(shader, source);

参数

  • shader

    • 类型:WebGLShader
    • 指定要加载着色器代码的着色器对象。着色器对象可以通过 gl.createShader() 创建。
  • source

    • 类型:string
    • 包含着色器代码的字符串。着色器代码是用 GLSL(OpenGL Shading Language)编写的,用于定义顶点着色器或片段着色器的逻辑。

3. 使用场景

在 WebGL 中,渲染管线分为两个主要阶段:顶点着色器(Vertex Shader)和片段着色器(Fragment Shader)。每个着色器都需要一段 GLSL 代码来定义其行为。shaderSource() 的作用就是将这些代码加载到对应的着色器对象中。

4. 示例代码

以下是一个完整的示例,展示如何使用 shaderSource() 加载着色器代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>WebGL2 - Render a Triangle</title>
  <style>
    canvas {
      display: block;
      margin: 0 auto;
      border: 1px solid black;
    }
  </style>
</head>
<body>
  <canvas id="glCanvas" width="640" height="480"></canvas>
  <script>
    // 获取 canvas 元素
    const canvas = document.getElementById('glCanvas');
    const gl = canvas.getContext('webgl2');
​
    if (!gl) {
      alert('WebGL2 不被支持');
      throw new Error('WebGL2 不被支持');
    }
​
    // 顶点着色器代码
    const vertexShaderSource = `#version 300 es
      in vec4 a_position;
      void main() {
        gl_Position = a_position;
      }
    `;
​
    // 片段着色器代码
    const fragmentShaderSource = `#version 300 es
      precision highp float;
      out vec4 outColor;
      void main() {
        outColor = vec4(1.0, 0.5, 0.2, 1.0); // 橙色
      }
    `;
​
    // 创建着色器
    function createShader(gl, type, source) {
      const shader = gl.createShader(type);
      gl.shaderSource(shader, source);
      gl.compileShader(shader);
      if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        console.error('着色器编译失败:', gl.getShaderInfoLog(shader));
        gl.deleteShader(shader);
        return null;
      }
      return shader;
    }
​
    // 创建程序
    function createProgram(gl, vertexShader, fragmentShader) {
      const program = gl.createProgram();
      gl.attachShader(program, vertexShader);
      gl.attachShader(program, fragmentShader);
      gl.linkProgram(program);
      if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
        console.error('程序链接失败:', gl.getProgramInfoLog(program));
        gl.deleteProgram(program);
        return null;
      }
      return program;
    }
​
    // 创建顶点着色器和片段着色器
    const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
    const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
​
    // 创建程序并使用
    const program = createProgram(gl, vertexShader, fragmentShader);
    gl.useProgram(program);
​
    // 顶点数据
    const vertices = new Float32Array([
      -0.5, -0.5, 0.0,  // 顶点1
       0.5, -0.5, 0.0,  // 顶点2
       0.0,  0.5, 0.0   // 顶点3
    ]);
​
    // 创建缓冲区对象
    const vertexBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); // 绑定缓冲区对象到 ARRAY_BUFFER
    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); // 传输顶点数据到缓冲区
​
    // 获取顶点属性位置并启用
    const positionAttributeLocation = gl.getAttribLocation(program, 'a_position');
    gl.enableVertexAttribArray(positionAttributeLocation);
​
    // 设置顶点属性指针
    gl.vertexAttribPointer(
      positionAttributeLocation, // 属性位置
      3,                         // 每个顶点的分量数量
      gl.FLOAT,                  // 数据类型
      false,                     // 是否归一化
      0,                         // 每个顶点的字节偏移量
      0                          // 数据起始偏移量
    );
​
    // 设置视口大小
    gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
​
    // 清空画布
    gl.clearColor(0.0, 0.0, 0.0, 1.0); // 设置背景颜色为黑色
    gl.clear(gl.COLOR_BUFFER_BIT);
​
    // 绘制三角形
    gl.drawArrays(gl.TRIANGLES, 0, 3);
​
  </script>
</body>
</html>

5. 注意事项

  • 着色器代码格式shaderSource() 的第二个参数是一个字符串,因此需要确保 GLSL 代码格式正确,且没有语法错误。
  • 编译错误处理:加载着色器代码后,需要调用 gl.compileShader() 编译着色器,并通过 gl.getShaderParameter()gl.getShaderInfoLog() 检查编译是否成功。
  • 着色器类型shaderSource() 的第一个参数必须是一个有效的 WebGLShader 对象,且其类型(顶点着色器或片段着色器)必须与代码匹配。