WebGL:基础练习 / 简单学习 / demo / canvas3D
一、前置内容
canvas:理解canvas / 基础使用 / 实用demo-CSDN博客
WebGL:开始学习 / 理解 WebGL / WebGL 需要掌握哪些知识 / 应用领域 / 前端值得学WebGL吗_webgl培训-CSDN博客
二、在线运行HTML
用来运行WebGL代码,粘贴--运行(有时候不太好用,莫名报错)
在线运行Html5
三、获取画布、获取上下文环境对象
//获取画布元素
var canvas = document.getElementById('canvas')
//获取到元素的上下文环境对象
var webgl = canvas.getContext('webgl')
三、WebGL练习
demo来至AI
3.1、绘制正方形
在这个 Demo 中,我们首先获取了 WebGL 上下文,然后定义了一个顶点着色器和一个片元着色器。接着,我们创建了着色器程序对象,并将顶点着色器和片元着色器附加到这个程序对象上,并进行链接。
然后,我们创建了一个顶点缓冲区,并将顶点坐标存储在这个缓冲区中。我们启用了顶点属性,并将顶点缓冲区对象绑定到这个属性上。
接下来,我们设置了视口大小,并清空了画布。最后,我们使用 gl.drawArrays() 方法绘制了一个正方形。
需要注意的是,绘制图形时,我们使用的是 gl.TRIANGLE_FAN,它表示绘制一个三角形扇形,也就是一个由五个三角形组成的正方形。这样可以减少绘制的顶点数量,提高性能。
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>WebGL 基础 Demo</title><style>canvas {border: 1px solid black;}</style>
</head>
<body><canvas id="canvas" width="500" height="500"></canvas><script>// 获取 WebGL 上下文const canvas = document.getElementById('canvas');const gl = canvas.getContext('webgl');// 定义顶点着色器代码const vertexShaderCode = `attribute vec3 a_position;void main() {gl_Position = vec4(a_position, 1.0);}`;// 定义片元着色器代码const fragmentShaderCode = `precision mediump float;void main() {gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);}`;// 创建顶点着色器对象const vertexShader = gl.createShader(gl.VERTEX_SHADER);gl.shaderSource(vertexShader, vertexShaderCode);gl.compileShader(vertexShader);// 创建片元着色器对象const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);gl.shaderSource(fragmentShader, fragmentShaderCode);gl.compileShader(fragmentShader);// 创建着色器程序对象const shaderProgram = gl.createProgram();gl.attachShader(shaderProgram, vertexShader);gl.attachShader(shaderProgram, fragmentShader);gl.linkProgram(shaderProgram);// 获取着色器变量位置const positionLocation = gl.getAttribLocation(shaderProgram, 'a_position');// 创建顶点数据const vertices = [-0.5, -0.5, 0.0,0.5, -0.5, 0.0,0.5, 0.5, 0.0,-0.5, 0.5, 0.0];// 创建顶点缓冲区对象const vertexBuffer = gl.createBuffer();// 绑定缓冲区对象gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);// 将数据写入缓冲区对象gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);// 启用顶点属性gl.enableVertexAttribArray(positionLocation);// 将缓冲区对象绑定到顶点属性上gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);// 设置视口gl.viewport(0, 0, canvas.width, canvas.height);// 清空画布gl.clearColor(0.0, 0.0, 0.0, 1.0);gl.clear(gl.COLOR_BUFFER_BIT);// 使用着色器gl.useProgram(shaderProgram);// 绘制图形gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);</script>
</body>
</html>

3.2、清屏
这个 Demo 创建了一个空的 WebGL 上下文并在 canvas 上进行了清屏操作。可以通过更改 clearColor() 的参数来修改屏幕上的颜色。
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>WebGL Demo</title><style>html, body {margin: 0;padding: 0;height: 100%;overflow: hidden;}canvas {width: 100%;height: 100%;}</style></head><body><canvas id="canvas"></canvas><script>const canvas = document.getElementById('canvas');const gl = canvas.getContext('webgl');gl.clearColor(0.0, 0.0, 0.0, 1.0);gl.clear(gl.COLOR_BUFFER_BIT);</script></body>
</html>

3.3、WebGL 三角形渲染
它包括以下步骤:
获取 canvas 元素和 WebGL 上下文对象。
定义顶点着色器和片段着色器。
创建顶点着色器和片段着色器对象。
创建着色器程序对象。
定义三角形顶点坐标并写入缓冲区。
获取顶点着色器中 aPosition 的地址并启用。
清除画布并绘制三角形。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>WebGL Demo</title>
</head>
<body><canvas id="glCanvas" width="640" height="480"></canvas><script>function init() {// 获取 canvas 元素var canvas = document.getElementById("glCanvas");// 获取 WebGL 上下文var gl = canvas.getContext("webgl");// 定义顶点着色器var vertexShaderSource = `attribute vec3 aPosition;void main() {gl_Position = vec4(aPosition, 1.0);}`;// 定义片段着色器var fragmentShaderSource = `void main() {gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);}`;// 创建顶点着色器var vertexShader = gl.createShader(gl.VERTEX_SHADER);gl.shaderSource(vertexShader, vertexShaderSource);gl.compileShader(vertexShader);// 创建片段着色器var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);gl.shaderSource(fragmentShader, fragmentShaderSource);gl.compileShader(fragmentShader);// 创建着色器程序var program = gl.createProgram();gl.attachShader(program, vertexShader);gl.attachShader(program, fragmentShader);gl.linkProgram(program);gl.useProgram(program);// 定义三角形顶点坐标var vertices = [0.0, 0.5, 0.0,-0.5, -0.5, 0.0,0.5, -0.5, 0.0];// 创建缓冲区并写入数据var vertexBuffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);// 获取顶点着色器中 aPosition 的地址var aPosition = gl.getAttribLocation(program, "aPosition");gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, 0, 0);gl.enableVertexAttribArray(aPosition);// 清除画布并绘制三角形gl.clearColor(0.0, 0.0, 0.0, 1.0);gl.clear(gl.COLOR_BUFFER_BIT);gl.drawArrays(gl.TRIANGLES, 0, 3);}init();</script>
</body>
</html>

3.4、WebGL 绘制了一个红色的三角形
WebGL 绘制了一个红色的三角形,该三角形的顶点坐标分别为 (0.0, 0.5)、(-0.5, -0.5) 和 (0.5, -0.5)。在绘制过程中,我们首先编译和链接了顶点着色器和片元着色器,并创建了一个着色器程序。然后我们创建了一个顶点缓冲,并将顶点数据绑定到该缓冲上。接下来我们通过顶点属性将顶点数据传递给顶点着色器,在片元着色器中设置了颜色,并通过调用 gl.drawArrays(gl.TRIANGLES, 0, 3) 绘制了该三角形。
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title>WebGL Demo</title><style>canvas {border: 1px solid black;}</style></head><body><canvas id="my-canvas" width="500" height="500"></canvas><script>const canvas = document.getElementById('my-canvas');const gl = canvas.getContext('webgl');// 定义顶点着色器const vertexShader = gl.createShader(gl.VERTEX_SHADER);gl.shaderSource(vertexShader, `attribute vec4 a_position;void main() {gl_Position = a_position;}`);gl.compileShader(vertexShader);// 定义片元着色器const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);gl.shaderSource(fragmentShader, `precision mediump float;uniform vec4 u_color;void main() {gl_FragColor = u_color;}`);gl.compileShader(fragmentShader);// 创建着色器程序const program = gl.createProgram();gl.attachShader(program, vertexShader);gl.attachShader(program, fragmentShader);gl.linkProgram(program);gl.useProgram(program);// 定义顶点数据const vertices = [0.0, 0.5,-0.5, -0.5,0.5, -0.5,];// 创建顶点缓冲const buffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, buffer);gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);// 绑定顶点属性const positionAttributeLocation = gl.getAttribLocation(program, 'a_position');gl.enableVertexAttribArray(positionAttributeLocation);gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);// 设置颜色const colorUniformLocation = gl.getUniformLocation(program, 'u_color');gl.uniform4f(colorUniformLocation, 1.0, 0.0, 0.0, 1.0);// 清空画布gl.clearColor(0.0, 0.0, 0.0, 1.0);gl.clear(gl.COLOR_BUFFER_BIT);// 绘制三角形gl.drawArrays(gl.TRIANGLES, 0, 3);</script></body>
</html>

3.5、WebGL 绘制颜色渐变矩形
在这个 Demo 中,我们首先创建了一个 WebGL 上下文,并定义了一个顶点着色器和一个片元着色器。接着,我们创建了一个着色器程序对象,并将顶点着色器和片元着色器附加到这个程序对象上,并进行链接。
然后,我们创建了一个顶点缓冲区,并将顶点坐标存储在这个缓冲区中。我们还设置了视图和投影矩阵,并使用着色器程序。接下来,我们启用了顶点属性,并将顶点缓冲区绑定到这个属性上。最后,我们使用 gl.drawArrays() 方法绘制了一个矩形。
在片元着色器中,我们使用了 mix() 函数来计算每个像素的颜色,从而实现了颜色渐变效果。我们还定义了两个 uniform 变量 u_colorA 和 u_colorB,用于控制矩形的颜色。
在这个 Demo 中,我们只是绘制了一个简单的颜色渐变矩形,但你可以根据需要对其进行修改和扩展。
<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title>WebGL Demo</title><script type="text/javascript">window.onload = function() {const canvas = document.getElementById("canvas");const gl = canvas.getContext("webgl");// 顶点着色器代码const vertexShaderSource = `attribute vec2 a_position;void main() {gl_Position = vec4(a_position, 0.0, 1.0);}`;// 片元着色器代码const fragmentShaderSource = `precision mediump float;uniform vec4 u_colorA;uniform vec4 u_colorB;void main() {gl_FragColor = mix(u_colorA, u_colorB, gl_FragCoord.y / 500.0);}`;// 创建顶点着色器对象const vertexShader = gl.createShader(gl.VERTEX_SHADER);gl.shaderSource(vertexShader, vertexShaderSource);gl.compileShader(vertexShader);// 创建片元着色器对象const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);gl.shaderSource(fragmentShader, fragmentShaderSource);gl.compileShader(fragmentShader);// 创建着色器程序对象const program = gl.createProgram();gl.attachShader(program, vertexShader);gl.attachShader(program, fragmentShader);gl.linkProgram(program);// 获取顶点着色器中的变量位置const positionLocation = gl.getAttribLocation(program, "a_position");// 创建顶点缓冲区const positionBuffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);const positions = [0, 0,0, 500,500, 0,500, 500,];gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);// 设置视图和投影矩阵gl.viewport(0, 0, canvas.width, canvas.height);gl.clearColor(0, 0, 0, 1);gl.clear(gl.COLOR_BUFFER_BIT);// 使用着色器程序gl.useProgram(program);// 启用顶点属性gl.enableVertexAttribArray(positionLocation);// 将顶点缓冲区绑定到顶点属性gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);// 设置 uniform 变量const colorALocation = gl.getUniformLocation(program, 'u_colorA');const colorBLocation = gl.getUniformLocation(program, 'u_colorB');gl.uniform4f(colorALocation, 1, 0, 0, 1);gl.uniform4f(colorBLocation, 0, 0, 1, 1);// 绘制矩形gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);};</script><style>canvas {border: 1px solid black;}</style></head><body><canvas id="canvas" width="500" height="500"></canvas></body>
</html>

3.6、绘制一个彩色三角形
<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title>WebGL Demo</title><style>body {margin: 0;padding: 0;}#glcanvas {width: 100vw;height: 100vh;display: block;}</style></head><body><canvas id="glcanvas"></canvas><script>const canvas = document.querySelector("#glcanvas");const gl = canvas.getContext("webgl");const vertexShaderSource = `attribute vec3 aPosition;attribute vec3 aColor;varying vec3 vColor;void main() {gl_Position = vec4(aPosition, 1.0);vColor = aColor;}`;const fragmentShaderSource = `precision mediump float;varying vec3 vColor;void main() {gl_FragColor = vec4(vColor, 1.0);}`;const shaderProgram = createShaderProgram(gl, vertexShaderSource, fragmentShaderSource);const positionAttributeLocation = gl.getAttribLocation(shaderProgram, "aPosition");const colorAttributeLocation = gl.getAttribLocation(shaderProgram, "aColor");const positionBuffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);const positions = [-0.5, 0.5, 0.0, 0.5, 0.5, 0.0, 0.0, -0.5, 0.0];gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);const colorBuffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);const colors = [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0];gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);function createShaderProgram(gl, vertexShaderSource, fragmentShaderSource) {const vertexShader = gl.createShader(gl.VERTEX_SHADER);gl.shaderSource(vertexShader, vertexShaderSource);gl.compileShader(vertexShader);if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {console.log("Error compiling vertex shader:", gl.getShaderInfoLog(vertexShader));return null;}const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);gl.shaderSource(fragmentShader, fragmentShaderSource);gl.compileShader(fragmentShader);if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {console.log("Error compiling fragment shader:", gl.getShaderInfoLog(fragmentShader));return null;}const shaderProgram = gl.createProgram();gl.attachShader(shaderProgram, vertexShader);gl.attachShader(shaderProgram, fragmentShader);gl.linkProgram(shaderProgram);if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {console.log("Error linking shader program:", gl.getProgramInfoLog(shaderProgram));return null;}return shaderProgram;}function render() {gl.clearColor(0.0, 0.0, 0.0, 1.0);gl.clear(gl.COLOR_BUFFER_BIT);gl.useProgram(shaderProgram);gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);gl.enableVertexAttribArray(positionAttributeLocation);gl.vertexAttribPointer(positionAttributeLocation, 3, gl.FLOAT, false, 0, 0);gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);gl.enableVertexAttribArray(colorAttributeLocation);gl.vertexAttribPointer(colorAttributeLocation, 3, gl.FLOAT, false, 0, 0);gl.drawArrays(gl.TRIANGLES, 0, 3);}requestAnimationFrame(render);</script></body>
</html>

3.7、旋转的立方体
本例的代码中,我们使用 THREE.js 库创建了一个场景,相机和渲染器。我们还创建了一个立方体,并将其添加到场景中。最后,我们创建了一个动画函数,使立方体绕 X 和 Y 轴旋转,并在每个帧中更新渲染器。
运行上面的代码,您将在浏览器中看到一个绿色的立方体,它在不断旋转。
<!DOCTYPE html>
<html>
<head><title>WebGL Demo</title><script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script><style>body { margin: 0; }canvas { width: 100%; height: 100%; display: block; }</style>
</head>
<body><script>// 初始化场景var scene = new THREE.Scene();// 初始化相机var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);camera.position.z = 5;// 初始化渲染器var renderer = new THREE.WebGLRenderer();renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);// 创建立方体var geometry = new THREE.BoxGeometry();var material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });var cube = new THREE.Mesh(geometry, material);scene.add(cube);// 创建动画function animate() {requestAnimationFrame(animate);cube.rotation.x += 0.01;cube.rotation.y += 0.01;renderer.render(scene, camera);}animate();</script>
</body>
</html>

3.8、彩色三角形
获取 WebGL 上下文;
编写顶点着色器和片元着色器代码;
初始化着色器程序和获取 attribute 变量和 uniform 变量的位置;
准备顶点数据和颜色数据,并创建对应的缓冲区;
设置绘制参数,包括启用 attribute 位置、绑定缓冲区和设置指针;
设置投影矩阵和模型视图矩阵,并绘制三角形。
<!DOCTYPE html>
<html>
<head><title>WebGL Demo</title><script src="https://cdn.bootcdn.net/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"></script>
</head>
<body><canvas id="canvas" width="800" height="600"></canvas><script>const canvas = document.getElementById('canvas');const gl = canvas.getContext('webgl');if (!gl) {alert('WebGL not supported.');}// 顶点着色器代码const vsSource = `attribute vec4 aVertexPosition;attribute vec4 aVertexColor;uniform mat4 uModelViewMatrix;uniform mat4 uProjectionMatrix;varying lowp vec4 vColor;void main() {gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;vColor = aVertexColor;}`;// 片元着色器代码const fsSource = `varying lowp vec4 vColor;void main() {gl_FragColor = vColor;}`;// 初始化着色器程序const shaderProgram = initShaderProgram(gl, vsSource, fsSource);// 获取 attribute 变量和 uniform 变量的位置const programInfo = {program: shaderProgram,attribLocations: {vertexPosition: gl.getAttribLocation(shaderProgram, 'aVertexPosition'),vertexColor: gl.getAttribLocation(shaderProgram, 'aVertexColor'),},uniformLocations: {projectionMatrix: gl.getUniformLocation(shaderProgram, 'uProjectionMatrix'),modelViewMatrix: gl.getUniformLocation(shaderProgram, 'uModelViewMatrix'),},};// 设置顶点数据const positions = [0, 0.5, 0,-0.5, -0.5, 0,0.5, -0.5, 0,];const colors = [1, 0, 0, 1,0, 1, 0, 1,0, 0, 1, 1,];// 创建顶点缓冲区const positionBuffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);const colorBuffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);// 设置绘制参数gl.enableVertexAttribArray(programInfo.attribLocations.vertexPosition);gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);gl.vertexAttribPointer(programInfo.attribLocations.vertexPosition, 3, gl.FLOAT, false, 0, 0);gl.enableVertexAttribArray(programInfo.attribLocations.vertexColor);gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);gl.vertexAttribPointer(programInfo.attribLocations.vertexColor, 4, gl.FLOAT, false, 0, 0);gl.useProgram(programInfo.program);// 设置投影矩阵和模型视图矩阵const projectionMatrix = mat4.create();mat4.perspective(projectionMatrix, 45 * Math.PI / 180, canvas.width / canvas.height, 0.1, 100.0);const modelViewMatrix = mat4.create();mat4.translate(modelViewMatrix, modelViewMatrix, [-0.0, 0.0, -3.0]);// 绘制gl.uniformMatrix4fv(programInfo.uniformLocations.projectionMatrix, false, projectionMatrix);gl.uniformMatrix4fv(programInfo.uniformLocations.modelViewMatrix, false, modelViewMatrix);gl.drawArrays(gl.TRIANGLES, 0, 3);// 初始化着色器程序函数function initShaderProgram(gl, vsSource, fsSource) {const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);const shaderProgram = gl.createProgram();gl.attachShader(shaderProgram, vertexShader);gl.attachShader(shaderProgram, fragmentShader);gl.linkProgram(shaderProgram);if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {alert('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram));return null;}return shaderProgram;}// 加载着色器函数function loadShader(gl, type, source) {const shader = gl.createShader(type);gl.shaderSource(shader, source);gl.compileShader(shader);if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader));gl.deleteShader(shader);return null;}return shader;}</script>
</body>
</html>

3.9、绘制圆形
获取 canvas 元素和绘图上下文
定义 顶点着色器 和 片元着色器,顶点着色器用于处理顶点数据,片元着色器用于处理每个像素的颜色值
创建 顶点着色器 和 片元着色器,并编译
创建 程序对象,并将 顶点着色器 和 片元着色器 附加到程序对象上
链接程序对象,并使用
定义圆形顶点数据(分割成 n 个三角形)
创建缓冲对象并绑定到目标上
向缓冲对象写入数据
获取 属性变量 位置
设置 属性变量,并启用
获取 uniform 变量位置
设置背景颜色
清空画布
绘制圆形
这个 demo 绘制了一个红色的圆形。
<!DOCTYPE html>
<html>
<head><title>WebGL Demo</title><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /><script src="https://cdn.bootcdn.net/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"></script><script type="text/javascript">window.onload = function () {// 获取 canvas 元素var canvas = document.getElementById('myCanvas');// 获取绘图上下文var gl = canvas.getContext('webgl');// 定义顶点着色器var vertexShaderSource = `attribute vec4 a_Position;void main() {gl_Position = a_Position;}`;// 定义片元着色器var fragmentShaderSource = `precision mediump float;uniform vec4 u_FragColor;void main() {gl_FragColor = u_FragColor;}`;// 创建顶点着色器var vertexShader = gl.createShader(gl.VERTEX_SHADER);gl.shaderSource(vertexShader, vertexShaderSource);gl.compileShader(vertexShader);// 创建片元着色器var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);gl.shaderSource(fragmentShader, fragmentShaderSource);gl.compileShader(fragmentShader);// 创建程序对象var program = gl.createProgram();gl.attachShader(program, vertexShader);gl.attachShader(program, fragmentShader);gl.linkProgram(program);gl.useProgram(program);// 定义圆形顶点数据var circleVertices = [];var r = 0.5; // 半径var centerX = 0; // 圆心 X 坐标var centerY = 0; // 圆心 Y 坐标var n = 360; // 分割成 n 个三角形,每个三角形有三个顶点var angle = 0;for (var i = 0; i < n; i++) {circleVertices.push(centerX, centerY, 0);circleVertices.push(centerX + r * Math.cos(angle), centerY + r * Math.sin(angle), 0);angle += 2 * Math.PI / n;circleVertices.push(centerX + r * Math.cos(angle), centerY + r * Math.sin(angle), 0);}// 创建缓冲对象并绑定到目标var buffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, buffer);// 向缓冲对象写入数据var vertices = new Float32Array(circleVertices);gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);// 获取属性变量位置var a_Position = gl.getAttribLocation(program, 'a_Position');gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, 0, 0);gl.enableVertexAttribArray(a_Position);// 获取 uniform 变量位置var u_FragColor = gl.getUniformLocation(program, 'u_FragColor');// 设置背景颜色gl.clearColor(0.9, 0.9, 0.9, 1.0);// 清空画布gl.clear(gl.COLOR_BUFFER_BIT);// 绘制圆形gl.uniform4f(u_FragColor, 1.0, 0.0, 0.0, 1.0); // 设置颜色(红色)gl.drawArrays(gl.TRIANGLES, 0, circleVertices.length / 3);};</script>
</head>
<body><canvas id="myCanvas" width="400" height="400"></canvas>
</body>
</html>

四、过程记录
记录一、WebGL是基于canvas吗
WebGL是基于HTML5中的canvas元素的。WebGL使用OpenGL ES 2.0规范来编写3D图形。WebGL的API允许JavaScript在canvas元素上绘制各种类型的3D图像,并使用GPU加速。所以,可以说WebGL是基于canvas,但它使用了更高级的图形处理技术来实现复杂的3D图像。
记录二、理解 canvas3D
canvas3D是HTML5的一个新特性,它提供了对3D图形的支持,使得在网页上实现3D效果成为可能。canvas3D是基于WebGL实现的,WebGL是一种基于OpenGL ES 2.0的图形库,它可以在网页中实现高性能的3D图形渲染。
使用canvas3D,您可以创建和操作3D对象、应用材质和贴图、添加光照和阴影等等。它提供了一组丰富的API,可以用于绘制和操作3D图形,包括对物体的旋转、缩放、平移等操作。
虽然canvas3D目前还处于实验阶段,但它已经得到了许多浏览器的支持,未来可能会成为HTML5标准的一部分。如果您对3D图形编程感兴趣,可以尝试使用canvas3D来实现您的项目。
----文心一言
五、欢迎交流指正
六、参考链接
什么是WebGL? | 码上动力
【精选】【WebGL】简单入门教程_webgl教程-CSDN博客
相关文章:
WebGL:基础练习 / 简单学习 / demo / canvas3D
一、前置内容 canvas:理解canvas / 基础使用 / 实用demo-CSDN博客 WebGL:开始学习 / 理解 WebGL / WebGL 需要掌握哪些知识 / 应用领域 / 前端值得学WebGL吗_webgl培训-CSDN博客 二、在线运行HTML 用来运行WebGL代码,粘贴--运行ÿ…...
Python基础入门例程44-NP44 判断列表是否为空(条件语句)
最近的博文: Python基础入门例程43-NP43 判断布尔值(条件语句)-CSDN博客 Python基础入门例程42-NP42 公式计算器(运算符)-CSDN博客 Python基础入门例程41-NP41 二进制位运算(运算符)-CSDN博客…...
【每日一题Day369】LC187重复的DNA序列 | 字符串哈希
重复的DNA序列【LC187】 DNA序列 由一系列核苷酸组成,缩写为 A, C, G 和 T.。 例如,"ACGAATTCCG" 是一个 DNA序列 。 在研究 DNA 时,识别 DNA 中的重复序列非常有用。 给定一个表示 DNA序列 的字符串 s ,返回所有在 DNA…...
服务器密码机主要功能及特点 安当加密
服务器密码机的主要功能包括: 数据加密:密码机使用各种加密算法对数据进行加密,确保只有拥有正确密钥的接收者才能解密和查看数据。数据解密:密码机使用相应的解密算法和密钥对已加密的数据进行解密,使其恢复成原始数据…...
RIP路由配置
RIP路由配置步骤与命令: 1.启用RIP路由:router rip 2.通告直连网络:network 直连网络 3.启用RIPv2版本:version 2 4.禁用自动汇总:no auto-summary 注意:静态路由通告远程网络,动态路由通告…...
尚硅谷Docker基础篇和Dockerfile超详细整合笔记
Docker基础篇DockerFile Docker:您要如何确保应用能够在这些环境中运行和通过质量检测?并且在部署过程中不出现令人头疼的版本、配置问题,也无需重新编写代码和进行故障修复?而这个就是使用容器。Docker解决了运行环境和配置问题…...
JavaScript_Date对象_实例方法_get类
计算这一年还剩多少天: <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0"> <title>Document&…...
Go语言在区块链开发中的应用
引言 区块链是近年来备受关注的技术领域,它不仅改变了传统的数据交换和存储方式,还为各种应用场景提供了全新的解决方案。而Go语言(Golang)作为一门简洁、高效的编程语言,正逐渐成为开发区块链应用的首选语言。本文将…...
S4.2.4.5 Fast Training Sequence (FTS)
一 本章节主讲知识点 1.1 FTS的用途和实现注意 二 本章节原文翻译 Fast Training Sequence (FTS) 主要用于在L0s->L0跳转的过程中,让Receiver 检测到电气空闲退出,以及实现bit 和 symbol lock。 2.1 Gen1 and Gen2 速率 对于Gen1/2 FTS的组成如下…...
Gitlab CICD实用技巧汇总
关于.gitlab-ci.yml的实用配置 1、stage参数 stages: - build - test - deploy 相同stage的作业会并行执行,有一个失败,则认为这个stage失败。 不同stage的作业会按序执行,前面stage有失败,后续stage不会继续执行。 可以使用ne…...
JavaSpringbootMySQL高校实训管理平台01557-计算机毕业设计项目选题推荐(附源码)
目 录 摘要 1 绪论 1.1 研究背景 1.2 研究意义 1.3论文结构与章节安排 2 高校实训管理平台系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据增加流程 2.2.2 数据修改流程 2.2.3 数据删除流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能性分析 2.4 系…...
初阶JavaEE(14)表白墙程序
接上次博客:初阶JavaEE(13)(安装、配置:Smart Tomcat;访问出错怎么办?Servlet初识、调试、运行;HttpServlet:HttpServlet;HttpServletResponse)-C…...
算法设计与分析第二章作业
1. 描述最大字段和的分治算法 题目 思路 判断最大子段和,可以用分治的思想,每次将序列一分为二,选择两个序列的最大子段和。 但是这里还有一种可能,就是子段可以横跨两个子序列,所以我们的最大子段和就是࿱…...
《视觉SLAM十四讲》-- 三维空间的刚体运动
文章目录 02 三维空间的刚体运动2.0 机器人位姿表述2.1 点和坐标系2.1.1 三维坐标系有关表述2.1.2 坐标系变换 2.2 旋转向量和欧拉角2.2.1 旋转向量2.2.2 欧拉角 2.3 四元数2.3.1 四元数的定义2.3.2 四元数的计算2.3.3 四元数表示旋转2.3.4 四元数与其他旋转表示法的转换 2.4 相…...
关于iOS:如何使用SwiftUI调整图片大小?
How to resize Image with SwiftUI? 我在Assets.xcassets中拥有很大的形象。 如何使用SwiftUI调整图像大小以缩小图像? 我试图设置框架,但不起作用: 1 2 Image(room.thumbnailImage) .frame(width: 32.0, height: 32.0) 在Image上应用…...
【MySQL】数据库MySQL基础知识与操作
作者主页:paper jie_博客 本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。 本文录入于《MySQL》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造&a…...
vim手册(vim cheatsheet)
vim手册(vim cheatsheet) 1. 命令模式 1). 移动光标 在命令模式下,可以使用以下命令来移动光标: - h:向左移动一个字符。 - j:向下移动一行。 - k:向上移动一行。 - l:向右移动一个…...
软件测试具体人员分工
最近看了点敏捷测试的东西,看得比较模糊。一方面是因为没有见真实的环境与流程,也许它跟本就没有固定的模式与流程,它就像告诉人们要“勇敢”“努力”。有的人在勇敢的面对生活,有些人在勇敢的挑战自我,有些人在勇敢的…...
计算机网络-应用层
文章目录 应用层协议原理万维网和HTTP协议万维网概述统一资源定位符HTML文档 超文本传输协议(HTTP)HTTP报文格式请求报文响应报文cookie 万维网缓存与代理服务器 DNS系统域名空间域名服务器和资源记录域名解析过程递归查询迭代查询 动态主机配置协议&…...
linux 创建git项目并提交到gitee(保姆式教程)
01、git安装与初始化设置 mhzzjmhzzj-virtual-machine:~/work/skynetStudy$ apt install mhzzjmhzzj-virtual-machine:~/work/skynetStudy$ git config --global user.name "用户名" mhzzjmhzzj-virtual-machine:~/work/skynetStudy$ git config --global user.ema…...
《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...
【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝
目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为:一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
