顶点-片段着色器基础(四)

本系列文章系学习 唐福幸《Unity ShaderLab 新手宝典》的笔记,包含个人理解,如有错误欢迎批评指出

顶点-片段着色器基础

4.3.4 在CG中调用属性变量

4.3.4.1声明属性变量

之前展示的简单shader,最终效果是纯红色。如果要改变颜色只能修改代码,我们可以通过属性让颜色变量在材质面板中开放,便于随意调整。

新建一个材质,新建一个Shader,代码如下:

Shader "Chapter4/NewUnlitShader1"
{
    Properties
    {
        _MyFloat ("Float Type", Float) = 1
        _MyRange ("Range Type", Range(0,1)) = 0.1
        _MyColor ("Color Type", Color) = (1,1,0,1)
        _MyVector ("Vector Type", Vector) = (0,1,0,0)
        _MyTex("Texture Type", 2D) = "white" {}
        _MyCube("Cube Type",Cube) = "" {}
        _My3D("3D Type",3D) = "" {}
    }
        SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            float _MyFloat;
            float _MyRange;
            fixed4 _MyColor;
            float4 _MyVector;
            sampler2D _MyLuoLuo;
            samplerCUBE _MyCube;
            sampler3D _Mp3D;
            
            void vert()
            {
            
            }

            void frag()
            {

            }
            ENDCG
        }
    }
}

材质面板中显示如下:这些数值是可以任意调整的,但是还没有具体效果
顶点-片段着色器基础(四)

4.3.4.2在shader中使用颜色

新建一个材质,新建一个Shader,代码如下:

Shader "Chapter4/NewUnlitShaderColor"
{
    Properties
    {
    	//开放颜色属性
        _MainColor("Color Type", Color) = (1,0,1,1)
    }
        SubShader
    {

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // 声明属性变量
            float4 _MainColor;

            float4 vert (in float4 v : POSITION) : SV_POSITION
            {
                return UnityObjectToClipPos(v);//把顶点坐标从模型空间转换成剪裁空间,如果不转换,后面颜色根本无法显示
            }

            fixed4 frag () : SV_Target
            {
            	//调用颜色变量
                return _MainColor;
            }
            ENDCG
        }
    }
}

4.3.4.3在shader中使用贴图

代码中将贴图与颜色混和,代码如下:

Shader "Chapter4/NewUnlitShaderTex"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _MainColor ("MainColor",Color) = (1,1,1,1)
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            sampler2D _MainTex;
            float4 _MainTex_ST;//表示uv的缩放和平移
            float4 _MainColor;

            void vert(in float4 vertex : POSITION, in float2 uv : TEXCOORD0, out float4 position : SV_POSITION, out float2 texcoord : TEXCOORD0)
            {
                position = UnityObjectToClipPos(vertex);
                texcoord = uv * _MainTex_ST.xy + _MainTex_ST.zw;//纹理坐标的计算公式
            }

            void frag(in float4 position : SV_POSITION, in float2 texcoord : TEXCOORD0, out fixed4 color : SV_TARGET)
            {
                color = tex2D(_MainTex, texcoord) * _MainColor;//使用纹理坐标texcoord对纹理_MainTex进行采样,结果与_MainColor颜色混合
                //tex2D:https://blog.csdn.net/yuanerjiang/article/details/88681589
            }
            ENDCG
        }
    }
}


顶点-片段着色器基础(四)

Tiling:表示平铺(放大缩小)
Offset:偏移
texcoord = uv * _MainTex_ST.xy + _MainTex_ST.zw;
xy表示Tiling的X、Y;zw表示Offset的X、Y
计算纹理坐标一定要先乘平铺值,再加偏移值,避免偏移后对原坐标放大错误比例

4.3.4.4在shader中使用立方体贴图

新建一个材质,新建一个Shader,代码如下:

Shader "Chapter4/NewUnlitShaderCube"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _MainColor ("Color", Color) = (1,1,1,1)
        _MainCubemap ("Cubemap Type", Cube) = "" {}
        _Reflection ("Reflection", Range(0,1)) = 0
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            sampler _MainTex;
            float4 _MainTex_ST;
            fixed4 _MainColor;

            samplerCUBE _MainCubemap;
            fixed _Reflection;

            void vert (in float4 verte :POSITION, in float3 normal : NORMAL,in float4 uv : TEXCOORD0,
                        out float4 position : SV_POSITION, out float4 worldPos : TEXCOORD0, out float3 worldNormal : TEXCOORD1, out float2 texcoord : TEXCOORD2)
            {
                position = UnityObjectToClipPos(verte);
                worldPos = mul(unity_ObjectToWorld, verte); //将顶点坐标变换到世界空间
                worldNormal = mul(normal,(float3x3)unity_WorldToObject);//将法线向量变换到世界空间
                worldNormal = normalize(worldNormal);//法线归一化

                texcoord = uv * _MainTex_ST.xy + _MainTex_ST.wz;
            }

            void frag (in float4 position : SV_POSITION, in float4 worldPos : TEXCOORD0, in float3 worldNormal : TEXCOORD1, in float2 texcoord : TEXCOORD2,
                        out fixed4 colo : SV_TARGET)
            {
                fixed4 main = tex2D(_MainTex, texcoord)*_MainColor;
                
                float3 ViewDir = worldPos.xyz - _WorldSpaceCameraPos;//计算世界空间中从摄像机指向顶点方向向量
                ViewDir = normalize(ViewDir);//标准化向量

                float3 refDir = 2 * dot(-ViewDir, worldNormal) *worldNormal +ViewDir;//套用公式计算反射向量
                refDir = normalize(refDir);//标准化向量

                fixed4 reflection = texCUBE(_MainCubemap,refDir);//对Cubemap采样

                colo = lerp(main,reflection,_Reflection);//使用_Reflection对颜色和反射进行线性插值计算
            }
            ENDCG
        }
    }
}

再贴图属性面板中把Texture Shape从2D改成Cube,点击下方的Apply
之后就可以把图片放到材质上了
顶点-片段着色器基础(四)

上一篇:亚马逊跟卖,如何进行安全跟卖?


下一篇:卜若的代码笔记-webgl系列-第二十三章:glsl的应用(三)>尽可能的去掉白边