[Unity Shader 프로 그래 밍] 의 14 가장자리 발광 Shader (Rim Shader) 의 두 가지 실현 형태

이 시 리 즈 는 @ 연 묵모 성운 출품, 전재 출처 를 밝 혀 주세요.   글 링크: http://blog.csdn.net/poem_qianmo/article/details/51764028 저자: 모 성운 (연 묵)    웨 이 보:http://weibo.com/u/1723155442 본 프로젝트 에 사 용 된 Unity3D 버 전: 5.2.1 
이 글 은 Unity3D 에서 각각 Surface Shader 와 Vertex & Fragment Shader 를 사용 하여 가장자리 발광 Shader 를 만 드 는 방법 을 설명 한다.
 
1. 최종 실현 의 효과
 
가장자리 발광 Shader 의 직관 적 인 운용 은 바로 우주 속 의 별 효 과 를 모 의 하 는 것 이다.본 논문 에서 실 현 된 가장자리 발광 Shader 를 먼저 Material 을 부여 하고 이 Material 를 하나의 구체 에 부여 하 며 Galaxy Skybox 를 더 하면 다음 과 같은 효 과 를 얻 을 수 있 습 니 다.
  【Unity Shader编程】之十四 边缘发光Shader(Rim Shader)的两种实现形态_第1张图片
물론 가장자리 발광 Shader 도 예 를 들 어 암흑 3 중 정 영 몬스터 의 하 이 라이트 효 과 를 실현 할 수 있 습 니 다. 한 몬스터 모델 자체 의 Shader 를 가장자리 발광 Shader 로 대체 하여 다음 그림 과 같이 효 과 를 실현 할 수 있 습 니 다.
【Unity Shader编程】之十四 边缘发光Shader(Rim Shader)的两种实现形态_第2张图片
 
다음은 본 논문 에서 실 현 된 Shader 가 편집기 에서 의 효과 그림 입 니 다.
  【Unity Shader编程】之十四 边缘发光Shader(Rim Shader)的两种实现形态_第3张图片    【Unity Shader编程】之十四 边缘发光Shader(Rim Shader)的两种实现形态_第4张图片      
  【Unity Shader编程】之十四 边缘发光Shader(Rim Shader)的两种实现形态_第5张图片    【Unity Shader编程】之十四 边缘发光Shader(Rim Shader)的两种实现形态_第6张图片
2. Shader 실현 사고 분석
 
사고방식 은 사실 이해 하기 매우 간단 하 다. 바로 정상 적 인 난반사 Shader 를 바탕 으로 최종 난반사 색상 값 이 나 온 후에 자체 발광 색상 값 을 준비 하고 부가 하면 최종 적 으로 자체 발광 색상 값 을 얻 을 수 있다.
공식 적 으로 표현 하면 바로 이렇다.
 
최종 색상 = 만반 사 계수 x 텍 스 처 컬러 x RGB 색상) + 자체 발광 색상
 
영어 공식 에 따라 표현 하면 바로 이렇다.
FinalColor=(Diffuse x Texture x RGBColor)+Emissive
 
 
 
 
 
3. Surface Shader 판 가장자리 발광 Shader 실현
이 시리즈 의 첫 번 째 글 을 읽 은 친구 라면 이 시리즈 의 첫 번 째 글 (전송 문:http://blog.csdn.net/poem_qianmo/article/details/40723789), 안에 있 는 The First Shader 는 표준 적 인 사용 Unity 입 니 다. 서 피 스 셰 이 더 가 구현 한 테두리 발광 셰 이 더.
Unity 자체 의 Shader 패 키 징, Surface Shader, 즉 Shaderlab 을 이용 하여 초보 자 나 빠 른 속도 로 시작 하고 싶 은 어린이 신발 로 Unity 에서 Shader 가 쓴 아주 좋 은 착안점 을 배 웠 습 니 다.
강 화 된 1 기 The First Shader 의 상세 한 설명 을 거 친 소스 코드 가 붙 어 있 습 니 다.주요 프레임 워 크 에 대한 주석 이 모두 중 영 이중 언어 인 것 을 발견 할 수 있 습 니 다. 왜냐하면 많은 외국 친구 들 도 제 가 Github 에 있 는 Shader repo (https://github.com/QianMo/Awesome-Unity-Shader) 이들 과 그 뒤에 더 많은 외국 친구 들 을 편리 하 게 하기 위해 앞으로 주말 에 블 로 그 를 쓸 시간 이 넉넉 하 다 면 아예 중 영 이중 언어 주석 을 쓰 면 된다.
OK, 상세 설명 후 Surface Shader 판 발광 가능 Shader 소스 코드 는 다음 과 같 습 니 다.
Shader "Learning Unity Shader/Lecture 14/Surface Rim Shader"
{
	//-----------------------------------【属性 || Properties】------------------------------------------  
	Properties
	{
		//主颜色 || Main Color
		_MainColor("【主颜色】Main Color", Color) = (0.5,0.5,0.5,1)
		//漫反射纹理 || Diffuse Texture
		_MainTex("【纹理】Texture", 2D) = "white" {}
		//凹凸纹理 || Bump Texture
		_BumpMap("【凹凸纹理】Bumpmap", 2D) = "bump" {}
		//边缘发光颜色 || Rim Color
		_RimColor("【边缘发光颜色】Rim Color", Color) = (0.17,0.36,0.81,0.0)
		//边缘发光强度 ||Rim Power
		_RimPower("【边缘颜色强度】Rim Power", Range(0.6,36.0)) = 8.0
		//边缘发光强度系数 || Rim Intensity Factor
		_RimIntensity("【边缘颜色强度系数】Rim Intensity", Range(0.0,100.0)) = 1.0
	}

	//----------------------------------【子着色器 || SubShader】---------------------------------------  
	SubShader
	{
		//渲染类型为Opaque,不透明 || RenderType Opaque
		Tags
		{
			"RenderType" = "Opaque" 
		}

		//-------------------------开启CG着色器编程语言段 || Begin CG Programming Part---------------------- 
		CGPROGRAM

			//【1】声明使用兰伯特光照模式 ||Using the Lambert light mode
			#pragma surface surf Lambert  

			//【2】定义输入结构 ||  Input Struct
			struct Input
			{
				//纹理贴图 || Texture
				float2 uv_MainTex;
				//法线贴图 || Bump Texture
				float2 uv_BumpMap;
				//观察方向 || Observation direction
				float3 viewDir;  
			};

			//【3】变量声明 || Variable Declaration
			//边缘颜色
			float4 _MainColor;
			//主纹理
			sampler2D _MainTex;  
			//凹凸纹理  
			sampler2D _BumpMap;
			//边缘颜色
			float4 _RimColor;
			//边缘颜色强度
			float _RimPower;
			//边缘颜色强度
			float _RimIntensity;

			//【4】表面着色函数的编写 || Writing the surface shader function
			void surf(Input IN, inout SurfaceOutput o)
			{
				//表面反射颜色为纹理颜色  
				o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb*_MainColor.rgb;
				//表面法线为凹凸纹理的颜色  
				o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
				//边缘颜色  
				half rim = 1.0 - saturate(dot(normalize(IN.viewDir), o.Normal));
				//计算出边缘颜色强度系数  
				o.Emission = _RimColor.rgb * pow(rim, _RimPower)*_RimIntensity;
			}

		//-------------------结束CG着色器编程语言段 || End CG Programming Part------------------  
		ENDCG
	}

		//后备着色器为普通漫反射 || Fallback use Diffuse
		Fallback "Diffuse"
}

 
조금 만 생각해 보면 알 수 있 듯 이 이 Shader 는 Unity 5 에 포 장 된 Standard Surface Output 구조 체 의 Emission (자 발 광) 속성 을 이용 하여 이러한 가장자리 빛 효 과 를 내 는 것 으로 기술 함량 이 매우 제한 적 이다.여기에 Unity 5 의 Surface OutputStandard 원형 을 첨부 합 니 다.
 
// Unity5 SurfaceOutputStandard原型:
struct SurfaceOutputStandard
{
	fixed3 Albedo;                  // 漫反射颜色
	fixed3 Normal;                  // 切线空间法线
	half3 Emission;                 //自发光
	half Metallic;                    // 金属度;取0为非金属, 取1为金属
	half Smoothness;             // 光泽度;取0为非常粗糙, 取1为非常光滑
	half Occlusion;                 // 遮挡(默认值为1)
	fixed Alpha;                      // 透明度
};

이 Shader 를 Material 에 부여 한 후 편집기 효과 그림:
【Unity Shader编程】之十四 边缘发光Shader(Rim Shader)的两种实现形态_第7张图片
【Unity Shader编程】之十四 边缘发光Shader(Rim Shader)的两种实现形态_第8张图片
 
 안에 6 개의 매개 변수 가 있 는데 주요 색채, 무늬, 요철 무늬, 가장자리 발광 색채, 가장자리 색채 강도, 가장자리 색채 강도 계수 등 6 개의 매개 변 수 는 맞 춤 형 으로 조절 할 수 있 고 스티커 자원 이 제자리 에 있 으 면 자신 이 만족 하 는 효 과 를 쉽게 조절 할 수 있다.
 
 
4. 프로 그래 밍 가능 한 Shader 판 가장자리 발광 Shader 의 실현
이 글 의 핵심 은 이 절 을 실현 하 는 이 프로 그래 밍 가능 판 (즉, Vertex & Fragment Shader) 가장자리 발광 Shader 이다.알다 시 피 베 르 텍 스 & 프 래 그 먼 트 셰 이 더 는 서 피 스 셰 이 더 보다 한 단계 높 은 구현 형태 로, 더 큰 제어 성, 더 좋 은 프로 그래 밍 성, 더 풍부 한 효 과 를 구현 할 수 있 으 며, CG 착색 언어 에 더욱 가 까 운 셰 이 더 형태 다.
OK, 상세 한 주석 을 거 친 Vertex & Fragment Shader 판 가장자리 발광 Shader 구현 소스 코드 를 직접 붙 입 니 다.
 
Shader "Learning Unity Shader/Lecture 14/Basic Rim Shader" 
{
	//-----------------------------------【属性 || Properties】------------------------------------------  
	Properties
	{
		//主颜色 || Main Color
		_MainColor("【主颜色】Main Color", Color) = (0.5,0.5,0.5,1)
		//漫反射纹理 || Diffuse Texture
		_TextureDiffuse("【漫反射纹理】Texture Diffuse", 2D) = "white" {}	
		//边缘发光颜色 || Rim Color
		_RimColor("【边缘发光颜色】Rim Color", Color) = (0.5,0.5,0.5,1)
		//边缘发光强度 ||Rim Power
		_RimPower("【边缘发光强度】Rim Power", Range(0.0, 36)) = 0.1
		//边缘发光强度系数 || Rim Intensity Factor
		_RimIntensity("【边缘发光强度系数】Rim Intensity", Range(0.0, 100)) = 3
	}

	//----------------------------------【子着色器 || SubShader】---------------------------------------  
	SubShader
	{
		//渲染类型为Opaque,不透明 || RenderType Opaque
		Tags
		{
			"RenderType" = "Opaque"
		}

		//---------------------------------------【唯一的通道 || Pass】------------------------------------
		Pass
		{
			//设定通道名称 || Set Pass Name
			Name "ForwardBase"

			//设置光照模式 || LightMode ForwardBase
			Tags
			{
				"LightMode" = "ForwardBase"
			}

			//-------------------------开启CG着色器编程语言段 || Begin CG Programming Part----------------------  
			CGPROGRAM

				//【1】指定顶点和片段着色函数名称 || Set the name of vertex and fragment shader function
				#pragma vertex vert
				#pragma fragment frag

				//【2】头文件包含 || include
				#include "UnityCG.cginc"
				#include "AutoLight.cginc"

				//【3】指定Shader Model 3.0 || Set Shader Model 3.0
				#pragma target 3.0

				//【4】变量声明 || Variable Declaration
				//系统光照颜色
				uniform float4 _LightColor0;
				//主颜色
				uniform float4 _MainColor;
				//漫反射纹理
				uniform sampler2D _TextureDiffuse; 
				//漫反射纹理_ST后缀版
				uniform float4 _TextureDiffuse_ST;
				//边缘光颜色
				uniform float4 _RimColor;
				//边缘光强度
				uniform float _RimPower;
				//边缘光强度系数
				uniform float _RimIntensity;

				//【5】顶点输入结构体 || Vertex Input Struct
				struct VertexInput 
				{
					//顶点位置 || Vertex position
					float4 vertex : POSITION;
					//法线向量坐标 || Normal vector coordinates
					float3 normal : NORMAL;
					//一级纹理坐标 || Primary texture coordinates
					float4 texcoord : TEXCOORD0;
				};

				//【6】顶点输出结构体 || Vertex Output Struct
				struct VertexOutput 
				{
					//像素位置 || Pixel position
					float4 pos : SV_POSITION;
					//一级纹理坐标 || Primary texture coordinates
					float4 texcoord : TEXCOORD0;
					//法线向量坐标 || Normal vector coordinates
					float3 normal : NORMAL;
					//世界空间中的坐标位置 || Coordinate position in world space
					float4 posWorld : TEXCOORD1;
					//创建光源坐标,用于内置的光照 || Function in AutoLight.cginc to create light coordinates
					LIGHTING_COORDS(3,4)
				};

				//【7】顶点着色函数 || Vertex Shader Function
				VertexOutput vert(VertexInput v) 
				{
					//【1】声明一个顶点输出结构对象 || Declares a vertex output structure object
					VertexOutput o;

					//【2】填充此输出结构 || Fill the output structure
					//将输入纹理坐标赋值给输出纹理坐标
					o.texcoord = v.texcoord;
					//获取顶点在世界空间中的法线向量坐标  
					o.normal = mul(float4(v.normal,0), _World2Object).xyz;
					//获得顶点在世界空间中的位置坐标  
					o.posWorld = mul(_Object2World, v.vertex);
					//获取像素位置
					o.pos = mul(UNITY_MATRIX_MVP, v.vertex);

					//【3】返回此输出结构对象  || Returns the output structure
					return o;
				}

				//【8】片段着色函数 || Fragment Shader Function
				fixed4 frag(VertexOutput i) : COLOR
				{
					//【8.1】方向参数准备 || Direction
					//视角方向
					float3 ViewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz);
					//法线方向
					float3 Normalection = normalize(i.normal);
					//光照方向
					float3 LightDirection = normalize(_WorldSpaceLightPos0.xyz);

					//【8.2】计算光照的衰减 || Lighting attenuation
					//衰减值
					float Attenuation = LIGHT_ATTENUATION(i);
					//衰减后颜色值
					float3 AttenColor = Attenuation * _LightColor0.xyz;

					//【8.3】计算漫反射 || Diffuse
					float NdotL = dot(Normalection, LightDirection);
					float3 Diffuse = max(0.0, NdotL) * AttenColor + UNITY_LIGHTMODEL_AMBIENT.xyz;

					//【8.4】准备自发光参数 || Emissive
					//计算边缘强度
					half Rim = 1.0 - max(0, dot(i.normal, ViewDirection));
					//计算出边缘自发光强度
					float3 Emissive = _RimColor.rgb * pow(Rim,_RimPower) *_RimIntensity;

					//【8.5】计在最终颜色中加入自发光颜色 || Calculate the final color
					//最终颜色 = (漫反射系数 x 纹理颜色 x rgb颜色)+自发光颜色 || Final Color=(Diffuse x Texture x rgbColor)+Emissive
					float3 finalColor = Diffuse * (tex2D(_TextureDiffuse,TRANSFORM_TEX(i.texcoord.rg, _TextureDiffuse)).rgb*_MainColor.rgb) + Emissive;
				
					//【8.6】返回最终颜色 || Return final color
					return fixed4(finalColor,1);
				}

			//-------------------结束CG着色器编程语言段 || End CG Programming Part------------------  
			ENDCG
		}
	}

	//后备着色器为普通漫反射 || Fallback use Diffuse
	FallBack "Diffuse"
}

 많은 친구 들 이 이미 알 아 차 렸 을 것 이 라 고 믿 습 니 다. 일반적인 난반사 Shader 에 비해 이 Shader 의 마력 은 '8.4 자체 발광 매개 변수 준비' 와 '8.5 최종 색상 에 자체 발광 색상' 두 단계 만 더 넣 었 을 뿐 앞 에는 모두 일반적인 Vertex & Fragment Shader 일반적인 표기 법 입 니 다.
이 Shader 를 Material 에 부여 하면 다음 과 같은 효 과 를 얻 을 수 있 습 니 다.
【Unity Shader编程】之十四 边缘发光Shader(Rim Shader)的两种实现形态_第9张图片    【Unity Shader编程】之十四 边缘发光Shader(Rim Shader)的两种实现形态_第10张图片
 
【Unity Shader编程】之十四 边缘发光Shader(Rim Shader)的两种实现形态_第11张图片    【Unity Shader编程】之十四 边缘发光Shader(Rim Shader)的两种实现形态_第12张图片
물론 이 두 개의 Shader 를 장면 의 각종 모델 에 사용 할 수 있 습 니 다. 다음은 효과 그림 입 니 다.
  【Unity Shader编程】之十四 边缘发光Shader(Rim Shader)的两种实现形态_第13张图片
【Unity Shader编程】之十四 边缘发光Shader(Rim Shader)的两种实现形态_第14张图片
【Unity Shader编程】之十四 边缘发光Shader(Rim Shader)的两种实现形态_第15张图片
【Unity Shader编程】之十四 边缘发光Shader(Rim Shader)的两种实现形态_第16张图片
OK, 이 글 의 내용 은 대체로 이와 같 습 니 다. 우리 다음 글, 안녕 히 계 세 요.
첨부: 본문 세트 소스 다운로드 링크
[Github] 본문 Shader 소스 코드

좋은 웹페이지 즐겨찾기