webgl2 方法解析: shaderSource()

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

1. 方法定义

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

2. 语法

arduino 复制代码
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() 加载着色器代码:

html 复制代码
<!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 对象,且其类型(顶点着色器或片段着色器)必须与代码匹配。
相关推荐
光影少年1 天前
WebGIS 和GIS学习路线图
学习·前端框架·webgl
DBBH1 天前
Cesium源码分析之渲染3DTile的一点思考
图形渲染·webgl·cesium.js
Robet2 天前
TS2d渲染引擎
webgl
Robet2 天前
WebGL2D渲染引擎
webgl
goodName3 天前
如何实现精准操控?Cesium模型移动旋转控件实现
webgl·cesium
丫丫7237346 天前
Three.js 模型树结构与节点查询学习笔记
javascript·webgl
allenjiao8 天前
WebGPU vs WebGL:WebGPU什么时候能完全替代WebGL?Web 图形渲染的迭代与未来
前端·图形渲染·webgl·threejs·cesium·webgpu·babylonjs
mapvthree9 天前
mapvthree Engine 设计分析——二三维一体化的架构设计
webgl·数字孪生·mapvthree·jsapi2d·jsapigl·引擎对比
GISer_Jing10 天前
3D Cesium渲染架剖析
javascript·3d·webgl
Swift社区10 天前
用 Chrome DevTools 深度分析 Vue WebGL 内存泄漏(进阶篇)
vue.js·webgl·chrome devtools