Unity3D URP 仿蜘蛛侠风格化BloomAO

news2025/1/20 14:56:48

Unity3D URP 仿蜘蛛侠风格化Bloom&AO

  • Bloom
    • Bloom效果流程:
    • 制作控制面板VolumeComponent.CS
    • Custom Renderer Feather
    • Custom Renderer Pass
      • Bloom Shader
      • Composite Shader
    • 完善Custom Feather
    • 风格化AO
  • 总结

本篇文章介绍在URP中如何进行风格化后处理,使用Renderer Feather 和自定义 Render Pass 实现。这种做法比起使用PostProcessing具有很大的自由度,能够自由控制渲染时机,减少束缚。

本教程使用Unity2022.3.5f1 版本。较低版本Shader Graph 没有Full Screen Sample Buffer。

以下两张图是蜘蛛侠动画剧照,高光Bloom部分很多是点阵的方式表现,一些AO使用混合平行斜线来表现。
在这里插入图片描述
在这里插入图片描述

类似的卡通渲染方案也被游戏 HiFi Rush 所使用。
在这里插入图片描述

Bloom

Bloom效果流程:

Composite Shader
Bloom
Texture
Screen

先制作Bloom效果,将Bloom渲染到一张Texture上,再将这个Texture通过我们的风格化Shader最后渲染到屏幕上

原始Bloom基本参照Unity的做法,在Packages/com.unity.render-pipelines.core/Runtime 文件夹中可找到相关代码

制作控制面板VolumeComponent.CS

  1. 直接复制Unity Bloom需要的控制参数。
  2. 添加我们风格化点阵需要的控制参数。
[VolumeComponentMenuForRenderPipeline("CustomBloomEffect", typeof(UniversalRenderPipeline))]
public class CustomBloomEffectComponent : VolumeComponent, IPostProcessComponent
{
    //bloom settings copy from Unity default Bloom
    [Header("Bloom Settings")]
    public FloatParameter threshold = new FloatParameter(0.9f,true);
    public FloatParameter intensity = new FloatParameter(1,true);
    public ClampedFloatParameter scatter = new ClampedFloatParameter(0.7f,0,1,true);
    public IntParameter clamp = new IntParameter(65472,true);
    public ClampedIntParameter maxIterations = new ClampedIntParameter(6,0,10);
    public NoInterpColorParameter tint = new NoInterpColorParameter(Color.white);
	
	//Custom Bloom Dots
    [Header("Dots")] 
    public IntParameter dotsDensity = new IntParameter(10,true);
    public ClampedFloatParameter dotsCutoff = new ClampedFloatParameter(0.4f,0,1, true);
    public Vector2Parameter scrollDirection = new Vector2Parameter(new Vector2());
    
    [Header("AOLines")]
    public ClampedFloatParameter linesWidth = new ClampedFloatParameter(0.001f,0.001f,0.01f, true);
    public ClampedFloatParameter linesIntensity = new ClampedFloatParameter(0.05f,0,0.05f, true);
    public ColorParameter linesColor = new ColorParameter(Color.black, true, true, true);
    public FloatParameter linesAngle = new FloatParameter(30f, true);
    
    public bool IsActive()
    {
        return true;
    }

    public bool IsTileCompatible()
    {
        return false;
    }
}
  1. 将这个脚本挂载到场景中,我们就得到了一个和Unity原生很相识的一个控制面板,并且有新增的Dots控制功能:
    在这里插入图片描述

Custom Renderer Feather

参照Unity自带的Renderer Feather 我们可仿写一个我们自己的Renderer Feather
Unity自带Renderer Feather 目录:
在这里插入图片描述

Custom Renderer Pass

先创建一个简单的自定义Pass,这是渲染Pass,在FrameDebugger中这些根节点都是一个Pass,如图:
在这里插入图片描述
最简代码如下:

[System.Serializable]
public class CustomPostProcessPass : ScriptableRenderPass{
	public override void Execute(ScriptableRenderContext context,ref RenderingData renderingData)
	}
	
	}
}

然后我们再创建一个Custom Renderer Feather
代码:

[System.Serializable]
public class CustomPostProcessRendererFeature : ScriptableRendererFeature{
	private CustomPostProcessPass m_customPass;
	public override void AddRenderPasses(ScriptableRenderer renderer,ref RenderingData renderingData){
		renderer.EnqueuePass(m_customPass);
	}
	public override void Create(
		m_customPass = new CustomPostProcessPass()
	}
}

有了这两个后,我们就能在Renderer Data 面板中添加这个新Feather了
在这里插入图片描述

Bloom Shader

这个为了方便直接复制Unity自带的Bloom。地址:Packages/com.unity.render-pipelines.universal/Shaders/PostProcessing/Bloom.shader

Composite Shader

  1. 使用Shader Graph 制作用于风格化Bloom后的Texture。创建一个FullscreenShaderGraph(Unity 2022以上)
    在这里插入图片描述
  2. 创建SampleTexture2D 节点,并且修改名称,注意Reference名称,我们需要通过这个名称向shader传入bloom texture
    在这里插入图片描述
  3. 使用Voronoi Node输 设置AngleOffset为0, 使用Screen Position 作为UV 得到一组排列整齐的圆点格子,创建Density属性,用于控制格子密度(大小)
    在这里插入图片描述
  4. 再通过一个Comparision Node 这样得到1,0分明的圆点,并创建Cutoff属性进行圆点占据格子比例大小控制
    在这里插入图片描述
  5. 使用URP Sample Buffer(这个就是当前屏幕渲染图像Screen Texture) 和点阵相加。
    在这里插入图片描述
  6. 完整的shader graph:
    在这里插入图片描述

完善Custom Feather

这个主要参考Unity URP的Bloom PostProcession写法。
CustomPostProcessRenderFeature 完整代码:

public class CustomPostProcessRenderFeature : ScriptableRendererFeature
{
    [SerializeField]
    private Shader m_bloomShader;
    [SerializeField]
    private Shader m_compositeShader;
    
    private Material m_bloomMaterial;
    private Material m_compositeMaterial;
    
    private CustomPostProcessPass m_customPass;
    
    public override void Create()
    {
        m_bloomMaterial = CoreUtils.CreateEngineMaterial(m_bloomShader);
        m_compositeMaterial = CoreUtils.CreateEngineMaterial(m_compositeShader);
        m_customPass = new CustomPostProcessPass(m_bloomMaterial, m_compositeMaterial);
    }

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        
        renderer.EnqueuePass(m_customPass);
    }
    
    public override void SetupRenderPasses(ScriptableRenderer renderer, in RenderingData renderingData)
    {
        if (renderingData.cameraData.cameraType == CameraType.Game)
        {
            m_customPass.ConfigureInput(ScriptableRenderPassInput.Depth);
            m_customPass.ConfigureInput(ScriptableRenderPassInput.Color);
            m_customPass.SetTarget(renderer.cameraColorTargetHandle, renderer.cameraDepthTargetHandle);
        }
    }
    
    protected override void Dispose(bool disposing)
    {
        CoreUtils.Destroy(m_bloomMaterial);
        CoreUtils.Destroy(m_compositeMaterial);
    }
}

CustomPostProcessingPass 完整代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.Rendering.Universal.Internal;

public class CustomPostProcessPass : ScriptableRenderPass
{
    private Material m_bloomMaterial;
    private Material m_compositeMaterial;

    //RTHandles 是一种特殊RenderTexture,它可以在运行时动态调整大小,而不是在编辑器中预先分配固定大小的RenderTexture。
    private RTHandle m_CameraColorTarget;
    private RTHandle m_CameraDepthTarget;
    
    const int k_MaxPyramidSize = 16;
    private int[] _BloomMipUp;
    private int[] _BloomMipDown;
    private RTHandle[] m_BloomMipUp;
    private RTHandle[] m_BloomMipDown;
    private GraphicsFormat hdrFormat;
    private CustomBloomEffectComponent m_BloomEffect;
    private RenderTextureDescriptor m_Descriptor;
    private static readonly int ScreenSpaceOcclusionTexture = Shader.PropertyToID("_ScreenSpaceOcclusionTexture");


    public void SetTarget(RTHandle cameraColorTarget, RTHandle cameraDepthTarget)
    {
        this.m_CameraColorTarget = cameraColorTarget;
        this.m_CameraDepthTarget = cameraDepthTarget;
    }

    public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
    {
        m_Descriptor = renderingData.cameraData.cameraTargetDescriptor;
    }

    public CustomPostProcessPass(Material bloomMaterial, Material compositeMaterial)
    {
        this.m_bloomMaterial = bloomMaterial;
        this.m_compositeMaterial = compositeMaterial;
        
        renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing;

        _BloomMipUp = new int[k_MaxPyramidSize];
        _BloomMipDown = new int[k_MaxPyramidSize];
        m_BloomMipUp = new RTHandle[k_MaxPyramidSize];
        m_BloomMipDown = new RTHandle[k_MaxPyramidSize];

        for (int i = 0; i < k_MaxPyramidSize; i++)
        {
            _BloomMipUp[i] = Shader.PropertyToID("_BloomMipUp" + i);
            _BloomMipDown[i] = Shader.PropertyToID("_BloomMipDown" + i);
            
            m_BloomMipUp[i] = RTHandles.Alloc(_BloomMipUp[i], name: "_BloomMipUp" + i);
            m_BloomMipDown[i] = RTHandles.Alloc(_BloomMipDown[i], name: "_BloomMipDown" + i);
        }

        const FormatUsage usage = FormatUsage.Linear | FormatUsage.Render;
        if (SystemInfo.IsFormatSupported(GraphicsFormat.B10G11R11_UFloatPack32, usage)) //判断是否支持HDR格式
        {
            hdrFormat = GraphicsFormat.B10G11R11_UFloatPack32;
        }
        else
        {
            hdrFormat = QualitySettings.activeColorSpace == ColorSpace.Linear ? GraphicsFormat.R8G8B8_SRGB : GraphicsFormat.R8G8B8_UNorm;
        }
    }

    public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    {
        VolumeStack stack = VolumeManager.instance.stack;
        m_BloomEffect = stack.GetComponent<CustomBloomEffectComponent>();
        
        CommandBuffer cmd = CommandBufferPool.Get();

        //使用ProfilingScope 才能在FrameDebugger中看到
        using (new ProfilingScope(cmd, new ProfilingSampler("Custom Post Process Effect")))
        {
            Texture ssaoTex = Shader.GetGlobalTexture(ScreenSpaceOcclusionTexture);
            m_compositeMaterial.SetTexture("_SSAOTexture", ssaoTex);
            //Shader.SetGlobalTexture("_SSAOTexture", ssaoTex);
            
            SetupBloom(cmd, m_CameraColorTarget);
            
            m_compositeMaterial.SetFloat("_Cutoff", m_BloomEffect.dotsCutoff.value);
            m_compositeMaterial.SetFloat("_Density", m_BloomEffect.dotsDensity.value);
            m_compositeMaterial.SetVector("_Direction", m_BloomEffect.scrollDirection.value);
            m_compositeMaterial.SetFloat("_LineWidth", m_BloomEffect.linesWidth.value);
            m_compositeMaterial.SetFloat("_LineIntensity", m_BloomEffect.linesIntensity.value);
            m_compositeMaterial.SetColor("_LineColor", m_BloomEffect.linesColor.value);
            m_compositeMaterial.SetFloat("_LineAngle", m_BloomEffect.linesAngle.value);
            
            Blitter.BlitCameraTexture(cmd, m_CameraColorTarget, m_CameraColorTarget, m_compositeMaterial, 0);
        }
        
        context.ExecuteCommandBuffer(cmd);
        cmd.Clear();
        CommandBufferPool.Release(cmd);
    }

    private void SetupBloom(CommandBuffer cmd, RTHandle source)
    {
        // 初始大小减半 降采样
        int downres = 1;
        int tw = m_Descriptor.width >> downres;
        int th = m_Descriptor.height >> downres;
        
        //Determine the iteration count based on the size of the pyramid
        int maxSize = Mathf.Max(tw, th);
        int iterations = Mathf.FloorToInt(Mathf.Log(maxSize,2f) - 1);
        int mipCount = Mathf.Clamp(iterations,1, m_BloomEffect.maxIterations.value);
        
        // Pre-filtering parameters
        float clamp = m_BloomEffect.clamp.value;
        float threshold = Mathf.GammaToLinearSpace(m_BloomEffect.threshold.value);
        float thresholdKnee = threshold * 0.5f;// Hardcoded soft knee
        
        // Material setup
        float scatter = Mathf.Lerp(0.05f,0.95f,m_BloomEffect.scatter.value);
        var bloomMaterial = m_bloomMaterial;
        bloomMaterial.SetVector("_Params",new Vector4(scatter,clamp,threshold,thresholdKnee));
        
        //Prefilter
        var desc = GetCompatibleDescriptor(tw,th,hdrFormat);
        for (int i = 0; i < mipCount; i++)
        {
            RenderingUtils.ReAllocateIfNeeded(ref m_BloomMipUp[i],desc,FilterMode.Bilinear,TextureWrapMode.Clamp,name: m_BloomMipUp[i].name);
            RenderingUtils.ReAllocateIfNeeded(ref m_BloomMipDown[i], desc, FilterMode.Bilinear, TextureWrapMode.Clamp,
                name: m_BloomMipDown[i].name);
            desc.width = Mathf.Max(1, desc.width >> 1);
            desc.height = Mathf.Max(i, desc.height >> i);
        }
        
        Blitter.BlitCameraTexture(cmd, source, m_BloomMipDown[0], RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, bloomMaterial, 0);
        
        //Downsample
        var lastdown = m_BloomMipDown[0];
        for (int i = 0; i < mipCount - 1; i++)
        {
            //第一个Pass是 2x 降采样 + 9tap高斯模糊
            //第二个Pass是 使用5tap过滤的9tap高斯模糊 + 双线性过滤 
            Blitter.BlitCameraTexture(cmd, lastdown, m_BloomMipUp[i], RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, bloomMaterial, 1);
            Blitter.BlitCameraTexture(cmd, m_BloomMipUp[i], m_BloomMipDown[i], RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, bloomMaterial, 2);

            lastdown = m_BloomMipDown[i];
        }

        // Upsample
        for (int i = mipCount - 2; i >= 0; i--)
        {
            
            var lowMip = (i == mipCount - 2)? m_BloomMipDown[i + 1] : m_BloomMipUp[i + 1];
            var highMip = m_BloomMipDown[i];
            var dst = m_BloomMipUp[i];
            
            cmd.SetGlobalTexture("_SourceTexLowMip", lowMip);

            Blitter.BlitCameraTexture(cmd, highMip, dst, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, bloomMaterial, 3);
        }
        
        m_compositeMaterial.SetTexture("_Bloom_Texture", m_BloomMipUp[0]);
        m_compositeMaterial.SetFloat("_BloomIntensity", m_BloomEffect.intensity.value);
        cmd.SetGlobalFloat("_BloomIntensity", m_BloomEffect.intensity.value);
    }

    private RenderTextureDescriptor GetCompatibleDescriptor()
    {
        return GetCompatibleDescriptor(m_Descriptor.width, m_Descriptor.height, m_Descriptor.graphicsFormat);
    }

    private RenderTextureDescriptor GetCompatibleDescriptor(int tw, int th, GraphicsFormat graphicsFormat, DepthBits depthBufferBits = DepthBits.None)
    {
        return GetCompatibleDescriptor(m_Descriptor, tw, th, graphicsFormat, depthBufferBits);
    }
    
    internal static RenderTextureDescriptor GetCompatibleDescriptor(RenderTextureDescriptor desc, int tw, int th, GraphicsFormat format, DepthBits depthBufferBits = DepthBits.None)
    {
        desc.depthBufferBits = (int)depthBufferBits;
        desc.width = tw;
        desc.height = th;
        desc.graphicsFormat = format;
        desc.msaaSamples = 1;
        return desc;
    }
    
}

在Renderer Data上吧Bloom Shader 和Composite Shader 拖拽进去
在这里插入图片描述
成功运行就能看到结果了:

在这里插入图片描述

风格化AO

要点: 添加Screen Space Ambient Occlusion 然后通过_ScreenSpaceOcclusionTexture 获取AO贴图,再把AO贴图作为Mask,在Mask内画斜线。
在这里插入图片描述

private static readonly int ScreenSpaceOcclusionTexture = Shader.PropertyToID("_ScreenSpaceOcclusionTexture");

可以在Composite Shader一起处理
一种效果如下:
在这里插入图片描述

总结

在实际游戏中,这些效果处理要更加复杂一些,这里给大家开个头,发挥想象把效果做得更出彩吧~

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

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

相关文章

【MATLAB第74期】#源码分享 | 基于MATLAB的ARX-ARMAX线性自回归移动平均外生模型(结合最小二乘思路)

【MATLAB第74期】#源码分享 | 基于MATLAB的ARX-ARMAX线性自回归移动平均外生模型&#xff08;结合最小二乘思路&#xff09; 根据ARX预测输出和实际输出的误差向量&#xff0c;采用ARMAX算法结合ARX误差建模&#xff0c;对预测值进一步细化。通过将误差描述为白噪声的移动平均…

Spring事务管理: 构建稳健的数据库事务处理

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

C++算法 —— 动态规划(4)子数组

文章目录 1、动规思路简介2、最大子数组和3、环形子数组的最大和4、乘积最大子数组5、乘积为正数的最长子数组长度6、等差数列划分7、最长湍流子数组8、单词拆分9、环绕字符串中唯一的子字符串 每一种算法都最好看完第一篇再去找要看的博客&#xff0c;因为这样会帮你梳理好思路…

商城系统优化

1、DB、模板的渲染速度&#xff08;thymeleaf&#xff09;、静态资源、日志、JVM 数据库的优化&#xff08;参照数据库优化课程&#xff09;使用索引&#xff0c;减少数据库的交互次数、缓存 thymeleaf使用缓存 静态资源&#xff1a;放到nginx中&#xff0c;实现动静分离 2、…

【数学】ABC 319 E

E - Bus Stops 题意&#xff1a; 思路&#xff1a; 感觉思路比较简单 首先注意到每个询问的范围是1e9&#xff0c;不难想到答案一定存在某个循环节&#xff0c;最后一定是要 %T的 那么问题就在于找到这个循环节是什么 猜想循环节为lcm(p1, p2, p3, ....) 用小数据验证 n…

一篇博客教会您SpringMVC文件上传、下载,多文件上传及工具jrebel的使用

目录 一.文件上传 二.文件下载 三.多文件上传 四&#xff0c;jrebel的介绍 前言&#xff1a; 我们之前已经实现了SpringMVC的增删改查&#xff0c;今天这一篇博客教会您SpringMVC文件上传、下载&#xff0c;多文件上传及工具jrebel的使用&#xff0c;希望这篇博客能够给正在…

二、Spark 调度系统

目录 Spark 调度系统DAGSchedulerSchedulerBackendTaskSchedulerExecutorBackendSpark 任务调度流程 Spark 调度系统 分布式计算的精髓&#xff0c;在于如何把抽象的计算图&#xff0c;转化为实实在在的分布式计算任务&#xff0c;然后以并行计算的方式交付执行。 Spark调度系…

Mojo安装使用初体验

一个声称比python块68000倍的语言 蹭个热度&#xff0c;安装试试 系统配置要求&#xff1a; 不支持Windows系统 配置要求: 系统&#xff1a;Ubuntu 20.04/22.04 LTSCPU&#xff1a;x86-64 CPU (with SSE4.2 or newer)内存&#xff1a;8 GiB memoryPython 3.8 - 3.10g or cla…

华为云云耀云服务器L实例评测 | 分分钟完成打地鼠小游戏部署

前言 在上篇文章【华为云云耀云服务器L实例评测 | 快速部署MySQL使用指南】中&#xff0c;我们已经用【华为云云耀云服务器L实例】在命令行窗口内完成了MySQL的部署并简单使用。但是后台有小伙伴跟我留言说&#xff0c;能不能用【华为云云耀云服务器L实例】来实现个简单的小游…

车载诊断数据库——诊断问卷调查表与CDD关联关系

车载诊断数据库——诊断问卷调查表与CDD关联关系 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 没有人关注你。也无需有人关注你。你必须承认自己的价值,你不能站在他人的角度来反对自己。人生…

超级电容-电池-超级电容混合储能系统能量管理simulink仿真建模模型

建立混合储能系统模型 在Simulink中&#xff0c;首先需要建立一个超级电容和蓄电池并联的混合储能系统模型。其中&#xff0c;超级电容和蓄电池的荷电状态&#xff08;SOC&#xff09;需要根据实际情况进行管理。荷电状态可以通过对电池和超级电容的电压、电流等进行测量&…

说透 Nacos 一致性协议

1 Nacos ⼀致性协议 1.1 为什么 Nacos 需要⼀致性协议 Nacos尽可能减少用户部署以及运维成本&#xff0c;做到用户只需要⼀个程序包&#xff0c;就快速单机模式启动 Nacos 或集群模式启动 Nacos。而 Nacos 是⼀个需要存储数据的组件&#xff0c;为实现目标&#xff0c;就要在…

透视俄乌网络战之二:Conti勒索软件集团(上)

透视俄乌网络战之一&#xff1a;数据擦除软件 Conti勒索软件集团&#xff08;上&#xff09; 1. Conti简介2. 组织架构3. 核心成员4. 招募途径5. 工作薪酬6. 未来计划参考 1. Conti简介 Conti于2019年首次被发现&#xff0c;现已成为网络世界中最危险的勒索软件之一&#xff0…

汇川PLC学习Day3:轴控代码编写、用户程序结构说明与任务配置示例、

汇川PLC学习Day3&#xff1a;轴控代码编写、用户程序结构说明、任务配置示例 一、新建轴与轴控代码编写 1. 新建轴 (1)新建一个轴 &#xff08;2&#xff09;将轴名字更新为实际名字 可以后面实例化后再更改&#xff0c;汇川可以在更新名字时同步更新其他编写的代码名字&a…

GStreamer时钟同步

播放复杂媒体时&#xff0c;每个audio和video sample必须在特定时间按特定顺序播放。为此&#xff0c;GStreamer提供了一种同步机制&#xff0c;通过使用 GstClock object、buffer timestamps和SEGMENT event来实现&#xff1a; &#xff08;1&#xff09;GstClock&#xff1a;…

Java中如何获取一个字符串是什么类型

Java中如何获取一个字符串是什么类型&#xff1f; 在Java中&#xff0c;您可以使用一些方法来确定一个字符串的类型。下面是一些常用的方法&#xff1a; 使用正则表达式&#xff1a;您可以使用正则表达式来匹配字符串是否符合特定的模式或格式&#xff0c;以确定其类型。例如&…

【Linux入门指北】Linux磁盘扩容

文章目录 1、给 / 分区扩容 Linux在使用过程中由于数据量不断增大&#xff0c;导致磁盘空间不足&#xff0c;需要增加磁盘空间&#xff0c;主要有以下三种方式: 直接给 / 分区&#xff08;或者某一分区&#xff09;扩容&#xff0c;直接在原有磁盘上增大空间给虚拟机新增一块磁…

typeScript 学习笔记(二)

类接口 TypeScript 入门教程 (xcatliu.com) 十四.类 ① 类 类&#xff1a;定义了一件事物的抽象特点&#xff0c;包含它的属性和方法对象&#xff1a;类的实例&#xff0c;通过new生成面向对象&#xff08;OOP&#xff09;的三大特性&#xff1a;封装、继承、多态封装&…

C++学习笔记(重载、类)

C 1、函数重载2、类2.1、类的方法和属性2.2、类的方法的定义2.3、构造器和析构器2.4、基类与子类2.5、类的public、protected、private继承2.6、类的方法的重载2.7、子类方法的覆盖2.8、继承中的构造函数和析构函数 1、函数重载 函数重载大概可以理解为&#xff0c;定义两个名…