上個MMO項目結束有段時間了 ,最近開始新的沙盒項目了,把自己這段時間遇到的問題都整理整理,分享出來。
本文主要講解如何用Unity Standard核心來快速的實作自定義PBR Shader,給大家一些簡單的參考意見。
話不多說,直接上代碼:
Shader "Custom/SimplePBRTest"
{
Properties
{
_AlbedoMap("AlbedoMap", 2D) = "white" {}
_BaseColor("BaseColor", Color) = (1,1,1,1)
_Smooth("Smooth", Range( 0 , 1)) = 1
}
SubShader
{
Tags { "RenderType"="Opaque" }
CGPROGRAM
//StandardCustomLighting 自定義光照模型
//noinstancing noforwardadd 為了減少surface shader 生成通道
#pragma surface surf StandardCustomLighting fullforwardshadows noinstancing noforwardadd
#pragma target 3.0
//引用PBR核心庫
#include "UnityPBSLighting.cginc"
#include "Lighting.cginc"
//自定義輸入結構體
struct Input
{
float2 uv_texcoord;
float3 worldNormal;
};
//自定義輸出結構體
struct SurfaceOutputCustomLightingCustom
{
half3 Albedo;
half3 Normal;
half3 Emission;
half Metallic;
half Smoothness;
half Occlusion;
half Alpha;
Input SurfInput;
UnityGIInput GIData;
};
float4 _BaseColor;
sampler2D _AlbedoMap;
float4 _AlbedoMap_ST;
float _Smooth;
inline half4 LightingStandardCustomLighting( inout SurfaceOutputCustomLightingCustom s, half3 viewDir, UnityGI gi )
{
UnityGIInput data = s.GIData;
Input i = s.SurfInput;
half4 c = 0;
SurfaceOutputStandard sufaceStandard = (SurfaceOutputStandard ) 0;
float2 uv_AlbedoMap = i.uv_texcoord * _AlbedoMap_ST.xy + _AlbedoMap_ST.zw;
float4 mainTex = tex2D( _AlbedoMap, uv_AlbedoMap );
sufaceStandard.Albedo = ( _BaseColor * mainTex ).rgb;
float3 worldNormal = i.worldNormal;
sufaceStandard.Normal = worldNormal;
sufaceStandard.Emission = float3( 0,0,0 );
sufaceStandard.Metallic = 0.0; //可以自行從metallic 貼圖中采樣,這裡簡略了
sufaceStandard.Smoothness = _Smooth;
sufaceStandard.Occlusion = 1.0;
data.light = gi.light;
UnityGI customGI = gi;
#ifdef UNITY_PASS_FORWARDBASE
Unity_GlossyEnvironmentData g = UnityGlossyEnvironmentSetup( sufaceStandard.Smoothness, data.worldViewDir, sufaceStandard.Normal, float3(0,0,0));
customGI = UnityGlobalIllumination( data, sufaceStandard.Occlusion, sufaceStandard.Normal, g);
#endif
c.rgb = LightingStandard ( sufaceStandard, viewDir, customGI ).rgb; //Unity Standard 光照模型 PBR核心算法
c.rbg+=sufaceStandard.Emission; //自發光
c.a = 1;
return c;
}
inline void LightingStandardCustomLighting_GI( inout SurfaceOutputCustomLightingCustom s, UnityGIInput data, inout UnityGI gi )
{
s.GIData = data;
}
void surf (Input i, inout SurfaceOutputCustomLightingCustom o)
{
o.SurfInput = i;
}
ENDCG
}
FallBack "Diffuse"
}
通過surface shader,利用Standard 核心算法來實作PBR。
當然具體生成代碼可以通過

檢視。
過surface shader,利用Standard 核心算法來實作PBR。
這裡隻是提供一種思路,用surface shader要考慮變體的問題,不然解析起來有點費勁。
需要PBR 頂點片元着色器的shader,可以留言,大家讨論。