WebGL编程笔记1
1 | < canvas id="myCanvas" width="600" height="300" style="border: 1px solid red"></ canvas > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | 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函数决定 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决