1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
| 两个通道
shader:
#define DistanceToProjectionWindow 5.671281819617709 //1.0 / tan(0.5 * radians(20)); #define DPTimes300 1701.384545885313 //DistanceToProjectionWindow * 300 #define SamplerSteps 25 uniform sampler2D _CameraDepthTexture; float4 _CameraDepthTexture_TexelSize;
float4 SSS(float4 SceneColor, float2 UV, float2 SSSIntencity) { float SceneDepth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, UV)); float BlurLength = DistanceToProjectionWindow / SceneDepth; float2 UVOffset = SSSIntencity * BlurLength; float4 BlurSceneColor = SceneColor; BlurSceneColor.rgb *= _Kernel[0].rgb;
[loop] for (int i = 1; i < SamplerSteps; i++) { float2 SSSUV = UV + _Kernel[i].a * UVOffset; float4 SSSSceneColor = tex2D(_MainTex, SSSUV); float SSSDepth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, SSSUV)).r; float SSSScale = saturate(DPTimes300 * SSSIntencity * abs(SceneDepth - SSSDepth)); SSSSceneColor.rgb = lerp(SSSSceneColor.rgb, SceneColor.rgb, SSSScale); BlurSceneColor.rgb += _Kernel[i].rgb * SSSSceneColor.rgb; } return BlurSceneColor; }
float4 frag(VertexOutput i) : SV_TARGET { float4 SceneColor = tex2D(_MainTex, i.uv); float SSSIntencity = (_SSSScale * _CameraDepthTexture_TexelSize.x); float3 XBlur = SSS(SceneColor, i.uv, float2(SSSIntencity, 0) ).rgb; return float4(XBlur, SceneColor.a); }
float4 frag(VertexOutput i) : COLOR { float4 SceneColor = tex2D(_MainTex, i.uv); float SSSIntencity = (_SSSScale * _CameraDepthTexture_TexelSize.y); float3 YBlur = SSS(SceneColor, i.uv, float2(0, SSSIntencity)).rgb; return float4(YBlur, SceneColor.a); }
cs:
public static class SeparableSSS { public static void CalculateKernel(List<Vector4> kernel, int nSamples, Vector3 strength, Vector3 falloff){ float RANGE = nSamples > 20 ? 3.0f : 2.0f; float EXPONENT = 2.0f; kernel.Clear();
float step = 2.0f * RANGE / (nSamples - 1); for (int i = 0; i < nSamples; i++){ float o = -RANGE + i * step; float sign = o < 0.0f ? -1.0f : 1.0f; float w = RANGE * sign *Mathf.Abs(Mathf.Pow(o, EXPONENT)) / Mathf.Pow(RANGE, EXPONENT); kernel.Add(new Vector4(0, 0, 0, w)); } for (int i = 0; i < nSamples; i++){ float w0 = i > 0 ? Mathf.Abs(kernel[i].w - kernel[i - 1].w) : 0.0f; float w1 = i < nSamples - 1 ? Mathf.Abs(kernel[i].w - kernel[i + 1].w) : 0.0f; float area = (w0 + w1) / 2.0f; Vector3 temp = profile(kernel[i].w, falloff); Vector4 tt = new Vector4(area * temp.x, area * temp.y, area * temp.z, kernel[i].w); kernel[i] = tt; } Vector4 t = kernel[nSamples / 2]; for (int i = nSamples / 2; i > 0; i--) kernel[i] = kernel[i - 1]; kernel[0] = t; Vector4 sum = Vector4.zero; for (int i = 0; i < nSamples; i++){ sum.x += kernel[i].x; sum.y += kernel[i].y; sum.z += kernel[i].z; }
for (int i = 0; i < nSamples; i++){ Vector4 vecx = kernel[i]; vecx.x /= sum.x; vecx.y /= sum.y; vecx.z /= sum.z; kernel[i] = vecx; }
Vector4 vec = kernel[0]; vec.x = (1.0f - strength.x) * 1.0f + strength.x * vec.x; vec.y = (1.0f - strength.y) * 1.0f + strength.y * vec.y; vec.z = (1.0f - strength.z) * 1.0f + strength.z * vec.z; kernel[0] = vec;
for (int i = 1; i < nSamples; i++){ var vect = kernel[i]; vect.x *= strength.x; vect.y *= strength.y; vect.z *= strength.z; kernel[i] = vect; } }
private static Vector3 gaussian(float variance, float r, Vector3 falloff){ Vector3 g;
float rr1 = r / (0.001f + falloff.x); g.x = Mathf.Exp((-(rr1 * rr1)) / (2.0f * variance)) / (2.0f * 3.14f * variance);
float rr2 = r / (0.001f + falloff.y); g.y = Mathf.Exp((-(rr2 * rr2)) / (2.0f * variance)) / (2.0f * 3.14f * variance);
float rr3 = r / (0.001f + falloff.z); g.z = Mathf.Exp((-(rr3 * rr3)) / (2.0f * variance)) / (2.0f * 3.14f * variance);
return g; } private static Vector3 profile(float r, Vector3 falloff){ return 0.100f * gaussian(0.0484f, r, falloff) + 0.118f * gaussian(0.187f, r, falloff) + 0.113f * gaussian(0.567f, r, falloff) + 0.358f * gaussian(1.99f, r, falloff) + 0.078f * gaussian(7.41f, r, falloff); } }
Vector3 SSSC = Vector3.Normalize(new Vector3 (SubsurfaceColor.r, SubsurfaceColor.g, SubsurfaceColor.b)); Vector3 SSSFC = Vector3.Normalize(new Vector3 (SubsurfaceFalloff.r, SubsurfaceFalloff.g, SubsurfaceFalloff.b)); SeparableSSS.CalculateKernel(KernelArray, 25, SSSC, SSSFC); SubsurfaceEffects.SetVectorArray (Kernel, KernelArray); SubsurfaceEffects.SetFloat (SSSScaler, SubsurfaceScaler);
SubsurfaceBuffer.Clear(); SubsurfaceBuffer.GetTemporaryRT (SceneColorID, RenderCamera.pixelWidth, RenderCamera.pixelHeight, 0, FilterMode.Trilinear, RenderTextureFormat.DefaultHDR);
SubsurfaceBuffer.BlitStencil(BuiltinRenderTextureType.CameraTarget, SceneColorID, BuiltinRenderTextureType.CameraTarget, SubsurfaceEffects, 0); SubsurfaceBuffer.BlitSRT(SceneColorID, BuiltinRenderTextureType.CameraTarget, SubsurfaceEffects, 1);
|