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"
}