Added the project.

This commit is contained in:
Robert Cupisz
2016-11-01 13:25:56 +01:00
parent 93760b331c
commit 947b6de3a5
137 changed files with 33276 additions and 0 deletions

View File

@ -0,0 +1,48 @@
Shader "Hidden/ApplyToOpaque" {
SubShader {
Pass {
ZTest Always Cull Off ZWrite Off
Blend Off
CGPROGRAM
#pragma target 3.0
#include "UnityCG.cginc"
#include "VolumetricFog.cginc"
#pragma vertex vert
#pragma fragment frag
sampler2D _CameraDepthTexture;
sampler2D _MainTex;
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert (appdata_img v)
{
v2f o;
o.pos = v.vertex;
o.pos.xy = o.pos.xy * 2 - 1;
o.uv = v.texcoord.xy;
#if UNITY_UV_STARTS_AT_TOP
if (_ProjectionParams.x < 0)
o.uv.y = 1-o.uv.y;
#endif
return o;
}
half4 frag (v2f i) : SV_Target
{
half linear01Depth = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv));
half4 fog = Fog(linear01Depth, i.uv);
return tex2D(_MainTex, i.uv) * fog.a + fog;
}
ENDCG
}
}
}

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 6f73df8e11615074dbf62a3a384af521
timeCreated: 1432216767
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,240 @@
Shader "Hidden/BlurShadowmap" {
Properties
{
_MainTex ("Base (RGB)", 2D) = "white" {}
_Bloom ("Bloom (RGB)", 2D) = "black" {}
}
CGINCLUDE
#include "UnityCG.cginc"
half4 _TexelSize;
struct v2f_tap
{
float4 pos : SV_POSITION;
half2 uv20 : TEXCOORD0;
half2 uv21 : TEXCOORD1;
half2 uv22 : TEXCOORD2;
half2 uv23 : TEXCOORD3;
};
v2f_tap vert4Tap ( appdata_img v )
{
v2f_tap o;
o.pos = v.vertex;
o.uv20 = v.texcoord + _TexelSize.xy;
o.uv21 = v.texcoord + _TexelSize.xy * half2(-0.5, -0.5);
o.uv22 = v.texcoord + _TexelSize.xy * half2( 0.5, -0.5);
o.uv23 = v.texcoord + _TexelSize.xy * half2(-0.5, 0.5);
return o;
}
// TODO: consolidate with the above, but make sure both area and dir shadows work
v2f_tap vert4TapDir ( appdata_img v )
{
v2f_tap o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv20 = v.texcoord + _TexelSize.xy;
o.uv21 = v.texcoord + _TexelSize.xy * half2(-0.5, -0.5);
o.uv22 = v.texcoord + _TexelSize.xy * half2( 0.5, -0.5);
o.uv23 = v.texcoord + _TexelSize.xy * half2(-0.5, 0.5);
return o;
}
float4 _ZParams;
float _ESMExponent;
Texture2D _Shadowmap;
SamplerComparisonState sampler_Shadowmap;
// To get a sampler, which doesn't do comparison
Texture2D _ShadowmapDummy;
SamplerState sampler_ShadowmapDummy;
#define VSM 1
float4 fragDownsampleFromShadowmapFormat ( v2f_tap i ) : SV_Target
{
float4 z;
z.r = _Shadowmap.Sample(sampler_ShadowmapDummy, i.uv20).r;
z.g = _Shadowmap.Sample(sampler_ShadowmapDummy, i.uv21).r;
z.b = _Shadowmap.Sample(sampler_ShadowmapDummy, i.uv22).r;
z.a = _Shadowmap.Sample(sampler_ShadowmapDummy, i.uv23).r;
// The texture contains just 0. But we need to sample it somewhere for Unity to initialize the corresponding sampler.
z.r += _ShadowmapDummy.Sample(sampler_ShadowmapDummy, 0).a;
// Transform to linear z, 0 at near, 1 at far
z = z * 2 - 1;
z = _ZParams.x * (z + 1.0) / (z + _ZParams.y);
#if VSM
// TODO: this is wrong. We can't average/blur z values before converting to VSM.
// This doesn't affect m, but affects m * m, so I should swap those two lines.
float m = dot(z, 0.25);
return float4(m, m * m, 0, 0);
#else
z = exp(_ESMExponent * z);
return dot(z, 0.25);
#endif
}
sampler2D _DirShadowmap;
float4 fragDownsampleFromShadowmapFormatDir ( v2f_tap i ) : SV_Target
{
float4 z;
z.r = tex2D (_DirShadowmap, i.uv20).r;
z.g = tex2D (_DirShadowmap, i.uv21).r;
z.b = tex2D (_DirShadowmap, i.uv22).r;
z.a = tex2D (_DirShadowmap, i.uv23).r;
return z.r;
// Transform to linear z, 0 at near, 1 at far
// z = z * 2 - 1;
// z = _ZParams.x * (z + 1.0) / (z + _ZParams.y);
#if 1
// float m = dot(z, 0.25);
// return float4(m, m * m, 0, 0);
float4 z2 = z * z;
return float4(dot(z, 0.25), dot(z2, 0.25), 0, 0);
#else
//z = exp(_ESMExponent * z);
z = exp(40.0 * z);
return dot(z, 0.25);
#endif
}
sampler2D _MainTex;
float4 fragDownsample ( v2f_tap i ) : SV_Target
{
float4 color = tex2D (_MainTex, i.uv20);
color += tex2D (_MainTex, i.uv21);
color += tex2D (_MainTex, i.uv22);
color += tex2D (_MainTex, i.uv23);
return color * 0.25;
}
struct v2f
{
float4 pos : SV_POSITION;
half4 uv : TEXCOORD0;
half2 offs : TEXCOORD1;
};
float _BlurSize;
v2f vertBlurHorizontal (appdata_img v)
{
v2f o;
o.pos = v.vertex;
o.uv = half4(v.texcoord.xy,1,1);
o.offs = _TexelSize.xy * half2(1.0, 0.0) * _BlurSize;
return o;
}
v2f vertBlurVertical (appdata_img v)
{
v2f o;
o.pos = v.vertex;
o.uv = half4(v.texcoord.xy, 1, 1);
o.offs = _TexelSize.xy * half2(0.0, 1.0) * _BlurSize;
return o;
}
float4 fragBlur8 (v2f i) : SV_Target
{
half2 coords = i.uv.xy - i.offs * 5.0;
float4 color = 0;
for(int k = 0; k < 11; k++)
{
color += tex2D(_MainTex, coords);
coords += i.offs;
}
return color/11.0;
}
ENDCG
SubShader {
ZTest Off Cull Off ZWrite Off Blend Off
// 0
Pass
{
CGPROGRAM
#pragma vertex vert4Tap
#pragma fragment fragDownsampleFromShadowmapFormat
ENDCG
}
// 1
Pass
{
CGPROGRAM
#pragma vertex vert4Tap
#pragma fragment fragDownsample
ENDCG
}
// 2
Pass {
ZTest Always
Cull Off
CGPROGRAM
#pragma vertex vertBlurVertical
#pragma fragment fragBlur8
ENDCG
}
// 3
Pass {
ZTest Always
Cull Off
CGPROGRAM
#pragma vertex vertBlurHorizontal
#pragma fragment fragBlur8
ENDCG
}
// 4
Pass
{
CGPROGRAM
#pragma vertex vert4TapDir
#pragma fragment fragDownsampleFromShadowmapFormatDir
ENDCG
}
// 5
Pass
{
CGPROGRAM
#pragma vertex vert4TapDir
#pragma fragment fragDownsample
ENDCG
}
}
FallBack Off
}

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 701192b62a7678549918bc87434699fe
timeCreated: 1432227463
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,43 @@
Shader "Hidden/CopyShadowParams"
{
SubShader
{
Pass
{
CGPROGRAM
#pragma target 5.0
#pragma only_renderers d3d11
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct ShadowParams
{
float4x4 worldToShadow[4];
float4 shadowSplitSpheres[4];
float4 shadowSplitSqRadii;
};
// Hmm, we can't be sure u2 doesn't conflict with other effects.
RWStructuredBuffer<ShadowParams> _ShadowParams : register(u2);
float4 vert () : SV_POSITION
{
for (int i = 0; i < 4; i++)
{
_ShadowParams[0].worldToShadow[i] = unity_WorldToShadow[i];
_ShadowParams[0].shadowSplitSpheres[i] = unity_ShadowSplitSpheres[i];
}
_ShadowParams[0].shadowSplitSqRadii = unity_ShadowSplitSqRadii;
return float4(0, 0, 0, 1);
}
fixed4 frag () : SV_Target
{
return 0;
}
ENDCG
}
}
}

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 33fc45db43408764c8dd7647b877e561
timeCreated: 1463056552
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,56 @@
Shader "Hidden/Debug" {
SubShader {
Pass {
ZTest Always Cull Off ZWrite Off
Blend Off
CGPROGRAM
#pragma target 3.0
#include "UnityCG.cginc"
#pragma vertex vert
#pragma fragment frag
sampler2D _CameraDepthTexture;
sampler3D _VolumeInject;
sampler3D _VolumeScatter;
sampler2D _Shadowmap;
sampler2D _ShadowmapBlurred;
sampler2D _MainTex;
sampler2D _BoxLightShadowmap;
float _Z;
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert (appdata_img v)
{
v2f o;
o.pos = v.vertex;
o.pos.xy = o.pos.xy * 2 - 1;
o.uv = v.texcoord.xy;
#if UNITY_UV_STARTS_AT_TOP
if (_ProjectionParams.x < 0)
o.uv.y = 1-o.uv.y;
#endif
return o;
}
half4 frag (v2f i) : SV_Target
{
half depth = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv));
// return i.uv.xyyy;
return tex2D(_BoxLightShadowmap, i.uv);
//return log(tex2D(_ShadowmapBlurred, i.uv))/80.0;
return tex3D(_VolumeInject, half3(i.uv.x, i.uv.y, _Z)).a;// * tex2D(_MainTex, float2(i.uv.x, i.uv.y));
}
ENDCG
}
}
}

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 91e29ad407521e447a7254f5c1ea9b54
timeCreated: 1431963567
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,538 @@
#pragma kernel CSMain TUBE_LIGHTS TUBE_LIGHT_SHADOW_PLANES FOG_ELLIPSOIDS ANISOTROPY AREA_LIGHTS POINT_LIGHTS
// Directional light support not quite ready yet
// #pragma kernel CSMain TUBE_LIGHTS TUBE_LIGHT_SHADOW_PLANES FOG_ELLIPSOIDS ANISOTROPY AREA_LIGHTS POINT_LIGHTS DIR_LIGHT
#define TUBE_LIGHT_ATTENUATION_LEGACY 1
#include "..\..\TubeLight\Shaders\TubeLightAttenuation.cginc"
#ifdef TUBE_LIGHT_SHADOW_PLANES
#include "..\..\TubeLight\Shaders\TubeLightShadowPlanes.cginc"
#endif
RWTexture3D<half4> _VolumeInject;
Texture2D _Shadowmap;
SamplerState sampler_Shadowmap;
float4 _FrustumRays[4];
float4 _CameraPos;
float4 _FrustumRaysLight[4];
float4 _CameraPosLight;
float _Density;
float _Intensity;
float _Anisotropy;
Texture2D _Noise;
SamplerState sampler_Noise;
float4 _FogParams;
float _NoiseFogAmount;
float _NoiseFogScale;
float _WindSpeed;
float3 _WindDir;
float _Time;
Texture2D _LightTextureB0;
SamplerState sampler_LightTextureB0;
float _NearOverFarClip;
float3 _AmbientLight;
#ifdef FOG_BOMB
float _FogBombRadius;
float3 _FogBombPos;
#endif
#ifdef DIR_LIGHT
float3 _DirLightColor;
float3 _DirLightDir;
#ifdef DIR_LIGHT_SHADOWS
float _DirLightShadows;
float _ESMExponentDirLight;
struct ShadowParams
{
float4x4 worldToShadow[4];
float4 shadowSplitSpheres[4];
float4 shadowSplitSqRadii;
};
RWStructuredBuffer<ShadowParams> _ShadowParams;
Texture2D _DirectionalShadowmap;
SamplerState sampler_DirectionalShadowmap;
#endif
#endif
#ifdef POINT_LIGHTS
struct PointLight
{
float3 pos;
float range;
float3 color;
float padding;
};
StructuredBuffer<PointLight> _PointLights;
float _PointLightsCount;
#endif
#ifdef TUBE_LIGHTS
struct TubeLight
{
float3 start;
float range;
float3 end;
float radius;
float3 color;
float padding;
};
StructuredBuffer<TubeLight> _TubeLights;
float _TubeLightsCount;
#ifdef TUBE_LIGHT_SHADOW_PLANES
// Same count as _TubeLightsCount
StructuredBuffer<TubeLightShadowPlane> _TubeLightShadowPlanes;
#endif
#endif // TUBE_LIGHTS
#ifdef AREA_LIGHTS
struct AreaLight
{
float4x4 mat;
float4 pos; // only needed for anisotropy. w: 0 ortho, 1 proj
float3 color;
float bounded;
};
StructuredBuffer<AreaLight> _AreaLights;
float _AreaLightsCount;
Texture2D _AreaLightShadowmap;
SamplerState sampler_AreaLightShadowmap;
float _ShadowedAreaLightIndex;
float4 _AreaLightShadowmapZParams;
float _ESMExponentAreaLight;
#endif
#ifdef FOG_ELLIPSOIDS
struct FogEllipsoid
{
float3 pos;
float radius;
float3 axis;
float stretch;
float density;
float noiseAmount;
float noiseSpeed;
float noiseScale;
float feather;
float blend;
float padding1;
float padding2;
};
StructuredBuffer<FogEllipsoid> _FogEllipsoids;
float _FogEllipsoidsCount;
#endif
float hash( float n ) { return frac(sin(n)*753.5453123); }
float noisep(float3 x)
{
float3 p = floor(x);
float3 f = frac(x);
f = f*f*(3.0-2.0*f);
float n = p.x + p.y*157.0 + 113.0*p.z;
return lerp(lerp(lerp( hash(n+ 0.0), hash(n+ 1.0),f.x),
lerp( hash(n+157.0), hash(n+158.0),f.x),f.y),
lerp(lerp( hash(n+113.0), hash(n+114.0),f.x),
lerp( hash(n+270.0), hash(n+271.0),f.x),f.y),f.z);
}
float noise(float3 x)
{
float3 p = floor(x);
float3 f = frac(x);
f = f * f * (3.0 - 2.0 * f);
float2 uv = (p.xy + float2(37.0,17.0) * p.z) + f.xy;
float2 rg = _Noise.SampleLevel(sampler_Noise, (uv + 0.5) / 256.0, 0).yx;
return -1.0 + 2.0 * lerp(rg.x, rg.y, f.z);
}
float ScrollNoise(float3 pos, float speed, float scale, float3 dir, float amount, float bias = 0.0, float mult = 1.0)
{
float time = _Time * speed;
float noiseScale = scale;
float3 noiseScroll = dir * time;
float3 q = pos - noiseScroll;
q *= scale;
float f = 0;
f = 0.5 * noisep(q);
// scroll the next octave in the opposite direction to get some morphing instead of just scrolling
q += noiseScroll * scale;
q = q * 2.01;
f += 0.25 * noisep(q);
f += bias;
f *= mult;
f = max(f, 0.0);
return lerp(1.0, f, amount);
}
#ifdef FOG_ELLIPSOIDS
void FogEllipsoids(float3 pos, inout float density)
{
for (int i = 0; i < _FogEllipsoidsCount; i++)
{
float3 dir = _FogEllipsoids[i].pos - pos;
float3 axis = _FogEllipsoids[i].axis;
float3 dirAlongAxis = dot(dir, axis) * axis;
float scrollNoise = ScrollNoise(dir, _FogEllipsoids[i].noiseSpeed, _FogEllipsoids[i].noiseScale, axis, _FogEllipsoids[i].noiseAmount);
dir = dir + dirAlongAxis * _FogEllipsoids[i].stretch;
float distsq = dot(dir, dir);
float radius = _FogEllipsoids[i].radius;
float feather = _FogEllipsoids[i].feather;
// float feather = 0.3;
feather = (1.0 - smoothstep (radius * feather, radius, distsq));
float contribution = scrollNoise * feather * _FogEllipsoids[i].density;
density = lerp(density + contribution, density * contribution, _FogEllipsoids[i].blend);
}
}
#endif
#ifdef FOG_BOMB
float Pulse(float c, float w, float x)
{
return smoothstep(c - w, c, x) - smoothstep(c, c + w, x);
}
#endif
float Density(float3 pos)
{
float fog = _FogParams.x;
fog += max(exp(_FogParams.y*(-pos.y + _FogParams.z)) * _FogParams.w, 0.0);
float3 warp = pos;
#ifdef FOG_BOMB
if (_FogBombRadius > 0)
{
float3 posToBomb = _FogBombPos - pos;
float distToBomb = length(posToBomb);
fog *= smoothstep (_FogBombRadius * 0.9, _FogBombRadius * 1.1, distToBomb);
fog *= 1.0 + 0.5 * Pulse(_FogBombRadius * 1.35, 0.7, distToBomb);
warp += (1 - smoothstep(_FogBombRadius, _FogBombRadius * 1.4, distToBomb)) * posToBomb * 0.3;
}
#endif
fog *= ScrollNoise(warp, _WindSpeed, _NoiseFogScale, _WindDir, _NoiseFogAmount, -0.3, 8.0);
#ifdef FOG_ELLIPSOIDS
FogEllipsoids(pos, fog);
#endif
return max(fog * _Density, 0.0);
}
float3 FrustumRay(float2 uv, float4 frustumRays[4])
{
float3 ray0 = lerp(frustumRays[0].xyz, frustumRays[1].xyz, uv.x);
float3 ray1 = lerp(frustumRays[3].xyz, frustumRays[2].xyz, uv.x);
return lerp(ray0, ray1, uv.y);
}
#ifdef ANISOTROPY
float anisotropy(float costheta)
{
float g = _Anisotropy;
float gsq = g*g;
float denom = 1 + gsq - 2.0 * g * costheta;
denom = denom * denom * denom;
denom = sqrt(max(0, denom));
return (1 - gsq) / denom;
}
#endif
#if AREA_LIGHTS || DIR_LIGHT_SHADOWS
#define VSM 1
#if VSM
float ChebyshevUpperBound(float2 moments, float mean)
{
// Compute variance
float variance = moments.y - (moments.x * moments.x);
float _VSMBias = 0.001f;
variance = max(variance, _VSMBias * mean * mean);
// Compute probabilistic upper bound
float d = mean - moments.x;
float pMax = variance / (variance + (d * d));
// One-tailed Chebyshev
return (mean <= moments.x ? 1.0f : pMax);
}
#endif
#endif
#if DIR_LIGHT
#if DIR_LIGHT_SHADOWS
float4 getCascadeWeights_splitSpheres(float3 pos)
{
float3 fromCenter0 = pos - _ShadowParams[0].shadowSplitSpheres[0].xyz;
float3 fromCenter1 = pos - _ShadowParams[0].shadowSplitSpheres[1].xyz;
float3 fromCenter2 = pos - _ShadowParams[0].shadowSplitSpheres[2].xyz;
float3 fromCenter3 = pos - _ShadowParams[0].shadowSplitSpheres[3].xyz;
float4 distances2 = float4(dot(fromCenter0,fromCenter0), dot(fromCenter1,fromCenter1), dot(fromCenter2,fromCenter2), dot(fromCenter3,fromCenter3));
float4 weights = float4(distances2 >= _ShadowParams[0].shadowSplitSqRadii);
return weights;
}
float4 getShadowCoord(float3 pos, float4 cascadeWeights)
{
return mul(_ShadowParams[0].worldToShadow[(int)dot(cascadeWeights, float4(1,1,1,1))], float4(pos, 1));
}
#endif
float3 DirectionalLight(float3 pos)
{
if (!any(_DirLightColor))
return 0;
float att = 1;
#if DIR_LIGHT_SHADOWS
if (_DirLightShadows > 0.0)
{
float4 cascadeWeights = getCascadeWeights_splitSpheres(pos);
//bool inside = dot(cascadeWeights, float4(1,1,1,1)) < 4;
float3 samplePos = getShadowCoord(pos, cascadeWeights).xyz;
//occlusion += inside ? UNITY_SAMPLE_SHADOW(u_CascadedShadowMap, samplePos) : 1.f;
#if 1
att *= _DirectionalShadowmap.SampleLevel(sampler_DirectionalShadowmap, samplePos.xy, 0).r > samplePos.z;
#else
float2 shadowmap = _DirectionalShadowmap.SampleLevel(sampler_DirectionalShadowmap, samplePos, 0).xy;
att *= ChebyshevUpperBound(shadowmap.xy, samplePos.z);
// float depth = exp(-40.0 * samplePos.z);
// att = saturate(shadowmap.r * depth);
#endif
}
#endif
#if ANISOTROPY
float3 posToCamera = normalize(_CameraPos.xyz - pos);
float costheta = dot(posToCamera, _DirLightDir);
att *= anisotropy(costheta);
#endif
return _DirLightColor * att;
}
#endif
#ifdef POINT_LIGHTS
float3 PointLights(float3 pos)
{
float3 color = 0;
for (int i = 0; i < _PointLightsCount; i++)
{
float3 posToLight = _PointLights[i].pos - pos;
float distNorm = dot(posToLight, posToLight) * _PointLights[i].range;
float att = Attenuation(distNorm);
#if ANISOTROPY
float3 cameraToPos = normalize(pos - _CameraPos.xyz);
float costheta = dot(cameraToPos, normalize(posToLight));
att *= anisotropy(costheta);
#endif
color += _PointLights[i].color * att;
}
return color;
}
#endif
#ifdef TUBE_LIGHTS
float almostIdentity(float x, float m, float n)
{
if (x > m)
return x;
float a = 2.0f*n - m;
float b = 2.0f*m - 3.0f*n;
float t = x/m;
return (a*t + b)*t*t + n;
}
float3 TubeLights(float3 pos)
{
float3 color = 0;
for (int i = 0; i < _TubeLightsCount; i++)
{
float3 L0 = _TubeLights[i].start - pos;
float3 L1 = _TubeLights[i].end - pos;
float distNorm = 0.5f * (length(L0) * length(L1) + dot(L0, L1)) * _TubeLights[i].range;
float att = Attenuation(distNorm);
#if ANISOTROPY
// Just like when calculating specular for area lights:
// assume forward scattering lobe -> the point on the light that's the closest to
// the view direction is representative
float3 posToCamera = normalize(pos - _CameraPos.xyz);
float3 r = -posToCamera;
float3 Ld = L1 - L0;
float L0oL0 = dot(L0, L0);
float RoL0 = dot(r, L0);
float RoLd = dot(r, Ld);
float L0oLd = dot(L0, Ld);
float LdoLd = dot(Ld, Ld);
float distLd = sqrt(LdoLd);
#if 1
// Smallest angle to ray
float t = (L0oLd * RoL0 - L0oL0 * RoLd) / (L0oLd * RoLd - LdoLd * RoL0);
t = saturate(t);
// As r becomes parallel to Ld and then points away, t flips from 0 to 1 (or vv) and a discontinuity shows up.
// Counteract by detecting that relative angle/position and flip t. The discontinuity in t moves to the back side.
float3 L0xLd = cross(L0, Ld);
float3 LdxR = cross(Ld, r);
float RAtLd = dot(L0xLd, LdxR);
// RAtLd is negative if R points away from Ld.
// TODO: check if lerp below is indeed cheaper.
// if (RAtLd < 0)
// t = 1 - t;
t = lerp(1 - t, t, step(0, RAtLd));
#else
// Original by Karis
// Closest distance to ray
float t = (RoL0 * RoLd - L0oLd) / (distLd * distLd - RoLd * RoLd);
t = saturate(t);
#endif
float3 closestPoint = L0 + Ld * t;
float3 centerToRay = dot(closestPoint, r) * r - closestPoint;
// closestPoint = closestPoint + centerToRay * saturate(_TubeLights[i].radius / length(centerToRay));
float centerToRayNorm = length(centerToRay) / _TubeLights[i].radius;
// The last param should in theory be 1
centerToRayNorm = almostIdentity(centerToRayNorm, 2, 1.2);
closestPoint = closestPoint + centerToRay / centerToRayNorm;
// Attenuation from the closest point looks really good if there's anisotropy, but breaks
// for (close to) isotropic medium. Probably because there's no forward lobe anymore, so
// the closest point to the view direction is not representative? But artifacts look like
// smth else is going on too.
// att = Attenuation(dot(closestPoint, closestPoint) * _TubeLights[i].range);
float costheta = dot(posToCamera, normalize(closestPoint));
att *= anisotropy(costheta);
#endif
#ifdef TUBE_LIGHT_SHADOW_PLANES
att *= ShadowPlanes(pos, _TubeLightShadowPlanes[i]);
#endif
// GDC hack
att = isnan(att) || isinf(att) ? 0 : att;
color += _TubeLights[i].color * att;
}
return color;
}
#endif
#ifdef AREA_LIGHTS
float3 AreaLights(float3 pos)
{
float3 color = 0;
uint count = _AreaLightsCount;
uint shadowedAreaLightIndex = _ShadowedAreaLightIndex;
for (uint i = 0; i < count; i++)
{
float4 pClip = mul(_AreaLights[i].mat, float4(pos, 1));
float3 p = float3(pClip.x / pClip.w, pClip.y / pClip.w, pClip.z);
float z = p.z * 0.5 + 0.5;
float att = 1;
if (_AreaLights[i].bounded)
{
att *= saturate(AttenuationToZero(z * z));
// Magic tweaks to the shape
float corner = 0.4;
float outset = 0.8;
float smooth = 0.7;
float d = length(max(abs(p.xy) - 1 + corner*outset, 0.0)) - corner;
att *= saturate(1 - smoothstep(-smooth, 0, d));
att *= smoothstep(-0.01, 0.01, z);
}
#if ANISOTROPY
float3 cameraToPos = normalize(pos - _CameraPos.xyz);
float4 lightPos = _AreaLights[i].pos;
float3 posToLight = lerp(lightPos.xyz, lightPos.xyz - pos, lightPos.w);
float costheta = dot(cameraToPos, normalize(posToLight));
att *= anisotropy(costheta);
#endif
if (i == shadowedAreaLightIndex && all(abs(p) < 1))
{
#if VSM
float2 shadowmap = _AreaLightShadowmap.SampleLevel(sampler_AreaLightShadowmap, p.xy * 0.5 + 0.5, 0).xy;
att *= ChebyshevUpperBound(shadowmap.xy, z);
#else
float shadowmap = _AreaLightShadowmap.SampleLevel(sampler_AreaLightShadowmap, p.xy * 0.5 + 0.5, 0);
float depth = exp(-_ESMExponentAreaLight * z);
att *= saturate(shadowmap * depth);
#endif
}
color += _AreaLights[i].color * att;
}
return color;
}
#endif
[numthreads(16,2,16)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
float3 color = _AmbientLight;
float2 uv = float2(id.x/159.0, id.y/89.0);
float z = id.z/127.0;
z = _NearOverFarClip + z * (1 - _NearOverFarClip);
float3 pos = FrustumRay(uv, _FrustumRays) * z + _CameraPos.xyz;
// Directional light
#ifdef DIR_LIGHT
color += DirectionalLight(pos);
#endif
// Point lights
#ifdef POINT_LIGHTS
color += PointLights(pos);
#endif
// Tube lights
#ifdef TUBE_LIGHTS
color += TubeLights(pos);
#endif
// Area lights
#ifdef AREA_LIGHTS
color += AreaLights(pos);
#endif
// Density
float density = Density(pos);
// Output
float4 output;
output.rgb = _Intensity * density * color;
output.a = density;
_VolumeInject[id] = output;
}

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 55812fd61bd54104aa23612fc28bfeb8
timeCreated: 1431967312
licenseType: Pro
ComputeShaderImporter:
currentBuildTarget: 5
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,38 @@
// Based on 'Volumetric fog: Unified, compute shader based solution to atmospheric scattering, ACM Siggraph 2014'
// https://bartwronski.com/publications/
#pragma kernel CSMain
#define VOLUME_DEPTH 128
Texture3D _VolumeInject;
RWTexture3D<float4> _VolumeScatter;
float Extinction(float density)
{
return exp(-density);
}
void WriteOutput(in uint3 pos, in float4 colorAndDensity)
{
_VolumeScatter[pos] = float4(colorAndDensity.rgb, Extinction(colorAndDensity.a));
}
float4 AccumulateScattering(float4 colorAndDensityFront, float4 colorAndDensityBack)
{
float3 light = colorAndDensityFront.rgb + saturate(Extinction(colorAndDensityFront.a)) * colorAndDensityBack.rgb;
return float4(light.rgb, colorAndDensityFront.a + colorAndDensityBack.a);
}
[numthreads(32, 2, 1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
float4 currentSlice = _VolumeInject[uint3(id.xy, 0)];
WriteOutput(uint3(id.xy, 0), currentSlice);
for(uint z = 1; z < VOLUME_DEPTH; z++)
{
float4 nextValue = _VolumeInject[uint3(id.xy, z)];
currentSlice = AccumulateScattering(currentSlice, nextValue);
WriteOutput(uint3(id.xy, z), currentSlice);
}
}

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 2a7c01c2354d03a4e9c31096bf130b6a
timeCreated: 1432198206
licenseType: Pro
ComputeShaderImporter:
currentBuildTarget: 5
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,32 @@
Shader "Hidden/Shadowmap" {
SubShader {
Tags { "RenderType"="Opaque" }
Pass
{
Fog { Mode Off }
Cull Back
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f
{
float4 pos : SV_POSITION;
};
v2f vert (appdata_base v)
{
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
return o;
}
float4 frag(v2f i) : COLOR
{
return 0;
}
ENDCG
}
}
}

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 2c4cd42b134f7864fa579350e9cf6896
timeCreated: 1432028591
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,34 @@
sampler3D _VolumeScatter;
float4 _VolumeScatter_TexelSize;
float4 _Screen_TexelSize;
float _CameraFarOverMaxFar;
float _NearOverFarClip;
int ihash(int n)
{
n = (n<<13)^n;
return (n*(n*n*15731+789221)+1376312589) & 2147483647;
}
float frand(int n)
{
return ihash(n) / 2147483647.0;
}
float2 cellNoise(int2 p)
{
int i = p.y*256 + p.x;
return float2(frand(i), frand(i + 57)) - 0.5;//*2.0-1.0;
}
half4 Fog(half linear01Depth, half2 screenuv)
{
half z = linear01Depth * _CameraFarOverMaxFar;
z = (z - _NearOverFarClip) / (1 - _NearOverFarClip);
if (z < 0.0)
return half4(0, 0, 0, 1);
half3 uvw = half3(screenuv.x, screenuv.y, z);
uvw.xy += cellNoise(uvw.xy * _Screen_TexelSize.zw) * _VolumeScatter_TexelSize.xy * 0.8;
return tex3D(_VolumeScatter, uvw);
}

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 5353ac921ca28c4448781247e4f9ec3b
timeCreated: 1452690568
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 KiB

View File

@ -0,0 +1,55 @@
fileFormatVersion: 2
guid: 35eb47181d630134c97488476efbda59
timeCreated: 1432252542
licenseType: Pro
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 0
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
cubemapConvolution: 0
cubemapConvolutionSteps: 8
cubemapConvolutionExponent: 1.5
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 2048
textureSettings:
filterMode: -1
aniso: -1
mipBias: -1
wrapMode: 0
nPOTScale: 1
lightmap: 0
rGBM: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: .5, y: .5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 0
textureType: 5
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant: