当前位置: 首页 > article >正文

前部分知识复习05

一、多级渐远贴图MipMap

 选择贴图,可以勾选贴图的多级渐远效果

[IntRange]_MipMap("MipMap",Range(0,12))=0     //多级渐远贴图的LOD调节滑杆

_MipMapTexture("MipMapTexture",2D)="white"{}   //定义多级渐远贴图

多级渐远贴图的采样:

float4 Mipmap=tex2Dlod(_MipMapTexture,float4(i.uv.xy,0,_MipMap));

二、立方体纹理 CubeMap

  利用立方体纹理制作反射效果:

反射效果的形成:

float3 R=reflect(-V,N);

reflect函数根据入射向量和法向量求反射向量

而向量V是从模型指向摄像机的方向的向量,所以此时的入射向量为-V

_CubeMap("CubeMap",Cube)="white"{}

samplerCUBE _Cubemap;       //声明立方体纹理

float4 Cubemap=texCUBE(_CubeMap,R);   //立方体纹理的采样

Shader"unity/Texture03"
{
	Properties
	{
		_MipMapTexture("MipMapTexture",2D)="white"{}
		[IntRange]_MipMap("MipMap",Range(0,12))=0
		_CubeMap("CubeMap",Cube)="white"{}
	 }
	SubShader
	{
		Pass
		{
			CGPROGRAM

			#pragma vertex vert
			#pragma fragment frag

			#include "UnityCG.cginc"

			sampler2D _MipMapTexture;
			int _MipMap;
			samplerCUBE _CubeMap;

			struct appdate 
			{
				float4 vertex : POSITION;
				float4 uv : TEXCOORD;
				float3 normal : NORMAL;
			 };

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

			v2f vert(appdate v)
			{
				v2f o;
				o.pos=UnityObjectToClipPos(v.vertex);
				o.worldNormal=UnityObjectToWorldNormal(v.normal);
				o.worldPos=mul(unity_ObjectToWorld,v.vertex);
				o.uv=v.uv;
				return o;
     		 }

			float4 frag(v2f i):SV_Target
			{
				float4 Mipmap=tex2Dlod(_MipMapTexture,float4(i.uv.xy,0,_MipMap));
				float3 N=normalize(i.worldNormal);
				float3 V =normalize(_WorldSpaceCameraPos-i.worldPos);
				float3 R=reflect(-V,N);
				float4 Cubemap=texCUBE(_CubeMap,R);
				return Cubemap;
			 }
			ENDCG
		 }
	 }
 }

三、法线纹理

 法线贴图中存储的是每个像素点在切线空间下的法线向量信息

   所以采样法线贴图后的值为切线空间下的法线值

//采样法线贴图 (采样结果为切线空间下的法线值)  UnpackNormal函数通常用于解压纹理中压缩的法线信息,以获取其正确的法线
float3 normalTex=UnpackNormal(tex2D(_NormalTex,i.uv));

但是光照计算所需要的法线值为世界空间下的法线信息,所以就需要将采样后的法线值转换到世界空间下

这时就需要使用到切线空间变换矩阵,将法线信息由切线空间转换到世界空间


其中 切线 tangent 是一个四维的向量

flaot4 tangent ;   //tangent.w代表切线的方向,tangent.xyz代表坐标

  • 在顶点着色器中将模型顶点的切线由本地空间转换到世界空间

float3 worldTangent=UnityObjectToWorldDir(v.tangent);

  • 再计算切线的方向

float tangentSign=v.tangent.w*unity_WorldTransformParams.w;

  • 由世界空间法线向量和世界空间切线向量的叉值算法来计算副切线向量

(注意:此时的世界空间法线向量为模型上各像素点的法线向量,而非采样后的法线值)

//副切线由切线向量和法线向量的叉积所得
float3 worldBinormal=cross(worldNormal,worldTangent)*tangentSign;

  • 然后构建切线空间变换矩阵

//给切线空间变换矩阵赋值
o.tSpace0=float3(worldTangent.x,worldBinormal.x,worldNormal.x);
o.tSpace1=float3(worldTangent.y,worldBinormal.y,worldNormal.y);
o.tSpace2=float3(worldTangent.z,worldBinormal.z,worldNormal.z);

  • 最后在片元着色器中将采样后的法线值和变换矩阵进行点积操作得到世界空间下法线贴图中的法线值

fixed3 worldN=float3(dot(normalTex,i.tSpace0),dot(normalTex,i.tSpace1),dot(normalTex,i.tSpace2));

Shader"unity/Texture02"
{
	Properties
	{
		//定义法线纹理  [Normal]标签的作用是使得该纹理贴图的位置只能装载法线贴图
		[Normal]_NormalTex("NormalTex",2D)="white"{}
	 }

	SubShader
	{
		Pass
		{
			CGPROGRAM

			#pragma vertex vert
			#pragma fragment frag

			#include "UnityCG.cginc"

			sampler2D _NormalTex;
			float4 _NormalTex_ST;

			struct appdate
			{
				float4 vertex:POSITION;
				float2 uv:TEXCOORD;
				float3 normal:NORMAL;
				//(tangent四维向量,xyz代表坐标,w代表切线的方向)
				float4 tangent:TANGENT;
			 };

			struct v2f
			{
				float4 pos:SV_POSITION;
				float2 uv:TEXCOORD;
				//定义切线空间变换矩阵
				float3 tSpace0:TEXCOORD1;
				float3 tSpace1:TEXCOORD2;
				float3 tSpace2:TEXCOORD3;
			 };

			v2f vert(appdate v)
			{
				v2f o;
				o.uv=TRANSFORM_TEX(v.uv,_NormalTex);
				o.pos=UnityObjectToClipPos(v.vertex);

				//世界空间法线
				float3 worldNormal=UnityObjectToWorldNormal(v.normal);

				//将模型顶点的切线由本地空间转换为世界空间
				float3 worldTangent=UnityObjectToWorldDir(v.tangent);

				//决定切线的方向
				float tangentSign=v.tangent.w*unity_WorldTransformParams.w;

				//副切线由切线向量和法线向量的叉积所得
				float3 worldBinormal=cross(worldNormal,worldTangent)*tangentSign;

				//给切线空间变换矩阵赋值
				o.tSpace0=float3(worldTangent.x,worldBinormal.x,worldNormal.x);
				o.tSpace1=float3(worldTangent.y,worldBinormal.y,worldNormal.y);
				o.tSpace2=float3(worldTangent.z,worldBinormal.z,worldNormal.z);

				return o;
			 }

			float4 frag(v2f i):SV_TARGET
			{	
				//法线纹理的采样(切线空间下的法线值)//采样法线贴图后的值为一个三维向量
				fixed3 normalTex=UnpackNormal(tex2D(_NormalTex,i.uv));

				//worldN是基于切线变换矩阵和切线空间下的法线值所计算得到的世界空间下的法线值
				fixed3 worldN=float3(dot(normalTex,i.tSpace0),dot(normalTex,i.tSpace1),dot(normalTex,i.tSpace2));

				fixed3 L=normalize(_WorldSpaceLightPos0);

				//lamber光照模型 max(0,dot(N,L)
				fixed NdotL=max(0,dot(worldN,L));

				return NdotL;
			 }

			ENDCG
		 }
	 }
 }


http://www.kler.cn/a/535043.html

相关文章:

  • 基于docker搭建Kafka集群,使用KRaft方式搭建,摒弃Zookeeper
  • 记录一下 在Mac下用pyinstallter 打包 Django项目
  • 动静态库的学习
  • 苹果再度砍掉AR眼镜项目?AR真的是伪风口吗?
  • Ubuntu x64下交叉编译ffmpeg、sdl2到目标架构为aarch64架构的系统(生成ffmpeg、ffprobe、ffplay)
  • 数据结构-堆和PriorityQueue
  • 机器学习大模型问题记录
  • ESP-Skainet智能语音助手,ESP32-S3物联网方案,设备高效语音交互
  • 《图解设计模式》笔记(五)一致性
  • nuxt3中使用useFetch请求刷新不返回数据或返回html结构问题解决-完整nuxt3useFetchtch请求封装
  • [NKU]C++安装环境 VScode
  • C++的 I/O 流
  • CentOS 6.5编译Rsyslog 8.1903.0
  • web3.0技术
  • 计算机组成与接口
  • 天童教育:帮助孩子建立稳定的自信心
  • 如何从0开始做自动化测试?
  • 深度学习系列--03.激活函数
  • Three.js实现炫酷图片粒子化效果:从聚合到扩散的动态演变
  • SystemVerilog系统函数之$system详细使用指南与举例
  • DeepSeek核心关键技术 (冷启动,拒绝采样,蒸馏,多头潜注意力,MoE等) 解读
  • 【Axure高保真原型】中继器表格控制动态面板
  • 不含101的数
  • 微信小程序~django Petting pets(爱抚宠物)小程序
  • 机器学习-线性回归(参数估计之结构风险最小化)
  • JavaScript系列(62)--实时通信系统实现详解