求WebGL并行性纯GLSL代码的简单完整示例
完整的WebGL并行计算示例(纯GLSL)
嘿,我懂你想要的是不依赖任何抽象库,直接用原生WebGL+GLSL实现并行性的最简完整示例——毕竟看封装好的库永远不如亲手写一遍来得明白。下面这个例子会用GPU并行计算每个像素坐标的平方值,然后把结果渲染成颜色,整个流程清晰易懂,你可以直接复制运行。
1. HTML基础结构
先准备一个canvas用来输出计算结果:
<canvas id="glCanvas" width="512" height="512"></canvas>
2. JavaScript部分(WebGL上下文初始化与调度)
这部分负责创建WebGL上下文、编译着色器、设置渲染状态,最后触发GPU的并行计算:
// 获取canvas和WebGL上下文 const canvas = document.getElementById('glCanvas'); const gl = canvas.getContext('webgl'); if (!gl) { alert('你的浏览器不支持WebGL'); throw new Error('WebGL not supported'); } // 顶点着色器代码(负责传递全屏顶点位置) const vertexShaderSource = ` attribute vec2 a_position; void main() { gl_Position = vec4(a_position, 0.0, 1.0); } `; // 片元着色器代码(核心并行计算逻辑在这里!) const fragmentShaderSource = ` precision mediump float; uniform vec2 u_resolution; void main() { // 把像素坐标转换到0.0-1.0的归一化范围 vec2 st = gl_FragCoord.xy / u_resolution; // 并行计算:每个像素独立计算x和y的平方值 float xSquare = st.x * st.x; float ySquare = st.y * st.y; // 把计算结果转换成颜色输出(红= x平方,绿= y平方,蓝=0) gl_FragColor = vec4(xSquare, ySquare, 0.0, 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; } // 创建并链接着色器程序 const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource); const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource); 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; } // 设置全屏顶点数据(覆盖整个canvas的两个三角形) const vertices = new Float32Array([ -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, ]); const vertexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); // 获取着色器中的属性和Uniform变量位置 const positionAttributeLocation = gl.getAttribLocation(program, 'a_position'); const resolutionUniformLocation = gl.getUniformLocation(program, 'u_resolution'); // 准备渲染环境 gl.useProgram(program); gl.enableVertexAttribArray(positionAttributeLocation); gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0); // 传递canvas分辨率给片元着色器 gl.uniform2f(resolutionUniformLocation, canvas.width, canvas.height); // 清空画布并触发绘制(这一步会让GPU并行处理所有片元) gl.clearColor(0.0, 0.0, 0.0, 1.0); gl.clear(gl.COLOR_BUFFER_BIT); gl.drawArrays(gl.TRIANGLES, 0, 6);
3. 核心并行逻辑解释
这个例子的并行性完全体现在片元着色器里:
- 当调用
gl.drawArrays时,GPU会同时启动成千上万个独立的“计算线程”,每个线程对应canvas上的一个像素(片元)。 - 每个线程独立执行
main()函数内的代码:计算自己对应像素的坐标平方,再转换成颜色输出。这些计算完全没有依赖关系,GPU可以同时处理所有片元,效率远高于CPU单线程。 - 你可以把平方计算换成任何需要并行处理的任务(比如矩阵运算、图像滤镜、数据加密),只要每个任务是独立的,都能用这种方式让GPU并行处理。
内容的提问来源于stack exchange,提问作者Lance Pollard
相关产品推荐
相关产品推荐

