- 前言
- 一、关键代码
- 二、全部代码
- 纹理相关知识点:
- 1.纹理展开技术(展UV):
- 2.在Unity shader中声明一个纹理的方式:
- 3.纹理的属性:
- 4.Unity中对顶点纹理坐标变换的代码
- 5.纹理的平铺方式:
- 6.纹理的滤波模式:
- 7.多级渐远纹理技术(mipmapping):
- 8.Format属性
前言
1.使用的光照模型:Blinn-Phong
一、关键代码
_Color("Color Tint",Color) = (1,1,1,1)
_MainTex("Main Tex",2D) = "white"{}
sampler2D _MainTex;
float4 _MainTex_ST;
//uv用于储存纹理坐标的变量
o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
//这一步相当于对纹理进行采集然后计算出漫反射颜色
fixed3 albedo = tex2D(_MainTex , i.uv).rgb * _Color.rgb
二、全部代码
Shader "Custom/SingleTextureMat"
{
Properties
{
_Color ("Color Tint", Color) = (1,1,1,1) //控制物体的整体色调
_Specular("Specular", Color) = (1,1,1,1)
_Gloss("Gloss",Range(8,256)) = 20
_MainTex("Main Tex", 2D) = "white" {} //声明了一个名为_MainTex的纹理 2D是纹理属性
}
SubShader
{
Pass{
Tags{ "LightMode" = "ForwardBase" } //定义的该Pass在unity中的光照流水线的角色
CGPROGRAM
#pragma vertex vert//定义了顶 点着色器的名字
#pragma fragment frag//定义了片元着色器的名字
#include "Lighting.cginc" //引用Unity的内置文件
//定义和 Properties 语义块中 相同 的声明的属性
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _Specular;
float _Gloss;
//定义顶点着色器和片元着色器的输入 结构体
struct a2v {
float4 vertex : POSITION; //数据类 型 名称 :( 类别?)
float3 normal : NORMAL;
//将模型的第一组纹理坐标存储到该变量中
float4 texcoord : TEXCOORD0;
};
struct v2f {
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1; //报错原因::写成;
//uv变量用于存储纹理坐标
float2 uv: TEXCOORD2;
};
//顶点着色器的计算
v2f vert(a2v v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);//将模型的顶点从模型空间转换到裁剪空间 transform the vertex from object space to projection space
o.worldNormal = UnityObjectToWorldNormal(v.normal); //mul(v.normal, (float3x3)unity_WorldToObject);//将模型的顶点的法线从模型空间转换到世界空间
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;//将模型顶点位置从模型空间转换到世界空间
//使用纹理的属性值_MainTex_ST来对顶点坐标进行变换得到最后的纹理坐标
o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
return o;
}
//片元着色器的计算
fixed4 frag(v2f i) : SV_Target{
//计算光照
// 0.计算反射率
fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;
//1.获取环境光
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
//2.计算漫反射
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed3 diffuse = _LightColor0.rgb * albedo * saturate(dot(worldNormal, worldLightDir));
//3.计算高光反射
//3.1 获取视角方向
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
//3.2获取新的矢量halfDir
fixed3 halfDir = normalize(viewDir + worldLightDir);
//3.3利用公式计算高光反射
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(worldNormal, halfDir)), _Gloss);
//fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0,dot(worldNormal, halfDir)), _Gloss);//思考的答案:因为前面已经归一化,所以这里可以直接用max来筛选大于0的数
return fixed4(ambient + diffuse + specular, 1);
}
ENDCG
}
}
FallBack "Specular"
}
纹理相关知识点: 1.纹理展开技术(展UV):
把纹理映射坐标(texture-mapping coordinates)存储在每一个顶点上。
纹理映射坐标 :定义了该顶点在纹理中对应的2D坐标。
_Name("Name",Type) = "字符串(内置纹理的名字)"{}
例子:_MainTex("Main Tex" , 2D) = "white"{}
与其它属性类型不同,我们需要为某个纹理声明属性,在Unity中,需要使用纹理命_ST的方式。
纹理命_ST:
- ST代表着缩放(scale)和平移(translation),_MainTex_ST可以让我们获取该纹理的缩放和平移值。
- _MainTex_ST.xy存储的是缩放值。
- _MainTex_ST.zw存储的是平移值。
o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
或者直接使用Unity内置宏TRANSFORM_TEX
来计算上述过程
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
第一个参数是顶点纹理坐标,第二个参数是纹理名
5.纹理的平铺方式:Unity中纹理坐标超过[0,1]
范围就会被平铺。
而平铺的方式有两种(Warp Mode):
- Repeat ,如果纹理坐标超过了1,那么它的整数部分就会被舍弃,直接使用小数部分进行采样,最终导致纹理不断重复。
- Clamp , 如果纹理坐标大于1,那么就会截取到1,如果小于0,那么就会截取到0。
纹理的Filter Mode属性决定了当纹理由于变换而产生拉伸时将会采用哪种滤波模式。
纹理大小和模型不匹配时需要对纹理进行变换。
三种滤波模式(它们会影响放大和缩小纹理时得到的图片的质量):
- Point
- Bilinear
- Trilinear
- 它们得到的图片滤波效果依次提升,但是需要耗费的性能也依次增大。
在纹理缩小的过程中,我们需要处理抗锯齿问题。
原因:当纹理过大时,一个像素需要需要对应多个纹素,那么会导致采样的频率和纹理图像的频率是不对等的。
处理抗锯齿的方法:将原纹理提前用滤波处理来得到很多更小的图像,每一层都是对上一层图像降采样的结果,这样在实时运行时,就可以快速得到结果像素。
但是这种方法是用空间换取时间。
8.Format属性Unity中Format决定了Unity使用哪种格式来存储纹理,使用的纹理格式精度越高,占用的空间越大,但是效果越好。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)