【TA之路知识总结】shader学习笔记——入门篇——纹理篇——使用一张纹理模拟物体的漫反射和对纹理的处理等相关知识

【TA之路知识总结】shader学习笔记——入门篇——纹理篇——使用一张纹理模拟物体的漫反射和对纹理的处理等相关知识,第1张

文章目录
  • 前言
  • 一、关键代码
  • 二、全部代码
  • 纹理相关知识点:
        • 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坐标。

2.在Unity shader中声明一个纹理的方式:

_Name("Name",Type) = "字符串(内置纹理的名字)"{}
例子:_MainTex("Main Tex" , 2D) = "white"{}

3.纹理的属性:

与其它属性类型不同,我们需要为某个纹理声明属性,在Unity中,需要使用纹理命_ST的方式。
纹理命_ST:

  • ST代表着缩放(scale)和平移(translation),_MainTex_ST可以让我们获取该纹理的缩放和平移值。
  • _MainTex_ST.xy存储的是缩放值。
  • _MainTex_ST.zw存储的是平移值。
4.Unity中对顶点纹理坐标变换的代码
  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。
6.纹理的滤波模式:

纹理的Filter Mode属性决定了当纹理由于变换而产生拉伸时将会采用哪种滤波模式。
纹理大小和模型不匹配时需要对纹理进行变换。

三种滤波模式(它们会影响放大和缩小纹理时得到的图片的质量):

  • Point
  • Bilinear
  • Trilinear
  • 它们得到的图片滤波效果依次提升,但是需要耗费的性能也依次增大。
7.多级渐远纹理技术(mipmapping):

在纹理缩小的过程中,我们需要处理抗锯齿问题。
原因:当纹理过大时,一个像素需要需要对应多个纹素,那么会导致采样的频率和纹理图像的频率是不对等的。

处理抗锯齿的方法:将原纹理提前用滤波处理来得到很多更小的图像,每一层都是对上一层图像降采样的结果,这样在实时运行时,就可以快速得到结果像素。

但是这种方法是用空间换取时间。

8.Format属性

Unity中Format决定了Unity使用哪种格式来存储纹理,使用的纹理格式精度越高,占用的空间越大,但是效果越好。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1294677.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-10
下一篇 2022-06-10

发表评论

登录后才能评论

评论列表(0条)

保存