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 对象,且其类型(顶点着色器或片段着色器)必须与代码匹配。
相关推荐
魂断蓝桥6661 天前
如何用 three.js 把 3D 消防演练落到一栋楼里——第一课:场景搭建与火情定位
webgl·three.js·3d建筑·物联网3d·、3d工厂、3d工业园区、智慧制造、智慧工业、智慧工厂·3d定位、三维室内定位、3d建筑·3d消防
总要学点什么3 天前
第96篇:三维数据加载-城市建筑白模样式+着色器——让色带按体量上色,最白的那档却涂不上去
前端·gis·webgl·cesium·着色器·空间分析·白模
总要学点什么4 天前
第97篇:三维数据加载-城市建筑白模自定义着色器——让一条光带沿高度扫上去,快慢却由帧率说了算
前端·gis·webgl·cesium·着色器·空间分析·白模
总要学点什么5 天前
第98篇:三维特效-材质线效果——给一条线换十种材质,虚线的图案只填了一半
开发语言·前端·javascript·ecmascript·gis·webgl·材质
总要学点什么12 天前
第92篇:三维特效-圆(逐渐消逝)——从圆心开始,让一个洞把整片光啃到只剩外圈
gis·webgl·cesium·空间分析·1024程序员节
总要学点什么12 天前
第89篇:三维特效-螺旋圆效果——让螺旋臂卷起一圈圈外扩的涟漪
开发语言·javascript·ecmascript·webgl·cesium·空间分析·1024程序员节
GoldenSpider.AI13 天前
一张户型图做成浏览器 3D 漫游:house.json 统一模型、1.2 m 剖切图纸与分阶段验收
ai编程·webgl·three.js·3d漫游·claude code
Jmyd012315 天前
WebGL 三维党史馆怎么扛住 720 度全景与移动端弱网?
webgl·三维数字化
limit007518 天前
三维 WebGIS 工具选型:加载、样式、分析、交付,一套界面能做完什么
android·前端·web3·安卓·webgl
总要学点什么19 天前
第79篇:数据可视化-模拟迁徙效果——把三十条航线画成会飞的弧
3d·信息可视化·数据挖掘·数据分析·gis·webgl·cesium