WebGL:基础练习 / 简单学习 / demo / canvas3D

news2024/11/26 16:37:59

一、前置内容

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Flutter 06 动画

一、动画基本原理以及Flutter动画简介 1、动画原理&#xff1a; 在任何系统的Ul框架中&#xff0c;动画实现的原理都是相同的&#xff0c;即&#xff1a;在一段时间内&#xff0c;快速地多次改变Ul外观&#xff1b;由于人眼会产生视觉暂留&#xff0c;所以最终看到的就是一个…

算法:弗洛里德算法Floyd

弗洛里德算法 简介 英文名Floyd 作用&#xff1a;寻找图中任意两点之间的最短路径 数据结构&#xff1a;邻接矩阵&#xff08;二维数组&#xff09; 思想 如果说从start到end之间转个弯能使得路径变短,那么就记录更短的路径&#xff0c; 对所有弯都试一下没到最后取最短的&am…

Zabbix监控联想服务器的配置方法

简介 图片 随着科技的发展&#xff0c;对于数据的敏感和安全大部分取决于对硬件性能、故障预判的监测&#xff0c;由此可见实时监测保障硬件的安全很重要&#xff0c;从而衍生了很多对硬件的监测软件&#xff0c;Zabbix就一个不错的选择。开源 开源 开源&#xff01; zabbix是…

SpringCloud(八) Gateway网关路由详解

目录 一, Gateway服务网关 1.1 为什么需要网关 1.2 网关的实现方式 1.3 Gateway快速入门 1. 创建gateway服务,引入依赖 2. 编写启动类 3. 编写基础配置和路由规则 4. 重启测试 5. 网关路由的流程图 6. 总结 二, Gateway断言工厂 三, 过滤器工厂 3.1 路由过滤器…

【Mysql】Mysql中表连接的原理

连接简介 在实际工作中&#xff0c;我们需要查询的数据很可能不是放在一张表中&#xff0c;而是需要同时从多张表中获取。下面我们以简单的两张表为例来进行说明。 连接的本质 为方便测试说明&#xff0c;&#xff0c;先创建两个简单的表并给它们填充一点数据&#xff1a; …

【Truffle】三、可视化测试报告的生成

在truffle中&#xff0c;我们可以引入第三方插件&#xff0c;对truffle的测试进行更好的提升&#xff0c;这里介绍两个插件&#xff0c;分别是mocha-junit-reporter和mochawesome两个插件。 一、mocha-junit-reporter插件 mocha-junit-reporter是一个用于Truffle测试框架的插件…

随机森林算法的加速:OpenMP方法

使用OpenMP加速随机森林 前言使用OpenMP对RF训练的加速代码加速效果 对特征重要性评估的加速代码 加速效果附录Windows中使用OpenMPLinux中使用OpenMP 项目主页&#xff1a;randomforest C implementation of random forests classification, regression, proximity and variab…

【德哥说库系列】-Oracle 19C PDB创建大全

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

双绞线(寻线仪,测线仪),光纤测试工具(红光笔,OTDR,光功率计)

网络测试方式&#xff1a; 根据测试中是否向被测网络注入测试流量&#xff0c;可以将网络测试方法分为主动测试和被动测试。 主动测试&#xff1a;利用测试工具有目的地主动问被测网络注入测试流量&#xff0c;根据测试流量的传送情况分析网络技术参数。优点是具备良好的灵活…

读程序员的制胜技笔记03_有用的反模式(上)

1. 教条 1.1. 一成不变的法则 1.2. 这些东西会遮蔽我们的双眼&#xff0c;你坚持相信的时间越久&#xff0c;你被遮蔽双眼的程度也就越深 2. 质疑所有教给你的东西 2.1. 它们有多么有用 2.2. 使用它们的理由 2.3. 使用它们的好处 2.4. 使用它们的代价 3. 反模式 3.1. …

13、Kubernetes核心技术 - Ingress

目录 一、概述 二、Ingress工作原理 三、Ingress 使用 3.1)、Ingress-http方式 3.1.1)、创建Ingress Controller和对应的Service 3.1.2)、创建tomcat的Pod和Service 3.1.3)、创建nginx的Pod和Service 3.1.4)、创建ingress http代理 3.1.5)、配置本地host文件 3.1.6)、…

基于STM32设计的室内环境监测系统(华为云IOT)_2023

一、设计需求 基于STM32+华为云物联网平台设计一个室内环境监测系统,以STM32系列单片机为主控器件,采集室内温湿度、空气质量、光照强度等环境参数,将采集的数据结果在本地通过LCD屏幕显示,同时上传到华为云平台并将上传的数据在Android移动端能够实时显示、查看。 【1…

更新版PHP神算网八字算命星座解梦周易占卜程序源码/PC+H5移动端整站适配/PHP源码带手机版

源码简介&#xff1a; 这个是更新版PHP神算网八字算命星座解梦周易占卜程序源码&#xff0c;能够在PCH5移动端整站适配。作为H5付费算命PHP源码&#xff0c;八字算命网站源码&#xff0c;功能很多强大实用。 2023.3 更新记录&#xff1a; 1、更新了23年属相信息&#xff1b;…

12 pinctrl 和 gpio 子系统

一、pinctrl 子系统 1. 什么是 pinctrl 子系统&#xff1f; 首先回顾一下如何初始化 LED 所使用的 GPIO&#xff1a; ①、修改设备树&#xff0c;添加相应的节点&#xff0c;节点里面重点是设置 reg 属性&#xff0c; reg 属性包括了 GPIO相关寄存器。 ②、获取 reg 属性中 …

基于顺序表实现的可存储性通讯录!!!

基于顺序表实现的通讯录 通讯录的基本功能 顺序表顺序表的部分变量修改修改处一修改处二修改处三 头文件 Contact.h通讯录自定义结构体 功能实现 源文件 Contact.c读取文件中联系人的信息 void ContactReadFile(contact* pcon)保存到文件 void ContactSave(contact* pcon) 测试…

Python:知道什么叫类吗,我这人实在不知道啥叫累。Python类的定义和使用。

前言 在 python 中&#xff0c;对于相同类型的对象进行分类&#xff0c;抽象后&#xff0c;得出共同的特征而形成了类&#xff08;class&#xff09;&#xff0c;面向对象程序设计的关键就是如何合理地定义这些类并且组织多个类之间的关系。 创建类时用变量形式表示对象特征的…

ChinaSoft 论坛巡礼|开源软件供应链论坛

2023年CCF中国软件大会&#xff08;CCF ChinaSoft 2023&#xff09;由CCF主办&#xff0c;CCF系统软件专委会、形式化方法专委会、软件工程专委会以及复旦大学联合承办&#xff0c;将于2023年12月1-3日在上海国际会议中心举行。 本次大会主题是“智能化软件创新推动数字经济与社…

Python基础之列表、元组和字典

一文拿捏Python基本数据类型“列表、数组和字典” 引言 Python中的 列表(英文叫list) 、 元组(英文叫tuple)和字典&#xff08;dictionary&#xff09; 也是 序列 特性的&#xff0c;它们也是非常常用的数据类型。 1、列表&#xff08;List&#xff09; 01、概述 列表&#…

【黑马程序员】SSM框架——SSM整合

文章目录 前言一、SSM 整合1. SSM 整合思路1.1 Spring 整合 MyBatis配置模型数据层标准开发业务层标准开发测试接口事务处理 1.2 Spring 整合 SpringMVCweb 配置类SpringMVC 配置类基于 Restful 的 Controller 开发 2. SSM 整合具体实现2.1 创建工程2.2 SSM 整合SpringMyBatisS…

forward和完美转发

std::move(value)是独立于值的右值引用&#xff0c;一个右值引用参数作为函数的形参&#xff0c;在函数内部再转发该参数的时候已经变成了一个左值&#xff0c;并不是它原来的类型了。 template<typename T> void forwardValue(T& val) {processValue(value); //…