Hair卡通渲染的效果(各向异性)

丽塔头发 各向异性渲染(截图)

在这里插入图片描述
各向异性的主要计算公式:
在这里插入图片描述

视频演示链接https://www.bilibili.com/video/av71067897

Glossiness和Metallic:

		void AnisotropicSurface (Input IN, inout SurfaceOutputStandardAnisotropic o) 
		{
			fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
			o.Albedo = c;
			o.Metallic = _Metallic;
			o.Smoothness = _Glossiness;
			o.Alpha = c.a;
			o.Anisotropy = _Anisotropy;
			o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_MainTex));
			
			float3x3 worldToTangent;
			worldToTangent[0] = float3(1, 0, 0);
			worldToTangent[1] = float3(0, 1, 0);
			worldToTangent[2] = float3(0, 0, 1); 

			float3 fTangent;
			fTangent = IN.tangentDir;
			
			o.WorldVectors = float3x3(fTangent, IN.bitangentDir, IN.normalDir);
		}

UnityAnisotropicLighting.cginc

//#ifndef UNITY_ANISOTROPIC_BRDF_INCLUDED
//#define UNITY_ANISOTROPIC_BRDF_INCLUDED

// Anisotropic GGX
// From HDRenderPipeline
float D_GGXAnisotropic(float TdotH, float BdotH, float NdotH, float roughnessT, float roughnessB)
{
	float f = TdotH * TdotH / (roughnessT * roughnessT) + BdotH * BdotH / (roughnessB * roughnessB) + NdotH * NdotH;
	return 1.0 / (roughnessT * roughnessB * f * f);
}

// Smith Joint GGX Anisotropic Visibility
// Taken from https://cedec.cesa.or.jp/2015/session/ENG/14698.html
float SmithJointGGXAnisotropic(float TdotV, float BdotV, float NdotV, float TdotL, float BdotL, float NdotL, float roughnessT, float roughnessB)
{
	float aT = roughnessT;
	float aT2 = aT * aT;
	float aB = roughnessB;
	float aB2 = aB * aB;

	float lambdaV = NdotL * sqrt(aT2 * TdotV * TdotV + aB2 * BdotV * BdotV + NdotV * NdotV);
	float lambdaL = NdotV * sqrt(aT2 * TdotL * TdotL + aB2 * BdotL * BdotL + NdotL * NdotL);

	return 0.5 / (lambdaV + lambdaL);
}

// Convert Anistropy to roughness
void ConvertAnisotropyToRoughness(float roughness, float anisotropy, out float roughnessT, out float roughnessB)
{
	// (0 <= anisotropy <= 1), therefore (0 <= anisoAspect <= 1)
	// The 0.9 factor limits the aspect ratio to 10:1.
	float anisoAspect = sqrt(1.0 - 0.9 * anisotropy);
	roughnessT = roughness / anisoAspect; // Distort along tangent (rougher)
	roughnessB = roughness * anisoAspect; // Straighten along bitangent (smoother)
}

// Schlick Fresnel
float FresnelSchlick(float f0, float f90, float u)
{
	float x = 1.0 - u;
	float x5 = x * x;
	x5 = x5 * x5 * x;
	return (f90 - f0) * x5 + f0; // sub mul mul mul sub mad
}

//Clamp roughness
float ClampRoughnessForAnalyticalLights(float roughness)
{
	return max(roughness, 0.000001);
}

// Ref: Donald Revie - Implementing Fur Using Deferred Shading (GPU Pro 2)
// The grain direction (e.g. hair or brush direction) is assumed to be orthogonal to the normal.
// The returned normal is NOT normalized.
float3 ComputeGrainNormal(float3 grainDir, float3 V)
{
	float3 B = cross(-V, grainDir);
	return cross(B, grainDir);
}

//Modify Normal for Anisotropic IBL (Realtime version)
// Fake anisotropic by distorting the normal.
// The grain direction (e.g. hair or brush direction) is assumed to be orthogonal to N.
// Anisotropic ratio (0->no isotropic; 1->full anisotropy in tangent direction)
float3 GetAnisotropicModifiedNormal(float3 grainDir, float3 N, float3 V, float anisotropy)
{
	float3 grainNormal = ComputeGrainNormal(grainDir, V);
	// TODO: test whether normalizing 'grainNormal' is worth it.
	return normalize(lerp(N, grainNormal, anisotropy));
}

float4 AnisotropicBRDF(float3 diffColor, float3 specColor, float oneMinusReflectivity, float smoothness, float3 normal, float3x3 worldVectors,
	float anisotropy, float metallic, float3 viewDir, UnityLight light, UnityIndirect gi)
{
	//Unpack world vectors
	float3 tangent = worldVectors[0];
	float3 bitangent = worldVectors[1];
	//Normal shift
	float shiftAmount = dot(normal, viewDir);
	normal = shiftAmount < 0.0f ? normal + viewDir * (-shiftAmount + 1e-5f) : normal;
	//Regular vectors
	float NdotL = saturate(dot(normal, light.dir));
	float NdotV = abs(dot(normal, viewDir));
	float LdotV = dot(light.dir, viewDir);
	float3 H = Unity_SafeNormalize(light.dir + viewDir);
	float invLenLV = rsqrt(abs(2 + 2 * normalize(LdotV)));
	float NdotH = saturate(dot(normal, H));
	float LdotH = saturate(dot(light.dir, H));
	//Tangent vectors
	float TdotH = dot(tangent, H);
	float TdotL = dot(tangent, light.dir);
	float BdotH = dot(bitangent, H);
	float BdotL = dot(bitangent, light.dir);
	float TdotV = dot(viewDir, tangent);
	float BdotV = dot(viewDir, bitangent);
	//Fresnels
	half grazingTerm = saturate(smoothness + (1 - oneMinusReflectivity));
	float3 F = FresnelLerp(specColor, grazingTerm, NdotV); //Original Schlick - Replace from SRP?
														   //float3 fresnel0 = lerp(specColor, diffColor, metallic);
														   //float3 F = FresnelSchlick(fresnel0, 1.0, LdotH);
														   //Calculate roughness
	float roughnessT;
	float roughnessB;
	float perceptualRoughness = SmoothnessToPerceptualRoughness(smoothness);
	float roughness = PerceptualRoughnessToRoughness(perceptualRoughness);
	ConvertAnisotropyToRoughness(roughness, anisotropy, roughnessT, roughnessB);
	//Clamp roughness
	roughnessT = ClampRoughnessForAnalyticalLights(roughnessT);
	roughnessB = ClampRoughnessForAnalyticalLights(roughnessB);
	//Visibility & Distribution terms
	float V = SmithJointGGXAnisotropic(TdotV, BdotV, NdotV, TdotL, BdotL, NdotL, roughnessT, roughnessB);
	float D = D_GGXAnisotropic(TdotH, BdotH, NdotH, roughnessT, roughnessB);
	//Specular term
	float3 specularTerm = V * D;
#	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 * NdotL);
#if defined(_SPECULARHIGHLIGHTS_OFF)
	specularTerm = 0.0;
#endif
	//Diffuse term
	float diffuseTerm = DisneyDiffuse(NdotV, NdotL, LdotH, perceptualRoughness) * NdotL;// - Need this NdotL multiply?
																						//Reduction
	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
																	//Final
	half3 color = (diffColor * (gi.diffuse + light.color * diffuseTerm))
		+ specularTerm * light.color * FresnelTerm(specColor, LdotH)
		+ surfaceReduction * gi.specular * FresnelLerp(specColor, grazingTerm, NdotV);
	return half4(color, 1);
}

//#endif UNITY_ANISOTROPIC_BRDF_INCLUDED

UnityAnisotropicLighting.cginc

//#ifndef UNITY_ANISOTROPIC_LIGHTING_INCLUDED
//#define UNITY_ANISOTROPIC_LIGHTING_INCLUDED

#include "UnityPBSLighting.cginc"
#include "UnityShaderVariables.cginc"
#include "UnityStandardConfig.cginc"
#include "UnityLightingCommon.cginc"
#include "UnityGBuffer.cginc"
#include "UnityGlobalIllumination.cginc"

//-------------------------------------------------------------------------------------
// Lighting Helpers

// Glossy Environment
half3 Unity_AnisotropicGlossyEnvironment(UNITY_ARGS_TEXCUBE(tex), half4 hdr, Unity_GlossyEnvironmentData glossIn, half anisotropy) //Reference IBL from HD Pipe (Add half3 L input and replace R)
{
	half perceptualRoughness = glossIn.roughness /* perceptualRoughness */;
#if 0
	float m = PerceptualRoughnessToRoughness(perceptualRoughness); // m is the real roughness parameter
	const float fEps = 1.192092896e-07F;        // smallest such that 1.0+FLT_EPSILON != 1.0  (+1e-4h is NOT good here. is visibly very wrong)
	float n = (2.0 / max(fEps, m*m)) - 2.0;        // remap to spec power. See eq. 21 in --> https://dl.dropboxusercontent.com/u/55891920/papers/mm_brdf.pdf

	n /= 4;                                     // remap from n_dot_h formulatino to n_dot_r. See section "Pre-convolved Cube Maps vs Path Tracers" --> https://s3.amazonaws.com/docs.knaldtech.com/knald/1.0.0/lys_power_drops.html

	perceptualRoughness = pow(2 / (n + 2), 0.25);      // remap back to square root of real roughness (0.25 include both the sqrt root of the conversion and sqrt for going from roughness to perceptualRoughness)
#else
	// MM: came up with a surprisingly close approximation to what the #if 0'ed out code above does.
	perceptualRoughness = perceptualRoughness*(1.7 - 0.7*perceptualRoughness);
#endif


	half mip = perceptualRoughnessToMipmapLevel(perceptualRoughness);
	half3 R = glossIn.reflUVW;// -half3(anisotropy, 0, 0);
	half4 rgbm = UNITY_SAMPLE_TEXCUBE_LOD(tex, R, mip);

	return DecodeHDR(rgbm, hdr);
}

// Indirect Specular
inline half3 UnityGI_AnisotropicIndirectSpecular(UnityGIInput data, half occlusion, Unity_GlossyEnvironmentData glossIn, half anisotropy, half3x3 worldVectors)
{
	half3 specular;

	float3 tangentX = worldVectors[0];
	float3 tangentY = worldVectors[1];
	float3 N = worldVectors[2];
	float3 V = data.worldViewDir;
	float3 iblNormalWS = GetAnisotropicModifiedNormal(tangentY, N, V, anisotropy);
	float3 iblR = reflect(-V, iblNormalWS);

#ifdef UNITY_SPECCUBE_BOX_PROJECTION
	// we will tweak reflUVW in glossIn directly (as we pass it to Unity_GlossyEnvironment twice for probe0 and probe1), so keep original to pass into BoxProjectedCubemapDirection
	
	half3 originalReflUVW = glossIn.reflUVW;
	glossIn.reflUVW = BoxProjectedCubemapDirection(iblR, data.worldPos, data.probePosition[0], data.boxMin[0], data.boxMax[0]);
#endif

#ifdef _GLOSSYREFLECTIONS_OFF
	specular = unity_IndirectSpecColor.rgb;
#else
	half3 env0 = Unity_AnisotropicGlossyEnvironment(UNITY_PASS_TEXCUBE(unity_SpecCube0), data.probeHDR[0], glossIn, anisotropy);
#ifdef UNITY_SPECCUBE_BLENDING
	const float kBlendFactor = 0.99999;
	float blendLerp = data.boxMin[0].w;
	UNITY_BRANCH
		if (blendLerp < kBlendFactor)
		{
#ifdef UNITY_SPECCUBE_BOX_PROJECTION
			glossIn.reflUVW = BoxProjectedCubemapDirection(iblR, data.worldPos, data.probePosition[1], data.boxMin[1], data.boxMax[1]);
#endif
			half3 env1 = Unity_AnisotropicGlossyEnvironment(UNITY_PASS_TEXCUBE_SAMPLER(unity_SpecCube1, unity_SpecCube0), data.probeHDR[1], glossIn, anisotropy);
			specular = lerp(env1, env0, blendLerp);
		}
		else
		{
			specular = env0;
		}
#else
	specular = env0;
#endif
#endif

	return specular * occlusion;
}

// Global Illumination
inline UnityGI UnityAnisotropicGlobalIllumination(UnityGIInput data, half occlusion, half3 normalWorld, Unity_GlossyEnvironmentData glossIn, half anisotropy, half3x3 worldVectors)
{
	UnityGI o_gi = UnityGI_Base(data, occlusion, normalWorld);
	o_gi.indirect.specular = UnityGI_AnisotropicIndirectSpecular(data, occlusion, glossIn, anisotropy, worldVectors);
	return o_gi;
}

// Surface shader output structure to be used with physically
// based shading model.

//-------------------------------------------------------------------------------------
// Anisotropic workflow

struct SurfaceOutputStandardAnisotropic
{
	fixed3 Albedo;		// base (diffuse or specular) color
	fixed3 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
	half Anisotropy;
	float3x3 WorldVectors;
};

inline half4 LightingStandardAnisotropic(SurfaceOutputStandardAnisotropic s, half3 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 = AnisotropicBRDF(s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Normal, s.WorldVectors, s.Anisotropy, s.Metallic, viewDir, gi.light, gi.indirect);
	c.a = outputAlpha;
	return c;
}

//This is pointless as always forward?
inline half4 LightingStandardAnisotropic_Deferred(SurfaceOutputStandardAnisotropic s, half3 viewDir, UnityGI gi, out half4 outGBuffer0, out half4 outGBuffer1, out half4 outGBuffer2)
{
	half oneMinusReflectivity;
	half3 specColor;
	s.Albedo = DiffuseAndSpecularFromMetallic(s.Albedo, s.Metallic, /*out*/ specColor, /*out*/ oneMinusReflectivity);

	half4 c = AnisotropicBRDF(s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Normal, s.WorldVectors, s.Anisotropy, s.Metallic, viewDir, gi.light, gi.indirect);

	UnityStandardData data;
	data.diffuseColor = s.Albedo;
	data.occlusion = s.Occlusion;
	data.specularColor = specColor;
	data.smoothness = s.Smoothness;
	data.normalWorld = s.Normal;

	UnityStandardDataToGbuffer(data, outGBuffer0, outGBuffer1, outGBuffer2);

	half4 emission = half4(s.Emission + c.rgb, 1);
	return emission;
}

inline void LightingStandardAnisotropic_GI(SurfaceOutputStandardAnisotropic 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 = UnityAnisotropicGlobalIllumination(data, s.Occlusion, s.Normal, g, s.Anisotropy, s.WorldVectors);
#endif
}

//#endif UNITY_ANISOTROPIC_LIGHTING_INCLUDED

UnityTranslucentLighting.cginc

float _Distortion;
float _Scale;
float _Power;
float _Fresnel;
float _FresnelDamp;

float4 TranslucentBRDF(float3 diffColor, float3 specColor, float oneMinusReflectivity, float smoothness, float3 normal, float3x3 worldVectors,
	float anisotropy, float metallic, float3 viewDir, UnityLight light, UnityIndirect gi)
{
	//Unpack world vectors
	float3 tangent = worldVectors[0];
	float3 bitangent = worldVectors[1];
	//Normal shift
	float shiftAmount = dot(normal, viewDir);
	normal = shiftAmount < 0.0f ? normal + viewDir * (-shiftAmount + 1e-5f) : normal;
	//Regular vectors
	float NdotL = saturate(dot(normal, light.dir));
	float NdotV = abs(dot(normal, viewDir));
	float LdotV = dot(light.dir, viewDir);
	float3 H = Unity_SafeNormalize(light.dir + viewDir);
	float invLenLV = rsqrt(abs(2 + 2 * normalize(LdotV)));
	float NdotH = saturate(dot(normal, H));
	float LdotH = saturate(dot(light.dir, H));
	//Tangent vectors
	float TdotH = dot(tangent, H);
	float TdotL = dot(tangent, light.dir);
	float BdotH = dot(bitangent, H);
	float BdotL = dot(bitangent, light.dir);
	float TdotV = dot(viewDir, tangent);
	float BdotV = dot(viewDir, bitangent);
	//Fresnels
	half grazingTerm = saturate(smoothness + (1 - oneMinusReflectivity));
	float3 F = FresnelLerp(specColor, grazingTerm, NdotV); //Original Schlick - Replace from SRP?
														   //float3 fresnel0 = lerp(specColor, diffColor, metallic);
														   //float3 F = FresnelSchlick(fresnel0, 1.0, LdotH);
														   //Calculate roughness
	float roughnessT;
	float roughnessB;
	float perceptualRoughness = SmoothnessToPerceptualRoughness(smoothness);
	float roughness = PerceptualRoughnessToRoughness(perceptualRoughness);
	ConvertAnisotropyToRoughness(roughness, anisotropy, roughnessT, roughnessB);
	//Clamp roughness
	roughnessT = ClampRoughnessForAnalyticalLights(roughnessT);
	roughnessB = ClampRoughnessForAnalyticalLights(roughnessB);
	//Visibility & Distribution terms
	float V = SmithJointGGXAnisotropic(TdotV, BdotV, NdotV, TdotL, BdotL, NdotL, roughnessT, roughnessB);
	float D = D_GGXAnisotropic(TdotH, BdotH, NdotH, roughnessT, roughnessB);
	//Specular term
	float3 specularTerm = V * D;
#	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 * NdotL);
#if defined(_SPECULARHIGHLIGHTS_OFF)
	specularTerm = 0.0;
#endif
	//Diffuse term
	float diffuseTerm = DisneyDiffuse(NdotV, NdotL, LdotH, perceptualRoughness) * NdotL;// - Need this NdotL multiply?
																						//Reduction
	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
																	//Final
	half3 color = (diffColor * (gi.diffuse + light.color * diffuseTerm))
		+ specularTerm * light.color * (FresnelTerm(specColor, LdotH))
		+ (surfaceReduction * gi.specular * FresnelLerp(specColor, grazingTerm, NdotV) * _Fresnel * lerp(float3(1,1,1),specColor,_FresnelDamp));
	return half4(color, 1);
}

inline half4 LightFunctionStandardAnisotropic(SurfaceOutputStandardAnisotropic s, half3 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 = TranslucentBRDF(s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Normal, s.WorldVectors, s.Anisotropy, s.Metallic, viewDir, gi.light, gi.indirect);
	c.a = outputAlpha;
	return c;
}


inline fixed4 LightingStandardTranslucent(SurfaceOutputStandardAnisotropic s, fixed3 viewDir, UnityGI gi)
{
	// Original colour
	fixed4 pbr = LightFunctionStandardAnisotropic(s, viewDir, gi);
	
	// --- Translucency ---
	float3 L = gi.light.dir;
	float3 V = viewDir;
	float3 N = s.Normal;
 
	float3 H = normalize(L + N * _Distortion);
	float I = (pow(saturate(dot(V, -H)), _Power) * _Scale);
 
	// Final add
	pbr.rgb = pbr.rgb + gi.light.color * (I*s.Albedo);
	
	return pbr;
}

//This is pointless as always forward?
inline half4 LightingStandardTranslucent_Deferred(SurfaceOutputStandardAnisotropic s, half3 viewDir, UnityGI gi, out half4 outGBuffer0, out half4 outGBuffer1, out half4 outGBuffer2)
{
	half oneMinusReflectivity;
	half3 specColor;
	s.Albedo = DiffuseAndSpecularFromMetallic(s.Albedo, s.Metallic, /*out*/ specColor, /*out*/ oneMinusReflectivity);

	half4 c = TranslucentBRDF(s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Normal, s.WorldVectors, s.Anisotropy, s.Metallic, viewDir, gi.light, gi.indirect);

	UnityStandardData data;
	data.diffuseColor = s.Albedo;
	data.occlusion = s.Occlusion;
	data.specularColor = specColor;
	data.smoothness = s.Smoothness;
	data.normalWorld = s.Normal;

	UnityStandardDataToGbuffer(data, outGBuffer0, outGBuffer1, outGBuffer2);

	// --- Translucency ---
	float3 L = gi.light.dir;
	float3 V = viewDir;
	float3 N = s.Normal;
 
	float3 H = normalize(L + N * _Distortion);
	float I = (pow(saturate(dot(V, -H)), _Power) * _Scale);
	
	
	half4 emission = half4(s.Emission + c.rgb, 1);
	return emission * (float4(1,1,1,1) + float4(I * c.rgb,0));
}

inline void LightingStandardTranslucent_GI(SurfaceOutputStandardAnisotropic 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 = UnityAnisotropicGlobalIllumination(data, s.Occlusion, s.Normal, g, s.Anisotropy, s.WorldVectors);
#endif
}

效果截图:

在这里插入图片描述
在这里插入图片描述

最终渲染源码:

Shader "Hair Shader" {
	Properties {
		_Color ("Color", Color) = (1,1,1,1)
		_MainTex ("Albedo (RGB)", 2D) = "white" {}
		_BumpMap ("Normal Map", 2D) = "" {}
		_Glossiness ("Smoothness", Range(0,1)) = 0.5
		_Metallic ("Metallic", Range(0,1)) = 0.0
		_TangentMap("Tangent Map (RG)", 2D) = "white" {}
		_Fresnel ("Fresnel Power", Range(0,30)) = 1.0
		_FresnelDamp ("Fresnel Damp", Range(0,1)) = 1.0
		_Anisotropy ("Anisotropy", Range(0,1)) = 1.0
		_Distortion ("Translucent Distortion", Range(0,5)) = 1.0
		_Scale ("Translucent Scale", Range(0,5)) = 1.0
		_Power ("Translucent Power", Range(0,5)) = 1.0
		_Cutoff ("Alpha Cutoff", Range(0,1)) = 0.5
	}
	SubShader {
		Tags { "RenderType"="Transparent" "Queue"="Transparent"}
		LOD 200
		
		Cull Front

		CGPROGRAM
		#include "UnityCG.cginc"
		#include "CGIncludes/UnityAnisotropicBRDF.cginc"
		#include "CGIncludes/UnityAnisotropicLighting.cginc"
		#include "CGIncludes/UnityTranslucentLighting.cginc"
		#define UNITY_BRDF_PBS BRDF_Unity_Anisotropic
		// Physically based Standard lighting model, and enable shadows on all light types
		#pragma surface AnisotropicSurface StandardTranslucent vertex:vert fullforwardshadows alphatest:_Cutoff nolightmap

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

		sampler2D _MainTex;
		sampler2D _BumpMap;
		float _Anisotropy;
		
		//Vertex struct
		struct Input
		{
			float2 uv_MainTex;
			float3 normal;
			float3 viewDir;
			float3 normalDir;
			float3 tangentDir;
			float3 bitangentDir;
		};

		//Vertex shader
		void vert(inout appdata_full v, out Input o)
		{
			v.normal *= -1;
		
			UNITY_INITIALIZE_OUTPUT(Input, o);
			//Normal 2 World
			o.normalDir = normalize(UnityObjectToWorldNormal(v.normal));
			//Tangent 2 World
			float3 tangentMul = normalize(mul(unity_ObjectToWorld, v.tangent.xyz));
			o.tangentDir = float4(tangentMul, v.tangent.w);
			// Bitangent
			o.bitangentDir = cross(o.normalDir, o.tangentDir);
		}

		half _Glossiness;
		half _Metallic;
		fixed4 _Color;

		void AnisotropicSurface (Input IN, inout SurfaceOutputStandardAnisotropic o) 
		{
			fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
			o.Albedo = c;
			o.Metallic = _Metallic;
			o.Smoothness = _Glossiness;
			o.Alpha = c.a;
			o.Anisotropy = _Anisotropy;
			o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_MainTex));
			
			float3x3 worldToTangent;
			worldToTangent[0] = float3(1, 0, 0);
			worldToTangent[1] = float3(0, 1, 0);
			worldToTangent[2] = float3(0, 0, 1); 

			float3 fTangent;
			fTangent = IN.tangentDir;
			
			o.WorldVectors = float3x3(fTangent, IN.bitangentDir, IN.normalDir);
		}
		ENDCG
		
		Cull Back
		
		CGPROGRAM
		#include "UnityCG.cginc"
		#include "CGIncludes/UnityAnisotropicBRDF.cginc"
		#include "CGIncludes/UnityAnisotropicLighting.cginc"
		#include "CGIncludes/UnityTranslucentLighting.cginc"
		#define UNITY_BRDF_PBS BRDF_Unity_Anisotropic
		// Physically based Standard lighting model, and enable shadows on all light types
		#pragma surface AnisotropicSurface StandardTranslucent vertex:vert fullforwardshadows alpha:fade nolightmap

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

		sampler2D _MainTex;
		sampler2D _TangentMap;
		sampler2D _BumpMap;
		float _Anisotropy;
				
		//Vertex struct
		struct Input
		{
			float2 uv_MainTex;
			float3 normal;
			float3 viewDir;
			float3 normalDir;
			float3 tangentDir;
			float3 bitangentDir;
		};

		//Vertex shader
		void vert(inout appdata_full v, out Input o)
		{
			UNITY_INITIALIZE_OUTPUT(Input, o);
			//Normal 2 World
			o.normalDir = normalize(UnityObjectToWorldNormal(v.normal));
			//Tangent 2 World
			float3 tangentMul = normalize(mul(unity_ObjectToWorld, v.tangent.xyz));
			o.tangentDir = float4(tangentMul, v.tangent.w);
			// Bitangent
			o.bitangentDir = cross(o.normalDir, o.tangentDir);
		}

		half _Glossiness;
		half _Metallic;
		fixed4 _Color;

		void AnisotropicSurface (Input IN, inout SurfaceOutputStandardAnisotropic o) 
		{
			fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
			o.Albedo = c;
			o.Metallic = _Metallic;
			o.Smoothness = _Glossiness;
			o.Alpha = c.a;
			o.Anisotropy = _Anisotropy;
			o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_MainTex));
			
			float3x3 worldToTangent;
			worldToTangent[0] = float3(1, 0, 0);
			worldToTangent[1] = float3(0, 1, 0);
			worldToTangent[2] = float3(0, 0, 1); 

			float3 tangentTS = tex2D(_TangentMap, IN.uv_MainTex);
			float3 tangentTWS = mul(tangentTS, worldToTangent);
			float3 fTangent;
			if (tangentTS.z < 1)
				fTangent = tangentTWS;
			else
				fTangent = IN.tangentDir;
			o.WorldVectors = float3x3(fTangent, IN.bitangentDir, IN.normalDir);
		}
		ENDCG
	}
	FallBack "Diffuse"
}

原创文章 24 获赞 26 访问量 7830

猜你喜欢

转载自blog.csdn.net/qq_42115447/article/details/102589465