技术美术TA之纹理全攻略

本文是视频课程《Unity技术美术TA:Shader篇》,算是对自己学习的总结,也希望分享下所学知识~~

渲染管线什么时候用到纹理?
1.定点/片段着色器(读取)
2.帧缓存(写入)

纹理有哪些?

  • 颜色纹理
    • 一维纹理
    • 二维纹理
    • 三维纹理
    • 立方体纹理
  • 几何纹理
    • 凹凸纹理
    • 视差纹理
    • 置换纹理
    • 法线纹理

Mipmap:纹理的LOD
近处采用大图,远处采用小图
生成规则:
依次生成分辨率xy分别/2的一级一级的贴图

在这里插入图片描述

优点:
1.角色在远处,采样抖动
2.分级加载,减少不同配置下的内存
坏处:+30%显存

Shader LOD 采样代码:

Shader "Custom/TA/Tex2"
{
    Properties
    {
    	...
    	
        [IntRange] _Mipmap("Mipmap", Range(0,10))=0
    }
    SubShader
    {
        Pass
        {
        	...
        	
            half _Mipmap;

            fixed4 frag(v2f i) : SV_Target
            {
                //tex2Dlod
                //二维纹理采样,w表示在mipmap的第几级
                fixed4 col = tex2Dlod(_MainTex, float4(i.uv, 0, _Mipmap));
                return col;
            }
            ENDCG
        }
    }
}

纹理过滤:
一个像素可能对应多个纹素,需要处理一下到底取哪个颜色
在这里插入图片描述

1.Point(no filter)
不过滤,只采样采样点最近的纹素
2.Bilinear
双线性过滤,采样点周围采样4个纹素,加权平均(离得近的权重高)
3.Trilinear
三线性过滤,双线性过滤基础上再加上对Mipmap远近级别过滤,采样8个纹素插值


纹理环绕方式:
1.Repeat:重复
2.Clamp:最后像素填充
3.其他

在这里插入图片描述

设置是在图片的 Inspector面板,一个图需要两种模式如果用两张图浪费内存
需要在Shader内实现

代码如下:

Shader "Custom/TA/Tex2"
{
    Properties
    {
    	...

		//关键字枚举定义方式,同时需要定义宏
        [KeywordEnum(Repeat,Clamp)]_WrapMode("WrapMode",int)=0
    }
    SubShader
    {
        Pass
        {
        	...
        
        	//这个不需要运行时候改,用shader_feature就行
            #pragma shader_feature _WRAPMODE_REPEAT _WRAPMODE_CLAMP

            fixed4 frag(v2f i) : SV_Target
            {
                fixed2 uv = i.uv;
                #if _WRAPMODE_REPEAT
                //只取小数部分
                uv = frac(uv);
                #elif _WRAPMODE_CLAMP
                //限制在0-1之间
                // uv = clamp(uv, 0,1);
                uv = saturate(uv);
                #endif
                
                ,,,
            }
            ENDCG
        }
    }
}

立方体纹理
Cubemap,通常用作反射效果

在这里插入图片描述

采样效果
在这里插入图片描述

如何采样呢?

Shader "Custom/TA/TexTest"
{
    Properties
    {
    	...
    		
    	//定义 Cubemap
        _CubeMap("CubeMap", cube) = "white" {}
    }
    SubShader
    {
        Pass
        {
        	...
        	
            samplerCUBE _CubeMap;

            fixed4 frag(v2f i) : SV_Target
            {
            	...
            	
                // v n r
                // 反射:视角方向延法线的反射坐标
                fixed3 v = normalize(UnityWorldSpaceViewDir(i.worldPos)); //内置函数求视角方向
                fixed3 n = normalize(i.worldNormal);
                fixed3 r = reflect(-v, n);

                fixed4 cubeMapCol = texCUBE(_CubeMap, r);


                return cubeMapCol;
            }
            ENDCG
        }
    }
}

法线贴图
给几何物体添加细节

发现纹理偏蓝色为主
因为rgb存储的是xyz轴上的偏移数据,z轴代表高度,z轴多一些,就是蓝色
xyz范围是[-1,1],需要*0.5+0.5,
例子:(0, 0,1)=>(0.5,0.5,1),就是蓝色

世界空间下采样如图:
(表现不正确,有点凹进去有的凸出来)
在这里插入图片描述

代码如下:

Shader "Custom/TA/TexTest"
{
    Properties
    {
    	...
    	
        //法线贴图格式 [Normal]
        //法线的默认值 bump
        [NoScaleOffset] [Normal]_NormalMap("NormalMap", 2D) = "bump"{}
    }
    SubShader
    {
        Pass
        {
        
        	...
		
            sampler2D _NormalMap;

            fixed4 frag(v2f i) : SV_Target
            {
                // 错误效果 [0,1] -> [-1,1]
                // fixed3 nMap = tex2D(_NormalMap, i.uv).xyz * 2 - 1;
                //  UnpackNormal
                //  发现采样不能这么用,在不同平台法线贴图不一样,需要解码 
                fixed3 nMap = UnpackNormal(tex2D(_NormalMap, i.uv));
                
                fixed3 n1 = normalize(nMap); //此处需要到切线空间下采样,否则表现不正确
                fixed3 l = UnityWorldSpaceLightDir(i.worldPos);

                fixed3 diffuse = max(0, dot(n1, l));
                return fixed4(diffuse, 1);
            }
            ENDCG
        }
    }
}

为什么要有法线空间?
可以在模型空间中做偏移,但是是强关联的,如果换模型 就不通用了
但是法线空间存的是绝对值,不随模型改变而变化

x:切线(T)
y:副切线(B)
z:法线(N)
俗称TBN矩阵

计算方式:
1.统一到切线空间(不常用)
2.统一到世界空间

Shader "Custom/TA/TexTest"
{
    SubShader
    {
        Pass
        {
            struct appdata
            {
            	...
            	
                //切线
                float4 tangent : TANGENT;
            };

            struct v2f
            {
            	...

                //表示切线空间下的旋转矩阵
                float3 tSpace0 : TEXCOORD4;
                float3 tSpace1 : TEXCOORD5;
                float3 tSpace2 : TEXCOORD6;
            };


            v2f vert(appdata v)
            {
            	...
            	
                //切线相关计算
                //切线从本地空间转世界空间
                float3 worldTangent = UnityWorldSpaceLightDir(v.tangent);
                
                //副切线计算,v.tangent.w 表示副切线的方向
                //unity_WorldTransformParams.w 缩放的值 1或者 -1
                fixed3 worldBinormal = cross(o.worldNormal, worldTangent) * v.tangent.w * unity_WorldTransformParams.w;
                
                
                //切线变换矩阵 * 世界空间下法线 = 切线空间下法线
                // 世界空间下法线 = 切线空间下法线 * 切线变换的逆矩阵
                // 切线变换矩阵 是单位矩阵,逆矩阵就等于转置矩阵
                
                //求从切线空间到世界空间的变换矩阵
                o.tSpace0 = float3(worldTangent.x, worldBinormal.x, o.worldNormal.x);
                o.tSpace1 = float3(worldTangent.y, worldBinormal.y, o.worldNormal.y);
                o.tSpace2 = float3(worldTangent.z, worldBinormal.z, o.worldNormal.z);

                return o;
            }

            fixed4 frag(v2f i) : SV_Target
            {
				...
				
                // 错误效果 [0,1] -> [-1,1]
                // fixed3 nMap = tex2D(_NormalMap, i.uv).xyz * 2 - 1;
                //  法线采样不能这么用 (tex2D),在不同平台法线贴图不一样,需要解码 
                //  UnpackNormal
                fixed3 nMap = UnpackNormal(tex2D(_NormalMap, uv));

                //切线空间转换为世界空间
                half3 worldNormal = half3(dot(i.tSpace0, nMap), dot(i.tSpace1, nMap), dot(i.tSpace2, nMap));
            
            }
            ENDCG
        }
    }
}

反射探针
烘焙会根据所有静态物体环境生成一个Cubemap
可以用来做反射

1.添加反射探针
在里面加静态物体
在这里插入图片描述

采样代码:

//当前激活的CubeMap存储在unity_SpecCube0当中
// 必须要用UNITY_SAMPLE_TEXCUBE进行采样,然后需要对其进行解码

fixed4 unity_CubeColData = UNITY_SAMPLE_TEXCUBE(unity_SpecCube0, r);
half3 unity_CubeCol = DecodeHDR(unity_CubeColData, unity_SpecCube0_HDR);

效果图:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值