Created
April 3, 2016 08:12
-
-
Save hecomi/5c30e8c834816c0d99f38a7d187b2aef to your computer and use it in GitHub Desktop.
This file contains hidden or 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
Shader "Hidden/ScreenSpaceLocalReflection" | |
{ | |
Properties | |
{ | |
_MainTex("Base (RGB)", 2D) = "" {} | |
} | |
SubShader | |
{ | |
Blend Off | |
ZTest Always | |
ZWrite Off | |
Cull Off | |
CGINCLUDE | |
#include "UnityCG.cginc" | |
sampler2D _MainTex; | |
sampler2D _CameraGBufferTexture2; | |
sampler2D _CameraDepthTexture; | |
sampler2D _ReflectionTexture; | |
sampler2D _PreDepthTexture; | |
sampler2D _PreAccumulationTexture; | |
sampler2D _AccumulationTexture; | |
float4 _ReflectionTexture_TexelSize; | |
float4x4 _InvViewProj; | |
float4x4 _ViewProj; | |
float4x4 _PreViewProj; | |
float ComputeDepth(float4 clippos) | |
{ | |
#if defined(SHADER_TARGET_GLSL) || defined(SHADER_API_GLES) || defined(SHADER_API_GLES3) | |
return (clippos.z / clippos.w) * 0.5 + 0.5; | |
#else | |
return clippos.z / clippos.w; | |
#endif | |
} | |
float noise(float2 seed) | |
{ | |
return frac(sin(dot(seed.xy, float2(12.9898, 78.233))) * 43758.5453); | |
} | |
struct appdata | |
{ | |
float4 vertex : POSITION; | |
float2 uv : TEXCOORD0; | |
}; | |
struct v2f | |
{ | |
float4 vertex : SV_POSITION; | |
float4 screenPos : TEXCOORD0; | |
}; | |
v2f vert(appdata v) | |
{ | |
v2f o; | |
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); | |
o.screenPos = ComputeScreenPos(o.vertex); | |
return o; | |
} | |
v2f vert_fullscreen(appdata v) | |
{ | |
v2f o; | |
o.vertex = v.vertex; | |
o.screenPos = ComputeScreenPos(o.vertex); | |
return o; | |
} | |
float4 frag_reflection(v2f i) : SV_Target | |
{ | |
float2 uv = i.screenPos.xy / i.screenPos.w; | |
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv); | |
if (depth >= 1.0) return float4(0, 0, 0, 0); | |
float2 spos = 2.0 * uv - 1.0; | |
float4 pos = mul(_InvViewProj, float4(spos, depth, 1.0)); | |
pos = pos / pos.w; | |
float3 camDir = normalize(pos - _WorldSpaceCameraPos); | |
float3 normal = tex2D(_CameraGBufferTexture2, uv).xyz * 2.0 - 1.0; | |
float3 refDir = normalize(camDir - 2.0 * dot(camDir, normal) * normal); | |
int maxRayNum = 30; | |
float maxLength = 2.0; | |
float3 step = maxLength / maxRayNum * refDir; | |
float maxThickness = 0.2 / maxRayNum; | |
float4 col = float4(0, 0, 0, 0); | |
for (int n = 1; n <= maxRayNum; ++n) { | |
float3 ray = (n + noise(uv + _Time.x)) * step; | |
float3 rayPos = pos + ray; | |
float4 vpPos = mul(_ViewProj, float4(rayPos, 1.0)); | |
float2 rayUv = vpPos.xy / vpPos.w * 0.5 + 0.5; | |
if (max(abs(rayUv.x - 0.5), abs(rayUv.y - 0.5)) > 0.5) break; | |
float rayDepth = ComputeDepth(vpPos); | |
float gbufferDepth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, rayUv); | |
if (rayDepth - gbufferDepth > 0 && rayDepth - gbufferDepth < maxThickness) { | |
float edgeFactor = 1.0 - pow(2.0 * length(rayUv - 0.5), 2); | |
float a = 0.5 * pow(min(1.0, (maxLength / 2) / length(ray)), 2.0) * edgeFactor; | |
a *= pow(length(rayUv - 0.5) / 0.5, 0.5); | |
col = float4(tex2D(_MainTex, rayUv).xyz, a); | |
break; | |
} | |
} | |
return col; | |
} | |
float4 frag_accumulation(v2f i) : SV_Target | |
{ | |
// 現在のワールド座標を復元 | |
float2 uv = i.screenPos.xy / i.screenPos.w; | |
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv); | |
if (depth >= 1.0) return float4(0, 0, 0, 0); | |
float2 spos = 2.0 * uv - 1.0; | |
float4 pos = mul(_InvViewProj, float4(spos, depth, 1.0)); | |
pos = pos / pos.w; | |
// 前の UV を復元 | |
float4 preVpPos = mul(_PreViewProj, pos); | |
float2 preUv = preVpPos.xy / preVpPos.w * 0.5 + 0.5; | |
float4 accumulation = tex2D(_PreAccumulationTexture, preUv); | |
float4 reflection = tex2D(_ReflectionTexture, uv); | |
float blend = 0.2; | |
return lerp(accumulation, reflection, 0.1); | |
/* | |
float2 uv = i.screenPos.xy / i.screenPos.w; | |
float4 accumulation = tex2D(_PreAccumulationTexture, uv); | |
float4 reflection = tex2D(_ReflectionTexture, uv); | |
float blend = 0.2; | |
return lerp(accumulation, reflection, 0.1); | |
*/ | |
} | |
float4 frag_composition(v2f i) : SV_Target | |
{ | |
float2 uv = i.screenPos.xy / i.screenPos.w; | |
float4 base = tex2D(_MainTex, uv); | |
float4 reflection = tex2D(_AccumulationTexture, uv); | |
float a = reflection.a; | |
return lerp(base, reflection, a); | |
} | |
ENDCG | |
Pass | |
{ | |
CGPROGRAM | |
#pragma vertex vert | |
#pragma fragment frag_reflection | |
ENDCG | |
} | |
Pass | |
{ | |
CGPROGRAM | |
#pragma vertex vert_fullscreen | |
#pragma fragment frag_accumulation | |
ENDCG | |
} | |
Pass | |
{ | |
CGPROGRAM | |
#pragma vertex vert | |
#pragma fragment frag_composition | |
ENDCG | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment