261 lines
9.6 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}
}
}