1 <!DOCTYPE html> 2 <html lang="en"> 3 4 <head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 8 <title>WebGL</title> 9 10 <!-- 顶点着色器 --> 11 <script id="shader-vs" type="x-shader/x-vertex"> 12 attribute vec3 aVertexPosition; 13 14 void main() { 15 // 直接将外部传入的顶点坐标作为最终坐标 16 gl_Position = vec4(aVertexPosition, 1.0); 17 } 18 </script> 19 20 <!-- 片段着色器 --> 21 <script id="shader-fs" type="x-shader/x-fragment"> 22 // 设定 float 的精度, 这里我们使用中等精度 23 precision mediump float; 24 25 void main() { 26 // 输出为纯白色 27 gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); 28 } 29 </script> 30 31 <script> 32 var gl; 33 var canvas; 34 var shaderProgram; 35 var vertexBuffer; 36 37 function createGLContext(canvas) { 38 var names = ["webgl", "experimental-webgl"]; 39 var context = null; 40 for (var i = 0; i < names.length; i++) { 41 try { 42 context = canvas.getContext(names[i]); 43 } catch (e) { } 44 if (context) { 45 break; 46 } 47 } 48 if (context) { 49 // 添加动态属性记录画布的大小 50 context.viewportWidth = canvas.width; 51 context.viewportHeight = canvas.height; 52 } else { 53 alert("Failed to create WebGL context!"); 54 } 55 return context; 56 } 57 58 function setupShaders() { 59 // 从 DOM 上创建对应的着色器 60 vertexShader = loadShaderFromDOM("shader-vs"); 61 fragmentShader = loadShaderFromDOM("shader-fs"); 62 63 // 创建程序并连接着色器 64 shaderProgram = gl.createProgram(); 65 gl.attachShader(shaderProgram, vertexShader); 66 gl.attachShader(shaderProgram, fragmentShader); 67 gl.linkProgram(shaderProgram); 68 69 // 连接失败的检测 70 if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { 71 alert("Failed to setup shaders"); 72 } 73 74 // 使用着色器 75 gl.useProgram(shaderProgram); 76 77 // 创建动态属性获取着色器中 aVertexPosition 属性的位置 78 shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); 79 } 80 81 function loadShaderFromDOM(id) { 82 // 获取 DOM 83 var shaderScript = document.getElementById(id); 84 85 if (!shaderScript) { 86 return null; 87 } 88 89 // 获取着色器代码 90 var shaderSource = ""; 91 var currentChild = shaderScript.firstChild; 92 while (currentChild) { 93 if (currentChild.nodeType == 3) { // 3 corresponds to TEXT_NODE 94 shaderSource += currentChild.textContent; 95 } 96 currentChild = currentChild.nextSibling; 97 } 98 99 // 创建着色器 100 var shader; 101 if (shaderScript.type == "x-shader/x-fragment") { 102 shader = gl.createShader(gl.FRAGMENT_SHADER); 103 } else if (shaderScript.type == "x-shader/x-vertex") { 104 shader = gl.createShader(gl.VERTEX_SHADER); 105 } else { 106 return null; 107 } 108 109 // 编译着色器 110 gl.shaderSource(shader, shaderSource); 111 gl.compileShader(shader); 112 113 // 判断编译是否成功 114 if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 115 alert(gl.getShaderInfoLog(shader)); 116 return null; 117 } 118 return shader; 119 } 120 121 function setupBuffers() { 122 // 创建顶点缓冲 123 vertexBuffer = gl.createBuffer(); 124 // 绑定顶点缓冲 125 gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); 126 // 定义顶点数据 127 var triangleVertices = [ 128 0.0, 0.5, 0.0, 129 -0.5, -0.5, 0.0, 130 0.5, -0.5, 0.0 131 ]; 132 // 提交顶点数据 133 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVertices), gl.STATIC_DRAW); 134 vertexBuffer.itemSize = 3; 135 vertexBuffer.numberOfItems = 3; 136 } 137 138 function draw() { 139 // 设置视口大小, 使用像素, 调整该大小不影响显示内容,只影响图像在 Canvas 上显示的位置和尺寸 140 gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight); 141 // 清除颜色缓冲 142 gl.clear(gl.COLOR_BUFFER_BIT); 143 // 将提交的顶点数据绑定到着色器的 aVertexPosition 属性 144 gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, vertexBuffer.itemSize, gl.FLOAT, false, 0, 0); 145 // 开启属性 aVertexPosition 的使用 146 gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); 147 // 绘制图像 148 gl.drawArrays(gl.TRIANGLES, 0, vertexBuffer.numberOfItems); 149 } 150 151 function startup() { 152 canvas = document.getElementById("myGLCanvas"); 153 gl = createGLContext(canvas); 154 setupShaders(); 155 setupBuffers(); 156 // 定义清除颜色缓冲之后的填充色为黑色 157 gl.clearColor(0.0, 0.0, 0.0, 1.0); 158 draw(); 159 } 160 </script> 161 </head> 162 163 <body onload="startup();"> 164 <canvas id="myGLCanvas" width="500" height="500"></canvas> 165 </body> 166 167 </html>