【U3D/Shader】06.基础纹理(下)渐变纹理,遮罩纹理

自我介绍

广东双非一本的大三小白,计科专业,想在制作毕设前夯实基础,毕设做出一款属于自己的游戏!

渐变纹理

效果

在这里插入图片描述

代码没什么好说的,跟单张纹理类似

不过要注意的是:

  • 渐变纹理是一维纹理,所以在vert中进行uv映射之后,在frag中进行采样的uv值中的v和u方向都用半兰伯特模型中的值即可(该半兰伯特模型中的值已被映射到 [0, 1] 中)
Shader "Unlit/014"
{
      Properties
	{
		_RampTex("MainTex", 2D) = "white" {}
		_Diffuse("Diffuse", Color) = (1,1,1,1)
		_Specular("Specular", Color) = (1,1,1,1)
		_Gloss("Gloss", Range(1,256)) = 5
	}

	SubShader
	{
		Tags { "RenderType"="Opaque" }
		LOD 100

		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"
			#include "Lighting.cginc"

			sampler2D _RampTex;
			float4 _RampTex_ST;
			fixed4 _Diffuse;
			fixed4 _Specular;
			float _Gloss;

			struct v2f
			{
				float4 vertex : SV_POSITION;
				fixed3 worldNormal: TEXCOORD0;
				float3 worldPos: TEXCOORD1;
				float2 uv : TEXCOORD2;
			};

			v2f vert (appdata_base v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				fixed3 worldNormal = UnityObjectToWorldNormal( v.normal);
				o.worldNormal = worldNormal;
				o.worldPos = mul(unity_ObjectToWorld, v.vertex);
				o.uv = TRANSFORM_TEX(v.texcoord, _RampTex);	//v.texcoord.xy * _RampTex_ST.xy + _RampTex_ST.zw;
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;

				//漫反射
				fixed3 worldLightDir = UnityWorldSpaceLightDir(i.worldPos);
				fixed halfLambert = max(0,dot(worldLightDir,i.worldNormal))*0.5+0.5;
				fixed3 diffuse = _LightColor0.rgb * tex2D(_RampTex, fixed2(halfLambert,halfLambert)) * _Diffuse.rgb;

				//高光反射
				//fixed3 reflectDir = normalize(reflect(-worldLightDir,i.worldNormal));
				fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
				//fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
				fixed3 halfDir = normalize(worldLightDir + viewDir);
				fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(i.worldNormal,halfDir)),_Gloss);
				
				fixed3 color = ambient + diffuse + specular;
				return fixed4(color,1);
			}
			ENDCG
		}
	}
}

但是在材质属性上需要进行一个小改动

在这里插入图片描述

Wrap Mode分别为Repeat和Clamp模式的效果对比

在这里插入图片描述

会有黑点是因为浮点精度造成的,比如 fixed2(halfLambert,halfLambert) 中,理论上他们的值在 [0,1] 之间浮动,但也有可能出现 1.00001,这时候如果是用的Reapeat模式,会舍弃掉整数部份,保留小数部份,得到0.00001,也就是黑色


遮罩纹理

这是非常有用的纹理,为了得到更加细腻的效果,需要用到遮罩纹理来控制光照,效果如下

在这里插入图片描述

流程:通过采样得到遮罩纹理的纹素值,然后使用其中某几个通道的值来与表面属性进行相乘(比如通道值为0,可以保护表面不受该属性影响)

可以看到下面我们只是用了这张遮罩纹理的一个分量值,其他值就被浪费了,实际制作中,要充分利用遮罩纹理中的每个颜色通道来存储不同的表面属性,后面会提到

Shader "Unlit/015"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _BumpMap("BumpMap", 2D) = "bump" {}
        _BumpScale("BumpScale", float) = 5
        _SpecularMask("Specular Mask", 2D) = "white"{}
        _SpecularScale("Specular Scale", float) = 1
        _Diffuse("Diffuse", color) = (1,1,1,1)
        _Specular("Specular", color) = (1,1,1,1)
        _Gloss("Gloss", Range(1, 256)) = 2
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #include "Lighting.cginc"

            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D _BumpMap;
            float4 _BumpMap_ST;
            float _BumpScale;
            sampler2D _SpecularMask;
			float4 _SpecularMask_ST;
			float _SpecularScale;
            fixed3 _Diffuse;
            fixed3 _Specular;
            float _Gloss;

            struct v2f 
            {
                float4 vertex : SV_POSITION;
                float4 TtiW0 : TEXCOORD0;
                float4 TtiW1 : TEXCOORD1;
                float4 TtiW2 : TEXCOORD2;
                float4 uv : Texcoord3;
                float2 maskUv : TEXCOORD4;
            };

            v2f vert(appdata_tan v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
                o.uv.zw = TRANSFORM_TEX(v.texcoord, _BumpMap);
                o.maskUv = TRANSFORM_TEX(v.texcoord, _SpecularMask);

                float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                float3 worldNormal = UnityObjectToWorldNormal(v.normal);
                float3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
                float3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;

                o.TtiW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
                o.TtiW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
                o.TtiW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);

                return o;
            }

            fixed4 frag(v2f o) : SV_TARGET0
            {
                float3 worldPos = float3(o.TtiW0.w, o.TtiW1.w, o.TtiW2.w);

                fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
                fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));

                fixed4 packedNormal = tex2D(_BumpMap, o.uv.zw);
                fixed3 tangentNormal = UnpackNormal(packedNormal);
                tangentNormal.xy *= _BumpScale;

                fixed3 worldNormal = normalize(float3(dot(o.TtiW0.xyz, tangentNormal), dot(o.TtiW1.xyz, tangentNormal), dot(o.TtiW2.xyz, tangentNormal)));
                
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;

                fixed3 albedo = tex2D(_MainTex, o.uv.xy).rgb;
                fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * albedo * (dot(lightDir, worldNormal) * 0.5 + 0.5);

                fixed3 specularMask = tex2D(_SpecularMask, o.maskUv).r * _SpecularScale;
                fixed3 halfDir = normalize(viewDir + lightDir);
                fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(worldNormal, halfDir)), _Gloss) * specularMask;

                fixed3 color = ambient + diffuse + specular;
                return fixed4(color, 1);
            }
            
            ENDCG
        }
    }
}

书上的shader是 主纹理_MainTex,法线纹理_BumpMap 和 遮罩纹理_SpecularMask 都用同一个纹理属性变量 _MainTex_ST 来控制

因为很多时候我们不需要对纹理进行平铺和位移操作,这样能节省需要存储的纹理坐标数目,空出顶点着色器中的插值寄存器

Shader "Unlit/015"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _BumpMap("BumpMap", 2D) = "bump" {}
        _BumpScale("BumpScale", float) = 5
        _SpecularMask("Specular Mask", 2D) = "white"{}
        _SpecularScale("Specular Scale", float) = 1
        _Diffuse("Diffuse", color) = (1,1,1,1)
        _Specular("Specular", color) = (1,1,1,1)
        _Gloss("Gloss", Range(1, 256)) = 2
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #include "Lighting.cginc"

            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D _BumpMap;
            float _BumpScale;
            sampler2D _SpecularMask;
			float _SpecularScale;
            fixed3 _Diffuse;
            fixed3 _Specular;
            float _Gloss;

            struct v2f 
            {
                float4 vertex : SV_POSITION;
                float4 TtiW0 : TEXCOORD0;
                float4 TtiW1 : TEXCOORD1;
                float4 TtiW2 : TEXCOORD2;
                float2 uv : Texcoord3;
            };

            v2f vert(appdata_tan v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv.xy = TRANSFORM_TEX(v.texcoord, _MainTex);

                float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                float3 worldNormal = UnityObjectToWorldNormal(v.normal);
                float3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
                float3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;

                o.TtiW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
                o.TtiW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
                o.TtiW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);

                return o;
            }

            fixed4 frag(v2f o) : SV_TARGET0
            {
                float3 worldPos = float3(o.TtiW0.w, o.TtiW1.w, o.TtiW2.w);

                fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
                fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));

                fixed4 packedNormal = tex2D(_BumpMap, o.uv);
                fixed3 tangentNormal = UnpackNormal(packedNormal);
                tangentNormal.xy *= _BumpScale;

                fixed3 worldNormal = normalize(float3(dot(o.TtiW0.xyz, tangentNormal), dot(o.TtiW1.xyz, tangentNormal), dot(o.TtiW2.xyz, tangentNormal)));
                
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;

                fixed3 albedo = tex2D(_MainTex, o.uv).rgb;
                fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * albedo * (dot(lightDir, worldNormal) * 0.5 + 0.5);

                fixed3 specularMask = tex2D(_SpecularMask, o.uv).r * _SpecularScale;
                fixed3 halfDir = normalize(viewDir + lightDir);
                fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(worldNormal, halfDir)), _Gloss) * specularMask;

                fixed3 color = ambient + diffuse + specular;
                return fixed4(color, 1);
            }
            
            ENDCG
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值