VR模拟枪支打靶,消灭鬼怪,换弹以及上弦等等硬核枪支操作。 使用HTCVive设备,开启SteamVR进行游玩。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

352 lines
9.5 KiB

3 years ago
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
// SSAO Pro - Unity Asset
// Copyright (c) 2015 - Thomas Hourdel
// http://www.thomashourdel.com
#ifndef SSAO_PRO_INCLUDED
#define SSAO_PRO_INCLUDED
// --------------------------------------------------------------------------------
// Uniforms
sampler2D _MainTex;
half4 _MainTex_TexelSize;
sampler2D _SSAOTex;
sampler2D_float _DepthNormalMapF32; // High precision depth map (Unity 4 only)
sampler2D_float _CameraDepthTexture;
sampler2D_float _CameraDepthNormalsTexture;
half4x4 _InverseViewProject;
half4x4 _CameraModelView;
sampler2D _NoiseTex;
half4 _Params1; // Noise Size / Sample Radius / Intensity / Distance
half4 _Params2; // Bias / Luminosity Contribution / Distance Cutoff / Cutoff Falloff
half4 _OcclusionColor;
half2 _Direction;
half _BilateralThreshold;
// --------------------------------------------------------------------------------
// Functions
inline half invlerp(half from, half to, half value)
{
return (value - from) / (to - from);
}
inline half getDepth(half2 uv)
{
#if HIGH_PRECISION_DEPTHMAP_OFF
return tex2D(_CameraDepthTexture, uv).x;
#elif HIGH_PRECISION_DEPTHMAP_ON
return tex2D(_DepthNormalMapF32, uv).x;
#endif
return 0;
}
inline half3 getWSPosition(half2 uv, half depth)
{
// Compute world space position from the view depth
half4 pos = half4(uv.xy * 2.0 - 1.0, depth, 1.0);
half4 ray = mul(_InverseViewProject, pos);
return ray.xyz / ray.w;
}
inline half3 getWSNormal(half2 uv)
{
// Get the view space normal and convert it to world space
half3 nn = tex2D(_CameraDepthNormalsTexture, uv).xyz * half3(3.5554, 3.5554, 0) + half3(-1.7777, -1.7777, 1.0);
half g = 2.0 / dot(nn.xyz, nn.xyz);
half3 vsnormal = half3(g * nn.xy, g - 1.0); // View space
half3 wsnormal = mul((half3x3)_CameraModelView, vsnormal); // World space
return wsnormal;
}
inline half calcAO(half2 tcoord, half2 uv, half3 p, half3 cnorm)
{
half2 t = tcoord + uv;
half depth = getDepth(t);
half3 diff = getWSPosition(t, depth) - p; // World space
half3 v = normalize(diff);
half d = length(diff) * _Params1.w;
return max(0.0, dot(cnorm, v) - _Params2.x) * (1.0 / (1.0 + d)) * _Params1.z;
}
half ssao(half2 uv)
{
const half2 CROSS[4] = { half2(1.0, 0.0), half2(-1.0, 0.0), half2(0.0, 1.0), half2(0.0, -1.0) };
half depth = getDepth(uv);
half eyeDepth = LinearEyeDepth(depth);
half3 position = getWSPosition(uv, depth); // World space
half3 normal = getWSNormal(uv); // World space
#if defined(SAMPLE_NOISE)
half2 random = normalize(tex2D(_NoiseTex, _ScreenParams.xy * uv / _Params1.x).rg * 2.0 - 1.0);
#endif
half radius = max(_Params1.y / eyeDepth, 0.005);
clip(_Params2.z - eyeDepth); // Skip out of range pixels
half ao = 0.0;
// Sampling
for (int j = 0; j < 4; j++)
{
half2 coord1;
#if defined(SAMPLE_NOISE)
coord1 = reflect(CROSS[j], random) * radius;
#else
coord1 = CROSS[j] * radius;
#endif
#if !SAMPLES_VERY_LOW
half2 coord2 = coord1 * 0.707;
coord2 = half2(coord2.x - coord2.y, coord2.x + coord2.y);
#endif
#if SAMPLES_ULTRA // 20
ao += calcAO(uv, coord1 * 0.20, position, normal);
ao += calcAO(uv, coord2 * 0.40, position, normal);
ao += calcAO(uv, coord1 * 0.60, position, normal);
ao += calcAO(uv, coord2 * 0.80, position, normal);
ao += calcAO(uv, coord1, position, normal);
#elif SAMPLES_HIGH // 16
ao += calcAO(uv, coord1 * 0.25, position, normal);
ao += calcAO(uv, coord2 * 0.50, position, normal);
ao += calcAO(uv, coord1 * 0.75, position, normal);
ao += calcAO(uv, coord2, position, normal);
#elif SAMPLES_MEDIUM // 12
ao += calcAO(uv, coord1 * 0.30, position, normal);
ao += calcAO(uv, coord2 * 0.60, position, normal);
ao += calcAO(uv, coord1 * 0.90, position, normal);
#elif SAMPLES_LOW // 8
ao += calcAO(uv, coord1 * 0.30, position, normal);
ao += calcAO(uv, coord2 * 0.80, position, normal);
#elif SAMPLES_VERY_LOW // 4
ao += calcAO(uv, coord1 * 0.50, position, normal);
#endif
}
#if SAMPLES_ULTRA
ao /= 20.0;
#elif SAMPLES_HIGH
ao /= 16.0;
#elif SAMPLES_MEDIUM
ao /= 12.0;
#elif SAMPLES_LOW
ao /= 8.0;
#elif SAMPLES_VERY_LOW
ao /= 4.0;
#endif
// Distance cutoff
ao = lerp(1.0 - ao, 1.0, saturate(invlerp(_Params2.z - _Params2.w, _Params2.z, eyeDepth)));
return ao;
}
// --------------------------------------------------------------------------------
// SSAO
struct v_data_simple
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
#if UNITY_UV_STARTS_AT_TOP
float2 uv2 : TEXCOORD1;
#endif
};
v_data_simple vert_ssao(appdata_img v)
{
v_data_simple o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.texcoord;
#if UNITY_UV_STARTS_AT_TOP
o.uv2 = v.texcoord;
if (_MainTex_TexelSize.y < 0.0)
o.uv.y = 1.0 - o.uv.y;
#endif
return o;
}
half4 getAOColor(half ao, half2 uv)
{
#if defined(LIGHTING_CONTRIBUTION)
// Luminance for the current pixel, used to reduce the AO amount in bright areas
// Could potentially be replaced by the lighting pass in Deferred...
half3 color = tex2D(_MainTex, uv).rgb;
half luminance = dot(color, half3(0.299, 0.587, 0.114));
half aofinal = lerp(ao, 1.0, luminance * _Params2.y);
return half4(aofinal, aofinal, aofinal, 1.0);
#else
return half4(ao, ao, ao, 1.0);
#endif
}
half4 frag_ssao(v_data_simple i) : SV_Target
{
#if UNITY_UV_STARTS_AT_TOP
return saturate(getAOColor(ssao(i.uv), i.uv2) + _OcclusionColor);
#else
return saturate(getAOColor(ssao(i.uv), i.uv) + _OcclusionColor);
#endif
}
// --------------------------------------------------------------------------------
// Gaussian Blur
struct v_data_blur
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float4 uv1 : TEXCOORD1;
float4 uv2 : TEXCOORD2;
};
v_data_blur vert_gaussian(appdata_img v)
{
v_data_blur o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = MultiplyUV(UNITY_MATRIX_TEXTURE0, v.texcoord);
float2 d1 = 1.3846153846 * _Direction;
float2 d2 = 3.2307692308 * _Direction;
o.uv1 = float4(o.uv + d1, o.uv - d1);
o.uv2 = float4(o.uv + d2, o.uv - d2);
return o;
}
float4 frag_gaussian(v_data_blur i) : SV_Target
{
half3 c = tex2D(_MainTex, i.uv).rgb * 0.2270270270;
c += tex2D(_MainTex, i.uv1.xy).rgb * 0.3162162162;
c += tex2D(_MainTex, i.uv1.zw).rgb * 0.3162162162;
c += tex2D(_MainTex, i.uv2.xy).rgb * 0.0702702703;
c += tex2D(_MainTex, i.uv2.zw).rgb * 0.0702702703;
return half4(c, 1.0);
}
// --------------------------------------------------------------------------------
// Bilateral Blur
v_data_blur vert_bilateral(appdata_img v)
{
v_data_blur o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = MultiplyUV(UNITY_MATRIX_TEXTURE0, v.texcoord);
float2 d2 = 2.0 * _Direction;
o.uv1 = float4(o.uv + _Direction, o.uv - _Direction);
o.uv2 = float4(o.uv + d2, o.uv - d2);
return o;
}
float4 frag_bilateral(v_data_blur i) : SV_Target
{
half4 depthTmp, coeff;
half depth = Linear01Depth(getDepth(i.uv));
half3 c = tex2D(_MainTex, i.uv).rgb;
depthTmp.x = Linear01Depth(getDepth(i.uv1.xy));
depthTmp.y = Linear01Depth(getDepth(i.uv1.zw));
depthTmp.z = Linear01Depth(getDepth(i.uv2.xy));
depthTmp.w = Linear01Depth(getDepth(i.uv2.zw));
coeff = 1.0 / (1e-06 + abs(depth - depthTmp));
c += tex2D(_MainTex, i.uv1.xy).rgb * coeff.x;
c += tex2D(_MainTex, i.uv1.zw).rgb * coeff.y;
c += tex2D(_MainTex, i.uv2.xy).rgb * coeff.z;
c += tex2D(_MainTex, i.uv2.zw).rgb * coeff.w;
c /= (coeff.x + coeff.y + coeff.z + coeff.w);
return half4(c, 1.0);
}
// --------------------------------------------------------------------------------
// High Quality Bilateral Blur
v_data_blur vert_hqbilateral(appdata_img v)
{
v_data_blur o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = MultiplyUV(UNITY_MATRIX_TEXTURE0, v.texcoord);
float2 d1 = 1.3846153846 * _Direction;
float2 d2 = 3.2307692308 * _Direction;
o.uv1 = float4(o.uv + d1, o.uv - d1);
o.uv2 = float4(o.uv + d2, o.uv - d2);
return o;
}
float4 frag_hqbilateral(v_data_blur i) : SV_Target
{
const half2 uvs[4] = { i.uv1.xy, i.uv1.zw, i.uv2.xy, i.uv2.zw };
half depth = Linear01Depth(getDepth(i.uv));
half3 accum = tex2D(_MainTex, i.uv).rgb * 0.2270270270;
half accumWeight = 0.2270270270;
half4 depthTmp;
depthTmp.x = Linear01Depth(getDepth(uvs[0]));
depthTmp.y = Linear01Depth(getDepth(uvs[1]));
depthTmp.z = Linear01Depth(getDepth(uvs[2]));
depthTmp.w = Linear01Depth(getDepth(uvs[3]));
half4 diff = abs(depth - depthTmp);
half4 weight = (1.0 - step(_BilateralThreshold, diff)) * half4(0.3162162162, 0.3162162162, 0.0702702703, 0.0702702703);
for (int i = 0; i < 4; i++)
{
accum += weight[i] * tex2D(_MainTex, uvs[i]).rgb;
accumWeight += weight[i];
}
return half4(accum / accumWeight, 1.0);
}
// --------------------------------------------------------------------------------
// Composite
v_data_simple vert_composite(appdata_img v)
{
v_data_simple o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.texcoord;
#if UNITY_UV_STARTS_AT_TOP
o.uv2 = v.texcoord;
if (_MainTex_TexelSize.y < 0.0)
o.uv.y = 1.0 - o.uv.y;
#endif
return o;
}
half4 frag_composite(v_data_simple i) : SV_Target
{
#if UNITY_UV_STARTS_AT_TOP
half4 color = tex2D(_MainTex, i.uv2).rgba;
#else
half4 color = tex2D(_MainTex, i.uv).rgba;
#endif
return half4(color.rgb * tex2D(_SSAOTex, i.uv).rgb, color.a);
}
#endif // SSAO_PRO_INCLUDED