webgl2 方法解析: useProgram()

0 阅读2分钟

在 WebGL2 中,useProgram() 是一个非常重要的函数,用于指定当前的着色器程序(Shader Program)。以下是关于 useProgram() 的详细说明:

1. 函数定义

useProgram() 的作用是将一个着色器程序对象绑定到 WebGL 上下文的当前状态中,以便后续的渲染操作可以使用该着色器程序。

void gl.useProgram(program);
  • 参数

    • program:一个 WebGLProgram 对象,表示要使用的着色器程序。如果传入 null,则会取消当前绑定的着色器程序。

2. 使用场景

在 WebGL2 的渲染流程中,着色器程序是核心组件之一,负责处理顶点数据和片元数据。useProgram() 用于在渲染过程中切换不同的着色器程序,以实现不同的渲染效果。

3. 示例代码

以下是一个可直接运行的示例,展示如何创建和使用着色器程序:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebGL2 Triangle</title>
    <style>
        body { margin: 0; overflow: hidden; }
        canvas { display: block; width: 600px; height: 400px; }
    </style>
</head>
<body>
    <canvas id="glCanvas"></canvas>
​
    <script>
        // 顶点着色器代码
        const vertexShaderSource = `#version 300 es
            layout(location = 0) in vec2 aPosition;
            layout(location = 1) in vec3 aColor;
            out vec3 vColor;
            void main() {
                gl_Position = vec4(aPosition, 0.0, 1.0);
                vColor = aColor;
            }
        `;
​
        // 片段着色器代码
        const fragmentShaderSource = `#version 300 es
            precision highp float;
            in vec3 vColor;
            out vec4 fragColor;
            void main() {
                fragColor = vec4(vColor, 1.0);
            }
        `;
​
        // 初始化WebGL2上下文
        const canvas = document.getElementById('glCanvas');
        const gl = canvas.getContext('webgl2');
        if (!gl) {
            alert('WebGL2 not supported in your browser!');
            throw new Error('WebGL2 not supported');
        }
​
        // 编译着色器
        function compileShader(source, type) {
            const shader = gl.createShader(type);
            gl.shaderSource(shader, source);
            gl.compileShader(shader);
            if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
                console.error('Shader compile error:', gl.getShaderInfoLog(shader));
                gl.deleteShader(shader);
                return null;
            }
            return shader;
        }
​
        // 创建着色器程序
        function createProgram(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('Program link error:', gl.getProgramInfoLog(program));
                gl.deleteProgram(program);
                return null;
            }
            return program;
        }
​
        // 编译和链接着色器
        const vertexShader = compileShader(vertexShaderSource, gl.VERTEX_SHADER);
        const fragmentShader = compileShader(fragmentShaderSource, gl.FRAGMENT_SHADER);
        const program = createProgram(vertexShader, fragmentShader);
​
        // 顶点数据(位置和颜色)
        const vertices = new Float32Array([
            // 位置(x,y)   颜色(r,g,b)
             0.0,  0.5,    1.0, 0.0, 0.0,  // 顶点1:红色
            -0.5, -0.5,    0.0, 1.0, 0.0,  // 顶点2:绿色
             0.5, -0.5,    0.0, 0.0, 1.0   // 顶点3:蓝色
        ]);
​
        // 创建并绑定顶点缓冲区
        const vertexBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
​
        // 配置顶点属性
        const stride = 5 * Float32Array.BYTES_PER_ELEMENT; // 每个顶点5个浮点数(2位置 + 3颜色)
        
        // 位置属性 (location = 0)
        gl.vertexAttribPointer(0, 2, gl.FLOAT, false, stride, 0);
        gl.enableVertexAttribArray(0);
        
        // 颜色属性 (location = 1)
        gl.vertexAttribPointer(1, 3, gl.FLOAT, false, stride, 2 * Float32Array.BYTES_PER_ELEMENT);
        gl.enableVertexAttribArray(1);
​
        // 渲染函数
        function render() {
            gl.clearColor(0.1, 0.1, 0.1, 1.0); // 设置背景色
            gl.clear(gl.COLOR_BUFFER_BIT);
            
            gl.useProgram(program);
            gl.drawArrays(gl.TRIANGLES, 0, 3); // 绘制3个顶点
            
            requestAnimationFrame(render);
        }
​
        // 开始渲染循环
        render();
    </script>
</body>
</html>

4. 注意事项

  • 绑定顺序:在调用 useProgram() 之前,必须先创建并链接好着色器程序。
  • 性能优化:如果在渲染过程中频繁切换着色器程序,可能会导致性能下降。尽量减少不必要的切换。
  • 默认值:如果传入 null,则当前的着色器程序会被取消绑定。