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

  • 丽塔头发 各向异性渲染(截图)
    • 视频演示链接https://www.bilibili.com/video/av71067897
    • 效果截图:
    • 最终渲染源码:

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


各向异性的主要计算公式:

视频演示链接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 vectorsfloat3 tangent = worldVectors[0];float3 bitangent = worldVectors[1];//Normal shiftfloat shiftAmount = dot(normal, viewDir);normal = shiftAmount < 0.0f ? normal + viewDir * (-shiftAmount + 1e-5f) : normal;//Regular vectorsfloat 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 vectorsfloat 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);//Fresnelshalf 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 roughnessfloat roughnessT;float roughnessB;float perceptualRoughness = SmoothnessToPerceptualRoughness(smoothness);float roughness = PerceptualRoughnessToRoughness(perceptualRoughness);ConvertAnisotropyToRoughness(roughness, anisotropy, roughnessT, roughnessB);//Clamp roughnessroughnessT = ClampRoughnessForAnalyticalLights(roughnessT);roughnessB = ClampRoughnessForAnalyticalLights(roughnessB);//Visibility & Distribution termsfloat V = SmithJointGGXAnisotropic(TdotV, BdotV, NdotV, TdotL, BdotL, NdotL, roughnessT, roughnessB);float D = D_GGXAnisotropic(TdotH, BdotH, NdotH, roughnessT, roughnessB);//Specular termfloat3 specularTerm = V * D;
#   ifdef UNITY_COLORSPACE_GAMMAspecularTerm = 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 valuespecularTerm = max(0, specularTerm * NdotL);
#if defined(_SPECULARHIGHLIGHTS_OFF)specularTerm = 0.0;
#endif//Diffuse termfloat diffuseTerm = DisneyDiffuse(NdotV, NdotL, LdotH, perceptualRoughness) * NdotL;// - Need this NdotL multiply?//Reductionhalf surfaceReduction;
#   ifdef UNITY_COLORSPACE_GAMMAsurfaceReduction = 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]
#   elsesurfaceReduction = 1.0 / (roughness*roughness + 1.0);         // fade \in [0.5;1]
#   endif//Finalhalf3 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 0float m = PerceptualRoughnessToRoughness(perceptualRoughness); // m is the real roughness parameterconst 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.pdfn /= 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.htmlperceptualRoughness = 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);
#endifhalf 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 BoxProjectedCubemapDirectionhalf3 originalReflUVW = glossIn.reflUVW;glossIn.reflUVW = BoxProjectedCubemapDirection(iblR, data.worldPos, data.probePosition[0], data.boxMin[0], data.boxMax[0]);
#endif#ifdef _GLOSSYREFLECTIONS_OFFspecular = unity_IndirectSpecColor.rgb;
#elsehalf3 env0 = Unity_AnisotropicGlossyEnvironment(UNITY_PASS_TEXCUBE(unity_SpecCube0), data.probeHDR[0], glossIn, anisotropy);
#ifdef UNITY_SPECCUBE_BLENDINGconst float kBlendFactor = 0.99999;float blendLerp = data.boxMin[0].w;UNITY_BRANCHif (blendLerp < kBlendFactor){
#ifdef UNITY_SPECCUBE_BOX_PROJECTIONglossIn.reflUVW = BoxProjectedCubemapDirection(iblR, data.worldPos, data.probePosition[1], data.boxMin[1], data.boxMax[1]);
#endifhalf3 env1 = Unity_AnisotropicGlossyEnvironment(UNITY_PASS_TEXCUBE_SAMPLER(unity_SpecCube1, unity_SpecCube0), data.probeHDR[1], glossIn, anisotropy);specular = lerp(env1, env0, blendLerp);}else{specular = env0;}
#elsespecular = env0;
#endif
#endifreturn 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 workflowstruct SurfaceOutputStandardAnisotropic
{fixed3 Albedo;     // base (diffuse or specular) colorfixed3 Normal;       // tangent space normal, if writtenhalf3 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 smoothnesshalf Smoothness;   // 0=rough, 1=smoothhalf Occlusion;       // occlusion (default 1)fixed Alpha;        // alpha for transparencieshalf 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 alphahalf 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_BUFFERSgi = UnityGlobalIllumination(data, s.Occlusion, s.Normal);
#elseUnity_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 vectorsfloat3 tangent = worldVectors[0];float3 bitangent = worldVectors[1];//Normal shiftfloat shiftAmount = dot(normal, viewDir);normal = shiftAmount < 0.0f ? normal + viewDir * (-shiftAmount + 1e-5f) : normal;//Regular vectorsfloat 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 vectorsfloat 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);//Fresnelshalf 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 roughnessfloat roughnessT;float roughnessB;float perceptualRoughness = SmoothnessToPerceptualRoughness(smoothness);float roughness = PerceptualRoughnessToRoughness(perceptualRoughness);ConvertAnisotropyToRoughness(roughness, anisotropy, roughnessT, roughnessB);//Clamp roughnessroughnessT = ClampRoughnessForAnalyticalLights(roughnessT);roughnessB = ClampRoughnessForAnalyticalLights(roughnessB);//Visibility & Distribution termsfloat V = SmithJointGGXAnisotropic(TdotV, BdotV, NdotV, TdotL, BdotL, NdotL, roughnessT, roughnessB);float D = D_GGXAnisotropic(TdotH, BdotH, NdotH, roughnessT, roughnessB);//Specular termfloat3 specularTerm = V * D;
#   ifdef UNITY_COLORSPACE_GAMMAspecularTerm = 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 valuespecularTerm = max(0, specularTerm * NdotL);
#if defined(_SPECULARHIGHLIGHTS_OFF)specularTerm = 0.0;
#endif//Diffuse termfloat diffuseTerm = DisneyDiffuse(NdotV, NdotL, LdotH, perceptualRoughness) * NdotL;// - Need this NdotL multiply?//Reductionhalf surfaceReduction;
#   ifdef UNITY_COLORSPACE_GAMMAsurfaceReduction = 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]
#   elsesurfaceReduction = 1.0 / (roughness*roughness + 1.0);         // fade \in [0.5;1]
#   endif//Finalhalf3 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 alphahalf 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 colourfixed4 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 addpbr.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_BUFFERSgi = UnityGlobalIllumination(data, s.Occlusion, s.Normal);
#elseUnity_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 200Cull FrontCGPROGRAM#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.5sampler2D _MainTex;sampler2D _BumpMap;float _Anisotropy;//Vertex structstruct Input{float2 uv_MainTex;float3 normal;float3 viewDir;float3 normalDir;float3 tangentDir;float3 bitangentDir;};//Vertex shadervoid vert(inout appdata_full v, out Input o){v.normal *= -1;UNITY_INITIALIZE_OUTPUT(Input, o);//Normal 2 Worldo.normalDir = normalize(UnityObjectToWorldNormal(v.normal));//Tangent 2 Worldfloat3 tangentMul = normalize(mul(unity_ObjectToWorld, v.tangent.xyz));o.tangentDir = float4(tangentMul, v.tangent.w);// Bitangento.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);}ENDCGCull BackCGPROGRAM#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.5sampler2D _MainTex;sampler2D _TangentMap;sampler2D _BumpMap;float _Anisotropy;//Vertex structstruct Input{float2 uv_MainTex;float3 normal;float3 viewDir;float3 normalDir;float3 tangentDir;float3 bitangentDir;};//Vertex shadervoid vert(inout appdata_full v, out Input o){UNITY_INITIALIZE_OUTPUT(Input, o);//Normal 2 Worldo.normalDir = normalize(UnityObjectToWorldNormal(v.normal));//Tangent 2 Worldfloat3 tangentMul = normalize(mul(unity_ObjectToWorld, v.tangent.xyz));o.tangentDir = float4(tangentMul, v.tangent.w);// Bitangento.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;elsefTangent = IN.tangentDir;o.WorldVectors = float3x3(fTangent, IN.bitangentDir, IN.normalDir);}ENDCG}FallBack "Diffuse"
}

Hair卡通渲染的效果(各向异性)相关推荐

  1. 米哈游贺甲:如何实现次世代卡通渲染效果?

    在5月12日Unite2017开发者大会上,米哈游技术总监兼美术指导贺甲进行了主题为次世代卡通渲染的演讲.一下为详细分享内容: 大家好,首先自我介绍一下,我叫贺甲,在米哈游担任技术总监和美术指导工作, ...

  2. 崩坏3》画面效果为何惊艳?看米哈游怎么做卡通渲染的你就明白了

    崩坏3>画面效果为何惊艳?看米哈游怎么做卡通渲染的你就明白了 http://youxiputao.com/articles/11839 <崩坏3>上架以来,我们看到了卡通渲染技术在游 ...

  3. UE4从零开始的卡通渲染——阴影篇(二)

    前言 上一篇中我们已经实现了卡通渲染最基本的色阶分离的效果,并且与原生UE渲染效果进行了比较.虽然整体效果是有了但是细节上还是缺少打磨,所以接下来我们看看该如何修改我们的效果 问题 当我们拉近观察人物 ...

  4. unity 3d物体描边效果_从零开始的卡通渲染描边篇

    序言: 一直对卡通渲染非常感兴趣,前后翻找了不少的文档,做了一些工作.前段时间<从零开始>的手游上线了,试着渲染了一下的其中模型,觉得效果很不错.打算写一个专栏记录其中的渲染技术.在后面的 ...

  5. 【Unity天空盒】卡通渲染中如何实现云的消散效果

    写在前面 完成大气渲染之后,接下来就是考虑云渲染了.因为我想做的天空盒本身是想跟着这位大佬Unity 卡通渲染 程序化天空盒 - 知乎里叙述的进程来的,里面云实现的是原神里的云,原神又是在崩3的基础上 ...

  6. 【非真实渲染】【卡通渲染技术点介绍】

    阅读指南 文本介绍卡通渲染的基本技术,实现会放在另外的文档 关键词 Cel Shading,ToonShading,色块.色调,各向异性,描边,高光 特征 看起来像手绘的图片 少渐变(指光影的变换), ...

  7. 二次元卡通渲染-着色

    前言 本文为"优梦创客"原创文章,您可以自由转载,但必须加入完整的版权声明 更多学习资源请加QQ:1517069595获取(企业级性能优化/热更新/Shader特效/服务器/商业项 ...

  8. Unity下的日式卡通渲染实现-着色篇(一)

    这篇文章讲述的是项目中二次元日式卡通着色渲染用到的一些跟着色相关的技术点. 一.卡通着色 何谓卡通着色?大概是让角色看起来卡通的角色吧.这里说的卡通着色,实际上指的是色阶着色.即根据光照和法线计算出当 ...

  9. 二次元卡通渲染——进阶技巧

    前言 随着<原神>游戏的盛行,国内对于二次元游戏这块儿领域越来越看重了.二次元项目中本身基于日本的卡通动漫而来,所以最后的本质都是为了尽量还原2D立绘,而并不像PBR追求物理正确,只要好看 ...

最新文章

  1. 模板方法模式 Template method 行为型 设计模式(二十六)
  2. 【错误记录】安卓编译错误 ( Could not find xxx.tools.build:aapt2 )
  3. 小程序开发总结一:mpvue框架及与小程序原生的混搭开发
  4. sql中常用的几种连接
  5. Python基础-List找重复数
  6. 配置FCKeditor_2.6.3+fckeditor-java-2.4
  7. 有研究irrlicht引擎的吗,交流交流
  8. python 进程 线程 协程
  9. Python3编写网络爬虫10-数据存储方式三-CSV文件存储
  10. 解决win7检测不到第二个显示器的方法
  11. 计算机网络简答题与计算题
  12. 史上最强三千六百道脑筋急转弯(4)
  13. clover删除多余引导_[转载]EFI引导如何去掉多余的这个clover启动项
  14. Color RGB颜色深浅的排序
  15. python使用给定字符密码_使用python生成一个指定长度的字符串(随机密码),要求包括数字、字母、特殊符号(string库解析)...
  16. 全民热议“10万彩礼结不了婚”的背后,百合网做了什么?
  17. 大数据基础(林子雨版)
  18. 青春野狼不做姐控偶像的梦 - 线段树 - 扫描线 - 单调栈
  19. 【520521】程序员中的“芳心纵火犯”, 这就是面向对象编程吗?
  20. 叉姐的魔法训练小结(未完结)

热门文章

  1. Tomcat8安装后tomcat8w.exe点击出现“指定的服务未安装”解决方案
  2. c语言的所有头文件,C语言所有头文件.doc
  3. 利用思维导图,快速整理小学语文复习重点,建议为孩子收藏!
  4. python学习——matplotlib使用之标注点学习
  5. 2020-11-3(安卓开发入门)
  6. rsync 同步本地文件到远端
  7. C语言实现SM4加解密算法
  8. python字符串是有序的吗_Python之字符串
  9. 丙丙-2个月面试20家大厂的知识点总结和建议(答案)
  10. C++STL容器总结