Shader学习的基础知识( 三十五)表面着色器下

版权声明:版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ww1351646544/article/details/88633790

两个结构体

表面着色器支持最多自定义4种关键函数
表面着色器:各种表面性制如反射率、法线等
光照函数:定义使用的光照模型
顶点修改函数:修改或传弟顶点属性
颜色修改函数:对最终的颜色进行修改

一个表面着色器需要两个结构体
表面函数输入结构体Input 和 存储表面属性的结构休SurfaceOutput(或SurfaceOutputStandard和SurfaceOutputStandardSpecular)

Input结构体数据来源:

变量 描述
float3 ViewDir 视角方向,用于计算边缘光等
COLOR语义定义的float4 包含 了插值后的逐点颜色
float4 screenPos 屏幕空间坐标,可用于反射或屏幕特效
float3 worldPos 世界下的位置
float3 worldRefl 世界空间下的反射方向,前提是没有修改表面法线o.Normal
float3 worldRefl;INTERNAL_DATA 如果改了表面法线o.Normal,要使用变量告诉Unity基于修改后的法线计算世界空间下的反射方向
float3 worldNormal 世界空间的法线方向。前提是没有修改表面法线 o.Normall
float3 worldNormal;INTERNAL_DATA 如果改了表面法线o.Normal,要使用变量告诉Unity基于修改后的法线计算世界空间下的法线方向

我们并不需要自己计算这些变量,只要在Input中严格声明这些变量即可。

表面属性:SurfaceOutput:
有SurfaceOutput、SurfaceOutputStandard、SurfaceOutputStandardSpecular
这个提前声明好的,你挑你喜欢的就可以了。

struct SurfaceOutput{
	fixed3 Albedo;
	fixed3 Normal;
	fixed3 Emission;
	half Specular;
	fixed Gloss;
	fixed Alpha;
}
struct SurfaceOutputStandard{
	fixed3 Albedo;
	fixed3 Normal;
	fixed3 Emission;
	half Metallic;
	half Smoothness;
	half Occlusion;
	fixed Alpha;
}
struct SurfaceOutputStandardSpecular{
	fixed3 Albedo;
	fixed3 Specular;
	fixed3 Normal;
	fixed3 Emission;
	half Smoothness;
	half Occlusion;
	fixed Alpha;
}

简单的、非物理的光照模型包括Lambert和BlinnPhong这种通常使用SubfaceOutput如果 是基于物理的光照则使用后面两个。
着重讲一下SubfaceOutput:

  • fixed3 Albedo:对光源的反射率。
  • fixed3 Normal:表面法线方向。
  • fixed3 Emission:自发光。
  • half Specular:高光反射中的指数部分系数。
  • fixed Gloss:高光反射中强度系数。
  • fixed Alpha:透明通道。

表面着色器极大的减少了我们的工作,但它的问题是我们不知道它为什么会得到这样的结果。

例子:

这效果其实非常简单,即是顶点向法线方向扩张。
在这里插入图片描述
解释都在代码里:

Shader "Unity Shaders Book/Chapter 17/Normal Extrusion" {
	Properties {
		_ColorTint ("Color Tint", Color) = (1,1,1,1)
		_MainTex ("Base (RGB)", 2D) = "white" {}
		_BumpMap ("Normalmap", 2D) = "bump" {}
		_Amount ("Extrusion Amount", Range(-0.5, 0.5)) = 0.1
	}
	SubShader {
		Tags { "RenderType"="Opaque" }
		LOD 300
		
		CGPROGRAM
		
		// surface surf 指定为表面着色器.
		// CustomLambert 使用简单兰伯特光照模型.
		// vertex:myvert  使用自定义顶点功能.
		// finalcolor:mycolor - 使用定制最终颜色功能.
		// addshadow - 使用阴影.
		// exclude_path:deferred/exclude_path:不生成延迟渲染相关的路径.
		// nometa - 取消对提取元数据的Pass生成.
		#pragma surface surf CustomLambert vertex:myvert finalcolor:mycolor addshadow exclude_path:deferred exclude_path:prepass nometa
		#pragma target 3.0
		
		fixed4 _ColorTint;
		sampler2D _MainTex;
		sampler2D _BumpMap;
		half _Amount;
		
		struct Input {
			float2 uv_MainTex;
			float2 uv_BumpMap;
		};
		
		void myvert (inout appdata_full v) {
			//顶点位置+法线方向位置
			v.vertex.xyz += v.normal * _Amount;
		}
		
		void surf (Input IN, inout SurfaceOutput o) {
			//纹理取样
			fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
			//反射即是取样结果
			o.Albedo = tex.rgb;
			o.Alpha = tex.a;
			//法线取样
			o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
		}
		
		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 "Legacy Shaders/Diffuse"
}

点开这里可以看到具体做了什么
在这里插入图片描述
有兴趣的同学自己研究研究或是直接看一下《Unity Shader 入门精要》冯乐乐吧。

猜你喜欢

转载自blog.csdn.net/ww1351646544/article/details/88633790