261 lines
9.6 KiB
Plaintext
261 lines
9.6 KiB
Plaintext
Shader "Unlit/volumeLight"
|
||
{
|
||
Properties {
|
||
_MainTex ("Base (RGB)", 2D) = "white" {}
|
||
}
|
||
|
||
SubShader
|
||
{
|
||
Tags { "RenderType"="Opaque" }
|
||
LOD 100
|
||
HLSLINCLUDE
|
||
|
||
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS //接受阴影
|
||
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE //产生阴影
|
||
#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
|
||
#pragma multi_compile _ _SHADOWS_SOFT //软阴影
|
||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"
|
||
//#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
|
||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
|
||
TEXTURE2D( _MainTex);
|
||
SAMPLER(sampler_MainTex);
|
||
TEXTURE2D( _LightMar); SAMPLER(sampler_LightMar);
|
||
float4 _MainTex_TexelSize;
|
||
float4 _MainTex_ST;
|
||
//步进次数
|
||
int _StepCount;
|
||
//最大步进距离
|
||
float _MaxStepDest;
|
||
static half dither[16] = {
|
||
1.0 / 17.0, 9.0 / 17.0, 3.0 / 17.0, 11.0 / 17.0,
|
||
13.0 / 17.0, 5.0 / 17.0, 15.0 / 17.0, 7.0 / 17.0,
|
||
4.0 / 17.0, 12.0 / 17.0, 2.0 / 17.0, 10.0 / 17.0,
|
||
16.0 / 17.0, 8.0 / 17.0, 14.0 / 17.0, 6.0 / 17.0
|
||
};
|
||
|
||
struct Attributes
|
||
{
|
||
float4 positionOS : POSITION;
|
||
float2 uv : TEXCOORD0;
|
||
};
|
||
|
||
struct Varyings
|
||
{
|
||
float4 positionCS : SV_POSITION;
|
||
float2 uv : TEXCOORD0;
|
||
};
|
||
float Remap(float x,float inMin,float inMax,float toMin,float toMax)
|
||
{
|
||
return (x-inMin)/(inMax-inMin)*(toMax-toMin)+toMin;
|
||
}
|
||
Varyings vert(Attributes v)
|
||
{
|
||
Varyings o = (Varyings)0;
|
||
o.positionCS = TransformObjectToHClip(v.positionOS.xyz);
|
||
o.uv =v.uv; //TRANSFORM_TEX(v.uv, _MainTex);
|
||
return o;
|
||
}
|
||
float _Strength;
|
||
half4 fragBlend(Varyings i) : SV_Target
|
||
{
|
||
float4 color= SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex, i.uv);
|
||
float4 light= SAMPLE_TEXTURE2D(_LightMar,sampler_LightMar, i.uv);
|
||
color=color*light*2*_Strength+color+light*0.1*_Strength;
|
||
return color;
|
||
}
|
||
float space_sigma;
|
||
float range_sigma ;
|
||
//高斯模糊->双边过滤
|
||
half4 fragBlur(Varyings input) : SV_Target
|
||
{
|
||
float weight_sum = 0;
|
||
float3 color_sum = 0;
|
||
float3 color_origin = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv);
|
||
float3 color = 0;
|
||
//float space_sigma=2;
|
||
//float range_sigma =5;
|
||
for(int i = -3; i < 3; i++){
|
||
for(int j = -3; j < 3; j++){
|
||
//空域高斯-uv加权
|
||
float2 varible = input.uv + float2(i * _MainTex_TexelSize.x, j * _MainTex_TexelSize.y)*3;
|
||
float space_factor = i * i + j * j;
|
||
space_factor = (-space_factor) / (2 * space_sigma* space_sigma);
|
||
float space_weight = 1/(space_sigma * space_sigma * 2 * PI) * exp(space_factor);
|
||
|
||
//值域高斯-颜色加权
|
||
float3 color_neighbor = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, varible);
|
||
float3 color_distance = (color_neighbor - color_origin);
|
||
float value_factor = color_distance.r * color_distance.r ;
|
||
value_factor = (-value_factor) / (2 * range_sigma * range_sigma);
|
||
float value_weight = (1 / (2 * PI * range_sigma)) * exp(value_factor);
|
||
|
||
weight_sum += space_weight * value_weight;
|
||
color_sum += color_neighbor * space_weight * value_weight;
|
||
}
|
||
}
|
||
color=lerp(color,color_sum / weight_sum,step(0,weight_sum));
|
||
return float4(color,1);
|
||
}
|
||
half4 fragBlurFast(Varyings i) : SV_Target
|
||
{
|
||
|
||
float2 size=_MainTex_TexelSize.xy*1;
|
||
float4 result=(SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex, i.uv+int2(1,1)*size)+
|
||
SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex, i.uv+int2(-1,-1)*size)+
|
||
SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex, i.uv+int2(-1,1)*size)+
|
||
SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex, i.uv+int2(1,-1)*size));
|
||
|
||
return result*0.25;
|
||
}
|
||
half4 fragBlurFast2(Varyings i) : SV_Target
|
||
{
|
||
float2 size=_MainTex_TexelSize.xy*1;
|
||
float4 result=(SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex, i.uv+int2(0,1)*size)+
|
||
SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex, i.uv+int2(0,-1)*size)+
|
||
SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex, i.uv+int2(-1,0)*size)+
|
||
SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex, i.uv+int2(1,0)*size));
|
||
return result*0.25;
|
||
}
|
||
float Getshadow(float3 posWorld)
|
||
{
|
||
float4 shadowCoord = TransformWorldToShadowCoord(posWorld);
|
||
float shadow = MainLightRealtimeShadow(shadowCoord);
|
||
return shadow;
|
||
}
|
||
//AABB包围盒,一个射线可以得到,打到以某一点为中心的xyz平面上的新射线点
|
||
float2 rayBoxDst(float3 boundsMin,float3 boundsMax,float3 rayOrigin ,float3 rayDir)
|
||
{
|
||
//t是分正负方向的
|
||
float3 t0 = (boundsMin - rayOrigin) / rayDir;
|
||
float3 t1 = (boundsMax - rayOrigin) / rayDir;
|
||
float3 tmin = min(t0, t1);
|
||
float3 tmax = max(t0, t1);
|
||
//左右上下的面因取最小值得到的都是负值,必然取到正面的值
|
||
float dstA = max(max(tmin.x, tmin.y), tmin.z);
|
||
float dstB = min(tmax.x, min(tmax.y, tmax.z));
|
||
float dstToBox = max(0, dstA);
|
||
float dstInsideBox = max(0, dstB - dstToBox);
|
||
//返回摄像机到包围盒的距离,穿过包围盒内部的距离
|
||
return float2(dstToBox, dstInsideBox);
|
||
}
|
||
float RandomRange(float2 Seed, float Min, float Max)
|
||
{
|
||
float randomno = frac(sin(dot(Seed, float2(12.9898, 78.233)))*43758.5453);
|
||
float Out = lerp(Min, Max, randomno);
|
||
return Out;
|
||
}
|
||
float3 _BoundMin;
|
||
float3 _BoundMax;
|
||
float _J;
|
||
half4 frag (Varyings i) : SV_Target
|
||
{
|
||
|
||
|
||
_J=24;
|
||
|
||
float depth=SampleSceneDepth(i.uv);
|
||
float3 wpos=ComputeWorldSpacePosition(i.uv, depth,UNITY_MATRIX_I_VP);
|
||
//世界空间下从当前点指向摄像机的方向
|
||
float3 dir= normalize(_WorldSpaceCameraPos-wpos);
|
||
float l1=length(_WorldSpaceCameraPos-wpos);
|
||
float2 result=rayBoxDst(_BoundMin,_BoundMax,_WorldSpaceCameraPos.xyz,-dir);
|
||
float dstToBox=result.x;
|
||
float dstInSideBox=result.y;
|
||
//主要dir的方向不然得到的点是错的
|
||
float3 startPos=_WorldSpaceCameraPos.xyz-dir*dstToBox-dir*dstInSideBox;
|
||
//float3 endPos=_WorldSpaceCameraPos.xyz-dir*dstToBox.x;
|
||
float l2=dstToBox+dstInSideBox;
|
||
|
||
|
||
uint index = (uint(i.uv.x*_ScreenSize.x) % 4) * 4 + uint(i.uv.y*_ScreenSize.y) % 4;
|
||
float jitter =Remap( dither[index],0,1,0.5,1);//*RandomRange(i.uv,0.96,1.04)
|
||
//在AABB包围盒中就使用固定间隔步进,按固定次数步进(视觉效果比按固定距离步进性能更好)
|
||
float d=0;
|
||
|
||
float3 currpos=0;
|
||
int Count=24;
|
||
if(l1>l2)
|
||
{
|
||
d=dstInSideBox/_J*RandomRange(i.uv,0.97,1.03);//*RandomRange(i.uv,0.96,1.04);
|
||
Count=dstInSideBox/d;
|
||
currpos=startPos;
|
||
}
|
||
else
|
||
{
|
||
float l=l1-dstToBox;
|
||
d=l/_J*RandomRange(i.uv,0.97,1.03);//*RandomRange(i.uv,0.96,1.04);
|
||
Count=l/d;
|
||
currpos=wpos;
|
||
}
|
||
//穿过AABB包围盒的距离为0时说明光线没有穿过体积光区域,不需要进行后续计算
|
||
if( dstToBox>l1 || dstInSideBox==0) return 0;
|
||
float total=0;
|
||
|
||
UNITY_LOOP
|
||
for(int j=0;j<Count;j++)
|
||
{
|
||
//if(length(currpos-_WorldSpaceCameraPos)<0.01 || total>1) break;
|
||
float shadow=Getshadow(currpos);
|
||
total+=shadow*1/Count;
|
||
//添加抖动
|
||
uint index = (uint(i.uv.x*_ScreenSize.x) % 4) * 4 + uint(i.uv.y*_ScreenSize.y) % 4;
|
||
float jitter = Remap( dither[index],0,1,0.5,1);//dither[index];
|
||
currpos+=dir*d;//*jitter;
|
||
}
|
||
|
||
//total=saturate(total)*pow(min(dstInSideBox*0.3,2),1);
|
||
total=(total/5*Count*d);
|
||
total=min(total,4);
|
||
return total.xxxx;
|
||
|
||
}
|
||
|
||
|
||
|
||
ENDHLSL
|
||
//光线步进
|
||
Pass
|
||
{
|
||
HLSLPROGRAM
|
||
#pragma vertex vert
|
||
#pragma fragment frag
|
||
ENDHLSL
|
||
}
|
||
//高斯模糊-双边过滤
|
||
Pass
|
||
{
|
||
HLSLPROGRAM
|
||
#pragma vertex vert
|
||
#pragma fragment fragBlur
|
||
ENDHLSL
|
||
}
|
||
//合并
|
||
Pass
|
||
{
|
||
HLSLPROGRAM
|
||
#pragma vertex vert
|
||
#pragma fragment fragBlend
|
||
ENDHLSL
|
||
}
|
||
//快速模糊
|
||
Pass
|
||
{
|
||
HLSLPROGRAM
|
||
#pragma vertex vert
|
||
#pragma fragment fragBlurFast
|
||
ENDHLSL
|
||
}
|
||
//快速模糊
|
||
Pass
|
||
{
|
||
HLSLPROGRAM
|
||
#pragma vertex vert
|
||
#pragma fragment fragBlurFast2
|
||
ENDHLSL
|
||
}
|
||
|
||
|
||
}
|
||
}
|