Aetheria/Assets/Shaders/Raymarching/VolumeRenderCustom.shader

236 lines
6.8 KiB
Text
Raw Normal View History

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