WebGL: basic exercises / simple learning / demo / canvas3D

1. Prerequisite content

canvas: understanding canvas / basic usage / practical demo-CSDN blog

WebGL: Start learning / Understand WebGL / What knowledge does WebGL need to master / Application areas / Is it worth learning WebGL on the front end_webgl training-CSDN blog

2. Run HTML online

Used to run WebGL code, paste - run (sometimes it is not easy to use, and an inexplicable error is reported)

Run Html5 online

3. Get canvas and context object

//获取画布元素
var canvas = document.getElementById('canvas')
//获取到元素的上下文环境对象
var webgl = canvas.getContext('webgl')

3. WebGL exercises

demo coming AI

3.1. Draw a square

In this Demo, we first obtain the WebGL context, and then define a vertex shader and a fragment shader. Next, we create the shader program object and attach and link the vertex shader and fragment shader to this program object.

Then, we create a vertex buffer and store the vertex coordinates in this buffer. We enable the vertex attribute and bind the vertex buffer object to this attribute.

Next, we set the viewport size and clear the canvas. Finally, we draw a square using the gl.drawArrays() method.

It should be noted that when drawing graphics, we use gl.TRIANGLE_FAN, which means drawing a triangular sector, which is a square composed of five triangles. This reduces the number of vertices drawn and improves performance.

<!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, Clear screen

This Demo creates an empty WebGL context and clears the screen on the canvas. The color on the screen can be modified by changing the parameters of 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 triangle rendering

它包括以下步骤:
获取 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 draws a red triangle

WebGL draws a red triangle whose vertex coordinates are (0.0, 0.5), (-0.5, -0.5) and (0.5, -0.5) respectively. During the drawing process, we first compiled and linked the vertex shader and fragment shader, and created a shader program. We then create a vertex buffer and bind the vertex data to that buffer. Next we pass the vertex data to the vertex shader via vertex attributes, set the color in the fragment shader, and draw the triangle by calling 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 draws color gradient rectangle

In this Demo, we first create a WebGL context and define a vertex shader and a fragment shader. Next, we create a shader program object and attach the vertex shader and fragment shader to this program object and link them.

Then, we create a vertex buffer and store the vertex coordinates in this buffer. We also set up the view and projection matrices and use the shader program. Next, we enable the vertex attribute and bind the vertex buffer to this attribute. Finally, we draw a rectangle using the gl.drawArrays() method.

In the fragment shader, we use the mix() function to calculate the color of each pixel to achieve the color gradient effect. We also define two uniform variables u_colorA and u_colorB to control the color of the rectangle.

In this demo, we just drew a simple color gradient rectangle, but you can modify and extend it as needed.

<!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. Draw a colored triangle

<!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. Rotating cube

In the code for this example, we use the THREE.js library to create a scene, camera and renderer. We also created a cube and added it to the scene. Finally, we created an animation function that rotates the cube around the X and Y axes and updates the renderer every frame.

Run the above code and you will see a green cube in your browser that is constantly spinning.

<!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, colored triangles

获取 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. Draw a circle

获取 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>

4. Process records

Record 1. Is WebGL based on canvas?

WebGL is based on the canvas element in HTML5. WebGL uses the OpenGL ES 2.0 specification for writing 3D graphics. WebGL's API allows JavaScript to draw various types of 3D images on canvas elements, using GPU acceleration. Therefore, it can be said that WebGL is based on canvas, but it uses more advanced graphics processing technology to achieve complex 3D images.

Record 2. Understanding canvas3D

canvas3D is a new feature of HTML5. It provides support for 3D graphics, making it possible to achieve 3D effects on web pages. canvas3D is implemented based on WebGL, a graphics library based on OpenGL ES 2.0, which can achieve high-performance 3D graphics rendering in web pages.

Using canvas3D, you can create and manipulate 3D objects, apply materials and maps, add lights and shadows, and more. It provides a rich set of APIs that can be used to draw and operate 3D graphics, including operations such as rotation, scaling, and translation of objects.

Although canvas3D is currently in an experimental stage, it is already supported by many browsers and may become part of the HTML5 standard in the future. If you are interested in 3D graphics programming, you can try using canvas3D to implement your projects.

----A word from Wen Xin

5. Welcome exchanges and corrections

6. Reference links

What is WebGL? | CodeShang Dynamics

[Selected] [WebGL] Simple introductory tutorial_webgl tutorial-CSDN blog

Guess you like

Origin blog.csdn.net/snowball_li/article/details/134164447