236 lines
6.8 KiB
Text
236 lines
6.8 KiB
Text
|
|
Shader "VolSample/Volume Render" {
|
||
|
|
Properties {
|
||
|
|
_MainTex( "", 2D ) = "white" {}
|
||
|
|
_StepExponent("Step Exponent", float) = 1
|
||
|
|
_NebulaSurfaceHeight("Surface Displacement", 2D) = "black" {}
|
||
|
|
_NebulaPatch("Patch", 2D) = "black" {}
|
||
|
|
_NebulaPatchHeight("Patch Displacement", 2D) = "black" {}
|
||
|
|
_NebulaTint("Tint Texture", 2D ) = "white" {}
|
||
|
|
[HDR]_Tint("Tint Color", Color) = (1,1,1,1)
|
||
|
|
//_GridTransform("Grid Transform", Vector) = (0,0,0,0)
|
||
|
|
_NebulaFillDensity("Fill Density", float) = 1
|
||
|
|
_NebulaFloorDensity("Floor Density", float) = 1
|
||
|
|
_NebulaPatchDensity("Patch Density", float) = 1
|
||
|
|
_NebulaFloorOffset("Floor Offset", float) = 1
|
||
|
|
_NebulaFloorBlend("Floor Blend", float) = 1
|
||
|
|
_NebulaPatchBlend("Patch Blend", float) = 1
|
||
|
|
_Exposure("Exposure", float) = 1
|
||
|
|
_Gamma("Gamma", float) = .5
|
||
|
|
_TintExponent("Tint Exponent", float) = .5
|
||
|
|
_DepthCeiling("Depth Ceiling", float) = 1000
|
||
|
|
_DepthBlend("Depth Blend", float) = 100
|
||
|
|
_NoiseAmplitude("Noise Amplitude", float) = 1
|
||
|
|
_NoiseScale("Noise Scale", float) = 100
|
||
|
|
_NoiseExponent("Noise Exponent", float) = 2
|
||
|
|
_NoiseSpeed("Noise Speed", float) = 1
|
||
|
|
_FlowScroll("Flow Scroll", float) = 1
|
||
|
|
_FlowScale("Flow Scale", float) = 1
|
||
|
|
_FlowAmplitude("Flow Amplitude", float) = 1
|
||
|
|
_FlowSpeed("Flow Speed", float) = 1
|
||
|
|
_SafetyDistance("Safety Distance", float) = 20
|
||
|
|
_Scattering("Scattering", float) = 1
|
||
|
|
_ScatteringMinDist("ScatteringMinDist", float) = 1
|
||
|
|
_ScatteringDistExponent("ScatteringDistExponent", float) = 1
|
||
|
|
_ScatteringDensityExponent("ScatteringDensityExponent", float) = 1
|
||
|
|
}
|
||
|
|
|
||
|
|
CGINCLUDE;
|
||
|
|
|
||
|
|
uniform sampler2D _MainTex;
|
||
|
|
uniform sampler2D _CameraDepthTexture;
|
||
|
|
|
||
|
|
#include "UnityCG.cginc"
|
||
|
|
#include "Assets/Shaders/Volumetric.cginc"
|
||
|
|
|
||
|
|
// the number of volume samples to take
|
||
|
|
#define SAMPLE_COUNT 96
|
||
|
|
|
||
|
|
// Shared shader code for pixel view rays, given screen pos and camera frame vectors.
|
||
|
|
// Camera vectors are passed in as this shader is run from a post proc camera, so the unity built-in values are not useful.
|
||
|
|
uniform float4x4 _CamProj;
|
||
|
|
uniform float4x4 _CamInvProj;
|
||
|
|
uniform float3 _CamPos;
|
||
|
|
uniform float3 _CamForward;
|
||
|
|
uniform float3 _CamRight;
|
||
|
|
uniform float _HalfFov;
|
||
|
|
uniform int _FrameNumber;
|
||
|
|
|
||
|
|
uniform float _StepExponent;
|
||
|
|
|
||
|
|
uniform half _Gamma,
|
||
|
|
_Exposure,
|
||
|
|
_DepthCeiling,
|
||
|
|
_DepthBlend,
|
||
|
|
_Scattering,
|
||
|
|
_ScatteringDensityExponent,
|
||
|
|
_ScatteringDistExponent,
|
||
|
|
_ScatteringMinDist;
|
||
|
|
|
||
|
|
// Dithering
|
||
|
|
sampler2D _DitheringTex;
|
||
|
|
float4 _DitheringCoords;
|
||
|
|
|
||
|
|
inline float nrand(float2 ScreenUVs)
|
||
|
|
{
|
||
|
|
return frac(sin(ScreenUVs.x * 12.9898 + ScreenUVs.y * 78.233) * 43758.5453);
|
||
|
|
}
|
||
|
|
|
||
|
|
void RaymarchStep( in float3 pos, in float stepSize, in float weight, inout float4 sum, in float scatter, inout float scatterSum)
|
||
|
|
{
|
||
|
|
float4 col = VolumeSampleColor( pos );
|
||
|
|
col.a *= stepSize * weight;
|
||
|
|
sum.rgb += col.rgb * col.a * (1.0 - sum.a);
|
||
|
|
sum.a += col.a;
|
||
|
|
scatterSum += pow(col.a, _ScatteringDensityExponent) * scatter;
|
||
|
|
}
|
||
|
|
|
||
|
|
float4 RayMarch( in float3 origin, in float3 direction, in float zbuf, in float2 screenUV, out float scatterSum )
|
||
|
|
{
|
||
|
|
scatterSum = 0;
|
||
|
|
float blue = tex2D(_DitheringTex, screenUV * _DitheringCoords.xy + _DitheringCoords.zw).r;
|
||
|
|
//float rand = frac(blue + _FrameNumber * 1.61803398875);
|
||
|
|
//return float4(rand, rand, rand, 1);
|
||
|
|
//half rand = frac(nrand(screenUV) + _FrameNumber * 1.61803398875);
|
||
|
|
//half rand = nrand(screenUV + frac(_Time.x));
|
||
|
|
half rand = blue;
|
||
|
|
float4 sum = (float4)0.;
|
||
|
|
scatterSum = 0.;
|
||
|
|
|
||
|
|
// setup sampling
|
||
|
|
|
||
|
|
float rayDist = 0;
|
||
|
|
for( int i = 0; i < SAMPLE_COUNT; i++ )
|
||
|
|
{
|
||
|
|
float prevRayDist = rayDist;
|
||
|
|
rayDist = pow((i+rand)/SAMPLE_COUNT,_StepExponent) * _DepthCeiling + 1;
|
||
|
|
float distToSurf = zbuf - rayDist;
|
||
|
|
if( distToSurf <= 0.001 || sum.a > .99) break;
|
||
|
|
|
||
|
|
float step = rayDist - prevRayDist;
|
||
|
|
//float wt = (distToSurf >= step) ? 1. : distToSurf / step;
|
||
|
|
|
||
|
|
RaymarchStep( origin + rayDist * direction, step, 1-rayDist/_DepthCeiling, sum, _Scattering/pow(max(rayDist,_ScatteringMinDist),_ScatteringDistExponent), scatterSum);
|
||
|
|
}
|
||
|
|
|
||
|
|
sum.rgb = pow( sum.rgb, 1 / _Gamma ) * _Exposure;
|
||
|
|
return sum;
|
||
|
|
}
|
||
|
|
|
||
|
|
struct v2f
|
||
|
|
{
|
||
|
|
float4 pos : SV_POSITION;
|
||
|
|
float4 screenPos : TEXCOORD1;
|
||
|
|
};
|
||
|
|
|
||
|
|
v2f vert( appdata_base v )
|
||
|
|
{
|
||
|
|
v2f o;
|
||
|
|
o.pos = UnityObjectToClipPos( v.vertex );
|
||
|
|
o.screenPos = ComputeScreenPos( o.pos );
|
||
|
|
return o;
|
||
|
|
}
|
||
|
|
|
||
|
|
void computeCamera( in float2 q, out float3 rayOrigin, out float3 rd )
|
||
|
|
{
|
||
|
|
rayOrigin = _WorldSpaceCameraPos;
|
||
|
|
|
||
|
|
float2 p = 2.0*(q - 0.5);
|
||
|
|
float4 d = mul(_CamProj, float4(p, 0, 1));
|
||
|
|
d.xyz /= d.w;
|
||
|
|
//rd = (d - rayOrigin);
|
||
|
|
rd = normalize(d - rayOrigin);
|
||
|
|
rayOrigin = d;
|
||
|
|
//rayOrigin += _ProjectionParams.y * rd;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline float LinearEyeDepthToOutDepth(float z)
|
||
|
|
{
|
||
|
|
return (1 - _ZBufferParams.w * z) / (_ZBufferParams.z * z);
|
||
|
|
}
|
||
|
|
|
||
|
|
float3 DepthToWorld(float2 uv, float depth) {
|
||
|
|
float z = (1-depth) * 2.0 - 1.0;
|
||
|
|
|
||
|
|
float4 clipSpacePosition = float4(uv * 2.0 - 1.0, z, 1.0);
|
||
|
|
|
||
|
|
float4 viewSpacePosition = mul(_CamInvProj,clipSpacePosition);
|
||
|
|
viewSpacePosition /= viewSpacePosition.w;
|
||
|
|
|
||
|
|
float4 worldSpacePosition = mul(unity_ObjectToWorld,viewSpacePosition);
|
||
|
|
|
||
|
|
return worldSpacePosition.xyz;
|
||
|
|
}
|
||
|
|
|
||
|
|
// MRT shader
|
||
|
|
struct FragmentOutput
|
||
|
|
{
|
||
|
|
half4 dest0 : COLOR0;
|
||
|
|
half4 dest1 : COLOR1;
|
||
|
|
};
|
||
|
|
|
||
|
|
FragmentOutput frag( v2f i ) : SV_Target //out float outDepth : SV_Depth
|
||
|
|
{
|
||
|
|
FragmentOutput o;
|
||
|
|
|
||
|
|
float2 q = i.screenPos.xy / i.screenPos.w;
|
||
|
|
|
||
|
|
// camera
|
||
|
|
float3 rayOrigin, rayDirection;
|
||
|
|
computeCamera( q, rayOrigin, rayDirection );
|
||
|
|
|
||
|
|
// z buffer / scene depth for this pixel
|
||
|
|
float4 screenPos = UNITY_PROJ_COORD( i.screenPos );
|
||
|
|
float2 screenUV = screenPos.xy / screenPos.w;
|
||
|
|
|
||
|
|
float depthSample = tex2Dproj( _CameraDepthTexture, screenPos ).r;
|
||
|
|
//float depthValue = LinearEyeDepth(depthSample);
|
||
|
|
|
||
|
|
float3 worldDepth = DepthToWorld(screenPos, depthSample);
|
||
|
|
float depthValue = length(worldDepth-rayOrigin);
|
||
|
|
|
||
|
|
// march through volume
|
||
|
|
float scatter;
|
||
|
|
float4 clouds = RayMarch( rayOrigin, rayDirection, depthValue, screenUV, scatter );
|
||
|
|
o.dest1 = .5 + scatter*.5;//smoothstep(1,.99,clouds.a)*pow(clouds.a,1)*.5;
|
||
|
|
|
||
|
|
float3 bgcol = tex2Dlod( _MainTex, float4(q, 0., 0.) );
|
||
|
|
// add in camera render colours, if not zfar (so we exclude skybox)
|
||
|
|
if(clouds.a < .99 && depthValue < _DepthCeiling)
|
||
|
|
{
|
||
|
|
// Blend out camera render when outside marching range
|
||
|
|
if( depthValue >= _DepthCeiling - _DepthBlend )
|
||
|
|
clouds.a = lerp(clouds.a, 1, (depthValue - (_DepthCeiling - _DepthBlend)) / _DepthBlend);
|
||
|
|
|
||
|
|
//clouds.xyz = lerp(clouds.xyz, bgcol, 1-clouds.a);
|
||
|
|
clouds.xyz += (1. - clouds.a) * bgcol;
|
||
|
|
// assume zbuffer represents opaque surface
|
||
|
|
|
||
|
|
}
|
||
|
|
clouds.a = 1.;
|
||
|
|
|
||
|
|
//outDepth = LinearEyeDepthToOutDepth(min(depthValue, rayDist));
|
||
|
|
|
||
|
|
o.dest0 = clouds;
|
||
|
|
return o;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
ENDCG
|
||
|
|
|
||
|
|
Subshader
|
||
|
|
{
|
||
|
|
Pass
|
||
|
|
{
|
||
|
|
ZTest Always Cull Off ZWrite Off
|
||
|
|
|
||
|
|
CGPROGRAM
|
||
|
|
#pragma target 3.0
|
||
|
|
#pragma vertex vert
|
||
|
|
#pragma fragment frag
|
||
|
|
ENDCG
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
Fallback off
|
||
|
|
|
||
|
|
} // shader
|