5.透明效果

news2024/12/23 15:40:49

实时渲染中要实现透明效果,通常会在渲染模型时控制它的透明通道(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,因此可以保证背面总是被渲染之前渲染,从而保证深度渲染关系正确

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

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

相关文章

php质量工具系列之phpmd

PHPMD PHP Mess Detector 它是PHP Depend的一个衍生项目&#xff0c;用于测量的原始指标。 PHPMD所做的是&#xff0c;扫描项目中可能出现的问题如&#xff1a; 可能的bug次优码过于复杂的表达式未使用的参数、方法、属性 PHPMD是一个成熟的项目&#xff0c;它提供了一组不同的…

网站安全小白也能搞定的SSL证书安装免费方法

大家都知道&#xff0c;部署一个网站&#xff0c;除了购买域名&#xff0c;现在基本标配SSL证书。 我们以aliyun为例 大家看到这个&#xff0c;收费的SSL证书几千-几万1年不等。这时候&#xff0c;你就会想有没有免费的可以搞。linux老鸟都知道&#xff0c; Let’s Encrypt 、…

痛风患者饮食指南

文章目录 &#x1f4d6; 介绍 &#x1f4d6;&#x1f4d2; 饮食指南 &#x1f4d2;&#x1f957; 可食用食品&#x1f966; 蔬菜类&#x1f34e; 水果类&#x1f33e; 全谷物&#x1f95b; 低脂奶制品&#x1f330; 坚果类&#xff08;适量&#xff09;&#x1fad8; 豆制品&am…

RunLoop小白入门

核心概念 什么是 RunLoop ? RunLoop 是 iOS 和 macOS 应用程序框架中的一个核心概念&#xff0c;用于管理线程的事件处理。它可以看作是一个循环&#xff0c;用于持续接收和处理各种事件&#xff0c;如用户输入、定时器、网络事件等。RunLoop 在保持应用程序响应用户交互和系…

docker create rm export exec命令详解

容器生命周期管理命令教程-3 1. 创建容器 docker create&#xff1a;创建一个新的容器但不启动它。 docker create -it --name mycontainer ubuntu bash通常使用 docker run(详细可看上一篇关于run命令的详细介绍) 2. 删除容器 docker rm&#xff1a;删除一个或多个容器。 d…

T-Pot多功能蜜罐实践@debian12@FreeBSD

T-Pot介绍 T-Pot是一个集所有功能于一身的、可选择分布式的多构架&#xff08;amd64&#xff0c;arm64&#xff09;蜜罐平台&#xff0c;支持20多个蜜罐和很多可视化选项&#xff0c;使用弹性堆栈、动画实时攻击地图和许多安全工具来进一步改善欺骗体验。GitHub - telekom-sec…

如何让 VSCode 认识你正在开发的 NPM 模块

假如你正在开发一个 NPM 模块 echox&#xff0c;并且在 src/index.js 里面导出了一系列方法: // ./src/index.js export function html() {// ... }然后在 tests/index.spec.js 里面新增了以下一行&#xff1a; // ./tests/index.spec.js import * as X from echox;如何让 VS…

【面试干货】SQL中count(*)、count(1)和count(column)的区别与用法

【面试干货】SQL中count&#xff08;*&#xff09;、count&#xff08;1&#xff09;和count&#xff08;column&#xff09;的区别与用法 1、count(*)2、count(1)3、count(column) &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在SQL中&a…

【Qt 学习笔记】Qt窗口 | 对话框 | Qt对话框的分类及介绍

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt窗口 | 对话框 | 模态对话框 文章编号&#xff1a;Qt 学习笔记 / 51…

【成品设计】基于STM32的智能厨房环境监测与报警系统

《基于STM32的智能厨房环境监测与报警系统》 所需器件&#xff1a; stm32f103c8t6烟雾气体传感器可燃性气体传感器温度传感器语音播放器模块和LED灯进行语音声光播报WIFI模块进行远程播报OLED 屏幕来显示火灾信息 整体功能&#xff1a; 通过温湿度传感器、烟雾气体传感器、…

数据可视化之常用图表热力图

1.什么是热力图&#xff1f; 热力图&#xff0c;是一种通过对色块着色来显示数据的统计图表。 绘图时&#xff0c;需指定颜色映射的规则。 例如&#xff0c;较大的值由较深的颜色表示&#xff0c;较小的值由较浅的颜色表示&#xff1b;较大的值由偏暖的颜色表示&#xff0c;…

搭建Vulnhub靶机网络问题(获取不到IP)

搭建好靶场后&#xff0c;在攻击机运行arp-scan -l无法发现靶机IP。 这时候去看下靶机网络有没有问题。 重新启动客户机&#xff0c;一直按e进入安全模式&#xff08;要是直接开机了就先按shift进入grub界面&#xff0c;再按e&#xff09;找到ro&#xff0c;将ro改为rw signie…

SELinux深度解析:安全增强型Linux的探索与应用(下)

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Linux &#xff1a;从菜鸟到飞鸟的逆袭》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、SELinux的工作机制 1、SELinux的三种状态&#xff1a;Pe…

SpringSecurity6从入门到实战之默认用户的生成流程

SpringSecurity6从入门到实战之默认用户的生成流程 这次还是如标题所示,上一章我们的登录页面已经知道是如何生成了.那么,我们通过表单登录的user用户以及密码SpringSecurity是如何进行生成的呢? 默认用户生成 让我们把登录流程重新拉回到读取/META-INF/spring/ .imports文件 …

Python用于简化数据操作和分析工作库之DaPy使用详解

概要 在数据科学和机器学习领域,处理和分析数据是关键的一步。Python 的 DaPy 库提供了一组强大的工具,用于简化数据操作和分析工作。DaPy 旨在提供高效且直观的 API,使得数据处理变得更加便捷。本文将详细介绍 DaPy 库,包括其安装方法、主要特性、基本和高级功能,以及实…

Python3 迭代器和生成器

前言 本文主要介绍Python中的迭代器和生成器&#xff0c;主要内容包括 迭代器概述、生成器简介。 文章目录 前言一、迭代器简介二、生成器简介 一、迭代器简介 在 Python 中&#xff0c;迭代器(iterator)是一个实现了迭代器协议&#xff08;Iterator Protocol&#xff09;的…

【JavaEE进阶】——MyBatis操作数据库 (#{}与${} 以及 动态SQL)

目录 &#x1f6a9;#{}和${} &#x1f388;#{} 和 ${}区别 &#x1f388;${}使用场景 &#x1f4dd;排序功能 &#x1f4dd;like 查询 &#x1f6a9;数据库连接池 &#x1f388;数据库连接池使⽤ &#x1f6a9;MySQL开发企业规范 &#x1f6a9;动态sql &#x1f388…

【Python】 探索Python中的目录遍历:获取当前目录下所有子目录列表

基本原理 在Python中&#xff0c;处理文件和目录是一项常见的任务&#xff0c;尤其是在进行文件管理、数据备份或自动化脚本时。Python的os模块提供了丰富的功能来与操作系统进行交互&#xff0c;包括文件和目录的遍历。要获取当前目录下的所有子目录&#xff0c;我们可以使用…

3年前端期望18K,云账户社招一面

一二面会有手写代码测试&#xff0c;一面或者二面当中&#xff0c;有一面必须到现场来的&#xff0c;对工作环境有一个直观的感受&#xff0c;前端二面取消了 一面&#xff08;通过&#xff09; 1、自我介绍、项目经历 2、怎么跟 xx模板的开发同学去沟通的呢&#xff1f;此处…

C++标准模板(STL)- 迭代器库-迭代器适配器- 逆序遍历的迭代器适配器 (二)

迭代器库-迭代器原语 迭代器库提供了五种迭代器的定义&#xff0c;同时还提供了迭代器特征、适配器及相关的工具函数。 迭代器分类 迭代器共有五 (C17 前)六 (C17 起)种&#xff1a;遗留输入迭代器 (LegacyInputIterator) 、遗留输出迭代器 (LegacyOutputIterator) 、遗留向前…