IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> 明日方舟页面球体动画 -> 正文阅读

[游戏开发]明日方舟页面球体动画

了解明日方舟页面球体动画

这是对明日方舟登录界面与官网球体动画名称的探索记录,并没有什么实际意义

没想到吧

结论

最后的结论是,就是球体网格动画

就是这个

起因

在登录游戏与进入游戏官网时一直都能看到以下这个球体动画

我就一直很好奇这玩意到底是个啥,有没有什么学名。但是从各种搜索引擎,游戏论坛乃至群友里问都没问出个所以然(可能是问的少了,就问了一次)。于是只好自己想办法看看。

居然社恐到不愿意上网多找大佬问问

动画分析

明日方舟球体动画

游戏客户端的没录,上面的是网页端的动画gif录屏。很明显是一个带有节点三角面组成的球体动画的一部分(我也不清楚相关名词有没有用对,只是搜刮了贫瘠的大脑拼凑一句描述)

平时还是多读点书比较好

动画来源

但是光分析出 三角面 球体 动画 3d 这几个关键词似乎还不够搜出精确的名词

类似的图倒是有,但是也没有给出具体的名词。(此时继续翻个十来页多翻几十个博客或许能找到,但还是决定先多找一些关键词来定位)

Bing搜索结果

动画显示的位置有客户端登陆界面和官网界面,客户端应该是unity打包的,对unity不太熟,而且原生apk反编译下就算找到控件位置估计也看不明白,只是感觉可能是opengl还是啥引擎实现的动画。于是决定从官网着手

对官网的查看

还好最近学了几天前端,直接打开开发者工具开找

canvas动画

最后一看是一个canvas标签展示的动画,那估计是js控制显示的了,然后这里的id也说明了应该是用webgl,也就是还是opengl实现的动画。但是网页的js很明显是压缩加密过的,对这玩意也不够了解,还是决定继续开搜。

对网页布局的查看最后又多了几个关键词 canvas js动画 webgl

接下来就是排列组合继续搜索一下

这下好办了

得到结果

然后找到了该博客在浏览器中画圆都会,但是画个 3D 的球呢? - 掘金 (juejin.cn)

(这和联想的关键词好像多少有点不沾边)

但是这里给出的第一个案例勾引(了我,看起来似曾相似

Sphere (woopen.github.io)

这是动态的案例,点击链接可以查看效果

从这里了解到画标准球(UV Sphere)的方法,但是搜索得到C++ 生成球体网格 - 知乎 (zhihu.com)后发现UV Sphere只是一种绘制球体的方式,此处引入四种绘制球体的方式与相关图片

The UV Sphere

The UV Sphere

The lcosphere

The lcosphere

The Quad Sphere

The Quad Sphere

Goldberg Polyhedra

Goldberg Polyhedra

很明显 The Icosphere 更接近我想要搜索的球体动画的名字,但这只是一种生成球体网格的方式。从第一句中看见了球体网格这个名词,让我感觉应该找到结果了。

官网的动画

于是我现在可能会用The Icosphere方式生成的球体网格动画来形容这个动画,简单说就是一个球体网格动画。虽然可能没什么意义,但大概或许还是能锻炼到搜索信息的能力的罢。我原本还以为是个有什么意义的图形(什么代表脑细胞啥的)

网络结构大脑Bing搜索结果图

可能是因为以前看过类似这张图的图片吧

抄一个球体网格动画实现

来都来了,前面在浏览器中画圆都会,但是画个 3D 的球呢? - 掘金 (juejin.cn)也给出了绘制球体网格动画的源码,干脆直接抄一个玩玩(也没指望学到啥,只是练练敲js,毕竟量子学习的时候只管用,对原理啥的记得不多)

最后看着改源码就弄出了这玩意(难视)

image-20220715171743487

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta name="referrer" content="no-referrer"/>
        <title>Title</title>
        <script src="https://cdn.jsdelivr.net/npm/gl-matrix@3.3.0/gl-matrix.js"></script>
        <style>
            
        </style>
        <script>

        </script>
    </head>
    <body>
        <div id="app">

            <h2>Sphere Anim</h2>
            <script>
                // 设置全局对象,大概
                window.mat4 = glMatrix.mat4;
                window.vec3 = glMatrix.vec3;

                // 创建canvas 添加到body
                const canvas = document.createElement('canvas');
                canvas.width = 400;
                canvas.height = 400;
                document.body.appendChild(canvas);

                // 获取webgl 设置视窗
                const gl = canvas.getContext('webgl');
                gl.viewport(0,0, gl.drawingBufferWidth, gl.drawingBufferHeight);

                const vs = `
                attribute vec4 aPosition;
                uniform mat4 uPVMat;
                uniform mat4 uModelMat;
                void main() {
                    gl_Position = uPVMat * uModelMat * aPosition;
                }
                // `;
                // FragColor代表使用颜色,根据rgb比例可调出相近色
                const fs = `
                precision mediump float;
                void main() {
                    gl_FragColor = vec4(0.58, 0.51, 0.07, 1.);
                }
                `;
                                
                const vertexShader = createShader(gl, gl.VERTEX_SHADER, vs);
                const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fs);
                const program = createProgram(gl, vertexShader, fragmentShader);
                gl.useProgram(program);
                // 背景颜色
                gl.clearColor(0.09, 0.09, 0.09, 1);

                // scaling后数组代表显示大小比例
                const baseModelMat = mat4.fromScaling(mat4.create(), [1,1,1]);
                const viewMat = mat4.lookAt(mat4.create(), [0, 0, 10], [0, 0, 0], [0, 1, 0]);
                const presMat = mat4.perspective(
                mat4.create(),
                // 此处rad是缩放比例?
                rad(12),
                gl.canvas.clientWidth / gl.canvas.clientHeight,
                1,
                2000
                );
                const pvMat = mat4.mul(mat4.create(), presMat, viewMat);
                // 传入的大概是三角形面数的比例,越高则相应面数越多
                const iSphere = createIcosahedronSphere(1);

                const iSphereCount = iSphere.length / 3;

                const uPVMat = gl.getUniformLocation(program, "uPVMat");
                const uModelMat = gl.getUniformLocation(program, "uModelMat");
                const aPosition = gl.getAttribLocation(program, "aPosition");

                const iBuffer = gl.createBuffer();
                gl.bindBuffer(gl.ARRAY_BUFFER, iBuffer);
                gl.bufferData(gl.ARRAY_BUFFER, iSphere, gl.STATIC_DRAW);

                gl.uniformMatrix4fv(uPVMat, false, pvMat);
                gl.enableVertexAttribArray(aPosition);
                gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, 0, 0);
                // 旋转角度
                let rotate = 0;
                function draw(){
                    gl.clear(gl.COLOR_BUFFER_BIT);
                    let modelMat = mat4.rotateY(
                        mat4.create(),
                        // 后面数组代表球体偏移位
                        mat4.translate([], baseModelMat, [0, 0, 0]),
                        rotate
                    );
                    gl.uniformMatrix4fv(uModelMat, false, modelMat);
                    gl.bindBuffer(gl.ARRAY_BUFFER, iBuffer);
                    gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, 0, 0);
                    for (let i = 0; i < iSphereCount; i += 3) gl.drawArrays(gl.LINE_LOOP, i, 3);

                    rotate += 0.01;
                    requestAnimationFrame(draw);
                }
                draw();
            
                function createIcosahedronSphere(count = 0) {
                    const points = [];

                    const t = (1 + Math.sqrt(5)) / 2;
                    const v1 = vec3.normalize([], [-1, t, 0]);
                    const v2 = vec3.normalize([], [1, t, 0]);
                    const v3 = vec3.normalize([], [-1, -t, 0]);
                    const v4 = vec3.normalize([], [1, -t, 0]);
                    const v5 = vec3.normalize([], [0, -1, t]);
                    const v6 = vec3.normalize([], [0, 1, t]);
                    const v7 = vec3.normalize([], [0, -1, -t]);
                    const v8 = vec3.normalize([], [0, 1, -t]);
                    const v9 = vec3.normalize([], [t, 0, -1]);
                    const v10 = vec3.normalize([], [t, 0, 1]);
                    const v11 = vec3.normalize([], [-t, 0, -1]);
                    const v12 = vec3.normalize([], [-t, 0, 1]);

                    function tri(a, b, c) {
                        points.push(...a, ...b, ...c);
                    }
                    function divide(a, b, c, count) {
                        if (count > 0) {
                        const ab = vec3.normalize([], vec3.scale([], vec3.add([], a, b), 0.5));
                        const ac = vec3.normalize([], vec3.scale([], vec3.add([], a, c), 0.5));
                        const bc = vec3.normalize([], vec3.scale([], vec3.add([], b, c), 0.5));

                        divide(a, ab, ac, count - 1);
                        divide(ab, b, bc, count - 1);
                        divide(bc, c, ac, count - 1);
                        divide(ab, bc, ac, count - 1);
                        } else {
                            tri(a, b, c);
                        }
                    }

                    divide(v1, v12, v6, count);
                    divide(v1, v6, v2, count);
                    divide(v1, v2, v8, count);
                    divide(v1, v8, v11, count);
                    divide(v1, v11, v12, count);
                    divide(v2, v6, v10, count);
                    divide(v6, v12, v5, count);
                    divide(v12, v11, v3, count);
                    divide(v11, v8, v7, count);
                    divide(v8, v2, v9, count);
                    divide(v4, v10, v5, count);
                    divide(v4, v5, v3, count);
                    divide(v4, v3, v7, count);
                    divide(v4, v7, v9, count);
                    divide(v4, v9, v10, count);
                    divide(v5, v10, v6, count);
                    divide(v3, v5, v12, count);
                    divide(v7, v3, v11, count);
                    divide(v9, v7, v8, count);
                    divide(v10, v9, v2, count);

                    return new Float32Array(points);
                }

                function rad(deg) {
                return (deg * Math.PI) / 180;
                }
                function createShader(gl, type, source) {
                const shader = gl.createShader(type);
                gl.shaderSource(shader, source);
                gl.compileShader(shader);
                const success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
                if (!success) {
                    throw new Error(
                    "could not compile shader -> " + source + gl.getShaderInfoLog(shader)
                    );
                }
                return shader;
                }

                function createProgram(gl, vertex, fragment) {
                const program = gl.createProgram();
                gl.attachShader(program, vertex);
                gl.attachShader(program, fragment);
                gl.linkProgram(program);
                const success = gl.getProgramParameter(program, gl.LINK_STATUS);
                if (!success) {
                    throw new Error(
                    "program failed to link -> " + gl.getProgramInfoLog(program)
                    );
                }
                return program;
                }

            </script>

        </div>
    </body>
</html>

Sphere_Anim (gitee.io)

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-07-21 21:49:23  更:2022-07-21 21:49:55 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 11:59:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码