Unity入门精要02---纹理

news2024/11/19 9:22:08

纹理和材质不可分割

本节知识结构

实践:简单贴一张纹理到模型上

首先在属性处添加相关属性

	Properties {
		_Color ("Color Tint", Color) = (1, 1, 1, 1)
		_MainTex ("Main Tex", 2D) = "white" {}//加入纹理
		_Specular ("Specular", Color) = (1, 1, 1, 1)
		_Gloss ("Gloss", Range(8.0, 256)) = 20
	}

然后在SubShader处引用

			fixed4 _Color;
			sampler2D _MainTex;
			float4 _MainTex_ST;
			fixed4 _Specular;
			float _Gloss;

其中  纹理名_ST用来储存UV的缩放和偏移 

这里UV的缩放和偏移可以自己更改数值

未更改前效果如下

 

 稍微有点恶心(

 然后定义输入输出结构体

	struct a2v {
				float4 vertex : POSITION;
				float3 normal : NORMAL;
				float4 texcoord : TEXCOORD0;//获得纹理模型纹理的纹理坐标
			};
			
			struct v2f {
				float4 pos : SV_POSITION;
				float3 worldNormal : TEXCOORD0;
				float3 worldPos : TEXCOORD1;
				float2 uv : TEXCOORD2;//传递uv坐标
			};

 在顶点着色器中最重要的一条代码

				o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;

 将纹理坐标(二维的)乘以纹理的缩放+纹理的平移值

用内置宏命令也行

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

 在片元着色器中涉及纹理的最重要的一条代码

fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;

根据模型的UV坐标获取该点在纹理上的像素的颜色并乘以环境光。

纹理的属性

·Texture Type,标记纹理的模式,可标记其为默认,法线贴图,GUI,2DSprite

  目前对我来说较常用的就是默认,法线,光照烘焙贴图,阴影遮罩,以及单通道

  标记的用处可能是为了让Unity能自动处理某些东西吧...

 ·Wrap Mode

 

 它决定了当纹理坐标超过[0,1]范围后将如何被平铺。书中只讲了两种模式 

1.Repeat,当纹理坐标超过了1,它的整数部分就会被舍弃,直接对小数部分进行采样,结果会不断重复

2. Clamp,超出部分会被截断,根据边界像素进行采样

  ·Filter Mode

 

 Point,使用了最近邻滤波,在放大缩小时,采样像素数目只有一个,因此图像有种像素风格的效果。

 Bilinear,使用了线性滤波,对每个像素会采样4个邻近像素,之后线性差值混合得到最终像素

 看着好一点了。

Trilinear的滤波几乎和Biliear是一样的,只不过该选项会使用mipmap技术进行混合,如果一张纹理没有mipmap,那么其结果和Biliear。

Max Size,不同平台的纹理尺寸和纹理质量是不同的,如果导入的纹理大小超过了Max,那么Unity会将其缩放为这个最大分辨率(尽量使用为2的幂的分辨率大小的纹理,否则影响空间和性能)。

Format,决定了Unity内部使用哪种格式来储存该纹理。有些不需要非常高精度的纹理就尽量使用压缩格式。

 凹凸映射。

  ·高度纹理(感觉很少用)

    优点是更加直观,缺点是计算跟复杂,因为还要由灰度图计算出法线贴图

   

 ·法线纹理

 正常情况下法线纹理是蓝色的

 这是因为,法线方向的分量范围为[-1,1]而像素的分量范围为[0,1]因此我们需要根据一个式子进行映射

 该贴图记录了每个点在各自的切线空间中的法线扰动方向,因为每个点的空间都不同,同时法线大多指向屏幕外,根据映射关系,比如0,0,1的法线方向,映射后对于了RGB(0.5,0.5,1)浅蓝色。

还有一种情况,去掉了B通道的法线纹理

这样做的好处是可以减小储存空间,法线的B通道可以直接计算出来 

而对于世界空间下的法线纹理实在是太少用了。

 

 书中也比较了两者的优缺点

 贴法线纹理实践

 ·在将光照等信息传到切线空间下进行计算

			v2f vert(a2v v) {
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				
				o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
				o.uv.zw = v.texcoord.xy * _BumpMap_ST.xy + _BumpMap_ST.zw;
				
				float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;  
				fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);  
				fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);  
				fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w; 
				
				// Compute the matrix that transform directions from tangent space to world space
				// Put the world position in w component for optimization
				o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
				o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
				o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
				
				return o;

·

		
			fixed4 frag(v2f i) : SV_Target {
				// Get the position in world space		
				float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);
				// Compute the light and view dir in world space
				fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
				fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));
				
				// Get the normal in tangent space
				fixed3 bump = UnpackNormal(tex2D(_BumpMap, i.uv.zw));
				bump.xy *= _BumpScale;
				bump.z = sqrt(1.0 - saturate(dot(bump.xy, bump.xy)));
				// Transform the narmal from tangent space to world space
				bump = normalize(half3(dot(i.TtoW0.xyz, bump), dot(i.TtoW1.xyz, bump), dot(i.TtoW2.xyz, bump)));
				
				fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;
				
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
				
				fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(bump, lightDir));

				fixed3 halfDir = normalize(lightDir + viewDir);
				fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(bump, halfDir)), _Gloss);
				
				return fixed4(ambient + diffuse + specular, 1.0);
			}

 ·将切线空间下的法线纹理转换到世界空间下进行计算

v2f vert(a2v v) {
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				
				o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
				o.uv.zw = v.texcoord.xy * _BumpMap_ST.xy + _BumpMap_ST.zw;

				///
				/// Note that the code below can handle both uniform and non-uniform scales
				///

				// Construct a matrix that transforms a point/vector from tangent space to world space
				fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);  
				fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);  
				fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w; 

				/*
				float4x4 tangentToWorld = float4x4(worldTangent.x, worldBinormal.x, worldNormal.x, 0.0,
												   worldTangent.y, worldBinormal.y, worldNormal.y, 0.0,
												   worldTangent.z, worldBinormal.z, worldNormal.z, 0.0,
												   0.0, 0.0, 0.0, 1.0);
				// The matrix that transforms from world space to tangent space is inverse of tangentToWorld
				float3x3 worldToTangent = inverse(tangentToWorld);
				*/
				
				//wToT = the inverse of tToW = the transpose of tToW as long as tToW is an orthogonal matrix.
				float3x3 worldToTangent = float3x3(worldTangent, worldBinormal, worldNormal);

				// Transform the light and view dir from world space to tangent space
				o.lightDir = mul(worldToTangent, WorldSpaceLightDir(v.vertex));
				o.viewDir = mul(worldToTangent, WorldSpaceViewDir(v.vertex));

				///
				/// Note that the code below can only handle uniform scales, not including non-uniform scales
				/// 

				// Compute the binormal
//				float3 binormal = cross( normalize(v.normal), normalize(v.tangent.xyz) ) * v.tangent.w;
//				// Construct a matrix which transform vectors from object space to tangent space
//				float3x3 rotation = float3x3(v.tangent.xyz, binormal, v.normal);
				// Or just use the built-in macro
//				TANGENT_SPACE_ROTATION;
//				
//				// Transform the light direction from object space to tangent space
//				o.lightDir = mul(rotation, normalize(ObjSpaceLightDir(v.vertex))).xyz;
//				// Transform the view direction from object space to tangent space
//				o.viewDir = mul(rotation, normalize(ObjSpaceViewDir(v.vertex))).xyz;
				
				return o;
			}
	fixed4 frag(v2f i) : SV_Target {				
				fixed3 tangentLightDir = normalize(i.lightDir);
				fixed3 tangentViewDir = normalize(i.viewDir);
				
				// Get the texel in the normal map
				fixed4 packedNormal = tex2D(_BumpMap, i.uv.zw);
				fixed3 tangentNormal;
				// If the texture is not marked as "Normal map"
//				tangentNormal.xy = (packedNormal.xy * 2 - 1) * _BumpScale;
//				tangentNormal.z = sqrt(1.0 - saturate(dot(tangentNormal.xy, tangentNormal.xy)));
				
				// Or mark the texture as "Normal map", and use the built-in funciton
				tangentNormal = UnpackNormal(packedNormal);
				tangentNormal.xy *= _BumpScale;
				tangentNormal.z = sqrt(1.0 - saturate(dot(tangentNormal.xy, tangentNormal.xy)));
				
				fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;
				
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
				
				fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(tangentNormal, tangentLightDir));

				fixed3 halfDir = normalize(tangentLightDir + tangentViewDir);
				fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(tangentNormal, halfDir)), _Gloss);
				
				return fixed4(ambient + diffuse + specular, 1.0);
			}

 还有些没关于法线贴图的细节没有补充,以及一些其他类型的贴图没有叙述,就先暂时写到这里。明天再写(

    

     

 

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

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

相关文章

虚拟机VirtualBox下载与安装+虚拟机配置

1、虚拟机VirtualBox下载与安装官网地址:Oracle VM VirtualBox进入官网,点击左侧Dwonlaods点击Windows hosts,开始下载3.打开文件.出现报错:Oracle VM VirtualBox 7.0.4 needs the Microsoft Visual C 2019 Redistributable Packa…

转义字符\033(设置终端的字体显示效果)

以下内容源于网络资源的学习与整理,如有侵权请告知删除。 参考博客 命令行特殊显示效果\033和发声音\007_华硕他哥的博客-CSDN博客 \033格式:指定输出格式_51CTO博客_wkt格式 一、\033的说明 在关于ASCII字符的那些事儿中提到,ASCII字符可以使用前面…

2023年天津医科大学临床医学院专升本专业课考试通知

天津医科大学到临床医学院2023年高职升本科专业课考试通知一、考试时间、地点 天津医科大学临床医学院2023年高职升本科考试定于2023年3月25日举行,考试地点为天津市滨海新区大港学苑路167号天津医科大学临床医学院教学楼。 二、准考证打印开放时间 本次考试打印准考…

3.4笔试总结

感觉题目好难没有做过这种类型的填空题真的是给应届实习生做的题吗第一大题 填空题一开始题目放在pdf里,我都没看清题目想干嘛其实题目看起来复杂.如果仔细读题意还是能做出几个空,无奈我太过紧张浪费了好几分钟空档时间public class Main { public static boolean isRegularMa…

内核角度谈谈Linux进程和线程

目录前言内核对进程和线程的表示创建进程的过程创建线程的过程创建进程和线程的异同揭秘 do_fork 系统调用结论前言 昨天面试的时候,面试官问我了个平平淡淡的问题–>“聊聊Linux中进程和线程”; 相比大家不管是在考试还是面试中或多或少都遇到过这个问题&…

python高德地图+58租房网站平台源码

wx供重浩:创享日记 对话框发送:python地图 免费获取完整源码源文件说明文档配置教程等 在PyCharm中运行《高德地图58租房》即可进入如图1所示的高德地图网页。 具体的操作步骤如下: (1)打开地图网页后,在编…

xgboost:防止过拟合的方法收缩和特征列、采样

xgboost除了第2.1节中提到的正则化目标之外,还使用了另外两种技术来进一步防止过拟合1。 目录shrinkage[^1]Column Subsampling[^2]shrinkage2 第一种技术是由弗里德曼提出的收缩。在树提升的每一步之后,收缩率以η因子的比例缩放新添加的权重。与随机优…

Scrapy框架(高效爬虫)

文章目录一、环境配置二、创建项目三、scrapy数据解析四、基于终端指令的持久化存储1、基于终端指令2、基于管道3、数据同时保存至本地及数据库4、基于spider爬取某网站各页面数据5、爬取本页和详情页信息(请求传参)6、图片数据爬取ImagesPipeline五、中…

IP欺骗种类有哪些?

每台计算机都有一个IP地址,发送的任何数据都被分成许多块(“数据包”),每个数据包单独传输,当这些数据包到达链的末端时,就会重新组装并作为一个整体呈现。此外,每个数据包还有其可识别信息&…

4、High-Resolution Image Synthesis with Latent Diffusion Models

简介github地址diffusion model明显的缺点是耗费大量的时间、计算资源,为此,论文将其应用于强大的预训练自编码器的潜在空间 ,这是首次允许在复杂性降低和细节保存之间达到一个近乎最佳的点,极大地提高了视觉保真度。通过在模型架…

操作系统复习题

什么是线程? 线程(Thread):轻量级进程,是操作系统进行调度的最小单位。一个线程是一个任务(一个程序段)的一次执行过程。线程不占有内存空间,它包括在进程的内存空间中。在同一个进程…

自然语言处理历史最全预训练模型(部署)汇集分享

什么是预训练模型?预练模型是其他人为解决类似问题而创建的且已经训练好的模型。代替从头开始建立模型来解决类似的问题,我们可以使用在其他问题上训练过的模型作为起点。预训练的模型在相似的应用程序中可能不是100%准确的。本文整理了自然语…

踩坑:maven打包失败的解决方式总结

Maven打包失败原因总结如下: 失败原因1:无法使用spring-boot-maven-plugin插件 使用spring-boot-maven-plugin插件可以创建一个可执行的JAR应用程序,前提是应用程序的parent为spring-boot-starter-parent。 需要添加parent的包spring-boot…

QML组件

一个QML文件定义了一个独立的、顶级的QML组件。 一个QML组件就是一个模板,被QML运行环境解释来创建一个带有一些预定义行为的对象。 一个独立的QML组件可以运行多次来禅城多个对象,每个对象都可以称为该组件的实例。 例子: 在项目中添加一…

Redis基础入门

文章目录前言一、redis是什么?二、安装步骤1.下载安装包2.安装三、Redis的数据类型redis是一种高级的key-value的存储系统,其中的key是字符串类型,尽可能满足如下几点:字符串(String)列表(List)集合(Set,不允许出现重复…

MySQL面试题-索引篇

1.什么是索引 MySQL的索引是一种数据结构,可以用于加快数据库中数据的查询速度。索引是基于表中一个或多个列的值排序的快速查找数据结构,可以大大提高查询效率。MySQL支持多种类型的索引,如B-tree索引、哈希索引、全文索引等。 索引可以在…

【java基础】异常处理(Exception)

文章目录基本介绍异常分类抛出异常非检查型异常检查型异常捕获异常捕获单个异常捕获多个异常创建自定义异常类finally字句try-with-Resource总结基本介绍 对于一个程序,总是有bug的。如果我们的程序遇到一个错误就终止了,那么肯定是不合理,程…

数据爬取(urllib+BeautifulSoup)

文章目录知识点总结爬虫步骤爬虫三要素爬虫注意事项python爬取技术学习网页抓取库Urllib网页解析库Beautifulsoup案例知识点总结 爬虫是一种按照一定规则,自动抓取互联网上网页中的相应信息的程序或脚本。 爬虫步骤 1.需求分析 2.找到要爬取信息的网站 3.下载reque…

基于halo后台管理+Gblog-wx搭建的微信小程序

先决条件 1、已经通过docker安装了halo后台管理系统(参考:http://43.136.39.20:8090/archives/halo-build) 2、安装的halo版本为1.5.3版本。此版本的halo才能安装小程序主题并启动小程序 3、需要修改小程序文件配置 解决安装的不是1.5.3的halo 1、如果是docker安装的halo…

蓝牙技术|蓝牙5.4标准正式发布,蓝牙ESL电子价签迎来一波利好

蓝牙技术联盟于2023年1月31日批准了蓝牙核心规范v5.4版本(以下简称蓝牙5.4版本),并已正式公布。 蓝牙5.4版本引入了四个新特性,如下: 广播数据加密(Encrypted Advertising Data):对广播数据进行加密以提高广播数据传…