# WebGL **Repository Path**: lzy_8920/web-gl ## Basic Information - **Project Name**: WebGL - **Description**: 学习webGL+threejs - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-02-21 - **Last Updated**: 2023-02-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 1.2 Canvas API - 提供二维绘图的方式 - 通过CanvasRenderingContext2D接口完成 - canvas.getContext('2d') ## 1.3 WebGL API - 提供三维绘图方式 - 通过WebGLRenderingContext接口完成 - canvas.getContext('webgl') ## 2.3 给画布换个颜色 ```JS const ctx = document.getElementById('canvas') const gl = ctx.getContext('webgl') gl.clearColor(1.0,0.0,0.0,1.0) // red 1.0 green 0.0 blue 0.0 alpha 1.0 gl.clear(gl.COLOR_BUFFER_BIT) ``` ## 2.4 绘制一个点 ```JS const ctx = document.getElementById('canvas') const gl = ctx.getContext('webgl') // 创建着色器源码 const VERTEX_SHADER_SOURCE = ` // 必须存在 main 函数 void main() { // 要绘制的点的坐标 gl_Position = vec4(0.0,0.0,0.0,1.0); // 点的大小 gl_PointSize = 100.0; } `; // 顶点着色器 // gl_Position vec4(0.0,0.0,0.0,1.0) x,y,z,w齐次坐标 (x/w,y/w,z/w) // gl_FragColor = vec4(1.0,0.0,0.0,1.0) r,g,b,a const FRAGMENT_SHADER_SOURCE = ` precision lowp float; void main() { // 计算距离 float dis = distance(gl_PointCoord, vec2(0.5,0.5)); if (dis > 0.5 || (dis < 0.4 && dis > 0.3) || dis < 0.2) { discard; } gl_FragColor = vec4(1.0,0.0,0.0,1.0); } `; // 片元着色器 // 创建着色器 const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE) gl.drawArrays(gl.POINTS, 0, 1); ``` ```JS function initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE) { const vertexShader = gl.createShader(gl.VERTEX_SHADER); const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(vertexShader, VERTEX_SHADER_SOURCE) // 指定顶点着色器的源码 gl.shaderSource(fragmentShader, FRAGMENT_SHADER_SOURCE) // 指定片元着色器的源码 // 编译着色器 gl.compileShader(vertexShader) gl.compileShader(fragmentShader) // 创建一个程序对象 const program = gl.createProgram(); gl.attachShader(program, vertexShader) gl.attachShader(program, fragmentShader) gl.linkProgram(program) gl.useProgram(program) return program; } ``` ![绘制流程](README.assets/绘制流程.png) ## 2.6 attribute 动态传入顶点数据 ```JS // 创建着色器源码 const VERTEX_SHADER_SOURCE = ` // 只传递顶点数据 // 变量声明 attribute vec4 aPosition; void main() { gl_Position = aPosition; // vec4(0.0,0.0,0.0,1.0) gl_PointSize = 30.0; } `; // 顶点着色器 const FRAGMENT_SHADER_SOURCE = ` void main() { gl_FragColor = vec4(1.0,0.0,0.0,1.0); } `; // 片元着色器 const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE) const aPosition = gl.getAttribLocation(program, 'aPosition'); // gl.vertexAttrib4f(aPosition, 0.5,0.5,0.0,1.0) // gl.vertexAttrib3f(aPosition, 0.5,0.5,0.0) // gl.vertexAttrib2f(aPosition, 0.5,0.5) let x = 0; setInterval(() => { x += 0.1; if (x > 1.0) { x = 0; } gl.vertexAttrib1f(aPosition, x) gl.drawArrays(gl.POINTS, 0, 1); }, 200) ``` ![attribute](README.assets/attribute.png) ## 2.7 通过鼠标绘制 ```JS // 创建着色器源码 const VERTEX_SHADER_SOURCE = ` // 只传递顶点数据 attribute vec4 aPosition; void main() { gl_Position = aPosition; // vec4(0.0,0.0,0.0,1.0) gl_PointSize = 10.0; } `; // 顶点着色器 const FRAGMENT_SHADER_SOURCE = ` void main() { gl_FragColor = vec4(1.0,0.0,0.0,1.0); } `; // 片元着色器 const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE) const aPosition = gl.getAttribLocation(program, 'aPosition'); const points = [] ctx.onclick = function(ev) { // 坐标 const x = ev.clientX const y = ev.clientY const domPosition = ev.target.getBoundingClientRect(); const domx = x - domPosition.left const domy = y - domPosition.top; /* 0 200 400 -1 0 1 -200 0 200 -1 0 1 需要先 -200 (当前画布的宽度) 然后再 除以 200 1 0 -1 0 200 400 200 0 -200 / 200 需要先让 200 减这个数,然后再 / 200 * */ const halfWidth = ctx.offsetWidth / 2 const halfHeight = ctx.offsetHeight / 2 const clickX = (domx - halfWidth) / halfWidth const clickY = (halfHeight - domy) / halfHeight points.push({ clickX, clickY }) for (let i = 0; i < points.length; i++) { gl.vertexAttrib2f(aPosition, points[i].clickX, points[i].clickY) gl.drawArrays(gl.POINTS, 0, 1); } } ``` 鼠标绘制