You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

479 lines
12 KiB
Plaintext

// Copyright(c) 2016, Michal Skalsky
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors
// may be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT
// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
// OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
// TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//Modified for use with Enviro - Sky and Weather
Shader "Enviro/Standard/VolumeLight"
{
Properties
{ _MainTex("Texture", any) = "" {}
[HideInInspector]_ZTest ("ZTest", Float) = 0
[HideInInspector]_LightColor("_LightColor", Color) = (1,1,1,1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
CGINCLUDE
#if defined(SHADOWS_DEPTH) || defined(SHADOWS_CUBE)
#define SHADOWS_NATIVE
#endif
#include "UnityCG.cginc"
#include "UnityDeferredLibrary.cginc"
#include "../Core/EnviroVolumeLightCore.cginc"
struct appdata
{
float4 vertex : POSITION;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float4 pos : SV_POSITION;
float4 uv : TEXCOORD0;
float3 wpos : TEXCOORD1;
float4 interpolatedRay : TEXCOORD2;
UNITY_VERTEX_OUTPUT_STEREO
};
v2f vert(appdata v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v); //Insert
UNITY_INITIALIZE_OUTPUT(v2f, o); //Insert
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); //Ins
if (unity_StereoEyeIndex == 0)
o.pos = mul(_WorldViewProj, v.vertex);
else
o.pos = mul(_WorldViewProj_SP, v.vertex);
o.uv = ComputeScreenPos(o.pos);
o.wpos = mul(unity_ObjectToWorld, v.vertex);
return o;
}
ENDCG
// pass 0 - point light, camera inside
Pass
{
ZTest Off
Cull Front
ZWrite Off
Blend One One
CGPROGRAM
#pragma vertex vert
#pragma fragment fragPointInside
#pragma target 3.5
#pragma exclude_renderers d3d9 gles
#define UNITY_HDR_ON
#pragma shader_feature HEIGHT_FOG
#pragma shader_feature NOISE
#pragma shader_feature SHADOWS_CUBE
#pragma shader_feature POINT_COOKIE
#pragma shader_feature POINT
#ifdef SHADOWS_DEPTH
#define SHADOWS_NATIVE
#endif
fixed4 fragPointInside(v2f i) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
float2 uv = i.uv.xy / i.uv.w;
#if defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED)
if(unity_StereoEyeIndex != _Eye)
return float4(0,0,0,0);
#endif
// read depth and reconstruct world position
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, UnityStereoScreenSpaceUVAdjust(uv,_CameraDepthTexture_ST));
float3 rayStart = _WorldSpaceCameraPos;
float3 rayEnd = i.wpos;
float3 rayDir = (rayEnd - rayStart);
float rayLength = length(rayDir);
rayDir /= rayLength;
float linearDepth = LinearEyeDepth(depth);
float projectedDepth = linearDepth / dot(_CameraForward, rayDir);
rayLength = min(rayLength, projectedDepth);
return RayMarch(i.pos.xy, rayStart, rayDir, rayLength);
}
ENDCG
}
// pass 1 - spot light, camera inside
Pass
{
ZTest Off
Cull Front
ZWrite Off
Blend One One
CGPROGRAM
#pragma vertex vert
#pragma fragment fragSpotInside
#pragma target 3.5
#pragma exclude_renderers d3d9 gles
#define UNITY_HDR_ON
#pragma shader_feature HEIGHT_FOG
#pragma shader_feature NOISE
#pragma shader_feature SHADOWS_DEPTH
#pragma shader_feature SPOT
#ifdef SHADOWS_DEPTH
#define SHADOWS_NATIVE
#endif
fixed4 fragSpotInside(v2f i) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
float2 uv = i.uv.xy / i.uv.w;
#if defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED)
if(unity_StereoEyeIndex != _Eye)
return float4(0,0,0,0);
#endif
// read depth and reconstruct world position
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, UnityStereoScreenSpaceUVAdjust(uv,_CameraDepthTexture_ST));
float3 rayStart = _WorldSpaceCameraPos;
float3 rayEnd = i.wpos;
float3 rayDir = (rayEnd - rayStart);
float rayLength = length(rayDir);
rayDir /= rayLength;
float linearDepth = LinearEyeDepth(depth);
float projectedDepth = linearDepth / dot(_CameraForward, rayDir);
rayLength = min(rayLength, projectedDepth);
return RayMarch(i.pos.xy, rayStart, rayDir, rayLength);
}
ENDCG
}
// pass 2 - point light, camera outside
Pass
{
//ZTest Off
ZTest [_ZTest]
Cull Back
ZWrite Off
Blend One One
CGPROGRAM
#pragma vertex vert
#pragma fragment fragPointOutside
#pragma target 3.5
#pragma exclude_renderers d3d9 gles
#define UNITY_HDR_ON
#pragma shader_feature HEIGHT_FOG
#pragma shader_feature SHADOWS_CUBE
#pragma shader_feature NOISE
#pragma shader_feature POINT_COOKIE
#pragma shader_feature POINT
fixed4 fragPointOutside(v2f i) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
float2 uv = i.uv.xy / i.uv.w;
#if defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED)
if(unity_StereoEyeIndex != _Eye)
return float4(0,0,0,0);
#endif
// read depth and reconstruct world position
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, UnityStereoScreenSpaceUVAdjust(uv,_CameraDepthTexture_ST));
float3 rayStart = _WorldSpaceCameraPos;
float3 rayEnd = i.wpos;
float3 rayDir = (rayEnd - rayStart);
float rayLength = length(rayDir);
rayDir /= rayLength;
float3 lightToCamera = _WorldSpaceCameraPos - _LightPos;
float b = dot(rayDir, lightToCamera);
float c = dot(lightToCamera, lightToCamera) - (_VolumetricLight.z * _VolumetricLight.z);
float d = sqrt((b*b) - c);
float start = -b - d;
float end = -b + d;
float linearDepth = LinearEyeDepth(depth);
float projectedDepth = linearDepth / dot(_CameraForward, rayDir);
end = min(end, projectedDepth);
rayStart = rayStart + rayDir * start;
rayLength = end - start;
return RayMarch(i.pos.xy, rayStart, rayDir, rayLength);
}
ENDCG
}
// pass 3 - spot light, camera outside
Pass
{
//ZTest Off
ZTest[_ZTest]
Cull Back
ZWrite Off
Blend One One
CGPROGRAM
#pragma vertex vert
#pragma fragment fragSpotOutside
#pragma target 3.5
#pragma exclude_renderers d3d9 gles
#define UNITY_HDR_ON
#pragma shader_feature HEIGHT_FOG
#pragma shader_feature SHADOWS_DEPTH
#pragma shader_feature NOISE
#pragma shader_feature SPOT
#ifdef SHADOWS_DEPTH
#define SHADOWS_NATIVE
#endif
float _CosAngle;
float4 _ConeAxis;
float4 _ConeApex;
float _PlaneD;
fixed4 fragSpotOutside(v2f i) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
float2 uv = i.uv.xy / i.uv.w;
#if defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED)
if(unity_StereoEyeIndex != _Eye)
return float4(0,0,0,0);
#endif
// read depth and reconstruct world position
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, UnityStereoScreenSpaceUVAdjust(uv,_CameraDepthTexture_ST));
float3 rayStart = _WorldSpaceCameraPos;
float3 rayEnd = i.wpos;
float3 rayDir = (rayEnd - rayStart);
float rayLength = length(rayDir);
rayDir /= rayLength;
// inside cone
float3 r1 = rayEnd + rayDir * 0.001;
// plane intersection
float planeCoord = RayPlaneIntersect(_ConeAxis, _PlaneD, r1, rayDir);
// ray cone intersection
float2 lineCoords = RayConeIntersect(_ConeApex, _ConeAxis, _CosAngle, r1, rayDir);
float linearDepth = LinearEyeDepth(depth);
float projectedDepth = linearDepth / dot(_CameraForward, rayDir);
float z = (projectedDepth - rayLength);
rayLength = min(planeCoord, min(lineCoords.x, lineCoords.y));
rayLength = min(rayLength, z);
return RayMarch(i.pos.xy, rayEnd, rayDir, rayLength);
}
ENDCG
}
// pass 4 - directional light
Pass
{
ZTest Off
Cull Off
ZWrite Off
Blend One One, One Zero
CGPROGRAM
#pragma vertex vertDir
#pragma fragment fragDir
#pragma target 3.5
#pragma exclude_renderers d3d9 gles
#define UNITY_HDR_ON
#pragma shader_feature HEIGHT_FOG
#pragma shader_feature NOISE
#pragma shader_feature SHADOWS_DEPTH
#pragma shader_feature DIRECTIONAL_COOKIE
#pragma shader_feature DIRECTIONAL
#ifdef SHADOWS_DEPTH
#define SHADOWS_NATIVE
#endif
v2f vertDir(appdata_img v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_OUTPUT(v2f, o);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.pos = UnityObjectToClipPos(v.vertex);
//o.pos = v.vertex * float4(2,2,1,1) + float4(-1,-1,0,0);
o.uv.xy = v.texcoord.xy;
#if UNITY_UV_STARTS_AT_TOP
//o.uv.y = 1.0f - o.uv.y; //blit flips the uv for some reason
#endif
return o;
}
fixed4 fragDir(v2f i) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
float2 uv = i.uv.xy;
//return lerp(float4(1,0,0,1),float4(0,0,1,1),unity_StereoEyeIndex);
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv);
float4x4 proj, eyeToWorld;
if (unity_StereoEyeIndex == 0)
{
proj = _LeftViewFromScreen;
eyeToWorld = _LeftWorldFromView;
}
else
{
proj = _RightViewFromScreen;
eyeToWorld = _RightWorldFromView;
}
//bit of matrix math to take the screen space coord (u,v,depth) and transform to world space
float2 uvClip = i.uv * 2.0 - 1.0;
float clipDepth = depth; // Fix for OpenGl Core thanks to Lars Bertram
clipDepth = (UNITY_NEAR_CLIP_VALUE < 0) ? clipDepth * 2 - 1 : clipDepth;
float4 clipPos = float4(uvClip, clipDepth, 1.0);
float4 viewPos = mul(proj, clipPos); // inverse projection by clip position
viewPos /= viewPos.w; // perspective division
float3 wpos = mul(eyeToWorld, viewPos).xyz;
//float3 wpos = i.interpolatedRay + _WorldSpaceCameraPos;
float linearDepth = Linear01Depth(depth);
float3 rayStart = _WorldSpaceCameraPos;
float3 rayDir = wpos - _WorldSpaceCameraPos;
//rayDir *= linearDepth;
float rayLength = length(rayDir);
rayDir /= rayLength;
rayLength = min(rayLength, _MaxRayLength);
float4 color = RayMarch(i.pos.xy, rayStart, rayDir, rayLength);
if (linearDepth > 0.999999)
{
color.w = lerp(color.w, 1, _VolumetricLight.w);
}
return color;
}
ENDCG
}
// pass 5 - black
Pass
{
ZTest Off
Cull Off
ZWrite Off
Blend One One, One Zero
CGPROGRAM
#pragma vertex vertW
#pragma fragment fragW
#pragma target 3.5
#pragma exclude_renderers d3d9 gles
#ifdef SHADOWS_DEPTH
#define SHADOWS_NATIVE
#endif
v2f vertW(appdata_img i)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(i); //Insert
UNITY_INITIALIZE_OUTPUT(v2f, o); //Insert
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); //Ins
half index = i.vertex.z;
i.vertex.z = 0.1;
o.pos = UnityObjectToClipPos(i.vertex);
o.uv.xy = i.texcoord.xy;
return o;
}
fixed4 fragW(v2f i) : SV_Target
{
return float4(0,0,0,0);
}
ENDCG
}
}
}