218 lines
8.4 KiB
Plaintext
218 lines
8.4 KiB
Plaintext
![]() |
// ***********************************************************************
|
||
|
// Author : Kimch
|
||
|
// Created : 2018-7-1
|
||
|
// Description : 角色Shader
|
||
|
// Last Modified By : Kimch
|
||
|
// Last Modified On : 2019-7-1
|
||
|
// ***********************************************************************
|
||
|
// <copyright file= "MY_PBS_MountV1" company="kk"></copyright>
|
||
|
// ***********************************************************************
|
||
|
Shader "MY/PBS/MountV1"
|
||
|
{
|
||
|
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
|
||
|
_FabricScatterColor("Fabric Scatter Color", Color) = (1,1,1,1)
|
||
|
_FabricScatterScale("Fabric Scatter Scale", Range(0, 1)) = 0
|
||
|
|
||
|
}
|
||
|
SubShader
|
||
|
{
|
||
|
Tags { "RenderType" = "Opaque" }
|
||
|
LOD 200
|
||
|
CGINCLUDE
|
||
|
//#include "UnityStandardBRDF.cginc"
|
||
|
ENDCG
|
||
|
|
||
|
CGPROGRAM
|
||
|
// Physically based Standard lighting model, and enable shadows on all light types
|
||
|
#pragma surface surf Standard1 fullforwardshadows exclude_path:deferred exclude_path:prepass nometa nolightmap nofog noambient nolppv noinstancing
|
||
|
|
||
|
// Use shader model 3.0 target, to get nicer looking lighting
|
||
|
#pragma target 3.0
|
||
|
|
||
|
sampler2D _MainTex;
|
||
|
half3 _FabricScatterColor;
|
||
|
half _FabricScatterScale;
|
||
|
|
||
|
struct Input
|
||
|
{
|
||
|
float2 uv_MainTex;
|
||
|
};
|
||
|
|
||
|
half _Glossiness;
|
||
|
half _Metallic;
|
||
|
fixed4 _Color;
|
||
|
|
||
|
struct SurfaceOutputStandard
|
||
|
{
|
||
|
fixed3 Albedo; // base (diffuse or specular) color
|
||
|
float3 Normal; // tangent space normal, if written
|
||
|
half3 Emission;
|
||
|
half Metallic; // 0=non-metal, 1=metal
|
||
|
// Smoothness is the user facing name, it should be perceptual smoothness but user should not have to deal with it.
|
||
|
// Everywhere in the code you meet smoothness it is perceptual smoothness
|
||
|
half Smoothness; // 0=rough, 1=smooth
|
||
|
half Occlusion; // occlusion (default 1)
|
||
|
fixed Alpha; // alpha for transparencies
|
||
|
};
|
||
|
|
||
|
// Default BRDF to use:
|
||
|
//#if !defined (UNITY_BRDF_PBS) // allow to explicitly override BRDF in custom shader
|
||
|
// // still add safe net for low shader models, otherwise we might end up with shaders failing to compile
|
||
|
//#if SHADER_TARGET < 30 || defined(SHADER_TARGET_SURFACE_ANALYSIS) // only need "something" for surface shader analysis pass; pick the cheap one
|
||
|
//#define UNITY_BRDF_PBS BRDF3_Unity_PBS
|
||
|
//#elif defined(UNITY_PBS_USE_BRDF3)
|
||
|
//#define UNITY_BRDF_PBS BRDF3_Unity_PBS
|
||
|
//#elif defined(UNITY_PBS_USE_BRDF2)
|
||
|
//#define UNITY_BRDF_PBS BRDF2_Unity_PBS
|
||
|
//#elif defined(UNITY_PBS_USE_BRDF1)
|
||
|
//#define UNITY_BRDF_PBS BRDF1_Unity_PBS
|
||
|
//#else
|
||
|
//#error something broke in auto-choosing BRDF
|
||
|
//#endif
|
||
|
//#endif
|
||
|
|
||
|
#define _FABRIC
|
||
|
// 面料
|
||
|
inline float FabricD(float NdotH, float roughness)
|
||
|
{
|
||
|
return 0.96 * pow(1 - NdotH, 2) + 0.057;
|
||
|
}
|
||
|
|
||
|
inline half FabricScatterFresnelLerp(half nv, half scale)
|
||
|
{
|
||
|
half t0 = Pow4(1 - nv);
|
||
|
half t1 = 0.4 * (1 - nv);
|
||
|
return (t1 - t0) * scale + t0;
|
||
|
}
|
||
|
|
||
|
#ifdef _FABRIC
|
||
|
half4 FABRIC_BRDF_PBS(half3 diffColor, half3 specColor, half oneMinusReflectivity, half smoothness,
|
||
|
float3 normal, float3 viewDir,
|
||
|
UnityLight light, UnityIndirect gi)
|
||
|
{
|
||
|
float perceptualRoughness = SmoothnessToPerceptualRoughness(smoothness);
|
||
|
float3 halfDir = Unity_SafeNormalize(float3(light.dir) + viewDir);
|
||
|
|
||
|
// NdotV should not be negative for visible pixels, but it can happen due to perspective projection and normal mapping
|
||
|
// In this case normal should be modified to become valid (i.e facing camera) and not cause weird artifacts.
|
||
|
// but this operation adds few ALU and users may not want it. Alternative is to simply take the abs of NdotV (less correct but works too).
|
||
|
// Following define allow to control this. Set it to 0 if ALU is critical on your platform.
|
||
|
// This correction is interesting for GGX with SmithJoint visibility function because artifacts are more visible in this case due to highlight edge of rough surface
|
||
|
// Edit: Disable this code by default for now as it is not compatible with two sided lighting used in SpeedTree.
|
||
|
#define UNITY_HANDLE_CORRECTLY_NEGATIVE_NDOTV 0
|
||
|
|
||
|
#if UNITY_HANDLE_CORRECTLY_NEGATIVE_NDOTV
|
||
|
// The amount we shift the normal toward the view vector is defined by the dot product.
|
||
|
half shiftAmount = dot(normal, viewDir);
|
||
|
normal = shiftAmount < 0.0f ? normal + viewDir * (-shiftAmount + 1e-5f) : normal;
|
||
|
// A re-normalization should be applied here but as the shift is small we don't do it to save ALU.
|
||
|
//normal = normalize(normal);
|
||
|
|
||
|
half nv = saturate(dot(normal, viewDir)); // TODO: this saturate should no be necessary here
|
||
|
#else
|
||
|
half nv = abs(dot(normal, viewDir)); // This abs allow to limit artifact
|
||
|
#endif
|
||
|
|
||
|
half nl = saturate(dot(normal, light.dir));
|
||
|
float nh = saturate(dot(normal, halfDir));
|
||
|
|
||
|
half lv = saturate(dot(light.dir, viewDir));
|
||
|
half lh = saturate(dot(light.dir, halfDir));
|
||
|
|
||
|
// Diffuse term
|
||
|
half diffuseTerm = DisneyDiffuse(nv, nl, lh, perceptualRoughness) * nl;
|
||
|
|
||
|
// Specular term
|
||
|
// HACK: theoretically we should divide diffuseTerm by Pi and not multiply specularTerm!
|
||
|
// BUT 1) that will make shader look significantly darker than Legacy ones
|
||
|
// and 2) on engine side "Non-important" lights have to be divided by Pi too in cases when they are injected into ambient SH
|
||
|
float roughness = PerceptualRoughnessToRoughness(perceptualRoughness);
|
||
|
roughness = max(roughness, 0.002);
|
||
|
half V = SmithJointGGXVisibilityTerm(nl, nv, roughness);
|
||
|
float D = GGXTerm(nh, roughness);
|
||
|
|
||
|
float VxD = roughness > 0.99 ? 1 * FabricD(nh, roughness) : V * D;
|
||
|
|
||
|
half specularTerm = VxD * UNITY_PI; // Torrance-Sparrow model, Fresnel is applied later
|
||
|
|
||
|
#ifdef UNITY_COLORSPACE_GAMMA
|
||
|
specularTerm = sqrt(max(1e-4h, specularTerm));
|
||
|
#endif
|
||
|
|
||
|
//specularTerm * nl can be NaN on Metal in some cases, use max() to make sure it's a sane value
|
||
|
specularTerm = max(0, specularTerm * nl);
|
||
|
#if defined(_SPECULARHIGHLIGHTS_OFF)
|
||
|
specularTerm = 0.0;
|
||
|
#endif
|
||
|
|
||
|
//surfaceReduction = Int D(NdotH) * NdotH * Id(NdotL>0) dH = 1/(roughness^2+1)
|
||
|
half surfaceReduction;
|
||
|
#ifdef UNITY_COLORSPACE_GAMMA
|
||
|
surfaceReduction = 1.0 - 0.28*roughness*perceptualRoughness; // 1-0.28*x^3 as approximation for (1/(x^4+1))^(1/2.2) on the domain [0;1]
|
||
|
#else
|
||
|
surfaceReduction = 1.0 / (roughness*roughness + 1.0); // fade \in [0.5;1]
|
||
|
#endif
|
||
|
|
||
|
// To provide true Lambert lighting, we need to be able to kill specular completely.
|
||
|
specularTerm *= any(specColor) ? 1.0 : 0.0;
|
||
|
|
||
|
half grazingTerm = saturate(smoothness + (1 - oneMinusReflectivity));
|
||
|
half3 color = diffColor * (gi.diffuse + light.color * diffuseTerm)
|
||
|
+ specularTerm * light.color * FresnelTerm(specColor, lh)
|
||
|
+ _FabricScatterColor * (nl*0.5 + 0.5) * FabricScatterFresnelLerp(nv, _FabricScatterScale);
|
||
|
|
||
|
return half4(color, 1);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
inline half4 LightingStandard1(SurfaceOutputStandard s, float3 viewDir, UnityGI gi)
|
||
|
{
|
||
|
s.Normal = normalize(s.Normal);
|
||
|
|
||
|
half oneMinusReflectivity;
|
||
|
half3 specColor;
|
||
|
s.Albedo = DiffuseAndSpecularFromMetallic(s.Albedo, s.Metallic, /*out*/ specColor, /*out*/ oneMinusReflectivity);
|
||
|
|
||
|
// shader relies on pre-multiply alpha-blend (_SrcBlend = One, _DstBlend = OneMinusSrcAlpha)
|
||
|
// this is necessary to handle transparency in physically correct way - only diffuse component gets affected by alpha
|
||
|
half outputAlpha;
|
||
|
s.Albedo = PreMultiplyAlpha(s.Albedo, s.Alpha, oneMinusReflectivity, /*out*/ outputAlpha);
|
||
|
|
||
|
half4 c = FABRIC_BRDF_PBS(s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Normal, viewDir, gi.light, gi.indirect);
|
||
|
c.a = outputAlpha;
|
||
|
return c;
|
||
|
}
|
||
|
|
||
|
inline void LightingStandard1_GI(
|
||
|
SurfaceOutputStandard s,
|
||
|
UnityGIInput data,
|
||
|
inout UnityGI gi)
|
||
|
{
|
||
|
#if defined(UNITY_PASS_DEFERRED) && UNITY_ENABLE_REFLECTION_BUFFERS
|
||
|
gi = UnityGlobalIllumination(data, s.Occlusion, s.Normal);
|
||
|
#else
|
||
|
Unity_GlossyEnvironmentData g = UnityGlossyEnvironmentSetup(s.Smoothness, data.worldViewDir, s.Normal, lerp(unity_ColorSpaceDielectricSpec.rgb, s.Albedo, s.Metallic));
|
||
|
gi = UnityGlobalIllumination(data, s.Occlusion, s.Normal, g);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
ENDCG
|
||
|
}
|
||
|
FallBack "Diffuse"
|
||
|
}
|