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博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/116696.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【教3妹学编程-java基础5】java多态详解

3妹&#xff1a;“太阳当空照&#xff0c;花儿对我笑&#xff0c;小鸟说早早早&#xff0c;你为什么背上炸药包” 2哥 :3妹&#xff0c;什么事呀这么开心呀。 3妹&#xff1a;2哥你看今天的天气多好啊&#xff0c;阳光明媚、万里无云、秋高气爽&#xff0c;适合秋游。 2哥&…

基于STM32HAL库看门狗(独立看门狗)-简述

目录 概述 一、开发环境 二、STM32CubeMx配置 三、编码 四、运行结果 五、总结 概述 一个成熟靠谱的项目&#xff0c;离不开“看门狗”的必选项&#xff0c;凡是人写的程序多少都会有出现bug的情况&#xff08;或芯片外设受外界干扰导致故障程序卡死、跑飞的情况&#xf…

vue基于ElementUI/Plus自定义的一些组件

vue3-my-ElementPlus 源码请到GitHub下载使用MyTable、MySelect、MyPagination 置顶|Top | 使用案例&#xff1a; 1.0 定义表格数据&#xff08;测试使用&#xff09; data() {return {tableData: [],value:[],valueList: [],}; },// 构造表格测试数据// 1 第一行&#xf…

重生奇迹mu召唤师怎么加点?

召唤师在重生奇迹mu游戏里面是一个智力型的职业&#xff0c;所以智力自然就成为主要加点属性&#xff0c;但是此职业却又算是近身攻击&#xff0c;因为她的技能范围并不算远&#xff0c;而且还是呈现出一种半径趋势&#xff0c;一方面是攻击伤害&#xff0c;另一方面则是辅助造…

Python 中的 Gzip 解压

我们将介绍Python中的gzip解压。 我们还将介绍如何使用 gzip 解压缩来解压缩压缩内容。 Python 中的 Gzip 解压 Python 中构建了许多用于压缩和解压缩目的的库&#xff0c;但我们将介绍 Gzip 库。 它是一种流行的数据压缩工具。 我们可以使用 gzip 通过将数据编码为人类无法读…

ruby语言怎么写个通用爬虫程序?

Ruby语言爬虫是指使用Ruby编写的网络爬虫程序&#xff0c;用于自动化地从互联网上获取数据。其中&#xff0c;CRawler是一个基于文本的小型地牢爬虫&#xff0c;它被设计为可扩展&#xff0c;所有游戏数据均通过JSON文件提供&#xff0c;程序仅处理游戏引擎。除此之外&#xff…

【Java对象】一文读懂 Java 对象庐山真面目及指针压缩

文章目录 版本及工具介绍Java 对象结构对象头mark word 标记字mark word 标记字解析Lock Record class point 类元数据指针 实例数据对齐填充为什么需要对齐填充 常见 Java 数据类型对象分析ArrayListLongStringByteBoolean 其它指针压缩前置知识&#xff1a;32位操作系统为什么…

音频修复增强软件iZotope RX 10 mac中文特点

iZotope RX 10 mac是一款音频修复和增强软件。 iZotope RX 10 mac主要特点 声音修复&#xff1a;iZotope RX 10可以去除不良噪音、杂音、吱吱声等&#xff0c;使音频变得更加清晰干净。 音频增强&#xff1a;iZotope RX 10支持对音频进行音量调节、均衡器、压缩器、限制器等处…

宠物医院服务预约小程序的效果如何

随着养宠家庭增多及对爱宠的照顾加深&#xff0c;除了食品、服饰外&#xff0c;宠物医院近些年也迎来了较高发展&#xff0c;部分城市甚至聚集着众多品牌&#xff0c;以单店或多店品牌的方式拓展市场。 对宠物医院来说&#xff0c;一般都是拓展同市客户&#xff0c;或者多门店…

MongDB 的安装 无废话

MongDB 的安装 1 安装 MongDB https://www.mongodb.com/try/download/community-kubernetes-operator 这里我们选择 ZIP 解压到文件夹 创建 data 文件 在 data 文件夹里面创建 db 和 logs 文件夹 进入 bin 目录 输入 cmd 回车 2 启动 MongDB 输入启动命令 mongod --dbpath..\…

Technology strategy Pattern 学习笔记3-Creating the Strategy-Industry context

Creating the Strategy-Industry context 1 SWOT 1.1 create steps 1.与内部各方沟通 了解企业的人、流程和技术&#xff0c;包括与其它企业的不同了解哪些创新可以做竞争者及市场信息企业可以支撑的类似业务 按SWOT四象限分类&#xff0c;先做列表后放入象限 1.2 四象限…

sql server 对称加密例子,很好用

-- 创建对称密钥 CREATE MASTER KEY ENCRYPTION BY PASSWORD 输入一个对称密钥; -- 创建证书 CREATE CERTIFICATE MyCertificate WITH SUBJECT 创建一个证书名称; -- 创建对称密钥的加密密钥 CREATE SYMMETRIC KEY MySymmetricKey WITH ALGORITHM AES_128 ENCRY…

E-Office(泛微OA)前台任意文件读取漏洞复现

简介 泛微E-Office是一款企业级的全流程办公自动化软件&#xff0c;它包括协同办公、文档管理、知识管理、工作流管理等多个模块&#xff0c;涵盖了企业日常工作中的各个环节。在该产品前台登录页存在文件读取漏洞。 officeserver.php文件存在任意文件读取漏洞&#xff0c;通…

「图像 cv2.seamlessClone」无中生有制造数据

上一篇博客【「图像 merge」无中生有制造数据 】写的是图片直接融合&#xff0c;此方法生成的图片相对而言比较生硬&#xff0c;虽然目标图片已经透明化处理过了&#xff0c;但是生成的图片依旧很假 除了上述上述的图片叠加融合之外&#xff0c;还有一种更加自然的融合方法&…

通过51单片机控制28byj48步进电机按角度正反转旋转

一、前言 本项目基于STC89C52单片机&#xff0c;通过控制28BYJ-48步进电机实现按角度正反转旋转的功能。28BYJ-48步进电机是一种常用的电机&#xff0c;精准定位和高扭矩输出&#xff0c;适用于许多小型的自动化系统和机械装置。 在这个项目中&#xff0c;使用STC89C52单片机…

1822_使用python内置的库进行日期序列的生成

使用python的内置的库进行日期序列的生成 用到的库介绍 datetime 实现这样的功能其实只需要这一个库就够了&#xff0c;但是网络上找到的例程很多都额外增加了对time库的引用。只能说&#xff0c;这样不会出现错误&#xff0c;但是这样肯定会有一些计算资源上的消耗。 #!/u…

QT之多个界面相互切换 (stackedWidget控件)

TOC Chapter1 QT之多个界面相互切换 (stackedWidget控件) 原文链接 stackedWidget控件&#xff1a; 可以自由在多个widget切换&#xff0c;可以通过点击顶部菜单&#xff0c;显示不同界面&#xff0c;在实际开发中应用很广泛。 QStackedWidget是一个堆栈窗口控件&#xff0c…

字符型液晶显示器LCD 1602的显示控制(Keil+Proteus)

前言 趁机把LCD 1602的实验完成了&#xff0c;那个电路图有几个地方没弄懂&#xff0c;但是去掉也没有报错&#xff0c;就没管了。 LCD1602_百度百科 (baidu.com)https://baike.baidu.com/item/LCD1602/6014393?frge_ala LCD1602液晶显示屏通过电压来改变填充在两块平行板之…

“宽带中国”工具变量—海拔标准差数据集

参照刘传明&#xff08;2020&#xff09;、金环&#xff08;2021&#xff09;、胡浩然&#xff08;2023&#xff09;等的做法&#xff0c;将地级市-海拔标准差数据&#xff0c;作为“宽带中国”试点政策的工具变量 ➤相关性&#xff1a;地形起伏度会影响网络基础设施建设&…

京东数据平台:2023年Q3季度黄金市场数据分析

继9月国内黄金市场持续上涨后&#xff0c;进入10月中下旬后&#xff0c;黄金行情再度反转&#xff0c;多家品牌金饰价格再次突破600元/克&#xff0c;达到611元/克。 今年以来&#xff0c;黄金行情不断走俏&#xff0c;销售市场也有明显增长。根据鲸参谋平台的数据显示&#xf…