436 lines
12 KiB
HLSL
436 lines
12 KiB
HLSL
// Upgrade NOTE: replaced 'UNITY_PASS_TEXCUBE(unity_SpecCube1)' with 'UNITY_PASS_TEXCUBE_SAMPLER(unity_SpecCube1,unity_SpecCube0)'
|
|
|
|
|
|
float Test_;
|
|
|
|
struct appdata
|
|
{
|
|
float4 vertex : POSITION;
|
|
float3 normal : NORMAL0;
|
|
float2 uv : TEXCOORD0;
|
|
float2 uv2 : TEXCOORD1;
|
|
float2 uv3 : TEXCOORD2;
|
|
float2 uv4 : TEXCOORD3;
|
|
float2 uv5 : TEXCOORD4;
|
|
float4 Color : COLOR;
|
|
uint id : SV_VertexID;
|
|
float4 tangent : TANGENT;
|
|
};
|
|
|
|
|
|
|
|
float FresnelDispersionPower;
|
|
float FresnelDispersionScale;
|
|
float ColorByDepth;
|
|
|
|
float CentreIntensity;
|
|
float4x4 MatrixWorldToObject;
|
|
float4x4 MatrixWorldToObject2;
|
|
float4 CentreModel;
|
|
float lightEstimation2;
|
|
float MipLevel;
|
|
|
|
samplerCUBE _Environment;
|
|
half4 _Environment_HDR;
|
|
float FixedlightEstimation;
|
|
float ColorIntensity;
|
|
struct v2f
|
|
{
|
|
float2 uv : TEXCOORD0;
|
|
float2 uv2 : TEXCOORD1;
|
|
float2 uv3 : TEXCOORD2;
|
|
float3 WorldBitangent : TEXCOORD3;
|
|
float3 WorldNormal : TEXCOORD4;
|
|
float4 vertex : SV_POSITION0;
|
|
float3 Pos : TEXCOORD5;
|
|
float3 Pos2 : TEXCOORD6;
|
|
float3 Normal : NORMAL0;
|
|
float4 Color : COLOR;
|
|
uint id : TEXCOORD7;
|
|
float3 worldPos : TEXCOORD8;
|
|
float4 tangent : TEXCOORD9;
|
|
};
|
|
|
|
// vertex shader
|
|
v2f vert (appdata v)
|
|
{
|
|
v2f o;
|
|
UNITY_INITIALIZE_OUTPUT(v2f, o);
|
|
|
|
float3 _worldTangent = UnityObjectToWorldDir(v.tangent);
|
|
o.tangent.xyz = _worldTangent;
|
|
float3 _worldNormal = UnityObjectToWorldNormal(v.normal);
|
|
o.WorldNormal.xyz = _worldNormal;
|
|
float _vertexTangentSign = v.tangent.w * unity_WorldTransformParams.w;
|
|
float3 _worldBitangent = cross(_worldNormal, _worldTangent) * _vertexTangentSign;
|
|
o.WorldBitangent.xyz = _worldBitangent;
|
|
|
|
float4 pos = v.vertex;
|
|
|
|
pos.xyz = (pos.xyz - CentreModel.xyz);
|
|
|
|
float3 cameraLocalPos;
|
|
|
|
cameraLocalPos = mul(MatrixWorldToObject, float4(_WorldSpaceCameraPos, 1));
|
|
|
|
o.Pos2 = cameraLocalPos;
|
|
|
|
o.vertex = UnityObjectToClipPos(v.vertex);
|
|
o.uv = v.uv;
|
|
o.uv2 = v.uv2;
|
|
o.uv3 = v.uv3;
|
|
o.Pos = float4(pos.xyz, 1);
|
|
o.Normal = v.normal;
|
|
o.Color = v.Color;
|
|
o.id = v.id;
|
|
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
|
|
return o;
|
|
}
|
|
|
|
|
|
float Dispersion;
|
|
|
|
float DispersionLimitedAngle;
|
|
|
|
float DispersionR;
|
|
float DispersionG;
|
|
float DispersionB;
|
|
float Brightness;
|
|
float Power;
|
|
|
|
|
|
|
|
float DispersionIntensity;
|
|
sampler2D _ShapeTex;
|
|
float _Scale;
|
|
float TotalInternalReflection;
|
|
int _SizeX;
|
|
int _SizeY;
|
|
int _PlaneCount;
|
|
int _MaxReflection;
|
|
|
|
samplerCUBE ReflectionCube;
|
|
// samplerCUBE _Environment;
|
|
// half4 _Environment_HDR;
|
|
float _RefractiveIndex;
|
|
float _RefractiveIndex_;
|
|
float _BaseReflection;
|
|
#define MAX_REFLECTION (10)
|
|
|
|
float random(float2 st)
|
|
{
|
|
float r = frac(sin(dot(st.xy,float2(12.9898, 78.233)))* 43758.5453123);
|
|
return r * clamp(pow(distance(r, 0.6), 2.5) * 100, 0, 1);
|
|
}
|
|
|
|
float CalcReflectionRate(float3 normal, float3 ray, float baseReflection, float borderDot)
|
|
{
|
|
|
|
float normalizedDot = clamp((abs(dot(normal, ray)) - borderDot) / (1.0 - borderDot), 0.0, 1.0);
|
|
return baseReflection + (1.0-baseReflection)*pow(1.0-normalizedDot, 5);
|
|
}
|
|
|
|
|
|
half rgb2hsv(half3 c)
|
|
{
|
|
half4 K = half4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
|
half4 p = lerp(half4(c.bg, K.wz), half4(c.gb, K.xy), step(c.b, c.g));
|
|
half4 q = lerp(half4(p.xyw, c.r), half4(c.r, p.yzx), step(p.x, c.r));
|
|
|
|
float d = q.x - min(q.w, q.y);
|
|
float e = 1.0e-10;
|
|
return abs(q.z + (q.w - q.y) / (6.0 * d + e));
|
|
}
|
|
|
|
float Remap(float value, float min1, float max1, float min2, float max2)
|
|
{
|
|
return (min2 + (value - min1) * (max2 - min2) / (max1 - min1));
|
|
}
|
|
|
|
float4 GetUnpackedPlaneByIndex(uint index)
|
|
{
|
|
int x_index = index % _SizeX;
|
|
int y_index = index / _SizeX;
|
|
|
|
float ustride = 1.0 / _SizeX;
|
|
float vstride = 1.0 / _SizeY;
|
|
|
|
float2 uv = float2((0.5+x_index)*ustride, (0.5+y_index)*vstride);
|
|
|
|
float4 packedPlane = tex2D(_ShapeTex, uv);
|
|
|
|
#if !defined(UNITY_COLORSPACE_GAMMA)
|
|
packedPlane.xyz = LinearToGammaSpace(packedPlane.xyz);
|
|
#endif
|
|
|
|
float3 normal = packedPlane.xyz*2 - float3(1,1,1); // смена диапозона
|
|
|
|
return float4(normal, packedPlane.w*_Scale);
|
|
}
|
|
|
|
|
|
float CheckCollideRayWithPlane(float3 rayStart, float3 rayNormalized, float4 normalTriangle) // plane - normal.xyz и normal.w - distance
|
|
{
|
|
float dp = dot(rayNormalized, normalTriangle.xyz);
|
|
if( dp < 0 )
|
|
{
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
float distanceNormalized = normalTriangle.w - dot(rayStart.xyz, normalTriangle.xyz);
|
|
if( distanceNormalized < 0 )
|
|
{
|
|
return -1;
|
|
}
|
|
return distanceNormalized / dp;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
void CollideRayWithPlane(float3 Pos, float PassCount, float3 rayNormalized, float4 TriangleNormal, float startSideRelativeRefraction, out float reflectionRate, out float reflectionRate2, out float3 reflection, out float3 refraction, out float HorizontalElementSquared)
|
|
{
|
|
float3 rayVertical = dot(TriangleNormal.xyz, rayNormalized) * TriangleNormal.xyz;
|
|
reflection = rayNormalized - rayVertical*2.0;
|
|
|
|
|
|
float3 rayHorizontal = rayNormalized - rayVertical;
|
|
|
|
float3 refractHorizontal = rayHorizontal * startSideRelativeRefraction ;
|
|
|
|
float horizontalElementSquared = dot(refractHorizontal, refractHorizontal);
|
|
|
|
float borderDot = 0;
|
|
|
|
|
|
if( startSideRelativeRefraction > 1.0 )
|
|
{
|
|
borderDot = sqrt(1.0-1.0f/(startSideRelativeRefraction*startSideRelativeRefraction));
|
|
}
|
|
else
|
|
{
|
|
borderDot = 0.0;
|
|
}
|
|
|
|
HorizontalElementSquared = 0;
|
|
|
|
|
|
|
|
HorizontalElementSquared = horizontalElementSquared /3;
|
|
if (horizontalElementSquared >= TotalInternalReflection)
|
|
{
|
|
HorizontalElementSquared = 0;
|
|
reflectionRate = 1.0;
|
|
reflectionRate2 = 1.0;
|
|
refraction = TriangleNormal.xyz;
|
|
|
|
return;
|
|
}
|
|
|
|
float verticalSizeSquared = 1-horizontalElementSquared;
|
|
float3 refractVertical = rayVertical * sqrt( verticalSizeSquared / dot(rayVertical, rayVertical));
|
|
|
|
|
|
refraction = refractHorizontal + refractVertical;
|
|
reflectionRate = CalcReflectionRate(rayNormalized, TriangleNormal.xyz, _BaseReflection * PassCount, borderDot);
|
|
reflectionRate2 =0;// CalcReflectionRate(rayNormalized, TriangleNormal.xyz, _BaseReflection * PassCount, borderDot);
|
|
return;
|
|
}
|
|
|
|
float3 CalcColorCoefByDistance(float distance,float4 Color)
|
|
{
|
|
return lerp(pow(max(Color.xyz, 0.01), distance * Color.w), Color.rgb, ColorByDepth);
|
|
|
|
}
|
|
|
|
float4 SampleEnvironment(float3 rayLocal)
|
|
{
|
|
float3 rayWorld = mul(unity_ObjectToWorld, float4(rayLocal, 0));
|
|
|
|
rayWorld = normalize(rayWorld);
|
|
|
|
|
|
#if _CUBEMAPMODE_CUBEMAP
|
|
float4 tex = texCUBElod(_Environment, float4(rayWorld,MipLevel));
|
|
return float4(DecodeHDR(tex, _Environment_HDR), 1);
|
|
|
|
#endif
|
|
|
|
#if _CUBEMAPMODE_REFLECTIONPROBE
|
|
float4 tex = UNITY_SAMPLE_TEXCUBE_LOD(unity_SpecCube0,rayWorld, MipLevel);
|
|
return float4(DecodeHDR(tex, unity_SpecCube0_HDR), 1);
|
|
#endif
|
|
|
|
}
|
|
|
|
void CheckCollideRayWithAllPlanes(float3 rayStart, float3 rayDirection, out float4 hitPlane, out float hitTime)
|
|
{
|
|
hitTime=1000000.0;
|
|
hitPlane=float4(1,0,0,1);
|
|
//[unroll(20)]
|
|
for(int i=0; i<_PlaneCount; ++i)
|
|
{
|
|
float4 plane = GetUnpackedPlaneByIndex(i);
|
|
float tmpTime = CheckCollideRayWithPlane(rayStart, rayDirection, plane);
|
|
|
|
if(tmpTime >= -0.001 && tmpTime<hitTime)
|
|
{
|
|
hitTime = tmpTime;
|
|
hitPlane = plane;
|
|
}
|
|
}
|
|
}
|
|
|
|
float4 GetColorByRay(float3 rayStart, float3 rayDirection, float refractiveIndex, int MaxReflection, float4 Color, float lighttransmission)
|
|
{
|
|
float3 tmpRayStart = rayStart;
|
|
float3 tmpRayDirection = rayDirection;
|
|
float reflectionRates[MAX_REFLECTION];
|
|
float reflectionRates2[MAX_REFLECTION];
|
|
float4 refractionColors[MAX_REFLECTION];
|
|
float4 refractionColors2[MAX_REFLECTION];
|
|
float4 refractionColors3[MAX_REFLECTION];
|
|
float4 depthColors[MAX_REFLECTION];
|
|
|
|
int loopCount = min(MAX_REFLECTION, _MaxReflection);
|
|
|
|
int badRay = 0;
|
|
|
|
// [unroll(10)]
|
|
for( int i = 0; i<loopCount; ++i )
|
|
{
|
|
float hitTime=1000000.0;
|
|
float4 hitPlane=float4(1,0,0,1);
|
|
CheckCollideRayWithAllPlanes(tmpRayStart, tmpRayDirection, hitPlane, hitTime);
|
|
|
|
if (hitTime < 0.0)
|
|
{
|
|
badRay = 1;
|
|
}
|
|
|
|
float3 rayEnd = tmpRayStart + tmpRayDirection*hitTime;
|
|
|
|
float reflectionRate;
|
|
float reflectionRate2;
|
|
float3 reflectionRay;
|
|
float3 refractionRay;
|
|
float PlaneNull;
|
|
|
|
float i_Pass = i;
|
|
|
|
if (i_Pass >= 2)
|
|
{
|
|
i_Pass = 0;
|
|
|
|
}
|
|
|
|
if (i_Pass < 2)
|
|
{
|
|
i_Pass = 1;
|
|
|
|
}
|
|
|
|
|
|
CollideRayWithPlane(rayStart, i_Pass, tmpRayDirection, hitPlane, refractiveIndex, reflectionRate,reflectionRate2, reflectionRay, refractionRay, PlaneNull);
|
|
|
|
reflectionRates[i] = reflectionRate;
|
|
|
|
reflectionRates2[i] = reflectionRate2;
|
|
|
|
float3 _worldViewDir = UnityWorldSpaceViewDir(rayStart.xyz);
|
|
_worldViewDir = normalize(_worldViewDir);
|
|
|
|
float fresnelNdotV5 = dot(tmpRayStart, _worldViewDir);
|
|
float fresnelNode5 = (FresnelDispersionScale * pow(1.0 - fresnelNdotV5, FresnelDispersionPower));
|
|
|
|
fresnelNode5 = 1;
|
|
|
|
DispersionR = DispersionR * Dispersion * fresnelNode5;
|
|
DispersionG = DispersionG * Dispersion * fresnelNode5;
|
|
DispersionB = DispersionB * Dispersion * fresnelNode5;
|
|
|
|
|
|
float3 DispersionRay_r = lerp(refractionRay, lerp(rayEnd, refractionRay,2), DispersionR * PlaneNull);
|
|
|
|
float3 DispersionRay_g = lerp(refractionRay, lerp(rayEnd, refractionRay, 2), DispersionG * PlaneNull);
|
|
|
|
float3 DispersionRay_b = lerp(refractionRay, lerp(rayEnd, refractionRay, 2), DispersionB * PlaneNull);
|
|
|
|
refractionColors3[i] = SampleEnvironment(refractionRay);
|
|
|
|
refractionColors2[i] = 1;
|
|
|
|
refractionColors2[i].r = SampleEnvironment(DispersionRay_r).r;
|
|
refractionColors2[i].g = SampleEnvironment(DispersionRay_g).g;
|
|
refractionColors2[i].b = SampleEnvironment(DispersionRay_b).b;
|
|
|
|
Color.rgb = lerp(1, Color, ColorIntensity).rgb;
|
|
|
|
depthColors[i] = float4(CalcColorCoefByDistance(hitTime, lerp(Color, 1, lerp(0, (refractionColors3[i].r + refractionColors3[i].g + refractionColors3[i].b) / 2, lighttransmission))), 1);
|
|
|
|
refractionColors2[i] = clamp(lerp(refractionColors3[i], refractionColors2[i], DispersionIntensity),0,1);
|
|
|
|
refractionColors[i] = SampleEnvironment(refractionRay);
|
|
|
|
if (i == loopCount - 1)
|
|
{
|
|
reflectionRates[i] = 0.0;
|
|
reflectionRates2[i] = 0.0;
|
|
}
|
|
|
|
tmpRayStart = tmpRayStart + tmpRayDirection * hitTime;
|
|
tmpRayDirection = reflectionRay;
|
|
}
|
|
|
|
float4 tmpReflectionColor = float4(0, 0, 0, 0);
|
|
|
|
for (int j = loopCount - 1; j >= 0; --j)
|
|
{
|
|
|
|
tmpReflectionColor = lerp(refractionColors2[j], tmpReflectionColor, reflectionRates[j]) * depthColors[j];
|
|
tmpReflectionColor = pow(tmpReflectionColor * Brightness, Power);
|
|
|
|
}
|
|
|
|
if (badRay > 0)
|
|
{
|
|
return float4(1, 0, 0, 1);
|
|
}
|
|
|
|
return tmpReflectionColor;
|
|
}
|
|
|
|
|
|
float4 CalculateContrast(float contrastValue, float4 colorTarget)
|
|
{
|
|
float t = 0.5 * (1.0 - contrastValue);
|
|
return mul(float4x4(contrastValue, 0, 0, t, 0, contrastValue, 0, t, 0, 0, contrastValue, t, 0, 0, 0, 1), colorTarget);
|
|
}
|
|
//曝光、饱和、对比调整颜色
|
|
float4 ToneMap(float4 MainColor, float brightness, float Disaturate, float _max, float _min, float contrast, float Satur)
|
|
{
|
|
fixed4 output = MainColor;
|
|
output = output * brightness;
|
|
output = CalculateContrast(contrast, output);
|
|
|
|
float4 disatur = dot(output, float3(0.299, 0.587, 0.114)); // Desaturate
|
|
output = lerp(output, disatur, clamp(pow(((output.x + output.y + output.z) / 3) * Disaturate, 1.3), 0, 1));
|
|
output.x = clamp(Remap(output.x, 0, 1, _min, lerp(_max, 1, 0.5)), 0, 1.5);
|
|
output.y = clamp(Remap(output.y, 0, 1, _min, lerp(_max, 1, 0.5)), 0, 1.5);
|
|
output.z = clamp(Remap(output.z, 0, 1, _min, lerp(_max, 1, 0.5)), 0, 1.5);
|
|
|
|
output = pow(output, contrast);
|
|
|
|
output = lerp(clamp(output, 0, _max), output, pow(_max, 4));
|
|
|
|
output = lerp(smoothstep(output, -0.1, 0.25), output, (1 - distance(1, _max) * 2));
|
|
|
|
output = lerp(dot(output, float3(0.299, 0.587, 0.114)), output, Satur);
|
|
|
|
output = output * lerp(brightness, 1, 0.75);
|
|
|
|
return output;
|
|
|
|
|
|
} |