WebGL编程笔记1
<canvas id="myCanvas" width="600" height="300" style="border: 1px solid red"></canvas>
function createProgram(webgl, vertex, fragment) { // 创建程序 let shader_vertex = webgl.createShader(webgl.VERTEX_SHADER); let shader_fragment = webgl.createShader(webgl.FRAGMENT_SHADER); webgl.shaderSource(shader_vertex, vertex); webgl.shaderSource(shader_fragment, fragment); // 编译源码 webgl.compileShader(shader_vertex); webgl.compileShader(shader_fragment); if (webgl.getShaderParameter(shader_vertex, webgl.COMPILE_STATUS) === false) { console.error('Compile Shader Error: shader_vertex,' + webgl.getShaderInfoLog(shader_vertex)); } if (webgl.getShaderParameter(shader_fragment, webgl.COMPILE_STATUS) === false) { console.error('Compile Shader Error: shader_fragment,' + webgl.getShaderInfoLog(shader_fragment)); } // 创建执行程序 let program = webgl.createProgram(); webgl.attachShader(program, shader_vertex); webgl.attachShader(program, shader_fragment); // 连接context和program webgl.linkProgram(program); if(webgl.getProgramParameter(program, webgl.LINK_STATUS) === false) { console.error(webgl.getProgramInfoLog(program)); } webgl.useProgram(program); return program; } function bindBufferWidthData(webgl, target, data) { let buffer = webgl.createBuffer(); webgl.bindBuffer(target, buffer); webgl.bufferData(target, data, webgl.STATIC_DRAW); // 内存数据传入显存 } function bindVertexAttributePointer(webgl, program, varName, varSize, varType, normalized, stride, offset) { var pointer = webgl.getAttribLocation(program, varName); webgl.vertexAttribPointer(pointer, varSize, varType, normalized, stride, offset); webgl.enableVertexAttribArray(pointer); return pointer; } const vertex = ` precision lowp float; attribute vec3 vertexPosition; attribute vec4 inColor; varying vec4 outcolor; void main(void) { outcolor = inColor; gl_Position = vec4(vertexPosition, 1.0); } `; const fragment = ` precision lowp float; varying vec4 outcolor; void main(void) { gl_FragColor = vec4(outcolor); } `; let canvas = document.getElementById('myCanvas'); let webgl = canvas.getContext('webgl'); const data_position = new Float32Array([ // x y z r g b a -0.5, 0.5, 0.0, 0.9, 0.0, 0.0, 1.0, +0.5, 0.5, 0.0, 0.0, 0.8, 0.0, 1.0, +0.5, -0.5, 0.0, 0.0, 0.0, 1.0, 1.0, -0.5, -0.5, 0.0, 1.0, 1.0, 1.0, 1.0 ]); const data_index = new Uint16Array([ 0, 1, 2, 0, 2, 3 ]); const FSIZE = data_position.BYTES_PER_ELEMENT; webgl.clearColor(0, 1, 0, 1); webgl.clear(webgl.COLOR_BUFFER_BIT); // 第一步:编译Shader程序,并创建program let program = createProgram(webgl, vertex, fragment); // 第二步:创建数据缓冲区和索引缓冲区 let buffer_position = bindBufferWidthData(webgl, webgl.ARRAY_BUFFER, data_position); // 将顶点数据写入数据缓冲区并启用 let buffer_index = bindBufferWidthData(webgl, webgl.ELEMENT_ARRAY_BUFFER, data_index); // 将索引数据写入冲区并启用 // 第三步: 未Shader中的输入变量定义指针的,并分配取数位置 let vertexPosition = bindVertexAttributePointer(webgl, program, "vertexPosition", 3, webgl.FLOAT, false, FSIZE * 7, 0); // 每次从buffer中取28个字节,从这一段字节中的offset=0字节开始取3个浮点数 let inColor = bindVertexAttributePointer(webgl, program, "inColor", 4, webgl.FLOAT, false, FSIZE * 7, FSIZE * 3); // 每次从buffer中取28个字节,从这一段字节中的offset=12字节开始取4个浮点数作为inColor // 开始绘制 webgl.drawElements(webgl.TRIANGLES, 6, webgl.UNSIGNED_SHORT, 0); // 定义从buffer中取得次数,3次,从0开始 // webgl.drawArrays(webgl.TRIANGLES, 0, 3); // draw函数中的count参数指的是从buffer中取几次数据 // drawArrays直接从数据缓冲区中取数据,每次取多少字节,多少偏移由vertexAttribPointer函数决定 // drawElements先从索引缓冲区中取出索引index,然后从数据缓冲区对应的index中取数据,每次取多少字节,多少偏移由vertexAttribPointer函数决定