unity基础学习之法线贴图

原理和概念

法线是一个向量(x,y,z),每一个顶点都有一个法线,用一个纹理去存储的话,那就是(r,g,b),由于法线是垂直于一个面的,对于2d图片来说,那他的z值就是1

用一张纹理来存储法线的值,法线的xyz方向取值是【-1,1】,而rgb的取值是【0,1】,所以这里有一个转换
rgb = (normal+1)/2=0.5*normal+0.5

资源

在unity中引入两个cube,为其分别制作一个材质,一个材质有法线贴图,一个没有,用作对比

资源1:
将图片导入unity,设置类型为normalmap
在这里插入图片描述
资源2:
在这里插入图片描述
shader 如下:
法线贴图shader

Shader "Custom/normalMapNormal" {
	Properties {
		_Color ("Color", Color) = (1,1,1,1)
		//基本贴图
		_MainTex ("Albedo (RGB)", 2D) = "white" {}
	    //法线贴图
		_NormalMaping("NormalMaping", 2D) = "bump" {}
		_Glossiness ("Smoothness", Range(0,1)) = 0.5
		_Metallic ("Metallic", Range(0,1)) = 0.0
	}
	SubShader {
		Tags { "RenderType"="Opaque" }
		LOD 200

		CGPROGRAM
		// Physically based Standard lighting model, and enable shadows on all light types
		#pragma surface surf Standard fullforwardshadows

		// Use shader model 3.0 target, to get nicer looking lighting
		#pragma target 3.0

		sampler2D _MainTex;
		sampler2D _NormalMaping; //在CG模块重新声明一下  _NormalMaping

		struct Input {
			float2 uv_MainTex;
			float2 uv_NormalMaping;
		};

		half _Glossiness;
		half _Metallic;
		fixed4 _Color;

		// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
		// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
		// #pragma instancing_options assumeuniformscaling
		UNITY_INSTANCING_BUFFER_START(Props)
			// put more per-instance properties here
		UNITY_INSTANCING_BUFFER_END(Props)

		void surf (Input IN, inout SurfaceOutputStandard o) {
			// Albedo comes from a texture tinted by color
			fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;

			// 提取法线值,UnpackNormal接受一个fixed4的输入,并将其转换为相应的法线值(fixed3)
			o.Normal = UnpackNormal(tex2D(_NormalMaping, IN.uv_NormalMaping));

			o.Albedo = c.rgb;
			// Metallic and smoothness come from slider variables
			/*o.Metallic = _Metallic;
			o.Smoothness = _Glossiness;*/
			o.Alpha = c.a;
		}
		ENDCG
	}
	FallBack "Diffuse"
}

不加法线贴图shader

Shader "Custom/normalMapBase" {
	/*
	在Properties{}中定义着色器属性,在这里定义的属性将被作为输入提供给所有的子着色器。每一条属性的定义的语法是这样的:
	_Name("Display Name", type) = defaultValue[{options}]

	_Name - 属性的名字,简单说就是变量名,在之后整个Shader代码中将使用这个名字来获取该属性的内容
	Display Name - 这个字符串将显示在Unity的材质编辑器中作为Shader的使用者可读的内容

	type - 这个属性的类型,可能的type所表示的内容有以下几种:
		Color - 一种颜色,由RGBA(红绿蓝和透明度)四个量来定义;
		2D - 一张2的阶数大小(256,512之类)的贴图。这张贴图将在采样后被转为对应基于模型UV的每个像素的颜色,最终被显示出来;
		Rect - 一个非2阶数大小的贴图;
		Cube - 即Cube map texture(立方体纹理),简单说就是6张有联系的2D贴图的组合,主要用来做反射效果(比如天空盒和动态反射),
		也会被转换为对应点的采样;
		Range(min, max) - 一个介于最小值和最大值之间的浮点数,一般用来当作调整Shader某些特性的参数(比如透明度渲染的截止值可以是从0至1的值等);
		Float - 任意一个浮点数;
		Vector - 一个四维数;
	defaultValue 定义了这个属性的默认值,通过输入一个符合格式的默认值来指定对应属性的初始值(某些效果可能需要某些特定的参数值来达到需要的效果,虽然这些值可以在之后在进行调整,
			 但是如果默认就指定为想要的值的话就省去了一个个调整的时间,方便很多)。
	Color - 以0~1定义的rgba颜色,比如(1,1,1,1);
	2D/Rect/Cube - 对于贴图来说,默认值可以为一个代表默认tint颜色的字符串,可以是空字符串或者”white”,”black”,”gray”,”bump”中的一个
	Float,Range - 某个指定的浮点数
	Vector - 一个4维数,写为 (x,y,z,w)
	另外还有一个{option},它只对2D,Rect或者Cube贴图有关,在写输入时我们最少要在贴图之后写一对什么都不含的空白的{},
	当我们需要打开特定选项时可以把其写在这对花括号内。如果需要同时打开多个选项,可以使用空白分隔。
	可能的选择有ObjectLinear, EyeLinear, SphereMap, CubeReflect, CubeNormal中的一个,这些都是OpenGL中TexGen的模式
	*/
	Properties {
		_Color ("Color", Color) = (1,1,1,1)
		_MainTex ("Albedo (RGB)", 2D) = "white" {}
	    //光滑度
		_Glossiness ("Smoothness", Range(0,1)) = 0.5
		//金属光泽
		_Metallic ("Metallic", Range(0,1)) = 0.0
	}
	SubShader {

		//表面着色器可以被若干个标签所修饰,通过判断标签来决定硬件什么时候该调用着色器
		/*
		RendererType赋值有:
		1.Opaque:绝大部分的不透明物体渲染时使用
		2.Transparent:绝大部分的透明物体渲染时使用
		3.BackGround:天空盒
		4.Overlay:用来渲染叠加效果,镜头光晕等
		*/
		Tags { "RenderType"="Opaque" }
		/*
		LOD是LevelofDetail的缩写,我们能用什么样的shader由它来决定,如果我们在Unity的QualitySetting中设定最大LOD值小于subshader所指定的值时,
		则subshader不可使用
        Unity的Shader制定了一组LOD值,我们在写shader的时候作为参考,方便以后对设备图形性能调整,和画质有更精确的控制

			Vertexlitkindofshaders(顶点光照类型的shader)=100
			Diffuse(漫反射)=200
			ReflectiveBumpedUnlit(凸起反射不发光)=250
			ReflectiveBumpedVertexlit(顶点反射不发光)=250
			Bumped,Specular(凸起,高光)=300
			凹凸高光=400
			Parallax(视差)=500
			ParallaxSpecular(视差高光)=600
		*/
		LOD 200

		CGPROGRAM
		// Physically based Standard lighting model, and enable shadows on all light types
		#pragma surface surf Standard fullforwardshadows

		// Use shader model 3.0 target, to get nicer looking lighting
		#pragma target 3.0

		sampler2D _MainTex;

		struct Input {
			     // 输入结构体重一般包含着色器所需要的纹理坐标,命名规范:uv + 纹理名称
				 //当使用第二纹理,命名为:uv2+纹理名称
			     float3 viewDir;//视角方向
				 float4 COLOR; //每个顶点的颜色差值
				 float4 screenPos;//屏幕坐标(使用.xy/.wh来获取屏幕2D坐标)
				 float3 worldRefl;// 世界坐标系中反射向量
				 float3 worldNormal;// 世界坐标系中法线向量
				 float2 uv_MainTex;//纹理坐标
		};

		half _Glossiness;
		half _Metallic;
		fixed4 _Color;

		// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
		// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
		// #pragma instancing_options assumeuniformscaling
		UNITY_INSTANCING_BUFFER_START(Props)
			// put more per-instance properties here
		UNITY_INSTANCING_BUFFER_END(Props)

	    /*void myvert(inout appdata_full v) {
			v.vertex.xyz += v.normal * _Amount;
		}*/

	   /*
		其作用是结构输入的uv或者附加数据,然后进行处理,最后将结构填充到输出结构体中,所以只能按照规定来写
		参数1:Input:是我们需要定义的输入结构体,可以吧所需要参与计算的数据放到这个结构体中,传入方法使用
		参数2:inout:SurfaceOutput定义输出结构体的类型,需要把方法里面得到的结果赋值给该结构体里面的成员变量即可完成着色
		SurfaceOutput的输出结果结构定义如下:
			half3Albedo:像素的颜色
			half3Normal:法线
			half3Emission:自发光,不受光照影响
			halfSpecular:高光指数
			halfGloss:光泽度
			halfAlpha:透明度
		SurfaceOutPutStandard输出结果定义如下:
			fixed3Albedo:基础颜色
			fixed3Normal:切线空间法线
			halfSmoothness:是否光滑,0=粗糙,1=光滑
			halfMetallic:是否有金属光泽,0=非金属,1=金属
			halfOcclusion:遮挡(默认为1)
			fixedAlpha:透明度
	   */
		void surf (Input IN, inout SurfaceOutputStandard o) {
			// Albedo comes from a texture tinted by color
			fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
			o.Albedo = c.rgb;
			// Metallic and smoothness come from slider variables
			o.Metallic = _Metallic;
			o.Smoothness = _Glossiness;
			o.Alpha = c.a;
		}

		/*half4 LightingCustomLambert(SurfaceOutput s, half3 lightDir, half atten) {
			half NdotL = dot(s.Normal, lightDir);
			half4 c;
			c.rgb = s.Albedo * _LightColor0.rgb * (NdotL * atten);
			c.a = s.Alpha;
			return c;
		}

		void mycolor(Input IN, SurfaceOutput o, inout fixed4 color) {
			color *= _ColorTint;
		}*/

		ENDCG
	}
	FallBack "Diffuse"
}

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值