您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

236 行
6.9 KiB

Shader "Hidden/HDRenderPipeline/EyeAdaptation"
{
Properties
{
_MainTex("Texture", any) = "" {}
}
HLSLINCLUDE
#pragma target 5.0
#include "Common.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderVariables.hlsl"
#include "EyeAdaptation.hlsl"
TEXTURE2D(_MainTex);
SAMPLER2D(sampler_MainTex);
float4 _Params; // x: lowPercent, y: highPercent, z: minBrightness, w: maxBrightness
float2 _Speed; // x: down, y: up
float4 _ScaleOffsetRes; // x: scale, y: offset, w: histogram pass width, h: histogram pass height
float _ExposureCompensation;
StructuredBuffer<uint> _Histogram;
float GetBinValue(uint index, float maxHistogramValue)
{
return float(_Histogram[index]) * maxHistogramValue;
}
float FindMaxHistogramValue()
{
uint maxValue = 0u;
for (uint i = 0; i < HISTOGRAM_BINS; i++)
{
uint h = _Histogram[i];
maxValue = max(maxValue, h);
}
return float(maxValue);
}
void FilterLuminance(uint i, float maxHistogramValue, inout float4 filter)
{
float binValue = GetBinValue(i, maxHistogramValue);
// Filter dark areas
float offset = min(filter.z, binValue);
binValue -= offset;
filter.zw -= offset.xx;
// Filter highlights
binValue = min(filter.w, binValue);
filter.w -= binValue;
// Luminance at the bin
float luminance = GetLuminanceFromHistogramBin(float(i) / float(HISTOGRAM_BINS), _ScaleOffsetRes.xy);
filter.xy += float2(luminance * binValue, binValue);
}
float GetAverageLuminance(float maxHistogramValue)
{
// Sum of all bins
uint i;
float totalSum = 0.0;
[loop]
for (i = 0; i < HISTOGRAM_BINS; i++)
totalSum += GetBinValue(i, maxHistogramValue);
// Skip darker and lighter parts of the histogram to stabilize the auto exposure
// x: filtered sum
// y: accumulator
// zw: fractions
float4 filter = float4(0.0, 0.0, totalSum * _Params.xy);
[loop]
for (i = 0; i < HISTOGRAM_BINS; i++)
FilterLuminance(i, maxHistogramValue, filter);
// Clamp to user brightness range
return clamp(filter.x / max(filter.y, 1.0e-4), _Params.z, _Params.w);
}
float GetExposureMultiplier(float avgLuminance)
{
avgLuminance = max(1.0e-4, avgLuminance);
//half keyValue = 1.03 - (2.0 / (2.0 + log2(avgLuminance + 1.0)));
half keyValue = _ExposureCompensation;
half exposure = keyValue / avgLuminance;
return exposure;
}
float InterpolateExposure(float newExposure, float oldExposure)
{
float delta = newExposure - oldExposure;
float speed = delta > 0.0 ? _Speed.x : _Speed.y;
float exposure = oldExposure + delta * (1.0 - exp2(-unity_DeltaTime.x * speed));
//float exposure = oldExposure + delta * (unity_DeltaTime.x * speed);
return exposure;
}
struct Attributes
{
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
};
struct Varyings
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
Varyings Vert(Attributes v)
{
Varyings o;
o.pos = TransformWorldToHClip(v.vertex.xyz);
o.uv = v.texcoord.xy;
return o;
}
float4 FragAdaptProgressive(Varyings i) : SV_Target
{
float maxValue = 1.0 / FindMaxHistogramValue();
float avgLuminance = GetAverageLuminance(maxValue);
float exposure = GetExposureMultiplier(avgLuminance);
float prevExposure = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, (0.5).xx).r;
exposure = InterpolateExposure(exposure, prevExposure);
return exposure.xxxx;
}
float4 FragAdaptFixed(Varyings i) : SV_Target
{
float maxValue = 1.0 / FindMaxHistogramValue();
float avgLuminance = GetAverageLuminance(maxValue);
float exposure = GetExposureMultiplier(avgLuminance);
return exposure.xxxx;
}
// Editor stuff (histogram debug visualization)
int _DebugWidth;
struct VaryingsEditorHisto
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float maxValue : TEXCOORD1;
float avgLuminance : TEXCOORD2;
};
VaryingsEditorHisto VertEditorHisto(Attributes v)
{
VaryingsEditorHisto o;
o.pos = TransformWorldToHClip(v.vertex.xyz);
o.uv = v.texcoord.xy;
o.maxValue = 1.0 / FindMaxHistogramValue();
o.avgLuminance = GetAverageLuminance(o.maxValue);
return o;
}
float4 FragEditorHisto(VaryingsEditorHisto i) : SV_Target
{
const float3 kRangeColor = float3(0.05, 0.4, 0.6);
const float3 kAvgColor = float3(0.8, 0.3, 0.05);
float4 color = float4(0.0, 0.0, 0.0, 0.7);
uint ix = (uint)(round(i.uv.x * HISTOGRAM_BINS));
float bin = saturate(float(_Histogram[ix]) * i.maxValue);
float fill = step(i.uv.y, bin);
// Min / max brightness markers
float luminanceMin = GetHistogramBinFromLuminance(_Params.z, _ScaleOffsetRes.xy);
float luminanceMax = GetHistogramBinFromLuminance(_Params.w, _ScaleOffsetRes.xy);
color.rgb += fill.rrr;
if (i.uv.x > luminanceMin && i.uv.x < luminanceMax)
{
color.rgb = fill.rrr * kRangeColor;
color.rgb += kRangeColor;
}
// Current average luminance marker
float luminanceAvg = GetHistogramBinFromLuminance(i.avgLuminance, _ScaleOffsetRes.xy);
float avgPx = luminanceAvg * _DebugWidth;
if (abs(i.pos.x - avgPx) < 2)
color.rgb = kAvgColor;
return color;
}
ENDHLSL
SubShader
{
Cull Off ZWrite Off ZTest Always
Pass
{
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment FragAdaptProgressive
ENDHLSL
}
Pass
{
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment FragAdaptFixed
ENDHLSL
}
Pass
{
HLSLPROGRAM
#pragma vertex VertEditorHisto
#pragma fragment FragEditorHisto
ENDHLSL
}
}
Fallback Off
}