5.透明效果

实时渲染中要实现透明效果,通常会在渲染模型时控制它的透明通道(Alpha channel)

当一个物体被渲染到屏幕上时,每个片元除了颜色和深度值之外,它还有另一个属性—透明度。

当透明度为1时,表示该像素是完全不透明的,当为0时,表示该像素完全不会显示

Unity中实现透明效果有两种方法:

  • 透明度测试(Alpah Test):但无法得到真正的半透明效果
  • 透明度混合(Alpha Blending)

对于不透明物体,不考虑它们的渲染顺序也能得到正确的排序效果,这是深度缓冲的(depth buffer,也被称为z-buffer)的存在。

在实时渲染中,深度缓冲是用于可见性问题的,它可以绝定哪个物体的哪些部分会被渲染到前面,而哪些物体会被其他物体遮挡。

基本思想为为:根据深度缓冲中的值来判断该片元距离摄像机的距离,当渲染一个片元时,需要把它的深度值和已经存在于深度缓冲中的值进行比较(如果开启了深度测试),如果它的值距离摄像机更远,那么说明这个片元不该被渲染到屏幕上(有物体挡住了它);否则,这个片元因该覆盖掉此时颜色缓冲中的像素值,并把它的深度值更新到深度缓冲中(如果开启了深度写入)。

使用深度缓冲,可以不关心不透明物体的渲染顺序。但如果要实现透明效果,使用透明度混合时,就要关闭深度写入

透明度测试:

  • 只要一个片元的透明度不满足条件(通常是小于某个阈值),那么它对应的片元就会被舍弃。
  • 舍弃的片元不再进行任何处理,也不会对颜色缓冲产生任何影响
  • 否则就会按照普通的不透明物体的处理方式来处理它,进行深度测试,深度写入等
  • 不需要关闭深度写入,它和其他不透明物体最大的不同:它会根据透明度来舍弃一些片元。但是极端的,要么完全不透明,要么完全透明。

透明度混合:

  • 可以得到真正的半透明效果
  • 使用当前片元的透明度作为混合因子,与已经存储在颜色缓冲中的颜色值进行混合,得到新的颜色
  • 需要关闭深度写入,所以要非常小心物体的渲染顺序。
  • 透明度混合只关闭深度写入,不关闭深度测试
  • 当使用透明度混合渲染一个片元时,还是会比较它的深度值与当前深度缓冲中的深度值,如果它的深度值距离摄像机更远,那么就不会再进行混合操作
  • 当一个不透明物体出现在在一个透明物体的前面,我们先渲染不透明物体
  • 而我们先渲染不透明物体,它任然可以正常的遮挡住透明物体
  • 也就是说透明度混合中,深度缓冲是只读的

一、为什么渲染顺序很重要

渲染引擎一般都会先对物体进行排序,再进行渲染。常用的方法:

(1)先渲染所以不透明物体,并开启它们的深度测试和深度写入

(2)把半透明物体按照它们的距离摄像机的远近进行排序,然后按照从后往前的顺序渲染这些半透明物体,并开启它们的深度测试,但关闭深度写入

二、Unity Shader的渲染顺序

为了解决渲染顺序的问题,Unity提供了渲染队列,这一解决方案。

可以用SubShader的Queue标签来决定模型将归于哪个渲染队列。

Unity在内部使用一系列整数索引来了表示每个渲染队列,且索引号越小表示越早被渲染

如果我们想要通过透明度测试实现透明效果,代码中应包含类似一下代码

SubShader {
       Tags { “Queue”=“AlphaTest” }
       Pass {
                ...
            }
}

如果我们想要通过透明度混合来实现透明效果, 代码中应包含类似一下代码

SubShader {
       Tags { “Queue”=“TransParent” }
       Pass {
                ZWrite Off
                ...
            }
}

其中 ZWrite Off用于关闭深度写入,这里把它写在Pass中。

也可以写在SubShader中,这意味着该SubShader下的所有Pass都会关闭深度写入

三、透明度测试

透明度测试:只要一个片元的透明度不满足条件(通常是小于某个阈值),那么它对应的片元就会被舍弃。被舍弃的片元将不会再进行任何处理,也不会对颜色缓冲产生任何影响;否则,就会按照普通的不透明物体的处理方式来处理它

通常,在片元着色器中使用Clip函数来进行透明度测试。

Clip函数定义:

函数:void Clip(float4 x);void Clip(float3 x);void Clip(float2 x);void Clip(float x);void Clip(float x);

参数:裁剪时使用的标量或矢量条件

描述:如果给定参数的任何一个分量时负数,就会舍弃当前像素的输出颜色。它等同于下面代码

void Clip(float4 x)
{
     if (any(x < 0))
        discard;
}


 

Shader "Shader/AlphaTest"
{
    Properties
    {
        _Color ("Main Tint", Color) = (1,1,1,1)
        _MainTex ("Texture", 2D) = "white" {}
        //_Cutoff参数用于决定我们调用clip进行透明度测试时使用的判断条件。
        _Cutoff ("Alpha Cutoff", Range(0, 1)) = 0.5
    }
    SubShader
    {
        Tags { "Queue"="AlphaTest" // 透明度测试使用的渲染队列名为AlphaTest
                "IgnoreProjector"="True"//Shader不会受到投影器Projectors的影响
                "RenderType"="TransparentCutout" //RenderType标签用于着色器替换功能
             }

        Pass
        {
            Tags { "LightMode"="ForwardBase" }
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "Lighting.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float4 uv : TEXCOORD0;
            };

            struct v2f
            {
                float4 pos : SV_POSITION;
                float3 worldNormal : TEXCOORD0;
                float3 worldPos : TEXCOORD1;
                float2 uv : TEXCOORD2;
            };

            fixed4 _Color;
            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed _Cutoff;

            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);

                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;//顶点位置

                o.uv = TRANSFORM_TEX(v.uv, _MainTex);

                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed3 worldNormal = normalize(i.worldNormal);
                fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));

                fixed4 texColor = tex2D(_MainTex, i.uv);

                //Alpha test
                clip(texColor.a - _Cutoff);

                fixed3 albedo =texColor.rgb * _Color.rgb;

                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;

                fixed3 diffuse = _LightColor0.rgb * albedo * 
                               max(0, dot(worldLightDir, worldNormal));
                
                return fixed4(ambient + diffuse, 1.0);
            }
            ENDCG
        }
    }
    Fallback "Transparent/Cutout/VertexLit"
}

四、透明度混合

透明度混合:这种方法可以得到真正的半透明效果。它会使用当前片元的透明度作为混合因子,与已经存储在颜色缓冲中的颜色值进行混合,得到新的颜色。但是,透明度混合需要关闭深度写入,这使得我们要非常小心物体的渲染顺序。

Blend:Blend是Unity通过的设置混合模式的命令。要想实现半透明的效果就要把当前自身的颜色和已经存在于颜色缓冲中的颜色值进行混合,混合时使用的函数就是由该指令决定的。

 Blend SrcFactor DstFactor:

这个命令在设置混合因子的同时也开启了混合模式。只要开启混合之后,设置片元的透明通道才有意义,而Unity在我们使用Blend命令的时候就自动帮我们打开了。

如果模型没有任何透明效果,可能是因为没有在pass中使用Blend命令,一方面没有设置混合因子,另一方面没有打开混合模式。

把源颜色的混合因子SrcFactor设为SrcAlpha,而目标颜色的混合因子DstFactor设为OneMinusSrcAlpha。

混合后的新颜色为:
DstColor_{new}=SrcAlpha\times SrcColor+(1-SrcAlpha)\times DstColor_{old}

Shader "Shader/AlphaBlend"
{
    Properties
    {
        _Color ("Main Tint", Color) = (1,1,1,1)
        _MainTex ("Texture", 2D) = "white" {}
        _AlphaScale ("Alpha Scale", Range(0, 1)) = 1//在透明纹理的基础上控制整体的透明度
    }

    SubShader
    {
        Tags { "Queue"="Transparent" //Transparent
               "IgnoreProjector"="True"//Shader不会受到投影器Projectors的影响
               "RenderType"="Transparent" //RenderType标签用于着色器替换功能
     }

        Pass
        {
            Tags { "LightMode"="ForwardBase" }//前向渲染

            ZWrite Off//关闭深度写入
            Blend SrcAlpha OneMinusSrcAlpha//开启混合模式

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "Lighting.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float4 uv : TEXCOORD0;
            };

            struct v2f
            {
                float4 pos : SV_POSITION;
                float3 worldNormal : TEXCOORD0;
                float3 worldPos : TEXCOORD1;
                float2 uv : TEXCOORD2;
            };

            fixed4 _Color;
            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed _AlphaScale;

            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);

                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;//顶点位置

                o.uv = TRANSFORM_TEX(v.uv, _MainTex);

                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed3 worldNormal = normalize(i.worldNormal);
                fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));

                fixed4 texColor = tex2D(_MainTex, i.uv);

                fixed3 albedo =texColor.rgb * _Color.rgb;

                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;

                fixed3 diffuse = _LightColor0.rgb * albedo * 
                               max(0, dot(worldLightDir, worldNormal));
                
                return fixed4(ambient + diffuse, texColor.a * _AlphaScale);
            }
            ENDCG
        }
    }
    Fallback "Transparent/VertexLit"
}

五、开启深度写入的半透明效果

当模型本身有复杂的遮挡关系或者包含了复杂的非凹凸网格的时候,就会有各种各样因为排序错误而产生的透明效果

使用两个Pass来渲染模型:

第一个Pass开启深度写入,但不输入颜色,它的目的仅仅是为了把该模型的深度值写入深度缓冲中;

第二个Pass进行正常的透明度混合,由于上一个Pass已经得到了逐像素的正确深度信息,该Pass进就可以按照下像素级别的深度排序结果进行渲染透明。

缺点是:多使用一个Pass会对性能造成一定的影响

Shader "Shader/AlphaBlendZWrite"
{
    Properties
    {
        _Color ("Main Tint", Color) = (1,1,1,1)
        _MainTex ("Texture", 2D) = "white" {}
        _AlphaScale ("Alpha Scale", Range(0, 1)) = 1//在透明纹理的基础上控制整体的透明度
    }

    SubShader
    {
        Tags { "Queue"="Transparent" //Transparent
               "IgnoreProjector"="True"//Shader不会受到投影器Projectors的影响
               "RenderType"="Transparent" //RenderType标签用于着色器替换功能
     }

        Pass
        {
            ZWrite On//开启深度写入
            ColorMask 0//ColorMask用于设置颜色通道的写掩码
            //语义:
            //ColorMask RGB |A | 0 |其他任何R、G、B、A的组合
            //当ColorMask设置为0时,意味着该Pass不写入任何颜色通道,即不会输入任何颜色
            //这正是我们需要的——该Pass只需要写入深度缓存即可
        }

        Pass
        {
            Tags { "LightMode"="ForwardBase" }//前向渲染

            ZWrite Off//关闭深度写入
            Blend SrcAlpha OneMinusSrcAlpha//开启混合模式

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "Lighting.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float4 uv : TEXCOORD0;
            };

            struct v2f
            {
                float4 pos : SV_POSITION;
                float3 worldNormal : TEXCOORD0;
                float3 worldPos : TEXCOORD1;
                float2 uv : TEXCOORD2;
            };

            fixed4 _Color;
            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed _AlphaScale;

            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);

                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;//顶点位置

                o.uv = TRANSFORM_TEX(v.uv, _MainTex);

                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed3 worldNormal = normalize(i.worldNormal);
                fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));

                fixed4 texColor = tex2D(_MainTex, i.uv);

                fixed3 albedo =texColor.rgb * _Color.rgb;

                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;

                fixed3 diffuse = _LightColor0.rgb * albedo * 
                               max(0, dot(worldLightDir, worldNormal));
                
                return fixed4(ambient + diffuse, texColor.a * _AlphaScale);
            }
            ENDCG
        }
    }
    Fallback "Diffuse"
}

六、ShaderLab的混合命令

 混合是如何实现的:

当片元着色器产生一个颜色时,可以选择与颜色缓存中的颜色进行混合。这样一来混合就和两个操作有关:源颜色和目标颜色。

源颜色:用S表示。指由片元着色器产生的颜色值;

目标颜色:用D表示,指的是从颜色缓冲中读取到的颜色值。

输出颜色:对它们混合后得到的输出颜色用O表示,它会重新写入颜色缓冲区中。

注意:当我们谈及混合中的源颜色、目标颜色和输出颜色时,它们都包含了RGBA四个通道值,并非仅仅时RGB通道

如何开始混合: 

在Unity中,使用Blend(Blend Off命令除外)命令时,除了设置混合状态也开启了混合。但在其他图像API中要手动开启。如OpenGL中,我们要使用glEnable(GL_BLEND)来开启混合。但在Unity中,他已经在背后为我们做了这些工作

1.混合等式和参数

混合等式:用源颜色S和目标颜色D得到输出颜色O的等式。进行混合时,需要使用两个混合等式,一个用于混合RGB通道,一个用于混合A通道。当设置混合状态时,我们实际设置的就是混合等式中的操作和因子。

第一个命令指提供两个因子,使用同样的混合因子来混合RGB通道和A通道,即此时SrcFactorA将等于DStFactor。

使用这些因子进行加法混合时使用的混合公式:

O_{rgb}=SrcFactor\times S_{rgb}+DstFactor\times D_{rgb}

O_{a}=SrcFactorA\times S_{a}+DstFactorA\times D_{a}

混合因子有哪些值呢?

RGB通道的混合因子和A通道的混合因子都是一样的,有时我们希望可以使用不同的参数混合A通道,这时就可以利用Blend SrcFactor DstFactor, SrcFactorA  DstFactorA指令。

如:混合后,输出颜色的透明度值就是源颜色的透明度

Blend SrcAlphaA OneMinusSrcAlpha, One Zero

2.混合操作

BlendOp BlendOperation

 混合操作命令通常是与混合因子命令一起工作的。注意:当使用Min或Max混合操作时,混合因子不起作用,它们仅会判断原始的源颜色和目标颜色之间的比较结果

3.常见的混合类型

使用Min和Max混合操作时仍然设置了混合因子,但并不会对结果有任何影响 

七、双面渲染的透明效果

如果一个物体是透明的,意味着我们不仅可以透过它看其他物体的样子,也可以看到它内部的结构。但在现实的透明效果中,无论是透明度测试还是透明度混合,我们都无法观察到正方形内部以及其背面的形状,导致物体看起来好像只要半个。

默认情况下渲染引擎剔除物体背面的渲染图元,只渲染物体的正面。如果想要双面效果,可以使用Cull指令来控制需要剔除哪个面的渲染图元。

在unity中,Cull指令的语法如下:

Cull Back | Front | Off

Back:背对着摄像机的渲染图元就不会被渲染,这也是默认情况下的剔除状态;

Front:朝向摄像机的渲染图元不会被渲染;

Off:关闭剔除功能,所有图元都会被渲染,但需要渲染的图元会成倍增加,除特殊效果,一般是不会关闭的

1.透明度测试的双面渲染

如何使用透明测试实现双面渲染的效果。只需要在Pass的渲染设置中使用Cull指令来关闭剔除即可

2.透明度混合的双面渲染

把双面渲染的工作分成两个Pass——第一个Pass只渲染背面,第二个Pass只渲染正面,unity会顺序执行SubShader中的各个Pass,因此可以保证背面总是被渲染之前渲染,从而保证深度渲染关系正确

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

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

相关文章

信息系统项目管理师0141:产品范围和项目范围(9项目范围管理—9.1管理基础—9.1.1产品范围和项目范围)

点击查看专栏目录 文章目录 第9章 项目范围管理9.1 管理基础9.1.1 产品范围和项目范围 第9章 项目范围管理 项目范围管理包括确保项目做且只做所需的全部工作&#xff0c;以成功完成项目。项目范围管理主要在于定义和控制哪些工作应该包括在项目内&#xff0c;哪些不应该包含在…

Golang | Leetcode Golang题解之第131题分割回文串

题目&#xff1a; 题解&#xff1a; func partition(s string) (ans [][]string) {n : len(s)f : make([][]int8, n)for i : range f {f[i] make([]int8, n)}// 0 表示尚未搜索&#xff0c;1 表示是回文串&#xff0c;-1 表示不是回文串var isPalindrome func(i, j int) int8…

数据结构与算法之Floyd弗洛伊德算法求最短路径

目录 前言 Floyd弗洛伊德算法 定义 步骤 一、初始化 二、添加中间点 三、迭代 四、得出结果 时间复杂度 代码实现 结束语 前言 今天是坚持写博客的第18天&#xff0c;希望可以继续坚持在写博客的路上走下去。我们今天来看看数据结构与算法当中的弗洛伊德算法。 Flo…

如何学习SQL?YouTube近百万粉丝技术频道的学习路径图。

大家好&#xff0c;我是王有志&#xff0c;一个分享硬核 Java 技术的金融摸鱼侠&#xff0c;欢迎大家加入 Java 人自己的交流群“共同富裕的 Java 人”。 ByteByteGo 频道在 5 月 30 日的通信邮件中提到了“How to Learn SQL”这一主题&#xff0c;并给出了一张详细的学习路径…

python——网络编程

流程图 面向连接的套接字 面向连接的通信提供序列化的、可靠的和不重复的数据交付&#xff0c;而没有记录边界。主要的协议是传输控制协议&#xff08;TCP&#xff09;; TCP套接字&#xff0c;在python中&#xff0c;必须使用SOCK_STREAM作为套接字类型 tcp的特点 面向连接…

使用GitHub托管静态网页

前言​&#xff1a; 如果没有服务器&#xff0c;也没有域名&#xff0c;又想部署静态网页的同学&#xff0c;那就可以尝试使用GitHub托管自己的网页​。 正文&#xff1a; 首先要有自己的GitHub的账号&#xff0c;如果没有可以自己搜索官网进行注册登录&#xff0c;国内对Gi…

深入了解 C 语言 Bug

目录 一、引言二、Bug的定义三、Bug的由来四、Bug的影响五、应对 Bug 的方法六、结论 一、引言 1、在 C 语言的编程世界中&#xff0c;Bug 是一个我们无法回避的话题。 2、Bug&#xff0c;简单来说&#xff0c;就是程序中存在的错误或缺陷。它可以表现为程序运行结果的异常、崩…

容器运行nslookup提示bash: nslookup: command not found【笔记】

在容器中提示bash: nslookup: command not found&#xff0c;表示容器中没有安装nslookup命令。 可以通过以下命令安装nslookup&#xff1a; 对于基于Debian/Ubuntu的容器&#xff0c;使用以下命令&#xff1a; apt-get update apt-get install -y dnsutils对于基于CentOS/R…

机器学习、深度学习模型建模开发过程中常见的评估指标汇总学习记录

在机器学习、深度学习模型的开发过程中&#xff0c; 很重要的一个环节就是要对模型的性能进行评估分析&#xff0c;不同类型的任务不同的模型对应使用不同的评估指标体系&#xff0c;本文的主要目的是正好趁着最近有这块的需求&#xff0c;就想着找点时间把汇总学习的内容整理记…

TypeScript学习(一):开发环境搭建

官方文档搭建参考 https://learn.microsoft.com/zh-cn/training/modules/typescript-get-started/ 1.下载node.js https://nodejs.org/en/download 2.下载vscode https://code.visualstudio.com/ 3.在线ts的测试工具 https://www.typescriptlang.org/play/ 4.下载typescr…

Linux线程安全:线程互斥

一、线程互斥的概念 1.1临界资源与互斥的关系 临界资源&#xff1a;多线程执行流共享的资源就叫做临界资源。 临界区&#xff1a;每个线程内部&#xff0c;访问临界资源的代码&#xff0c;就叫做临界区。 互斥&#xff1a;任何时刻&#xff0c;互斥保证有且只有一个执行流进入…

274 基于matlab的随机粗糙表面对微气体轴承内气体压强分布的影响

基于matlab的随机粗糙表面对微气体轴承内气体压强分布的影响。采用差分法求解气体轴承的雷诺方程&#xff0c;通过尺寸参数、分形维数对粗糙度表面设置&#xff0c;滑流参数设置&#xff0c;实现气压分布可视化结果显示。程序已调通&#xff0c;可直接运行。 274 气体轴承 随机…

软件设计,建模及需求分析

文章目录 设计原则建模及需求分析重构 设计原则 SOLID原则 单一职责 开闭 &#xff08;扩展开放&#xff0c;修改关闭&#xff09; 里氏替换 &#xff08;父类出现地方都可以用子类替换&#xff09; 接口隔离 依赖倒置&#xff08;高层模块不依赖低层&#xff0c;两层都依…

[数据集][图像分类]茶叶叶子病害分类数据集304张4类别

数据集类型&#xff1a;图像分类用&#xff0c;不可用于目标检测无标注文件 数据集格式&#xff1a;仅仅包含jpg图片&#xff0c;每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数)&#xff1a;304 分类类别数&#xff1a;4 类别名称:[“anthracnose”,“bird_eye_spot”…

三维模型轻量化工具:手工模型、BIM、倾斜摄影等皆可用!

老子云是全球领先的数字孪生引擎技术及服务提供商&#xff0c;它专注于让一切3D模型在全网多端轻量化处理与展示&#xff0c;为行业数字化转型升级与数字孪生应用提供成套的3D可视化技术、产品与服务。 老子云是全球领先的数字孪生引擎技术及服务提供商&#xff0c;它专注于让…

端口映射如何检测?

端口映射是一种网络通信技术&#xff0c;它允许将公网IP地址的特定端口指向内部局域网中的特定设备或应用程序。通过端口映射&#xff0c;可以实现远程访问内部设备&#xff0c;解决了网络环境限制的问题。 在进行端口映射之前&#xff0c;需要进行端口映射检测&#xff0c;以确…

JS:setTimeout计时器优化

setTimeout会因为浏览器的事件循环机制导致计时器的误差&#xff0c;JS代码越复杂、越多&#xff0c;误差越大。 通过使用performance.now()可以一定程度上减小这个误差值。 performance.now()返回的是一个浮点数&#xff0c;表示从页面加载到现在的毫秒数&#xff0c;精度可…

动态数组的实现(仿写ArrayList)

动态数组是什么 之前写过一篇数组和静态数组的介绍&#xff1a;数组的定义和特点&#xff0c;静态数组CURD的实现 我们在静态数组的基础上&#xff0c;增加一些比较方便的功能&#xff0c;比如自动扩容&#xff0c;获取数组长度等&#xff0c;这样的数组叫动态数组 动态数组…

浅析Vue3基础知识(vue3笔记之入门篇)

本文是结合实践中和学习技术文章总结出来的笔记(个人使用),如有雷同纯属正常((✿◠‿◠)) 喜欢的话点个赞,谢谢! 时下Vue框架都是使用Vue3版本来开发项目了,为了加深对Vue3基本知识的了解,特写了这个笔记 1. 生命周期 1.1. vue3生命周期 一个组件从开始到结束,正常的生命周…

【免费】2021年数学建模国赛C题问题一--基于熵权法和TOPSIS法详细版附Word加代码

各位大佬好 &#xff0c;这里是阿川的博客&#xff0c;祝您变得更强 个人主页&#xff1a;在线OJ的阿川 大佬的支持和鼓励&#xff0c;将是我成长路上最大的动力 阿川水平有限&#xff0c;如有错误&#xff0c;欢迎大佬指正 Python 初阶 Python–语言基础与由来介绍 Python–…