- Mirrors no longer have culling enabled, since it caused too much flickering.

- Added a fake sub-surface scattering shader that might be used later.
- Apparently the arcade games were altered somehow? Don't remember that.
This commit is contained in:
2026-02-19 21:35:47 -05:00
parent 162f3391c1
commit 8fe5f7caf4
55 changed files with 8390 additions and 5455 deletions
+136
View File
@@ -0,0 +1,136 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: SSS Demo
m_Shader: {fileID: 4800000, guid: dd867f0212ded544396217ac461f949c, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords:
- _METALLICGLOSSMAP
m_InvalidKeywords:
- _
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BRDFTex:
m_Texture: {fileID: 2800000, guid: 438762e23bc56bf4188ce947bf60e0e3, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailBumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OverlayMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ThicknessMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _texcoord:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _texcoord2:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats:
- _BumpScale: 1
- _CullMode: 2
- _Cutoff: 0.5
- _Cutout: 0.5
- _DetailBumpMapScale: 1
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
- _OcclusionUVSource: 0
- _Parallax: 0.02
- _SSSAmbient: 0
- _SSSDist: 1
- _SSSIntensity: 1
- _SSSPow: 1
- _SSSShadow: 1
- _ScatteringByAlbedo: 1
- _SecondUVSource: 0
- _SmoothnessFromAlbedo: 0
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _ThicknessMapInvert: 1
- _ThicknessMapPower: 1
- _ThicknessUVSource: 0
- _UVSec: 0
- _UseAlphaToMask: 0
- _UseCutout: 0
- _UseSkinScattering: 1
- _WrappingFactor: 0.01
- _WrappingPowerFactor: 1
- _ZWrite: 1
- __dirty: 1
m_Colors:
- _Color: {r: 1, g: 0.8283805, b: 0.7216981, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _OverlayColor: {r: 1, g: 1, b: 1, a: 1}
- _SSSCol: {r: 1, g: 1, b: 1, a: 1}
m_BuildTextureStacks: []
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 511ba8c25b0549c4ba9a8dbd34424156
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:
+108
View File
@@ -0,0 +1,108 @@
// Put together with Amplify's help.
Shader "Silent/Subsurface Scattering (Specular)"
{
Properties
{
[Header(Standard)]
_Color ("Color", Color) = (1,1,1,1)
_MainTex("Albedo", 2D) = "white" {}
[NoScaleOffset][Normal]_BumpMap("Normal Map", 2D) = "bump" {}
_BumpScale ("Normal Scale", Float) = 1
[NoScaleOffset]_MetallicGlossMap("Specular", 2D) = "black" {}
_SpecularColor("Specular Tint", Color) = (1,1,1)
_GlossMapScale("Smoothness", Range(0, 1)) = 1.0
[ToggleUI]_SmoothnessFromAlbedo("Smoothness stored in Albedo alpha", Float) = 0.0
[NoScaleOffset]_OcclusionMap("Occlusion", 2D) = "white" {}
_OcclusionStrength("Occlusion Strength", Range(0, 1)) = 1.0
[Enum(UV1, 0, UV2, 1)] _OcclusionUVSource("Occlusion UV Source", Float) = 0
_EmissionMap("Emission", 2D) = "black" {}
[HDR]_EmissionColor ("Emission Color", Color) = (1,1,1,1)
[Header(Detail)]
[NoScaleOffset]_OverlayMap("Overlay", 2D) = "black" {}
_OverlayColor ("Overlay Color", Color) = (1,1,1,1)
[NoScaleOffset]_DetailMask("Detail Mask", 2D) = "white" {}
[Normal]_DetailBumpMap("Detail Normal Map", 2D) = "bump" {}
_DetailMetallicGlossMap("Detail Metallic", 2D) = "white" {}
_DetailBumpMapScale ("Detail Scale", Float) = 1
[Enum(UV1, 0, UV2, 1)] _SecondUVSource("Secondary UV Source", Float) = 0
[Header(Transmission)]
[NoScaleOffset]_ThicknessMap("Thickness Map", 2D) = "black" {}
[ToggleUI]_ThicknessMapInvert("Invert Thickness", Float) = 0.0
_ThicknessMapPower ("Thickness Map Power", Range(0.01, 10)) = 1
[Enum(UV1, 0, UV2, 1)] _ThicknessUVSource("Thickness UV Source", Float) = 0
[ToggleUI]_ScatteringByAlbedo("Tint Scattering with Albedo", Float) = 0.0
_SSSCol ("Scattering Color", Color) = (1,1,1,1)
_SSSIntensity ("Scattering Intensity", Range(0, 10)) = 1
_SSSPow ("Scattering Power", Range(0.01, 10)) = 1
_SSSDist ("Scattering Distance", Range(0, 10)) = 1
_SSSAmbient ("Scattering Ambient Intensity", Range(0, 0.5)) = 0
_SSSShadow ("Scattering Shadow Power", Range(0, 1)) = 1
[Header(Skin)]
[Toggle(_METALLICGLOSSMAP)]_UseSkinScattering("Use Skin Scattering", Float) = 0.0
[NoScaleOffset]_BRDFTex("Skin BRDF LUT", 2D) = "white" {}
[Header(Wrapped Diffuse)]
_WrappingFactor("Wrapping Factor", Range(0.001, 1)) = 0.01
[Gamma]_WrappingPowerFactor("Wrapping Power Factor", Float) = 1
[Header(System)]
[Enum(UnityEngine.Rendering.CullMode)] _CullMode("Cull Mode", Float) = 2
[Toggle(_ALPHATEST_ON)] _UseCutout("Alpha Test Cutout", Float) = 0
[Toggle(_ALPHABLEND_ON)] _UseAlphaToMask("Alpha To Coverage Transparency", Float) = 0
_Cutout("Cutout", Range(0, 1)) = 0.5
[ToggleOff(_SPECULARHIGHLIGHTS_OFF)]_SpecularHighlights ("Specular Highlights", Float) = 1.0
[ToggleOff(_GLOSSYREFLECTIONS_OFF)]_GlossyReflections ("Glossy Reflections", Float) = 1.0
[HideInInspector] _texcoord( "", 2D ) = "white" {}
[HideInInspector] _texcoord2( "", 2D ) = "white" {}
[HideInInspector] __dirty( "", Int ) = 1
}
SubShader
{
Tags{ "RenderType" = "TransparentCutout" "Queue" = "AlphaTest+0" }
Cull[_CullMode]
AlphaToMask [_UseAlphaToMask]
CGINCLUDE
#pragma shader_feature _SPECULARHIGHLIGHTS_OFF
#pragma shader_feature _GLOSSYREFLECTIONS_OFF
#pragma shader_feature _ALPHATEST_ON
// Reuse Standard keywords for features to avoid reaching limit
// This one is for scattering.
#pragma shader_feature _METALLICGLOSSMAP
#define SSS_SPECULAR
#include "SSS_Standard.cginc"
ENDCG
CGPROGRAM
#pragma surface surf StandardCustomLighting keepalpha fullforwardshadows
ENDCG
Pass
{
Name "ShadowCaster"
Tags{ "LightMode" = "ShadowCaster" }
ZWrite On
AlphaToMask Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#pragma multi_compile_shadowcaster
#pragma multi_compile UNITY_PASS_SHADOWCASTER
#pragma shader_feature _ _ALPHATEST_ON
#pragma skip_variants FOG_LINEAR FOG_EXP FOG_EXP2
#include "SSS_Shadow.cginc"
ENDCG
}
}
Fallback "Standard"
}
@@ -0,0 +1,20 @@
fileFormatVersion: 2
guid: 3286a5d3dc0c3dd4e8dfc9dcd833291c
ShaderImporter:
externalObjects: {}
defaultTextures:
- _MainTex: {instanceID: 0}
- _BumpMap: {instanceID: 0}
- _MetallicGlossMap: {instanceID: 0}
- _OcclusionMap: {instanceID: 0}
- _OverlayMap: {instanceID: 0}
- _DetailMask: {instanceID: 0}
- _DetailBumpMap: {instanceID: 0}
- _DetailMetallicGlossMap: {instanceID: 0}
- _ThicknessMap: {instanceID: 0}
- _BRDFTex: {fileID: 2800000, guid: 438762e23bc56bf4188ce947bf60e0e3, type: 3}
- _texcoord: {instanceID: 0}
- _texcoord2: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+107
View File
@@ -0,0 +1,107 @@
// Put together with Amplify's help.
Shader "Silent/Subsurface Scattering"
{
Properties
{
[Header(Standard)]
_Color ("Color", Color) = (1,1,1,1)
_MainTex("Albedo", 2D) = "white" {}
[NoScaleOffset][Normal]_BumpMap("Normal Map", 2D) = "bump" {}
_BumpScale ("Normal Scale", Float) = 1
[NoScaleOffset]_MetallicGlossMap("Metallic", 2D) = "black" {}
_GlossMapScale("Smoothness", Range(0, 1)) = 1.0
[ToggleUI]_SmoothnessFromAlbedo("Smoothness stored in Albedo alpha", Float) = 0.0
[NoScaleOffset]_OcclusionMap("Occlusion", 2D) = "white" {}
_OcclusionStrength("Occlusion Strength", Range(0, 1)) = 1.0
[Enum(UV1, 0, UV2, 1)] _OcclusionUVSource("Occlusion UV Source", Float) = 0
_EmissionMap("Emission", 2D) = "black" {}
[HDR]_EmissionColor ("Emission Color", Color) = (1,1,1,1)
[Header(Detail)]
[NoScaleOffset]_OverlayMap("Overlay", 2D) = "black" {}
_OverlayColor ("Overlay Color", Color) = (1,1,1,1)
[NoScaleOffset]_DetailMask("Detail Mask", 2D) = "white" {}
[Normal]_DetailBumpMap("Detail Normal Map", 2D) = "bump" {}
_DetailMetallicGlossMap("Detail Metallic", 2D) = "white" {}
_DetailBumpMapScale ("Detail Scale", Float) = 1
[Enum(UV1, 0, UV2, 1)] _SecondUVSource("Secondary UV Source", Float) = 0
[Header(Transmission)]
[NoScaleOffset]_ThicknessMap("Thickness Map", 2D) = "black" {}
[ToggleUI]_ThicknessMapInvert("Invert Thickness", Float) = 0.0
_ThicknessMapPower ("Thickness Map Power", Range(0.01, 10)) = 1
[Enum(UV1, 0, UV2, 1)] _ThicknessUVSource("Thickness UV Source", Float) = 0
[ToggleUI]_ScatteringByAlbedo("Tint Scattering with Albedo", Float) = 0.0
_SSSCol ("Scattering Color", Color) = (1,1,1,1)
_SSSIntensity ("Scattering Intensity", Range(0, 10)) = 1
_SSSPow ("Scattering Power", Range(0.01, 10)) = 1
_SSSDist ("Scattering Distance", Range(0, 10)) = 1
_SSSAmbient ("Scattering Ambient Intensity", Range(0, 0.5)) = 0
_SSSShadow ("Scattering Shadow Power", Range(0, 1)) = 1
[Header(Skin)]
[Toggle(_METALLICGLOSSMAP)]_UseSkinScattering("Use Skin Scattering", Float) = 0.0
[NoScaleOffset]_BRDFTex("Skin BRDF LUT", 2D) = "white" {}
[Header(Wrapped Diffuse)]
_WrappingFactor("Wrapping Factor", Range(0.001, 1)) = 0.01
[Gamma]_WrappingPowerFactor("Wrapping Power Factor", Float) = 1
[Header(System)]
[Enum(UnityEngine.Rendering.CullMode)] _CullMode("Cull Mode", Float) = 2
[Toggle(_ALPHATEST_ON)] _UseCutout("Alpha Test Cutout", Float) = 0
[Toggle(_ALPHABLEND_ON)] _UseAlphaToMask("Alpha To Coverage Transparency", Float) = 0
_Cutout("Cutout", Range(0, 1)) = 0.5
[ToggleOff(_SPECULARHIGHLIGHTS_OFF)]_SpecularHighlights ("Specular Highlights", Float) = 1.0
[ToggleOff(_GLOSSYREFLECTIONS_OFF)]_GlossyReflections ("Glossy Reflections", Float) = 1.0
[HideInInspector] _texcoord( "", 2D ) = "white" {}
[HideInInspector] _texcoord2( "", 2D ) = "white" {}
[HideInInspector] __dirty( "", Int ) = 1
}
SubShader
{
Tags{ "RenderType" = "TransparentCutout" "Queue" = "AlphaTest+0" }
Cull[_CullMode]
AlphaToMask [_UseAlphaToMask]
CGINCLUDE
#pragma shader_feature _SPECULARHIGHLIGHTS_OFF
#pragma shader_feature _GLOSSYREFLECTIONS_OFF
#pragma shader_feature _ALPHATEST_ON
// Reuse Standard keywords for features to avoid reaching limit
// This one is for scattering.
#pragma shader_feature _METALLICGLOSSMAP
#define SSS_METALLIC
#include "SSS_Standard.cginc"
ENDCG
CGPROGRAM
#pragma surface surf StandardCustomLighting keepalpha fullforwardshadows
#pragma target 3.0
ENDCG
Pass
{
Name "ShadowCaster"
Tags{ "LightMode" = "ShadowCaster" }
ZWrite On
AlphaToMask Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster
#pragma multi_compile UNITY_PASS_SHADOWCASTER
#pragma shader_feature _ _ALPHATEST_ON
#pragma skip_variants FOG_LINEAR FOG_EXP FOG_EXP2
#include "SSS_Shadow.cginc"
ENDCG
}
}
Fallback "Standard"
}
+20
View File
@@ -0,0 +1,20 @@
fileFormatVersion: 2
guid: dd867f0212ded544396217ac461f949c
ShaderImporter:
externalObjects: {}
defaultTextures:
- _MainTex: {instanceID: 0}
- _BumpMap: {instanceID: 0}
- _MetallicGlossMap: {instanceID: 0}
- _OcclusionMap: {instanceID: 0}
- _OverlayMap: {instanceID: 0}
- _DetailMask: {instanceID: 0}
- _DetailBumpMap: {instanceID: 0}
- _DetailMetallicGlossMap: {instanceID: 0}
- _ThicknessMap: {instanceID: 0}
- _BRDFTex: {fileID: 2800000, guid: 438762e23bc56bf4188ce947bf60e0e3, type: 3}
- _texcoord: {instanceID: 0}
- _texcoord2: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+330
View File
@@ -0,0 +1,330 @@
#ifndef SSS_CORE_INCLUDED
#define SSS_CORE_INCLUDED
//-----------------------------------------------------------------------------
// BRDF functions
//-----------------------------------------------------------------------------
// See UnityStandardBRDF for more info
UNITY_DECLARE_TEX2D(_BRDFTex);
half4 UNITY_BRDF_PBS_SSSS (half3 diffColor, half3 specColor, half oneMinusReflectivity, half smoothness, half thickness,
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);
float 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
float 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
half3 diffuseTerm = DisneyDiffuse(nv, nl, lh, perceptualRoughness) * nl;
#if defined(_METALLICGLOSSMAP) // Scattering
// Skin Lighting
float2 brdfUV;
// Half-Lambert lighting value based on blurred normals.
brdfUV.x = nl * 0.5 + 0.5;
// Curvature amount. Multiplied by light's luminosity so brighter light = more scattering.
// Pleae note: gi.light.color already contains light attenuation
brdfUV.y = thickness * dot(light.color, fixed3(0.22, 0.707, 0.071));
half3 brdf = UNITY_SAMPLE_TEX2D ( _BRDFTex, brdfUV ).rgb;
#else
float wrappedDiffuse = pow(saturate((diffuseTerm + _WrappingFactor) /
(1.0f + _WrappingFactor)), _WrappingPowerFactor) * (_WrappingPowerFactor + 1) / (2 * (1 + _WrappingFactor));
half3 brdf = wrappedDiffuse;
#endif
// 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);
#if UNITY_BRDF_GGX
// GGX with roughtness to 0 would mean no specular at all, using max(roughness, 0.002) here to match HDrenderloop roughtness remapping.
roughness = max(roughness, 0.002);
float V = SmithJointGGXVisibilityTerm (nl, nv, roughness);
float D = GGXTerm (nh, roughness);
#else
// Legacy
half V = SmithBeckmannVisibilityTerm (nl, nv, roughness);
half D = NDFBlinnPhongNormalizedTerm (nh, PerceptualRoughnessToSpecPower(perceptualRoughness));
#endif
float specularTerm = V*D * 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
const float epsilon = 1.192092896e-07; // Smallest positive number, such that 1.0 + epsilon != 1.0
// SH brdf term
#if defined(_METALLICGLOSSMAP) // Scattering
float3 shLength = GetSHLength();
float3 giBase = saturate(gi.diffuse / shLength);
float giBaseL = dot(giBase, 1.0/3.0) + epsilon;
giBase /= giBaseL;
brdfUV.x = giBaseL * 0.5 + 0.5;
brdfUV.y = thickness * dot(shLength, fixed3(0.22, 0.707, 0.071));
half3 brdfSH = UNITY_SAMPLE_TEX2D ( _BRDFTex, brdfUV ).rgb;
gi.diffuse = max(0, shLength * giBase * lerp(giBaseL, brdfSH, thickness));
#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 * lerp(diffuseTerm, brdf, thickness))
+ specularTerm * light.color * FresnelTerm (specColor, lh)
+ surfaceReduction * gi.specular * FresnelLerp (specColor, grazingTerm, nv);
return half4(color, 1);
}
//-----------------------------------------------------------------------------
// Surface functions
//-----------------------------------------------------------------------------
struct SurfaceOutputStandardSSSS
{
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
fixed Thickness;
};
struct SurfaceOutputStandardSpecularSSSS
{
fixed3 Albedo; // diffuse color
fixed3 Specular; // specular color
float3 Normal; // tangent space normal, if written
half3 Emission;
half Smoothness; // 0=rough, 1=smooth
half Occlusion; // occlusion (default 1)
fixed Alpha; // alpha for transparencies
fixed Thickness;
};
inline half4 LightingStandardSSSS (SurfaceOutputStandardSSSS s, UnityGIInput data, 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 = UNITY_BRDF_PBS_SSSS (s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Thickness, s.Normal, data.worldViewDir, gi.light, gi.indirect);
#if defined(UNITY_PASS_FORWARDBASE) && defined(VERTEXLIGHT_ON)
// energy conservation
UnityLight light = gi.light;
UnityIndirect nullGi = gi.indirect;
nullGi.diffuse = 0;
nullGi.specular = 0;
for(int num = 0; num < 4 && any(unity_LightColor[num].rgb > 0); num++)
{
UnityLight light;
float3 lightPos = float3(unity_4LightPosX0[num], unity_4LightPosY0[num], unity_4LightPosZ0[num]);
light.dir = lightPos - data.worldPos;
float lengthSq = dot(light.dir, light.dir);
float atten2 = saturate(1 - (lengthSq * unity_4LightAtten0[num] / 25));
if (atten2 > 0)
{
light.dir *= min(1e30, rsqrt(lengthSq));
float atten = 1.0 / (1.0 + (lengthSq * unity_4LightAtten0[num]));
//atten = unityPointAttenuation(lengthSq, unity_4LightAtten0[num]);
atten = min(atten, atten2 * atten2);
light.color = unity_LightColor[num].rgb * atten;
c += UNITY_BRDF_PBS_SSSS (s.Albedo, specColor,
oneMinusReflectivity, s.Smoothness,
s.Thickness, s.Normal,
data.worldViewDir, light, nullGi);
}
};
#endif
c.a = outputAlpha;
return c;
}
inline half4 LightingStandardSSSS_Deferred (SurfaceOutputStandardSSSS s, float3 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 = UNITY_BRDF_PBS_SSSS (s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Thickness, s.Normal, 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 LightingStandardSSSS_GI (
SurfaceOutputStandardSSSS s,
UnityGIInput data,
inout UnityGI gi)
{
#if defined(UNITY_PASS_DEFERRED) && UNITY_ENABLE_REFLECTION_BUFFERS
gi = UnityGlobalIllumination_Geom(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_Geom(data, s.Occlusion, s.Normal, g);
#endif
}
inline half4 LightingStandardSSSSSpecular (SurfaceOutputStandardSpecularSSSS s, UnityGIInput data, UnityGI gi)
{
s.Normal = normalize(s.Normal);
// energy conservation
half oneMinusReflectivity;
s.Albedo = EnergyConservationBetweenDiffuseAndSpecular (s.Albedo, s.Specular, /*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 = UNITY_BRDF_PBS_SSSS (s.Albedo, s.Specular, oneMinusReflectivity, s.Smoothness, s.Thickness, s.Normal, data.worldViewDir, gi.light, gi.indirect);
#if defined(UNITY_PASS_FORWARDBASE) && defined(VERTEXLIGHT_ON)
// energy conservation
UnityLight light = gi.light;
UnityIndirect nullGi = gi.indirect;
nullGi.diffuse = 0;
nullGi.specular = 0;
for(int num = 0; num < 4 && any(unity_LightColor[num].rgb > 0); num++)
{
UnityLight light;
float3 lightPos = float3(unity_4LightPosX0[num], unity_4LightPosY0[num], unity_4LightPosZ0[num]);
light.dir = lightPos - data.worldPos;
float lengthSq = dot(light.dir, light.dir);
float atten2 = saturate(1 - (lengthSq * unity_4LightAtten0[num] / 25));
if (atten2 > 0)
{
light.dir *= min(1e30, rsqrt(lengthSq));
float atten = 1.0 / (1.0 + (lengthSq * unity_4LightAtten0[num]));
//atten = unityPointAttenuation(lengthSq, unity_4LightAtten0[num]);
atten = min(atten, atten2 * atten2);
light.color = unity_LightColor[num].rgb * atten;
c += UNITY_BRDF_PBS_SSSS (s.Albedo, s.Specular,
oneMinusReflectivity, s.Smoothness,
s.Thickness, s.Normal,
data.worldViewDir, light, nullGi);
}
};
#endif
c.a = outputAlpha;
return c;
}
inline half4 LightingStandardSSSSSpecular_Deferred (SurfaceOutputStandardSpecularSSSS s, float3 viewDir, UnityGI gi, out half4 outGBuffer0, out half4 outGBuffer1, out half4 outGBuffer2)
{
// energy conservation
half oneMinusReflectivity;
s.Albedo = EnergyConservationBetweenDiffuseAndSpecular (s.Albedo, s.Specular, /*out*/ oneMinusReflectivity);
half4 c = UNITY_BRDF_PBS_SSSS (s.Albedo, s.Specular, oneMinusReflectivity, s.Smoothness, s.Thickness, s.Normal, viewDir, gi.light, gi.indirect);
UnityStandardData data;
data.diffuseColor = s.Albedo;
data.occlusion = s.Occlusion;
data.specularColor = s.Specular;
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 LightingStandardSSSSSpecular_GI (
SurfaceOutputStandardSpecularSSSS s,
UnityGIInput data,
inout UnityGI gi)
{
#if defined(UNITY_PASS_DEFERRED) && UNITY_ENABLE_REFLECTION_BUFFERS
gi = UnityGlobalIllumination_Geom(data, s.Occlusion, s.Normal);
#else
Unity_GlossyEnvironmentData g = UnityGlossyEnvironmentSetup(s.Smoothness, data.worldViewDir, s.Normal, s.Specular);
gi = UnityGlobalIllumination_Geom(data, s.Occlusion, s.Normal, g);
#endif
}
#endif // SSS_CORE_INCLUDED
+9
View File
@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: b397c9c20b437d6459940d848fd7bb20
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:
+83
View File
@@ -0,0 +1,83 @@
#ifndef SSS_SHADOW_INCLUDED
#define SSS_SHADOW_INCLUDED
#include "HLSLSupport.cginc"
#if ( SHADER_API_D3D11 || SHADER_API_GLCORE || SHADER_API_GLES3 || SHADER_API_METAL || SHADER_API_VULKAN )
#define CAN_SKIP_VPOS
#endif
#include "UnityCG.cginc"
#include "Lighting.cginc"
#include "UnityPBSLighting.cginc"
struct v2f
{
V2F_SHADOW_CASTER;
float4 customPack1 : TEXCOORD1;
float4 tSpace0 : TEXCOORD2;
float4 tSpace1 : TEXCOORD3;
float4 tSpace2 : TEXCOORD4;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
v2f vert( appdata_full v )
{
v2f o;
UNITY_SETUP_INSTANCE_ID( v );
UNITY_INITIALIZE_OUTPUT( v2f, o );
UNITY_TRANSFER_INSTANCE_ID( v, o );
Input customInputData;
float3 worldPos = mul( unity_ObjectToWorld, v.vertex ).xyz;
half3 worldNormal = UnityObjectToWorldNormal( v.normal );
half3 worldTangent = UnityObjectToWorldDir( v.tangent.xyz );
half tangentSign = v.tangent.w * unity_WorldTransformParams.w;
half3 worldBinormal = cross( worldNormal, worldTangent ) * tangentSign;
o.tSpace0 = float4( worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x );
o.tSpace1 = float4( worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y );
o.tSpace2 = float4( worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z );
o.customPack1.xy = customInputData.uv_texcoord;
o.customPack1.xy = v.texcoord;
o.customPack1.zw = v.texcoord1;
TRANSFER_SHADOW_CASTER_NORMALOFFSET( o )
return o;
}
half4 frag( v2f IN
#if !defined( CAN_SKIP_VPOS )
, UNITY_VPOS_TYPE vpos : VPOS
#endif
) : SV_Target
{
UNITY_SETUP_INSTANCE_ID( IN );
Input surfIN;
UNITY_INITIALIZE_OUTPUT( Input, surfIN );
surfIN.uv_texcoord = IN.customPack1.xy;
surfIN.uv2_texcoord2 = IN.customPack1.zw;
float3 worldPos = float3( IN.tSpace0.w, IN.tSpace1.w, IN.tSpace2.w );
half3 worldViewDir = normalize( UnityWorldSpaceViewDir( worldPos ) );
surfIN.worldNormal = float3( IN.tSpace0.z, IN.tSpace1.z, IN.tSpace2.z );
surfIN.internalSurfaceTtoW0 = IN.tSpace0.xyz;
surfIN.internalSurfaceTtoW1 = IN.tSpace1.xyz;
surfIN.internalSurfaceTtoW2 = IN.tSpace2.xyz;
SurfaceOutputCustomLightingCustom o;
UNITY_INITIALIZE_OUTPUT( SurfaceOutputCustomLightingCustom, o );
#if !defined(SSS_CUSTOM_SHADOW)
float2 scaledUV = TRANSFORM_TEX(surfIN.uv_texcoord, _MainTex);
float4 _MainTex_var = tex2D( _MainTex, scaledUV );
#if !(defined(_ALPHATEST_ON) || defined(_ALPHABLEND_ON) || defined(_ALPHAPREMULTIPLY_ON))
o.Alpha = 1.0;
#else
o.Alpha = (_SmoothnessFromAlbedo? 1.0 : _MainTex_var.a) * _Color.a ;
o.Alpha = ((o.Alpha - _Cutout) / 0.0001 + 0.5);
clip(o.Alpha - 1.0/255.0 );
#endif
#else
customShadow( surfIN, o );
#endif
#if defined( CAN_SKIP_VPOS )
float2 vpos = IN.pos;
#endif
SHADOW_CASTER_FRAGMENT( IN )
}
#endif // SSS_SHADOW_INCLUDED
@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 9670dae62ebdb8e4dbebe1dd39e0ba49
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:
+227
View File
@@ -0,0 +1,227 @@
#ifndef SSS_INPUT_INCLUDED
#define SSS_INPUT_INCLUDED
#include "UnityPBSLighting.cginc"
#include "Lighting.cginc"
#ifdef UNITY_PASS_SHADOWCASTER
#undef INTERNAL_DATA
#undef WorldReflectionVector
#undef WorldNormalVector
#define INTERNAL_DATA half3 internalSurfaceTtoW0; half3 internalSurfaceTtoW1; half3 internalSurfaceTtoW2;
#define WorldReflectionVector(data,normal) reflect (data.worldRefl, half3(dot(data.internalSurfaceTtoW0,normal), dot(data.internalSurfaceTtoW1,normal), dot(data.internalSurfaceTtoW2,normal)))
#define WorldNormalVector(data,normal) half3(dot(data.internalSurfaceTtoW0,normal), dot(data.internalSurfaceTtoW1,normal), dot(data.internalSurfaceTtoW2,normal))
#endif
struct Input
{
float3 worldNormal;
float4 screenPos;
INTERNAL_DATA
float2 uv_texcoord;
float2 uv2_texcoord2;
half facing : VFACE;
};
struct SurfaceOutputCustomLightingCustom
{
half3 Albedo;
half3 Normal;
half3 Emission;
half3 Specular;
half Smoothness;
half Occlusion;
half Alpha;
half Thickness;
half3 SubsurfaceColour;
Input SurfInput;
UnityGIInput GIData;
};
uniform sampler2D _MainTex; uniform float4 _MainTex_ST;
uniform sampler2D _BumpMap;
uniform sampler2D _MetallicGlossMap;
uniform sampler2D _OcclusionMap;
uniform sampler2D _ThicknessMap;
uniform sampler2D _OverlayMap;
uniform sampler2D _EmissionMap;
uniform sampler2D _DetailMask;
uniform sampler2D _DetailBumpMap; uniform float4 _DetailBumpMap_ST;
uniform sampler2D _DetailMetallicGlossMap; uniform float4 _DetailMetallicGlossMap_ST;
uniform float _ThicknessMapPower;
uniform float _ThicknessMapInvert;
uniform float3 _SSSCol;
uniform float _SSSAmbient;
uniform float _SSSIntensity;
uniform float _SSSPow;
uniform float _SSSDist;
uniform float _SSSShadow;
uniform float4 _Color;
uniform float3 _OverlayColor;
uniform float3 _EmissionColor;
uniform float3 _SpecularColor;
uniform float _DetailBumpMapScale;
uniform float _ScatteringByAlbedo;
uniform float _SmoothnessFromAlbedo;
uniform float _BumpScale;
uniform float _OcclusionStrength;
uniform float _GlossMapScale;
uniform float _Cutout;
uniform float _WrappingFactor;
uniform float _WrappingPowerFactor;
uniform float _SecondUVSource;
uniform float _OcclusionUVSource;
uniform float _ThicknessUVSource;
#include "SSS_Utils.cginc"
#include "SSS_Core.cginc"
inline void LightingStandardCustomLighting_GI( inout SurfaceOutputCustomLightingCustom s, UnityGIInput data, inout UnityGI gi )
{
s.GIData = data;
}
void surf( Input i , inout SurfaceOutputCustomLightingCustom s1 )
{
s1.SurfInput = i;
float2 scaledUV = TRANSFORM_TEX(i.uv_texcoord, _MainTex);
float4 _MainTex_var = tex2D( _MainTex, scaledUV );
float2 texcoord2 = _SecondUVSource? i.uv2_texcoord2 : scaledUV;
float detailMask = tex2D( _DetailMask, scaledUV ).a;
float3 overlayMask = tex2D(_OverlayMap,texcoord2).rgb*detailMask;
#if defined(USE_DETAIL_AS_ALPHA)
_Color.a = lerp( _Color.a, tex2D( _OverlayMap, texcoord2 ).rgb,
detailMask);
#endif
#if !(defined(_ALPHATEST_ON) || defined(_ALPHABLEND_ON) || defined(_ALPHAPREMULTIPLY_ON))
s1.Alpha = 1.0;
#else
s1.Alpha = (_SmoothnessFromAlbedo? 1.0 : _MainTex_var.a) * _Color.a;
s1.Alpha = ((s1.Alpha - _Cutout) / max(fwidth(s1.Alpha), 0.0001) + 0.5);
clip(s1.Alpha - 1.0/255.0 );
#endif
#if defined(USE_DETAIL_AS_ALPHA)
s1.Albedo = _MainTex_var.rgb * _Color;
#else
s1.Albedo = lerp(_MainTex_var.rgb * _Color, _OverlayColor, overlayMask);
#endif
s1.Normal = NormalInTangentSpace(scaledUV, texcoord2, detailMask);
s1.Emission = tex2D( _EmissionMap, scaledUV ).rgb * _EmissionColor.rgb;
float4 _MetallicGlossMap_var = tex2D( _MetallicGlossMap, scaledUV );
float4 detailMetallicGlossMap_var = tex2D (_DetailMetallicGlossMap, TRANSFORM_TEX(texcoord2, _DetailMetallicGlossMap));
_MetallicGlossMap_var *= lerp(1.0, detailMetallicGlossMap_var, detailMask);
#if defined(SSS_METALLIC)
s1.Specular = _MetallicGlossMap_var.r;
#else
s1.Specular = _MetallicGlossMap_var.rgb;
#endif
s1.Specular *= _SpecularColor;
s1.Smoothness = _SmoothnessFromAlbedo? _MainTex_var.a : _MetallicGlossMap_var.a;
s1.Smoothness *= _GlossMapScale;
float2 occlusionUV = _OcclusionUVSource? i.uv2_texcoord2 : scaledUV;
s1.Occlusion = LerpOneTo(tex2D( _OcclusionMap, occlusionUV ).g, _OcclusionStrength);
float2 thicknessUV = _ThicknessUVSource? i.uv2_texcoord2 : scaledUV;
float3 thicknessMap_var = tex2D( _ThicknessMap, thicknessUV ).rgb;
s1.Thickness = pow(abs(_ThicknessMapInvert-thicknessMap_var), _ThicknessMapPower);
s1.SubsurfaceColour = _ScatteringByAlbedo? _SSSCol*s1.Albedo : _SSSCol;
}
inline half4 LightingStandardCustomLighting( inout SurfaceOutputCustomLightingCustom s, half3 viewDir, UnityGI gi )
{
UnityGIInput data = s.GIData;
Input i = s.SurfInput;
half4 c = 0;
#if defined(SSS_METALLIC)
SurfaceOutputStandardSSSS s1 = (SurfaceOutputStandardSSSS ) 0;
#else
SurfaceOutputStandardSpecularSSSS s1 = (SurfaceOutputStandardSpecularSSSS ) 0;
#endif
s1.Albedo = s.Albedo;
s1.Normal = s.Normal;
s1.Emission = s.Emission;
#if defined(SSS_METALLIC)
s1.Metallic = s.Specular.r;
#else
s1.Specular = s.Specular;
#endif
s1.Smoothness = s.Smoothness;
s1.Occlusion = s.Occlusion;
s1.Alpha = s.Alpha;
s1.Thickness = s.Thickness;
s1.Smoothness = GeometricNormalFiltering(s1.Smoothness, i.worldNormal, 0.25, 0.5);
data.light = gi.light;
UnityGI gi1 = gi;
#ifdef UNITY_PASS_FORWARDBASE
Unity_GlossyEnvironmentData g1 =
UnityGlossyEnvironmentSetup( s.Smoothness, data.worldViewDir, s1.Normal, float3(0,0,0));
gi1 = UnityGlobalIllumination_Geom( data, 1.0, s1.Normal, g1, s1.Thickness);
#endif
#if 1
float NdotV = saturate(abs(dot(s1.Normal, viewDir)));
float occlusion = ComputeMicroShadowing(s1.Occlusion * 0.8 + 0.3, NdotV, 1.0);
float3 occlusionCol = GTAOMultiBounce( saturate(occlusion * 1.2), s1.Albedo);
gi1.indirect.diffuse *= occlusionCol;
gi1.indirect.specular *= occlusion;
float NdotL = saturate(abs(dot(s1.Normal, gi.light.dir)));
occlusion = ComputeMicroShadowing(s1.Occlusion * 0.8 + 0.3, NdotL, 1.0);
occlusionCol = GTAOMultiBounce( saturate(occlusion * 1.2), s1.Albedo);
gi.light.color *= occlusionCol;
#endif
#ifdef UNITY_PASS_FORWARDBASE
float ase_lightAtten = data.atten;
if( _LightColor0.a == 0)
ase_lightAtten = 0;
#else
float3 ase_lightAttenRGB = gi.light.color / ( ( _LightColor0.rgb ) + 0.000001 );
float ase_lightAtten = max( max( ase_lightAttenRGB.r, ase_lightAttenRGB.g ), ase_lightAttenRGB.b );
#endif
#if defined(HANDLE_SHADOWS_BLENDING_IN_GI)
half bakedAtten = UnitySampleBakedOcclusion(data.lightmapUV.xy, data.worldPos);
float zDist = dot(_WorldSpaceCameraPos - data.worldPos, UNITY_MATRIX_V[2].xyz);
float fadeDist = UnityComputeShadowFadeDistance(data.worldPos, zDist);
ase_lightAtten = UnityMixRealtimeAndBakedShadows(data.atten, bakedAtten, UnityComputeShadowFade(fadeDist));
#endif
#if defined(SSS_METALLIC)
float3 finalResult = LightingStandardSSSS ( s1, data, gi1 ).rgb;
#else
float3 finalResult = LightingStandardSSSSSpecular ( s1, data, gi1 ).rgb;
#endif
finalResult += getSubsurfaceScatteringLight(gi.light.color, gi.light.dir, s1.Normal, data.worldViewDir,
LerpOneTo(ase_lightAtten, _SSSShadow), s1.Thickness, gi1.indirect.diffuse, s.SubsurfaceColour );
finalResult += s1.Emission;
c.rgb = finalResult;
c.a = s1.Alpha;
return c;
}
#endif // SSS_INPUT_INCLUDED
@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 6e88fd0cd8e9dd446a184fd9e762d9a5
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:
+415
View File
@@ -0,0 +1,415 @@
#ifndef SSS_UTILS_INCLUDED
#define SSS_UTILS_INCLUDED
//-----------------------------------------------------------------------------
// Helper functions
//-----------------------------------------------------------------------------
float RoughnessToPerceptualRoughness_local(float roughness)
{
return sqrt(roughness);
}
float RoughnessToPerceptualSmoothness_local(float roughness)
{
return 1.0 - sqrt(roughness);
}
float PerceptualSmoothnessToRoughness_local(float perceptualSmoothness)
{
return (1.0 - perceptualSmoothness) * (1.0 - perceptualSmoothness);
}
float PerceptualSmoothnessToPerceptualRoughness_local(float perceptualSmoothness)
{
return (1.0 - perceptualSmoothness);
}
float PerceptualRoughnessToPerceptualSmoothness_local(float perceptualRoughness)
{
return (1.0 - perceptualRoughness);
}
// Return modified perceptualSmoothness based on provided variance (get from GeometricNormalVariance + TextureNormalVariance)
float NormalFiltering(float perceptualSmoothness, float variance, float threshold)
{
float roughness = PerceptualSmoothnessToRoughness_local(perceptualSmoothness);
// Ref: Geometry into Shading - http://graphics.pixar.com/library/BumpRoughness/paper.pdf - equation (3)
float squaredRoughness = saturate(roughness * roughness + min(2.0 * variance, threshold * threshold)); // threshold can be floatly low, square the value for easier control
return RoughnessToPerceptualSmoothness_local(sqrt(squaredRoughness));
}
// Reference: Error Reduction and Simplification for Shading Anti-Aliasing
// Specular antialiasing for geometry-induced normal (and NDF) variations: Tokuyoshi / Kaplanyan et al.'s method.
// This is the deferred approximation, which works reasonably well so we keep it for forward too for now.
// screenSpaceVariance should be at most 0.5^2 = 0.25, as that corresponds to considering
// a gaussian pixel reconstruction kernel with a standard deviation of 0.5 of a pixel, thus 2 sigma covering the whole pixel.
float GeometricNormalVariance(float3 geometricNormalWS, float screenSpaceVariance)
{
float3 deltaU = ddx(geometricNormalWS);
float3 deltaV = ddy(geometricNormalWS);
return screenSpaceVariance * (dot(deltaU, deltaU) + dot(deltaV, deltaV));
}
// Return modified perceptualSmoothness
float GeometricNormalFiltering(float perceptualSmoothness, float3 geometricNormalWS, float screenSpaceVariance, float threshold)
{
float variance = GeometricNormalVariance(geometricNormalWS, screenSpaceVariance);
return NormalFiltering(perceptualSmoothness, variance, threshold);
}
//SSS method from GDC 2011 conference by Colin Barre-Bresebois & Marc Bouchard and modified by Xiexe
float3 getSubsurfaceScatteringLight (float3 lightColor, float3 lightDirection, float3 normalDirection, float3 viewDirection,
float attenuation, float3 thickness, float3 indirectLight, float3 subsurfaceColour)
{
float3 vLTLight = lightDirection + normalDirection * _SSSDist; // Distortion
float3 fLTDot = pow(saturate(dot(viewDirection, -vLTLight)), _SSSPow)
* _SSSIntensity * 1.0/UNITY_PI;
return lerp(1, attenuation, float(any(_WorldSpaceLightPos0.xyz)))
* (fLTDot + _SSSAmbient) * thickness
* (lightColor + indirectLight) * subsurfaceColour;
}
inline float3 BlendNormalsPD(float3 n1, float3 n2) {
return normalize(float3(n1.xy*n2.z + n2.xy*n1.z, n1.z*n2.z));
}
// Based on NormalInTangentSpace from UnityStandardInput
inline float3 NormalInTangentSpace(float2 texcoords, float2 texcoords2, half mask)
{
//float3 normalTangent = UnpackNormal(tex2D(_BumpMap,TRANSFORM_TEX(texcoords.xy, _MainTex)));
//float3 normalTangent = UnpackNormal(tex2D(_BumpMap,texcoords.xy));
half3 normalTangent = UnpackScaleNormal(tex2D (_BumpMap, texcoords.xy), _BumpScale);
half3 detailNormalTangent = UnpackScaleNormal(tex2D (_DetailBumpMap, TRANSFORM_TEX(texcoords2.xy, _DetailBumpMap)), _DetailBumpMapScale);
#if _DETAIL_LERP
normalTangent = lerp(
normalTangent,
detailNormalTangent,
mask);
#else
normalTangent = lerp(
normalTangent,
BlendNormalsPD(normalTangent, detailNormalTangent),
mask);
#endif
return normalTangent;
}
// "R2" dithering
// Triangle Wave
float T(float z) {
return z >= 0.5 ? 2.-2.*z : 2.*z;
}
// R dither mask
float intensity(float2 pixel) {
const float a1 = 0.75487766624669276;
const float a2 = 0.569840290998;
return frac(a1 * float(pixel.x) + a2 * float(pixel.y));
}
// Get the maximum SH contribution
// synqark's Arktoon shader's shading method
half3 GetSHLength ()
{
half3 x, x1;
x.r = length(unity_SHAr);
x.g = length(unity_SHAg);
x.b = length(unity_SHAb);
x1.r = length(unity_SHBr);
x1.g = length(unity_SHBg);
x1.b = length(unity_SHBb);
return x + x1;
}
half3 min3(float a, float b, float c) {
return min(min(a, b), c);
}
half3 min3(float3 a) {
return min(min(a.x, a.y), a.z);
}
half3 max3(float a, float b, float c) {
return max(max(a, b), c);
}
half3 max3(float3 a) {
return max(max(a.x, a.y), a.z);
}
half3 GetSHAvg ()
{
return float3(unity_SHAr.w,unity_SHAg.w,unity_SHAb.w);
}
//-----------------------------------------------------------------------------
// Better GI functions
//-----------------------------------------------------------------------------
/* http://www.geomerics.com/wp-content/uploads/2015/08/CEDEC_Geomerics_ReconstructingDiffuseLighting1.pdf */
float shEvaluateDiffuseL1Geomerics_local(float L0, float3 L1, float3 n)
{
// average energy
float R0 = L0;
// avg direction of incoming light
float3 R1 = 0.5f * L1;
// directional brightness
float lenR1 = length(R1);
// linear angle between normal and direction 0-1
//float q = 0.5f * (1.0f + dot(R1 / lenR1, n));
//float q = dot(R1 / lenR1, n) * 0.5 + 0.5;
float q = dot(normalize(R1), n) * 0.5 + 0.5;
q = saturate(q); // Thanks to ScruffyRuffles for the bug identity.
// power for q
// lerps from 1 (linear) to 3 (cubic) based on directionality
float p = 1.0f + 2.0f * lenR1 / R0;
// dynamic range constant
// should vary between 4 (highly directional) and 0 (ambient)
float a = (1.0f - lenR1 / R0) / (1.0f + lenR1 / R0);
return R0 * (a + (1.0f - a) * (p + 1.0f) * pow(q, p));
}
// From https://github.com/lukis101/VRCUnityStuffs/tree/master/SH
// SH Convolution Functions
// Code adapted from https://blog.selfshadow.com/2012/01/07/righting-wrap-part-2/
///////////////////////////
float3 GeneralWrapSH(float fA) // original unoptimized
{
// Normalization factor for our model.
float norm = 0.5 * (2 + fA) / (1 + fA);
float4 t = float4(2 * (fA + 1), fA + 2, fA + 3, fA + 4);
return norm * float3(t.x / t.y, 2 * t.x / (t.y * t.z),
t.x * (fA * fA - t.x + 5) / (t.y * t.z * t.w));
}
float3 GeneralWrapSHOpt(float fA)
{
const float4 t0 = float4(-0.047771, -0.129310, 0.214438, 0.279310);
const float4 t1 = float4( 1.000000, 0.666667, 0.250000, 0.000000);
float3 r;
r.xyz = saturate(t0.xxy * fA + t0.yzw);
r.xyz = -r * fA + t1.xyz;
return r;
}
float3 GreenWrapSHOpt(float fW)
{
const float4 t0 = float4(0.0, 1.0 / 4.0, -1.0 / 3.0, -1.0 / 2.0);
const float4 t1 = float4(1.0, 2.0 / 3.0, 1.0 / 4.0, 0.0);
float3 r;
r.xyz = t0.xxy * fW + t0.xzw;
r.xyz = r.xyz * fW + t1.xyz;
return r;
}
float3 ShadeSH9_wrapped(float3 normal, float3 conv)
{
float3 x0, x1, x2;
conv *= float3(1, 1.5, 4); // Undo pre-applied cosine convolution
//conv *= _Bands.xyz; // debugging
// Constant (L0)
// Band 0 has constant part from 6th kernel (band 1) pre-applied, but ignore for performance
x0 = float3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w);
// Linear (L1) polynomial terms
x1.r = (dot(unity_SHAr.xyz, normal));
x1.g = (dot(unity_SHAg.xyz, normal));
x1.b = (dot(unity_SHAb.xyz, normal));
// 4 of the quadratic (L2) polynomials
float4 vB = normal.xyzz * normal.yzzx;
x2.r = dot(unity_SHBr, vB);
x2.g = dot(unity_SHBg, vB);
x2.b = dot(unity_SHBb, vB);
// Final (5th) quadratic (L2) polynomial
float vC = normal.x * normal.x - normal.y * normal.y;
x2 += unity_SHC.rgb * vC;
return x0 * conv.x + x1 * conv.y + x2 * conv.z;
}
float3 ShadeSH9_wrappedCorrect(float3 normal, float3 conv)
{
const float3 cosconv_inv = float3(1, 1.5, 4); // Inverse of the pre-applied cosine convolution
float3 x0, x1, x2;
conv *= cosconv_inv; // Undo pre-applied cosine convolution
//conv *= _Bands.xyz; // debugging
// Constant (L0)
x0 = float3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w);
// Remove the constant part from L2 and add it back with correct convolution
float3 otherband = float3(unity_SHBr.z, unity_SHBg.z, unity_SHBb.z) / 3.0;
x0 = (x0 + otherband) * conv.x - otherband * conv.z;
// Linear (L1) polynomial terms
x1.r = (dot(unity_SHAr.xyz, normal));
x1.g = (dot(unity_SHAg.xyz, normal));
x1.b = (dot(unity_SHAb.xyz, normal));
// 4 of the quadratic (L2) polynomials
float4 vB = normal.xyzz * normal.yzzx;
x2.r = dot(unity_SHBr, vB);
x2.g = dot(unity_SHBg, vB);
x2.b = dot(unity_SHBb, vB);
// Final (5th) quadratic (L2) polynomial
float vC = normal.x * normal.x - normal.y * normal.y;
x2 += unity_SHC.rgb * vC;
return x0 + x1 * conv.y + x2 * conv.z;
}
float PositivePow(float base, float power)
{
return pow(abs(base), power);
}
bool isReflectionProbeActive()
{
#ifndef SHADER_TARGET_SURFACE_ANALYSIS // Required to use GetDimensions
float height, width;
unity_SpecCube0.GetDimensions(width, height);
return !(height * width < 32);
#endif
return 1;
}
// Ref: Moving Frostbite to PBR - Gotanda siggraph 2011
// Return specular occlusion based on ambient occlusion (usually get from SSAO) and view/roughness info
float GetSpecularOcclusionFromAmbientOcclusion(float NdotV, float ambientOcclusion, float roughness)
{
return saturate(PositivePow(NdotV + ambientOcclusion, exp2(-16.0 * roughness - 1.0)) - 1.0 + ambientOcclusion);
}
inline UnityGI UnityGlobalIllumination_Geom (UnityGIInput data, half occlusion, half3 normalWorld, Unity_GlossyEnvironmentData glossIn,
half thickness = 0.5)
{
UnityGI o_gi = UnityGI_Base(data, occlusion, normalWorld);
#if UNITY_SHOULD_SAMPLE_SH
#if 0
o_gi.indirect.diffuse = ShadeSHPerPixel(normalWorld, data.ambient, data.worldPos);
#endif
#if 0
float3 L0 = float3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w);
float3 nonLinearSH = float3(0,0,0);
nonLinearSH.r = shEvaluateDiffuseL1Geomerics_local(L0.r, unity_SHAr.xyz, normalWorld);
nonLinearSH.g = shEvaluateDiffuseL1Geomerics_local(L0.g, unity_SHAg.xyz, normalWorld);
nonLinearSH.b = shEvaluateDiffuseL1Geomerics_local(L0.b, unity_SHAb.xyz, normalWorld);
nonLinearSH = max(nonLinearSH, 0);
nonLinearSH += SHEvalLinearL2(half4(normal, 1.0));
o_gi.indirect.diffuse += nonLinearSH * occlusion;
#endif
#if 1
float shWrap = thickness;
float3 sh_conv = GeneralWrapSH(shWrap);
o_gi.indirect.diffuse = ShadeSH9_wrappedCorrect(normalWorld, sh_conv);
#endif
#endif
#if 0
half NdotV = abs(dot(normalWorld, data.worldViewDir));
float specOcclusion = GetSpecularOcclusionFromAmbientOcclusion(NdotV, occlusion, glossIn.roughness);
#else
float specOcclusion = occlusion;
#endif
if (isReflectionProbeActive())
{
o_gi.indirect.specular = UnityGI_IndirectSpecular(data, specOcclusion, glossIn);
} else
{
// Use light probes for the indirect specular lighting.
o_gi.indirect.specular = o_gi.indirect.diffuse;
}
return o_gi;
}
half3 BetterSH9 (half4 normal) {
float3 indirect;
float3 L0 = float3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w);
indirect.r = shEvaluateDiffuseL1Geomerics_local(L0.r, unity_SHAr.xyz, normal);
indirect.g = shEvaluateDiffuseL1Geomerics_local(L0.g, unity_SHAg.xyz, normal);
indirect.b = shEvaluateDiffuseL1Geomerics_local(L0.b, unity_SHAb.xyz, normal);
indirect = max(0, indirect);
return indirect;
}
// Ref: Horizon Occlusion for Normal Mapped Reflections: http://marmosetco.tumblr.com/post/81245981087
float GetHorizonOcclusion(float3 V, float3 normalWS, float3 vertexNormal, float horizonFade)
{
float3 R = reflect(-V, normalWS);
float specularOcclusion = saturate(1.0 + horizonFade * dot(R, vertexNormal));
// smooth it
return specularOcclusion * specularOcclusion;
}
// ref: Practical floattime Strategies for Accurate Indirect Occlusion
// Update ambient occlusion to colored ambient occlusion based on statitics of how light is bouncing in an object and with the albedo of the object
float3 GTAOMultiBounce(float visibility, float3 albedo)
{
float3 a = 2.0404 * albedo - 0.3324;
float3 b = -4.7951 * albedo + 0.6417;
float3 c = 2.7552 * albedo + 0.6903;
float x = visibility;
return max(x, ((x * a + b) * x + c) * x);
}
// Ref: The Technical Art of Uncharted 4 - Brinck and Maximov 2016
float ComputeMicroShadowing(float AO, float NdotL, float opacity)
{
float aperture = 2.0 * AO * AO;
float microshadow = saturate(NdotL + aperture - 1.0);
return lerp(1.0, microshadow, opacity);
}
// Invoke with finalcolor:ApplyDitherAlpha
// Must be defined after surf in file.
void ApplyDitherAlpha(Input IN, SurfaceOutputCustomLightingCustom o, inout fixed4 color) {
float2 pos = (IN.screenPos.xy*_ScreenParams)/IN.screenPos.w;
pos += _SinTime.x%4;
float alpha = o.Alpha;
#if !(defined(_ALPHATEST_ON) || defined(_ALPHABLEND_ON) || defined(_ALPHAPREMULTIPLY_ON))
alpha = 1.0;
#else
alpha = ((alpha - _Cutout) / max(fwidth(alpha), 0.0001) + 0.5);
clip(alpha - 1.0/255.0 );
#endif
//float mask = (T(intensity(pos)));
//alpha = saturate(alpha + alpha * mask);
color.a = alpha;
}
float unityPointAttenuation(float lengthSq, float range)
{
// Based on https://geom.io/bakery/wiki/index.php?title=Point_Light_Attenuation
return 1/(pow((lengthSq/range)*5, 2.0)+1);
}
#endif // SSS_UTILS_INCLUDED
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5c0344c0f457988478df793fa62f9cdd
ShaderImporter:
externalObjects: {}
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

@@ -0,0 +1,96 @@
fileFormatVersion: 2
guid: 438762e23bc56bf4188ce947bf60e0e3
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant: