Chapter9 更复杂的光照——Shader入门精要学习笔记

Chapter9 更复杂的光照

  • 一、Unity的渲染路径
    • 1.渲染路径的概念
    • 2.渲染路径的类型
      • ①前向渲染路径
        • a. 前向渲染路径的原理
        • b. Unity中的前向渲染
        • c. 两种Pass
      • ②延迟渲染路径
        • a. 延迟渲染路径的原理
        • b. Unity中的延迟渲染
        • c. 两种Pass
      • ③顶点照明渲染路径
  • 二、Unity的光源类型
    • 1.光源类型
      • ①平行光
      • ②点光源
      • ③聚光灯
    • 2.前向渲染中处理不同的光源
      • ①实践
        • Base Pass
        • Additional Pass
  • 三、Unity光照衰减
    • 1.用于光照衰减的纹理
    • 2.数学公式计算
  • 四、Unity的阴影
    • 1.阴影如何实现
      • ①Shadow Map的生成
      • ②屏幕空间的阴影映射技术
      • ③阴影映射
    • 4.Unity Shader 使用内置宏和函数 来统一管理光照衰减和阴影
      • ①光照衰减和阴影的影响
      • ②内置宏 UNITY_LIGHT_ATTENUATION
    • 5.透明物体阴影的办法
      • ①透明物体阴影问题
      • ②透明度测试 物体的阴影处理
      • ③透明度混合 物体的阴影处理
  • 五、标准的Unity Shader

一、Unity的渲染路径

1.渲染路径的概念

渲染路径是 Unity 处理光照信息的方式,它决定了光照是如何被应用到 Unity Shader 中的。简单来说,渲染路径就像一个“沟通桥梁”,它告诉 Unity 底层渲染引擎,开发者想要以哪种方式来处理光照,以及需要哪些光照信息

2.渲染路径的类型

大多数情况下一个项目只使用一个渲染路径,在Player Setting中进行Rendering Path设置。也可以在每个摄像机中设置该摄像机的渲染路径。完成设置后,就可以在每个Pass中 使用 LightMode 标签 来指定Pass使用的渲染路径。
在这里插入图片描述

①前向渲染路径

a. 前向渲染路径的原理
  • 它将每个光源的光照计算独立进行,并逐个应用到物体上
  • 每进行一次完整的前向渲染,需要渲染该对象的渲染图元,计算两个缓冲区信息:颜色缓冲区(更新颜色缓存区中的颜色值)和 深度缓冲区(决定一个片元是否可见)
  • 对每个逐像素光源都要进行一次这样的Pass渲染,如果有多个逐像素光源,就要进行多次
b. Unity中的前向渲染
  • 渲染一个物体时,Unity会计算哪些光源照亮了它,以及这些光源照亮该物体的方式
  • 前向渲染中有三种照亮物体的方式:逐顶点处理、逐像素处理、球谐函数(SH)处理
  • 决定光源用哪种处理模式取决于 类型 和 渲染模式
    • 类型:指光源是平行光还是什么
    • 渲染模式:指该光源是否重要,重要就是逐像素
      在这里插入图片描述
c. 两种Pass
  • 前向渲染路径通常包含两个 Pass
  • Base Pass: 计算环境光、最重要的平行光(1个)、逐顶点/SH 光源和 Lightmaps
    • 只会执行一次
  • Additional Pass: 计算额外的逐像素光源,每个光源对应一个 Pass(不支持阴影)
    • 每个逐像素光源会被调用一次
    • 还开启和设置了渲染模式,每个Additional Pass可以与上一次的光照结果在帧缓存中进行叠加

②延迟渲染路径

a. 延迟渲染路径的原理
  • 除了前向渲染用到的颜色缓冲和深度缓冲,延迟渲染还会用到G缓冲(G-buffer),存储了我们所关心的表面的其他信息(法线、位置、用于光照计算的材质属性)
b. Unity中的延迟渲染
  • 若光源数目多,前向渲染会造成性能瓶颈,就适合延迟渲染;延迟渲染中每个光源都可以按逐像素的方式处理
  • 缺点:
    • 不支持真正的抗锯齿(anti-aliasing)
    • 不能处理半透明物体
    • 对显卡有要求
c. 两种Pass
  • 第一个Pass:不进行任何光照计算,仅仅计算哪些片元是可见的(深度缓冲);如果该片元可见,就把相关信息存储到G缓冲区中
    • 漫反射颜色、高光反射颜色、平滑度、法线、自发光和深度信息
  • 第二个Pass:利用G缓冲区中的信息进行真正的光照计算
  • 不依赖与场景复杂度,而是与屏幕空间的大小有关(缓冲区可以理解为2D图像,空间即为图像空间)

③顶点照明渲染路径

  • 一种简单的渲染方式,它只使用逐顶点光照,不支持阴影、法线映射等高级光照效果

二、Unity的光源类型

  • Unity中有4中类型:平行光、点光源、聚光灯和面光源(面光源仅在烘焙时用到)

1.光源类型

①平行光

没有具体位置,也没有衰减,所有点的方向都是一样的

②点光源

  • 照亮的范围可以由面板中Range来调,有光照衰减(衰减可以由函数定义)
  • 需要用 点光源的位置 - 某点位置 来得到该点的方向

③聚光灯

  • 是一块锥形区域,半径由Range来调,角度由Spot Angle来调,有光照衰减(衰减可以由函数定义)
  • 需要用 聚光灯的位置 - 某点位置 来得到该点的方向

2.前向渲染中处理不同的光源

  • 如何在Shader中访问5个属性:位置、方向、颜色、强度、衰减

①实践

// Upgrade NOTE: replaced '_LightMatrix0' with 'unity_WorldToLight'
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Unity Shaders Book/Chapter 9/Forward Rendering" {
	Properties {
		_Diffuse ("Diffuse", Color) = (1, 1, 1, 1)
		_Specular ("Specular", Color) = (1, 1, 1, 1)
		_Gloss ("Gloss", Range(8.0, 256)) = 20
	}
	SubShader {
		Tags { "RenderType"="Opaque" }
		
		Pass {
			// Pass for ambient light & first pixel light (directional light)
			Tags { "LightMode"="ForwardBase" }
		
			CGPROGRAM
			
			// Apparently need to add this declaration 
			#pragma multi_compile_fwdbase	
			
			#pragma vertex vert
			#pragma fragment frag
			
			#include "Lighting.cginc"
			
			fixed4 _Diffuse;
			fixed4 _Specular;
			float _Gloss;
			
			struct a2v {
				float4 vertex : POSITION;
				float3 normal : NORMAL;
			};
			
			struct v2f {
				float4 pos : SV_POSITION;
				float3 worldNormal : TEXCOORD0;
				float3 worldPos : TEXCOORD1;
			};
			
			v2f vert(a2v v) {
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				
				o.worldNormal = UnityObjectToWorldNormal(v.normal);
				
				o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
				
				return o;
			}
			
			fixed4 frag(v2f i) : SV_Target {
				fixed3 worldNormal = normalize(i.worldNormal);
				fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
				
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
				
			 	fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir));

			 	fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
			 	fixed3 halfDir = normalize(worldLightDir + viewDir);
			 	fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);

				fixed atten = 1.0;
				
				return fixed4(ambient + (diffuse + specular) * atten, 1.0);
			}
			
			ENDCG
		}
	
		Pass {
			// Pass for other pixel lights
			Tags { "LightMode"="ForwardAdd" }
			
			Blend One One
		
			CGPROGRAM
			
			// Apparently need to add this declaration
			#pragma multi_compile_fwdadd
			
			#pragma vertex vert
			#pragma fragment frag
			
			#include "Lighting.cginc"
			#include "AutoLight.cginc"
			
			fixed4 _Diffuse;
			fixed4 _Specular;
			float _Gloss;
			
			struct a2v {
				float4 vertex : POSITION;
				float3 normal : NORMAL;
			};
			
			struct v2f {
				float4 pos : SV_POSITION;
				float3 worldNormal : TEXCOORD0;
				float3 worldPos : TEXCOORD1;
			};
			
			v2f vert(a2v v) {
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				
				o.worldNormal = UnityObjectToWorldNormal(v.normal);
				
				o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
				
				return o;
			}
			
			fixed4 frag(v2f i) : SV_Target {
				fixed3 worldNormal = normalize(i.worldNormal);
				#ifdef USING_DIRECTIONAL_LIGHT
					fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
				#else
					fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz);
				#endif
				
				fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir));
				
				fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
				fixed3 halfDir = normalize(worldLightDir + viewDir);
				fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);
				
				#ifdef USING_DIRECTIONAL_LIGHT
					fixed atten = 1.0;
				#else
					#if defined (POINT)
				        float3 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1)).xyz;
				        fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
				    #elif defined (SPOT)
				        float4 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1));
				        fixed atten = (lightCoord.z > 0) * tex2D(_LightTexture0, lightCoord.xy / lightCoord.w + 0.5).w * tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
				    #else
				        fixed atten = 1.0;
				    #endif
				#endif

				return fixed4((diffuse + specular) * atten, 1.0);
			}
			
			ENDCG
		}
	}
	FallBack "Specular"
}

Base Pass
  • #pragma multi_compile_fwdbase 保证我们在shader中使用 光照衰减 等光照变量时可以被正确使用
#pragma multi_compile_fwdbase	
  • 在Base Pass中计算环境光照后,在Additional Pass中就不会再计算(物体自发光也是)
Additional Pass
  • 同样使用#pragma multi_compile_fwdadd 指令
  • 开启了Blend 命令,设置了混合模式,希望Additional Pass计算得到的光照结果可以在帧缓存中与之前的光照结果进行叠加
Pass {
			// Pass for other pixel lights
			Tags { "LightMode"="ForwardAdd" }
			
			Blend One One
		
			CGPROGRAM
			
			// Apparently need to add this declaration
			#pragma multi_compile_fwdadd
  • Additional Pass处理的光源类型可能是平行光、点光源或是聚光灯,在计算位置、方向、颜色、强度、衰减时,颜色和强度仍然可以使用 _LightColor0 来得到,由于位置、方向和衰减属性就需要根据光源类型分别计算
  • 方向
    如果是平行光,可以直接通过 _WorldSpaceLightPos0.xyz 来得到;如果是其他光源,_WorldSpaceLightPos0.xyz 表示的是光源在世界坐标中的位置,光源方向需要用这个位置减去世界空间下顶点的位置
			#ifdef USING_DIRECTIONAL_LIGHT
					fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
				#else
					fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz);
				#endif
  • 衰减
			#ifdef USING_DIRECTIONAL_LIGHT
					fixed atten = 1.0;
				#else
					#if defined (POINT)
				        float3 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1)).xyz;
				        fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
				    #elif defined (SPOT)
				        float4 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1));
				        fixed atten = (lightCoord.z > 0) * tex2D(_LightTexture0, lightCoord.xy / lightCoord.w + 0.5).w * tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
				    #else
				        fixed atten = 1.0;
				    #endif
				#endif

三、Unity光照衰减

1.用于光照衰减的纹理

  • 在Unity内部使用一张名为 _LightTexture0 的纹理来计算光源衰减(通常只关心对角线上的纹理颜色值),比如(0,0)点表示与光源重合的点的衰减值,(1,1)点表示了在光源中距离最远的点的衰减
  • 为了对_LightTexture0纹理采样得到给定点到该光源的衰减值,先知道点在光源空间中的位置 ,_LightMatrix0 为把顶点从世界坐标变换到光源空间的矩阵,与世界空间中的顶点坐标相乘即可
  • 再使用坐标的模的平方对衰减纹理进行采样
float3 lightCoord = mul(_LightMatrix0, float4(i.worldPos, 1)).xyz;
fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;

2.数学公式计算

float3 distance = length(_WorldSpaceLightPos0.xyz - i.worldPosition.xyz);
fixed atten = 1.0 / distance;

四、Unity的阴影

1.阴影如何实现

  • 让一个物体向其他物体投影
  • 在实时渲染中,经常使用Shadow Map,先把摄像机放在光源位置上,光源的阴影区域就是摄像机看不到的区域

①Shadow Map的生成

  • 摄像机位置:将摄像机放置在与光源重合的位置
  • ShadowCaster Pass:使用 LightMode 标签为 ShadowCaster 的 Pass 专门更新光源的阴影映射纹理。这个 Pass 渲染的目标不是帧缓存,而是阴影映射纹理(或深度纹理)

②屏幕空间的阴影映射技术

  • 根据光源的阴影映射纹理和摄像机的深度纹理得到屏幕空间的阴影图
  • 步骤
    • 通过调用 LightMode 标签为 ShadowCaster 的 Pass 来得到 光源的阴影映射纹理相机的深度纹理
    • 根据 光源的阴影映射纹理相机的深度纹理 得到屏幕空间的阴影图
    • 若摄像机深度图中记录的表面深度 > 转换到阴影映射纹理中的深度值 → \rightarrow 物体表面虽然可见,但出于该光源的阴影中

③阴影映射

  • 让物体 接收 来自其他物体的投影
    • 在Shader中队阴影映射纹理(包括屏幕空间的阴影图)进行采样,把采样结果与光照结果相乘得到阴影
  • 让物体向其他 投射阴影
    • 把该物体加到光源的阴影映射纹理计算中(通过为该物体执行 LightMode 标签为 ShadowCaster 的 Pass 来实现的)

4.Unity Shader 使用内置宏和函数 来统一管理光照衰减和阴影

①光照衰减和阴影的影响

  • 两个对物体最终的渲染效果本质上是相同的,都是通过将衰减因子和阴影值与光照结果相乘得到最终结果
  • 可以使用一个方法来同时计算这两个信息

②内置宏 UNITY_LIGHT_ATTENUATION

  • 包含进需要的头文件 #include “AutoLight.cginc”
  • 在v2f结构体中使用内置宏 SHADOW_COORDS 声明阴影坐标
struct v2f{
	float4 pos : SV_POSITION;
	float3 worldNormal : TEXCOORD0;
	float3 worldPos : TEXCOORD1;
	SHADOW_COORDS(2);
};
  • 在顶点着色器中使用内置宏 TRANSFER_SHADOW 计算并向片元着色器传递阴影坐标
v2f vert(a2v v){
	v2f o;
	...
	TRANSFER_SHADOW(o);
	return o;
}
  • 在片元着色器中使用内置宏 UNITY_LIGHT_ATTENUATION 来计算光照衰减和阴影,有三个参数
    • 第一个:用于存储光照衰减和阴影值相乘后的结果
    • 第二个:结构体 v2f ,用于传递内置宏计算阴影值
    • 第三个:世界空间的坐标,计算光源空间下的坐标,再对光照衰减纹理采样来得到光照衰减
fixed4 frag(v2f i) : SV_Target {
	...
	UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
	return fixed4(ambient + (diffuse + specular) * atten, 1.0);
} 
  • Base Pass 和 Additional Pass 代码得到统一,不需要在Base Pass里单独处理阴影,也不需要在Additional Pass中判断光源类型来处理光照衰减

5.透明物体阴影的办法

①透明物体阴影问题

  • 透明物体的实现通常会使用透明度测试或透明度混合,需要小心设置这些物体的 Fallback
  • 使用 VertexLit、Diffuse、Specular 等作为回调,往往无法得到正确的阴影(不透明物体可以,VertexLit中有ShadowCaster Pass),因为这些 Shader 中的 ShadowCaster Pass 没有进行透明度测试的计算。

②透明度测试 物体的阴影处理

  • 需要提供一个有透明度测试功能的 ShadowCaster Pass
  • Fallback “VertexLit” 改为 “Transparent/Cutout/VertexLit”
  • Cude 的 Mesh Renderer 的Cast Shadows 设置为 Two Sided
    在这里插入图片描述

③透明度混合 物体的阴影处理

  • 因为透明度混合需要关闭深度写入,这会带来阴影生成的问题,所以所有内置的透明度混合的 Unity Shader 都没有包含阴影投射的 Pass,因此,这些半透明物体不会向其他物体投射阴影,也不会接收来自其他物体的阴影
  • 可以使用一些 dirty trick 来强制为半透明物体生成阴影
    • 把它们的 Fallback 设置为 VertexLit、Diffuse 等不透明物体使用的 Unity Shader
    • 通过物体的 Mesh Renderer 组件上的 Cast Shadows 和 Receive Shadows 选项来控制是否需要向其他物体投射或接收阴影
      在这里插入图片描述

五、标准的Unity Shader

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

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

相关文章

毫秒级相应逆流检测电表安科瑞防逆流电能表

家庭储能系统 生态环境与人们的日常生活密切相关,越来越多的家庭开始重视居住环境的绿色、环保、智能及可持续性,并采取具体行动。截至2023年,欧洲太阳能发电容量已超200GW,家庭储能系统的安装量呈爆炸性增长。 用户痛点及需求 …

前端基础:JavaaScript(篇二)

目录 内置对象 String字符串 属性 代码 运行 方法 代码 运行 日期 代码 运行 Math 代码 运行 数组 定义 属性 代码 运行 方法 join(分隔符>) : 代码 运行 reverse(): 代码 运行 sort() : 代码 运行 事件 …

有哪些手持小风扇品牌推荐?五大手持小风扇诚意推荐!

在炎炎夏日,一款便携且高效的手持小风扇无疑是消暑的必备神器。为了帮助大家轻松应对酷暑,我们精心挑选了五大手持小风扇品牌进行诚意推荐。这些品牌不仅拥有出色的降温效果,更在外观设计、便携性、续航能力及操作便捷性上表现卓越。接下来&a…

电子邮件OTP验证身份认证接口API服务商比较

电子邮件OTP验证身份认证接口API服务商如何正确选择? 电子邮件OTP验证是一种广泛应用且安全的身份认证方式。AokSend将比较几家主要的电子邮件OTP验证身份认证接口API服务商,帮助企业选择合适的解决方案。 电子邮件OTP:验证优势 可以为用户…

软考高级-系统分析师知识点100条速记!

宝子们!上半年软考已经结束一段时间了,准备备考下半年软考高级-系统分析师的小伙伴可以开始准备了,毕竟高级科目的难度可是不低的,相信参加过上半年系分的小伙伴深有体会。 这里给大家整理了100条系分知识点,涵盖全书9…

【SPIE独立出版】第四届智能交通系统与智慧城市国际学术会议(ITSSC 2024)

第四届智能交通系统与智慧城市国际学术会议(ITSSC 2024)将于2024年8月23-25日在中国西安举行。本次会议主要围绕智能交通、交通新能源、无人驾驶、智慧城市、智能家居、智能生活等研究领域展开讨论, 旨在为该研究领域的专家学者们提供一个分享…

如何在 Java 应用中使用 Jedis 客户端库来实现 Redis 缓存的基本操作

本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》 公众号:JAVA开发王大师,专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持!本人外号:神秘小峯 山峯 转载说明:务必注明来源(注明:作者:王文峰…

【kubernetes】资源调度综合篇,HPA自动扩/缩容等功能

一、标签和选择器 1、标签 命令行操作 # 查看标签 kubectl get [资源类型] [资源名] --show-labels# 修改标签 kubectl label [资源类型] [资源名] [标签名][标签值] --overwrite# 创建标签 kubectl label [资源类型] [资源名] [标签名][标签值]Yalm文件操作 2、选择器 命…

十三、【源码】自动扫描注册Bean

源码地址&#xff1a;https://github.com/spring-projects/spring-framework 仓库地址&#xff1a;https://gitcode.net/qq_42665745/spring/-/tree/13-auto-scan-bean 自动扫描注册Bean 自动扫描Bean流程&#xff1a; 配置文件中配置标签<context:component-scan base-…

数据库管理-第216期 Oracle的高可用-01(20240703)

数据库管理216期 2024-07-03 数据库管理-第216期 Oracle的高可用-01&#xff08;20240703&#xff09;1 MAA简介2 MAA等级2.1 BRONZE2.2 SILVER2.3 GOLD2.4 PLATINUM 3 业务延续性总结 数据库管理-第216期 Oracle的高可用-01&#xff08;20240703&#xff09; 作者&#xff1a;…

巴西市场有哪些电商平台?巴西最畅销的产品有哪些?

巴西&#xff0c;作为南美洲最大的经济体之一&#xff0c;近年来在电子商务领域展现出强劲的增长势头。随着互联网的普及和消费者购物习惯的改变&#xff0c;电商平台在巴西市场上“打”得热火朝天&#xff0c;不过占据市场份额最大的依然还是美客多。本文将探讨巴西市场上的主…

TikTok矩阵管理系统:打造个人品牌的秘密武器

在当今数字化时代&#xff0c;个人品牌的建立对于个人和企业来说都变得至关重要。无论是企业家、自由职业者还是社交媒体个人&#xff0c;都希望能够在竞争激烈的市场中脱颖而出。而TikTok矩阵管理系统正是一个帮助个人打造个人品牌的秘密武器。 TikTok矩阵管理系统是一个集成了…

AI教育行业全景图(最新版);AI时代内容创作者的窘境;2年内AI教育赛道的切入机会;可汗学院创始人「AI教育革命」新书问世 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; 1. 可汗学院 (Khan Academy) 创始人新书发布&#xff1a;AI将如何颠覆传统教育 可汗学院&#xff08;Khan Academy&#xff09;是 Salman Khan 创立的…

HiAI Foundation开发平台,加速端侧AI应用的智能革命

如果您是一名开发者&#xff0c;正在寻找一种高效、灵活且易于使用的端侧AI开发框架&#xff0c;那么HarmonyOS SDKHiAI Foundation服务&#xff08;HiAI Foundation Kit&#xff09;就是您的理想选择。 作为一款AI开发框架&#xff0c;HiAI Foundation不仅提供强大的NPU计算能…

c/c++语言的一种日志的编写办法

今日分享一下&#xff0c;从某源码中看到这种日志编写方式&#xff0c;很强。可以借鉴。 这个函数调用的日志函数是不一样的&#xff0c;仔细观看&#xff1a; 这几种日志输出函数&#xff0c;背后都调用了相同的调用。 与之对应的区别就是&#xff0c;函数名称的差异取决于…

小D----海量数据商用短链平台项目大课

从0-1 掌握ClickHouse新一代OLAP数据库。 Kafka接入组件封装Ip获取地理位置信息库使用。 后端工程师角度进阶数据仓库分层大数据领域技术视野 Flinkkafka短链接数据实时计算多维度数据处理。 Async异步关联查询多维度宽表扩展。 Flink多流合并DWS层整合Click House存储。

JDBC【封装工具类、SQL注入问题】

day54 JDBC 封装工具类01 创建配置文件 DBConfig.properties driverNamecom.mysql.cj.jdbc.Driver urljdbc:mysql://localhost:3306/qnz01?characterEncodingutf8&serverTimezoneUTC usernameroot passwordroot新建配置文件&#xff0c;不用写后缀名 创建工具类 将变…

北斗/GPS模块输出的NMEA语句详解

NMEA协议采用 ASCII 码来传递 GPS 定位信息&#xff0c;我们称之为帧。 帧格式形如&#xff1a;$aaccc,ddd,ddd,…,ddd*hh(CR)(LF) 1、“$”&#xff1a;帧命令起始位 2、aaccc&#xff1a;地址域&#xff0c;前两位为识别符&#xff08;aa&#xff09;&#xff0c;后三位为…

记一次android打包,因路由规则设置不合理而导致pom文件无法访问的错误

一、错误详情 FAILURE: Build failed with an exception.* What went wrong: Could not determine the dependencies of task :mediaplayer:compileReleaseAidl. > Could not resolve all task dependencies for configuration :mediaplayer:releaseCompileClasspath.> C…

nodejs版本升级12->18

1.把老版本删除&#xff0c;没删除升级没成功。 2.在官网下载新版本。 3.在菜单中输入cmd&#xff0c;一定要用管理员身份运行&#xff0c;切记&#xff0c;不然会出现2503/2502错误。 4.安装即可。