forked from robcupisz/LightShafts
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Beta version of light shafts. Should be working. Mostly(tm).
- Loading branch information
robertcupisz
committed
Jan 9, 2014
0 parents
commit 0a3ab0d
Showing
31 changed files
with
3,622 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
Shader "Hidden/Coord" { | ||
Subshader { | ||
ZTest Always Cull Off ZWrite Off Fog { Mode Off } | ||
|
||
Pass { | ||
CGPROGRAM | ||
#pragma target 3.0 | ||
#pragma glsl | ||
#pragma vertex vert | ||
#pragma fragment frag | ||
#pragma multi_compile LIGHT_ON_SCREEN LIGHT_OFF_SCREEN | ||
#pragma multi_compile DIRECTIONAL_SHAFTS SPOT_SHAFTS | ||
#include "UnityCG.cginc" | ||
#include "Shared.cginc" | ||
|
||
float4 _CoordTexDim; | ||
float4 _ScreenTexDim; | ||
sampler2D _CameraDepthTexture; | ||
|
||
posuv vert (appdata_img v) | ||
{ | ||
posuv o; | ||
o.pos = v.vertex; | ||
#if !UNITY_UV_STARTS_AT_TOP | ||
o.pos.y *= -1; | ||
#endif | ||
o.uv = v.texcoord; | ||
return o; | ||
} | ||
|
||
void frag (posuv i, out float4 coord : COLOR0, out float4 depth : COLOR1) | ||
{ | ||
float2 uv = i.uv; | ||
|
||
float sampleOnEpipolarLine = uv.x - 0.5f/_CoordTexDim.x; | ||
float epipolarLine = saturate(uv.y - 0.5f/_CoordTexDim.y); | ||
|
||
// sampleOnEpipolarLine is now in the range [0, 1 - 1/_CoordTexDim.x] | ||
// We need to rescale it to be in [0, 1] | ||
sampleOnEpipolarLine *= _CoordTexDim.x / (_CoordTexDim.x-1); | ||
sampleOnEpipolarLine = saturate(sampleOnEpipolarLine); | ||
|
||
// epipolarLine is in the range [0, 1 - 1/_CoordTexDim.y] | ||
int edge = clamp(floor( epipolarLine * 4 ), 0, 3); | ||
float posOnEdge = frac( epipolarLine * 4 ); | ||
|
||
// Left, bottom, right, top | ||
float edgeCoord = -1 + 2*posOnEdge; | ||
float4 edgeX = float4(-1, edgeCoord, 1, -edgeCoord); | ||
float4 edgeY = float4(-edgeCoord, -1, edgeCoord, 1); | ||
bool4 edgeFlags = bool4(edge.xxxx == int4(0,1,2,3)); | ||
|
||
float2 exit = -float2(dot(edgeY, edgeFlags), dot(edgeX, edgeFlags)); | ||
float2 entry = GetEpipolarLineEntryPoint(exit); | ||
|
||
float2 coordTemp = lerp(entry, exit, sampleOnEpipolarLine); | ||
coordTemp = coordTemp*0.5 + 0.5; | ||
coord = float4(coordTemp.x, coordTemp.y, 0, 0); | ||
|
||
// Sample depth from the main buffer and store in epipolar space | ||
coordTemp = (floor(coordTemp*_ScreenTexDim.xy) + 0.5)*_ScreenTexDim.zw; | ||
depth = Linear01Depth(tex2D(_CameraDepthTexture, coordTemp).x).xxxx; | ||
|
||
// Test against the volume if we've hit at all | ||
float near, far, rayLength; | ||
float3 rayN; | ||
if(!IntersectVolume(coord.xy, near, far, rayN, rayLength) || (depth.x < near/rayLength)) | ||
{ | ||
// When detecting depth breaks, we'll skip this sample (no raymarching) | ||
depth *= -1.0; | ||
} | ||
else | ||
{ | ||
// Clamp depth to the far end of the volume, to avoid later generation of depth break | ||
// samples for things behind the volume (wasted computation, artifacts). | ||
// Requires the same clamp for depth sampled in the final interpolation step. | ||
depth = min(depth, far/rayLength); | ||
} | ||
|
||
// TODO: instead of intersecting volume here and in final interpolation, consider | ||
// rasterizing the light shape into a smaller res buffer. | ||
// Even though intersection is quite expensive in the final interpolation for every | ||
// rasterized screen pixel, still beats not doing it by about 10% and gets rid of the artifacts | ||
// of depth breaks for stuff behind the volume. | ||
} | ||
ENDCG | ||
} | ||
|
||
} | ||
|
||
Fallback off | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
Shader "Hidden/Depth" { | ||
SubShader { | ||
Tags { "RenderType"="Opaque" } | ||
Pass { | ||
Fog { Mode Off } | ||
Cull Off | ||
CGPROGRAM | ||
#pragma vertex vert | ||
#pragma fragment frag | ||
#include "UnityCG.cginc" | ||
|
||
struct v2f { | ||
float4 pos : SV_POSITION; | ||
float depth : TEXCOORD0; | ||
}; | ||
|
||
v2f vert (appdata_base v) { | ||
v2f o; | ||
o.pos = mul (UNITY_MATRIX_MVP, v.vertex); | ||
|
||
// We want [0,1] linear depth, so that 0.5 is half way between near and far. | ||
COMPUTE_EYEDEPTH(o.depth); | ||
o.depth = (o.depth - _ProjectionParams.y)/(_ProjectionParams.z - _ProjectionParams.y); | ||
|
||
return o; | ||
} | ||
|
||
float4 frag(v2f i) : COLOR { | ||
return i.depth; | ||
} | ||
ENDCG | ||
} | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
Shader "Hidden/DepthBreaks" { | ||
SubShader { | ||
Pass { | ||
ZWrite Off Fog { Mode Off } | ||
Blend Off | ||
Cull Back | ||
Stencil | ||
{ | ||
Ref 1 | ||
Comp always | ||
Pass replace | ||
} | ||
|
||
CGPROGRAM | ||
#include "UnityCG.cginc" | ||
#include "Shared.cginc" | ||
#pragma target 3.0 | ||
#pragma glsl | ||
#pragma vertex vert_simple | ||
#pragma fragment frag | ||
#pragma exclude_renderers xbox360 | ||
|
||
sampler2D _DepthEpi; | ||
float4 _DepthEpiTexDim; | ||
float _DepthThreshold; | ||
|
||
float SampleDepth(float x, float y) | ||
{ | ||
// tex2Dlod, because tex2D requires calculating derivatives and we can't do that in a loop | ||
return abs(tex2Dlod(_DepthEpi, float4(x*_DepthEpiTexDim.z, y, 0, 0))).x; | ||
} | ||
|
||
float4 frag(posuv i) : COLOR | ||
{ | ||
// _DepthEpi was marked -1 if the ray missed the volume completely. | ||
// Skip, but don't discard, so it won't be a raymarching sample. | ||
if (tex2Dlod(_DepthEpi, float4(i.uv.x, i.uv.y, 0, 0)).x < 0.0) | ||
return -1; | ||
|
||
float y = i.uv.y; | ||
int step = GetInterpolationStep(i.uv.x); | ||
float stepRcp = 1.0/float(step); | ||
|
||
int x = floor(i.uv.x*_DepthEpiTexDim.x); | ||
int start = x*stepRcp; | ||
start *= step; | ||
x -= start; | ||
int left = x; | ||
int right = x; | ||
|
||
while (left > 0) | ||
{ | ||
if (abs(SampleDepth(start + left - 1, y) - SampleDepth(start + left, y)) > _DepthThreshold) | ||
break; | ||
left--; | ||
} | ||
|
||
// We're going all the way to STEP, because if there's no depth break, we don't want to have | ||
// raymarching samples on both sides of whatever is our current step. So e.g. if STEP is 16, | ||
// we don't want a sample on the 15th and 16th pixel (16th is the leftmost from the next step), | ||
// because that's redundant and would actually show as discontinuity after interpolated along rays. | ||
// But if there is a depth break between the 15th and 16th pixel, we want samples on both. | ||
while (right < step) | ||
{ | ||
if (abs(SampleDepth(start + right, y) - SampleDepth(start + right + 1, y)) > _DepthThreshold) | ||
break; | ||
right++; | ||
} | ||
|
||
// Because of going all the way to STEP, the very last sample is a pixel too far - clamp it. | ||
right = min(start + right, _DepthEpiTexDim.x - 1) - start; | ||
|
||
float l = (x - left)*stepRcp; | ||
float r = (right - x)*stepRcp; | ||
|
||
// If either l or r is 0, it's a raymarching sample. The texture has been cleared to black, so | ||
// we don't have to write anything and since we're discarding, stencil for those pixels will stay at 0. | ||
// Then we only have to run raymarching for pixels will stencil 0. | ||
if (l*r == 0) | ||
discard; | ||
return float4(l, r, 0, 0); | ||
} | ||
|
||
ENDCG | ||
} | ||
|
||
// Temporary, to clear the stencil, as GL.Clear doesn't work. | ||
// Edit: fixed in 4.5, so this hack can be removed | ||
Pass { | ||
ZWrite Off Fog { Mode Off } | ||
Blend Off | ||
Cull Front | ||
Stencil | ||
{ | ||
Ref 0 | ||
Comp always | ||
Pass zero | ||
} | ||
|
||
CGPROGRAM | ||
#include "UnityCG.cginc" | ||
#include "Shared.cginc" | ||
#pragma target 3.0 | ||
#pragma glsl | ||
#pragma vertex vert_simple | ||
#pragma fragment frag | ||
|
||
float4 frag (posuv i) : COLOR | ||
{ | ||
return 0; | ||
} | ||
ENDCG | ||
} | ||
|
||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.