WebGL进阶(十一)层次模型

理论基础:

效果:

源码:

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 引入gl-matrix.js库,用于 WebGL 中的矩阵运算 -->
    <script src="gl-matrix.js"></script>
    <script>
        // 顶点着色器程序
        let vertexstring = `
        attribute vec4 a_position; // 顶点位置属性
        uniform mat4 u_formMatrix; // 变换矩阵
        attribute vec4 a_Normal; // 顶点法线属性
        uniform vec3 u_PointLightPosition; // 点光源位置
        uniform vec3 u_DiffuseLight; // 散射光颜色
        uniform vec3 u_AmbientLight; // 环境光颜色
        varying vec4 v_Color; // 传递给片段着色器的颜色
        void main(void){
            gl_Position = u_formMatrix * a_position; // 应用变换矩阵
            vec3 normal = normalize(a_Normal.xyz); // 法线归一化
            vec3 lightDirection = normalize(u_PointLightPosition - vec3(gl_Position.xyz)); // 计算光源方向
            float nDotL = max(dot(lightDirection, normal), 0.0); // 计算法线和光源方向的点积
            vec3 diffuse = u_DiffuseLight * vec3(1.0,0,1.0)* nDotL; // 计算散射光
            vec3 ambient = u_AmbientLight * vec3(1.0,0,1.0); // 计算环境光
            v_Color = vec4(diffuse + ambient, 1); // 结合散射光和环境光
        }
        `;
        // 片段着色器程序
        let fragmentstring = `
        precision mediump float; // 精度声明
        varying vec4 v_Color; // 从顶点着色器接收的颜色
        void main(void){
          gl_FragColor =v_Color; // 设置片断颜色
        }
        `;

        // WebGL上下文和一些变量的声明
        var webgl;
        var angle = 45;
        var webglDiv;
        var indices;
        var g_joint1Angle = 0.0;
        var ANGLE_STEP = 3.0;
        var g_arm1Angle = -90.0;

        // 初始化函数,设置WebGL环境
        function init() {
            // 初始化WebGL
            initWebgl();
            // 初始化着色器
            initShader();
            // 初始化数据
            initBuffer();
            // 初始化事件
            initEvent();
            // 清空画板
            clearn();
            // 创建光源
            initLight();
            // 绘制图形
            draw();
        }

        // 初始化WebGL上下文
        function initWebgl() {
            webglDiv = document.getElementById('myCanvas');
            webgl = webglDiv.getContext("webgl");
            webgl.viewport(0, 0, webglDiv.clientWidth, webglDiv.clientHeight);
        }

        // 初始化着色器
        function initShader() {
            // 创建顶点着色器和片段着色器
            let vsshader = webgl.createShader(webgl.VERTEX_SHADER);
            let fsshader = webgl.createShader(webgl.FRAGMENT_SHADER);

            // 设置着色器源码
            webgl.shaderSource(vsshader, vertexstring);
            webgl.shaderSource(fsshader, fragmentstring);

            // 编译着色器
            webgl.compileShader(vsshader);
            webgl.compileShader(fsshader);
            // 检查着色器编译状态
            if (!webgl.getShaderParameter(vsshader, webgl.COMPILE_STATUS)) {
                var err = webgl.getShaderInfoLog(vsshader);
                alert(err);
                return;
            }
            if (!webgl.getShaderParameter(fsshader, webgl.COMPILE_STATUS)) {
                var err = webgl.getShaderInfoLog(fsshader);
                alert(err);
                return;
            }
            // 创建程序并附加着色器
            let program = webgl.createProgram();
            webgl.attachShader(program, vsshader);
            webgl.attachShader(program, fsshader)
            webgl.linkProgram(program);
            webgl.useProgram(program);
            webgl.program = program;
        }

        // 清空画板并设置背景色和深度测试
        function clearn() {
            webgl.clearColor(0, 0, 0, 1);
            webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT);
            webgl.enable(webgl.DEPTH_TEST);
        }

        // 初始化变换矩阵
        function initTransformation(angele, rotateArr, ModelMatrix = glMatrix.mat4.create()) {
            let ProjMatrix = glMatrix.mat4.create();
            glMatrix.mat4.identity(ProjMatrix);
            glMatrix.mat4.perspective(ProjMatrix, angle * Math.PI / 180, webglDiv.clientWidth / webglDiv.clientHeight, 1, 1000); // 设置透视投影

            let uniformMatrix1 = webgl.getUniformLocation(webgl.program, "u_formMatrix");

            glMatrix.mat4.rotate(ModelMatrix, ModelMatrix, degreesToRads(angele), rotateArr); // 旋转模型矩阵
            let ViewMatrix = glMatrix.mat4.create();
            glMatrix.mat4.identity(ViewMatrix);
            glMatrix.mat4.lookAt(ViewMatrix, [50, 50, 50], [0, 0, 0], [0, 1, 0]); // 设置视图矩阵

            let mvMatrix = glMatrix.mat4.create();
            glMatrix.mat4.identity(mvMatrix);
            glMatrix.mat4.multiply(mvMatrix, ViewMatrix, ModelMatrix); // 计算模型视图矩阵

            let mvpMatrix = glMatrix.mat4.create();
            glMatrix.mat4.identity(mvpMatrix);
            glMatrix.mat4.multiply(mvpMatrix, ProjMatrix, mvMatrix); // 计算模型视图投影矩阵
            webgl.uniformMatrix4fv(uniformMatrix1, false, mvpMatrix);
            return ModelMatrix;
        }

        // 初始化事件监听
        function initEvent() {
            document.onkeydown = keydown;
        }

        // 初始化光源
        function initLight() {
            let u_DiffuseLight = webgl.getUniformLocation(webgl.program, 'u_DiffuseLight');
            webgl.uniform3f(u_DiffuseLight, 1.0, 1.0, 1.0); // 设置散射光颜色
            let u_LightDirection = webgl.getUniformLocation(webgl.program, 'u_PointLightPosition');
            webgl.uniform3fv(u_LightDirection, [3.0, 3.0, 4.0]); // 设置点光源位置
            let u_AmbientLight = webgl.getUniformLocation(webgl.program, 'u_AmbientLight');
            webgl.uniform3f(u_AmbientLight, 0.8, 0.8, 0.8); // 设置环境光颜色
        }

        // 初始化缓冲区
        function initBuffer() {
            // 顶点数据
            var vertices = new Float32Array([
                // 顶点坐标
            ]);

            // 法线数据
            var normals = new Float32Array([
                // 法线坐标
            ]);

            // 顶点索引
            indices = new Uint8Array([
                // 顶点索引
            ]);

            // 创建顶点位置缓冲区
            let pointPosition = new Float32Array(vertices);
            let aPsotion = webgl.getAttribLocation(webgl.program, "a_position");
            let triangleBuffer = webgl.createBuffer();
            webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer);
            webgl.bufferData(webgl.ARRAY_BUFFER, pointPosition, webgl.STATIC_DRAW);
            webgl.enableVertexAttribArray(aPsotion);
            webgl.vertexAttribPointer(aPsotion, 3, webgl.FLOAT, false, 0, 0);

            // 创建法线缓冲区
            let aNormal = webgl.getAttribLocation(webgl.program, "a_Normal");
            let normalsBuffer = webgl.createBuffer();
            let normalsArr = new Float32Array(normals);
            webgl.bindBuffer(webgl.ARRAY_BUFFER, normalsBuffer);
            webgl.bufferData(webgl.ELEMENT_ARRAY_BUFFER, normalsArr, webgl.STATIC_DRAW);
            webgl.enableVertexAttribArray(aNormal);
            webgl.vertexAttribPointer(aNormal, 3, webgl.FLOAT, false, 0, 0);

            // 创建索引缓冲区
            let indexBuffer = webgl.createBuffer();
            let indices1 = new Uint8Array(indices);
            webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER, indexBuffer);
            webgl.bufferData(webgl.ELEMENT_ARRAY_BUFFER, indices1, webgl.STATIC_DRAW);
        }

        // 按键事件处理函数
        function keydown(ev) {
            switch (ev.keyCode) {
                // 按键事件,控制关节角度
            }
            clearn()
            draw();
        }
html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 引入gl-matrix.js库,用于 WebGL 中的矩阵运算 -->
    <script src="gl-matrix.js"></script>
    <script>
        // 顶点着色器程序
        let vertexstring = `
        attribute vec4 a_position; // 顶点位置属性
        uniform mat4 u_formMatrix; // 变换矩阵
        attribute vec4 a_Normal; // 顶点法线属性
        uniform vec3 u_PointLightPosition; // 点光源位置
        uniform vec3 u_DiffuseLight; // 散射光颜色
        uniform vec3 u_AmbientLight; // 环境光颜色
        varying vec4 v_Color; // 传递给片段着色器的颜色
        void main(void){
            gl_Position = u_formMatrix * a_position; // 应用变换矩阵
            vec3 normal = normalize(a_Normal.xyz); // 法线归一化
            vec3 lightDirection = normalize(u_PointLightPosition - vec3(gl_Position.xyz)); // 计算光源方向
            float nDotL = max(dot(lightDirection, normal), 0.0); // 计算法线和光源方向的点积
            vec3 diffuse = u_DiffuseLight * vec3(1.0,0,1.0)* nDotL; // 计算散射光
            vec3 ambient = u_AmbientLight * vec3(1.0,0,1.0); // 计算环境光
            v_Color = vec4(diffuse + ambient, 1); // 结合散射光和环境光
        }
        `;
        // 片段着色器程序
        let fragmentstring = `
        precision mediump float; // 精度声明
        varying vec4 v_Color; // 从顶点着色器接收的颜色
        void main(void){
            gl_FragColor = v_Color; // 设置片断颜色
        }
        `;

        // WebGL上下文和一些变量的声明
        var webgl;
        var angle = 45;
        var webglDiv;
        var indices;
        // 各个关节的角度变量
        var g_joint1Angle = 86.0;
        var ANGLE_STEP = 3.0;
        var g_arm1Angle = 160.0;
        var g_palm1Angle = 0.0;
        var g_finger1Angle = 0.0;
        var g_chest1Angle = 0;

        // 初始化函数,设置WebGL环境
        function init() {
            // 初始化WebGL
            initWebgl();
            // 初始化着色器
            initShader();
            // 清空画板
            clearn();
            // 创建光源
            initLight();
            // 绘制头部
            drawHead()
            // 初始化数据
            initBuffer();
            // 初始化事件
            initEvent();
            // 绘制图形
            let drawMatrix = chestDraw();
            let drawMatrixCopy = drawMatrix.slice(0);
            drawLeft(drawMatrix);
            drawRight(drawMatrixCopy);
        }

        // 初始化WebGL上下文
        function initWebgl() {
            webglDiv = document.getElementById('myCanvas');
            webgl = webglDiv.getContext("webgl");
            webgl.viewport(0, 0, webglDiv.clientWidth, webglDiv.clientHeight);
        }

        // 初始化着色器
        function initShader() {
            // 创建顶点着色器和片段着色器
            let vsshader = webgl.createShader(webgl.VERTEX_SHADER);
            let fsshader = webgl.createShader(webgl.FRAGMENT_SHADER);

            // 设置着色器源码
            webgl.shaderSource(vsshader, vertexstring);
            webgl.shaderSource(fsshader, fragmentstring);

            // 编译着色器
            webgl.compileShader(vsshader);
            webgl.compileShader(fsshader);
            // 检查着色器编译状态
            if (!webgl.getShaderParameter(vsshader, webgl.COMPILE_STATUS)) {
                var err = webgl.getShaderInfoLog(vsshader);
                alert(err);
                return;
            }
            if (!webgl.getShaderParameter(fsshader, webgl.COMPILE_STATUS)) {
                var err = webgl.getShaderInfoLog(fsshader);
                alert(err);
                return;
            }
            // 创建程序并附加着色器
            let program = webgl.createProgram();
            webgl.attachShader(program, vsshader);
            webgl.attachShader(program, fsshader);
            webgl.linkProgram(program);
            webgl.useProgram(program);
            webgl.program = program;
        }

        // 清空画板并设置背景色和深度测试
        function clearn() {
            webgl.clearColor(0, 0, 0, 1);
            webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT);
            webgl.enable(webgl.DEPTH_TEST);
        }

        // 初始化变换矩阵
        function initTransformation(angle, rotateArr, ModelMatrix = glMatrix.mat4.create()) {
            let ProjMatrix = glMatrix.mat4.create();
            glMatrix.mat4.identity(ProjMatrix);
            glMatrix.mat4.perspective(ProjMatrix, angle * Math.PI / 180, webglDiv.clientWidth / webglDiv.clientHeight, 1, 1000); // 设置透视投影

            let uniformMatrix1 = webgl.getUniformLocation(webgl.program, "u_formMatrix");

            glMatrix.mat4.rotate(ModelMatrix, ModelMatrix, degreesToRads(angle), rotateArr);
            let ViewMatrix = glMatrix.mat4.create();
            glMatrix.mat4.identity(ViewMatrix);
            glMatrix.mat4.lookAt(ViewMatrix, [0, 0, 100], [0, 0, 0], [0, 1, 0]); // 设置视图矩阵

            let mvMatrix = glMatrix.mat4.create();
            glMatrix.mat4.identity(mvMatrix);
            glMatrix.mat4.multiply(mvMatrix, ViewMatrix, ModelMatrix); // 计算模型视图矩阵

            let mvpMatrix = glMatrix.mat4.create();
            glMatrix.mat4.identity(mvpMatrix);
            glMatrix.mat4.multiply(mvpMatrix, ProjMatrix, mvMatrix); // 计算模型视图投影矩阵
            webgl.uniformMatrix4fv(uniformMatrix1, false, mvpMatrix);
            return ModelMatrix;
        }

        // 初始化事件监听
        function initEvent() {
            document.onkeydown = keydown;
        }

        // 初始化光源
        function initLight() {
            let u_DiffuseLight = webgl.getUniformLocation(webgl.program, 'u_DiffuseLight');
            webgl.uniform3f(u_DiffuseLight, 1.0, 1.0, 1.0); // 设置散射光颜色
            let u_LightDirection = webgl.getUniformLocation(webgl.program, 'u_PointLightPosition');
            webgl.uniform3fv(u_LightDirection, [3.0, 3.0, 4.0]); // 设置点光源位置
            let u_AmbientLight = webgl.getUniformLocation(webgl.program, 'u_AmbientLight');
            webgl.uniform3f(u_AmbientLight, 0.8, 0.8, 0.8); // 设置环境光颜色
        }

        // 初始化缓冲区
        function initBuffer() {
            // 顶点数据
            var vertices = new Float32Array([
                // 顶点坐标
            ]);

            // 法线数据
            var normals = new Float32Array([
                // 法线坐标
            ]);

            // 顶点索引
            indices = new Uint8Array([
                // 顶点索引
            ]);

            // 创建顶点位置缓冲区
            let pointPosition = new Float32Array(vertices);
            let aPosition = webgl.getAttribLocation(webgl.program, "a_position");
            let triangleBuffer = webgl.createBuffer();
            webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer);
            webgl.bufferData(webgl.ARRAY_BUFFER, pointPosition, webgl.STATIC_DRAW);
            webgl.enableVertexAttribArray(aPosition);
            webgl.vertexAttribPointer(aPosition, 3, webgl.FLOAT, false, 0, 0);

            // 创建法线缓冲区
            let aNormal = webgl.getAttribLocation(webgl.program, "a_Normal");
            let normalsBuffer = webgl.createBuffer();
            let normalsArr = new Float32Array(normals);
            webgl.bindBuffer(webgl.ARRAY_BUFFER, normalsBuffer);
            webgl.bufferData(webgl.ARRAY_BUFFER, normalsArr, webgl.STATIC_DRAW);
            webgl.enableVertexAttribArray(aNormal);
            webgl.vertexAttribPointer(aNormal, 3, webgl.FLOAT, false, 0, 0);

            // 创建索引缓冲区
            let indexBuffer = webgl.createBuffer();
            let indices1 = new Uint8Array(indices);
            webgl.bindBuffer(web
复制代码
void gl.drawElements(mode, count, type, offset);

复盘:

相关推荐
ThreePointsHeat3 天前
Unity WebGL打包后启动方法,部署本地服务器
unity·游戏引擎·webgl
林枫依依4 天前
电脑配置流程(WebGL项目)
webgl
冥界摄政王6 天前
CesiumJS学习第四章 替换指定3D建筑模型
3d·vue·html·webgl·js·cesium
温宇飞7 天前
高效的线性采样高斯模糊
javascript·webgl
冥界摄政王8 天前
Cesium学习第一章 安装下载 基于vue3引入Cesium项目开发
vue·vue3·html5·webgl·cesium
光影少年11 天前
三维前端需要会哪些东西
前端·webgl
nnsix11 天前
Unity WebGL jslib 通信时,传入字符串,变成数值 问题
webgl
二狗哈11 天前
Cesium快速入门34:3dTile高级样式设置
前端·javascript·算法·3d·webgl·cesium·地图可视化
AlanHou11 天前
Three.js:Web 最重要的 3D 渲染引擎的技术综述
前端·webgl·three.js
二狗哈12 天前
Cesium快速入门33:tile3d设置样式
3d·状态模式·webgl·cesium·地图可视化