I want to know how to achieve persistent storage of textures.

  • BlueGary
  • Topic Author
More
5 days 18 hours ago #1 by BlueGary I want to know how to achieve persistent storage of textures. was created by BlueGary
When writing shaders, I ran into a problem: I found that textures get initialized every frame. I want to know how to achieve persistent storage for textures and ensure they are not initialized at the beginning or end of the frame.
/*
 * SCAC
 * 屏幕颜色自动校准
 * Screen colour automatic calibration
 * by 灰灰蓝 [email protected]
 * version 0.01 Create at 2025/12/13
 * TODO 添加亮度极值平滑系统。
 */
#include "ReShadeUI.fxh"
uniform float3 RGB_offset < __UNIFORM_SLIDER_FLOAT3
    ui_min = -1.0; ui_max = 1.0;
    ui_label = "RGB offset";
    ui_tooltip = "对颜色进行偏移,校准黑位/Adjust offset for color to calibrate the black level.";
> = float3(0.0, 0.0, 0.0);
uniform float3 RGB_Gamma < __UNIFORM_SLIDER_FLOAT3
    ui_min = 0.0; ui_max = 2.0;
    ui_label = "RGB Gamma";
    ui_tooltip = "对颜色进行幂乘,调整整体明暗/Adjust midtones for color.";
> = float3(1.0, 1.0, 1.0);
uniform float3 RGB_Gain < __UNIFORM_SLIDER_FLOAT3
    ui_min = 0.0; ui_max = 2.0;
    ui_label = "RGB Gain";
    ui_tooltip = "对颜色进行乘数,校准白位/Multiply the color to calibrate the white point.";
> = float3(1.0, 1.0, 1.0);
uniform float3 RGB_Contrast < __UNIFORM_SLIDER_FLOAT3
    ui_min = 0.0; ui_max = 2.0;
    ui_label = "RGB Contrast";
    ui_tooltip = "对颜色进行对称双曲线,修改对比度/Apply symmetrical hyperbola to colors and adjust contrast.";
> = float3(1.0, 1.0, 1.0);
uniform bool EnableDebug <
    ui_label = "Enable Debug View";
    ui_tooltip = "启用调试视图,显示所有规约纹理/Enable debug view to display all shader textures.";
> = false;
uniform bool EnableAutoStats <
    ui_label = "Enable Auto Statistics";
    ui_tooltip = "启用自动颜色统计计算/Enable automatic color statistics calculation.";
> = true;
uniform float WhiteLimiter <
    ui_type = "slider";
    ui_min = 0.0; ui_max = 1.5;
    ui_step = 0.01f;
    ui_label = "White Limiter";
    ui_tooltip = "自动校准最高亮度的无效范围/Automatic calibration of the invalid range of maximum brightness.";
> = 0.95;
uniform float BlackLimiter <
    ui_type = "slider";
    ui_min = 0.01; ui_max = 1.0;
    ui_step = 0.01f;
    ui_label = "Black Limiter";
    ui_tooltip = "自动校准最低亮度的无效范围/Automatic calibration of the invalid range of minimum brightness.";
> = 0.05;
uniform int SamplingAera <
    ui_type = "combo";
    ui_label = "Sampling Aera";
    ui_tooltip = "选择采样区域/Select sampling aera.";
    ui_items = "Full Screen\0Custom Area\0";
> = 0;
uniform float2 CustomAreaCenter <
    ui_type = "slider";
    ui_min = 0.0; ui_max = 1.0;
    ui_label = "Custom Area Center";
    ui_tooltip = "自定义采样区域的中心位置/Center position of custom sampling area. ";
> = float2(0.5, 0.5);
uniform float2 CustomAreaSize <
    ui_type = "slider";
    ui_min = 0.0; ui_max = 2.0;
    ui_label = "Custom Area Size";
    ui_tooltip = "自定义采样区域的大小/Size of custom sampling area. 1.0 = default size (1024x1024 pixels).";
> = float2(1.0, 1.0);
uniform bool ShowSamplingBorder <
    ui_label = "Show Sampling Border";
    ui_tooltip = "显示采样区域的边界/Show sampling area border.";
> = false;
uniform bool EnableUIFilter <
    ui_label = "Enable UI Filter";
    ui_tooltip = "启用UI滤除功能,排除UI元素对亮度统计的影响/Enable UI filtering to exclude UI elements from luminance statistics.";
> = true;
uniform float UiFilterBlack <
    ui_type = "slider";
    ui_min = 0.0; ui_max = 0.02;
    ui_step = 0.000001f;
    ui_label = "UI Filter Black Level";
    ui_tooltip = "滤除UI过暗像素的阈值/Threshold for filtering overly dark UI pixels.";
> = 0.0;
uniform bool ShowFilterEffect <
    ui_label = "Show Filter Effect";
    ui_tooltip = "显示滤除效果:确保黑色只在ui中出现,在画面中面积最小/Show filtering effect: ensure black only appears in the UI, with minimal area on the screen.";
> = false;
uniform float ScreenMin <
    ui_label = "Screen Minimum (Black Level)";
    ui_tooltip = "屏幕黑位校准值/Screen Black Level Calibration Value.";
    ui_type = "drag";
    ui_min = 0.0;
    ui_max = 1.0;
    ui_step = 0.000001f;
> = 0.0;
uniform float ScreenMax <
    ui_label = "Screen Maximum (White Level)";
    ui_tooltip = "屏幕白位校准颜色值/Screen White Level Calibration Value.";
    ui_type = "drag";
    ui_min = 0.0;
    ui_max = 50.0;
    ui_step = 0.001f;
> = 1.0;
uniform int CalibrationMode <
    ui_type = "combo";
    ui_label = "Calibration View";
    ui_tooltip = "选择校准模式,使画面刚好纯黑纯白/Select the calibration mode so that the screen is perfectly black and white.";
    ui_items = "Off\0Black Level Calibration\0White Level Calibration\0";
> = 0;
uniform bool EnableHistorySmoothing <
    ui_label = "Enable History Smoothing";
    ui_tooltip = "启用历史值平滑系统,使用16帧历史缓冲区/Enable history value smoothing system using 16-frame history buffer.";
> = true;
#include "ReShade.fxh"
// ============================================================================
// 辅助函数
// ============================================================================
// 计算像素亮度:max(max(r,g),b) - 单通道简化,max确保黑位准确。
float CalculateLuminance(float3 color)
{
    return max(max(color.r, color.g), color.b);
}
// 颜色校准函数 - 支持scRGB/HDR
float3 ColorCalibration(float3 color,
                        float3 offset,
                        float3 gamma,
                        float3 gain,
                        float3 contrast,
                        float3 minColor,
                        float3 maxColor)
{
    //限制maxColor和minColor
    maxColor = max(maxColor,ScreenMax * WhiteLimiter);
    minColor = min(minColor,ScreenMin + BlackLimiter);
   
    //maxColor = ScreenMax;
    // 校准黑位和白位(合并为一步)
    color = ScreenMin + (color - minColor) * (ScreenMax - ScreenMin) / (maxColor - minColor);
    // 将颜色调整至归一化范围,确保计算精度。
    color /= (ScreenMax + 0.1);
    // Gamma
    color = pow(color, 1.0 / gamma);
    // 对比度
    // 显示滤除效果(如果启用)
    [branch]
    if (ShowFilterEffect && EnableUIFilter)
    {
        contrast = (0.001,0.001,0.001);
    }
    color = 1.0 / (1.0 + pow(((1.0 - color) / color), contrast));
    color = min(color,1);//防止颜色越界
    // 恢复颜色范围
    color *= (ScreenMax + 0.1);
    //color = (color - 0.01)*1.0204081632;
    // 校准黑位
    //color += ScreenMin - minColor;
    // 校准白位
    //color *= ScreenMax/maxColor;
    //偏移
    color += offset;
    color = max(color, 0);
    //增益
    color *= gain;
    return color;
}
// 绘制校准图案函数
float3 DrawCalibrationPattern(float2 texcoord, int mode)
{
    // 计算4x4网格的单元格大小
    float cellWidth = 1.0 / 4.0;  // 每个单元格占屏幕宽度的1/4
    float cellHeight = 1.0 / 4.0; // 每个单元格占屏幕高度的1/4
   
    // 矩形占单元格面积的75%,所以矩形大小为单元格大小的sqrt(0.75) ≈ 0.866
    float rectSize = 0.866; // sqrt(0.75)
   
    // 矩形在单元格内的偏移量,使其居中
    float rectOffset = (1.0 - rectSize) * 0.5;
   
    // 确定当前像素属于哪个网格单元格
    int cellX = floor(texcoord.x / cellWidth);
    int cellY = floor(texcoord.y / cellHeight);
   
    // 计算在单元格内的归一化坐标
    float cellLocalX = (texcoord.x - cellX * cellWidth) / cellWidth;
    float cellLocalY = (texcoord.y - cellY * cellHeight) / cellHeight;
   
    // 检查当前像素是否在矩形区域内
    bool inRect = (cellLocalX >= rectOffset && cellLocalX <= rectOffset + rectSize &&
                   cellLocalY >= rectOffset && cellLocalY <= rectOffset + rectSize);
   
    // 根据校准模式返回颜色
    if (mode == 1) // 黑位校准
    {
        // 背景:纯黑,矩形:ScreenMin
        return inRect ? ScreenMin : float3(0.0, 0.0, 0.0);
    }
    else if (mode == 2) // 白位校准
    {
        // 背景:1e6(高亮度白色),矩形:ScreenMax
        float3 whiteBackground = float3(1e6, 1e6, 1e6);
        return inRect ? ScreenMax : whiteBackground;
    }
   
    // 如果不是校准模式,返回黑色(不应该到达这里)
    return float3(0.0, 0.0, 0.0);
}
// 通用4x4归约函数
float4 ReductionPass(float4 position : SV_Position, float2 texcoord : TexCoord, sampler2D inputSampler, float2 pixelSize) : SV_Target
{
    // texcoord是归一化坐标[0,1]
    // 每个输出像素对应输入纹理中的4x4块
    // 计算4x4块的起始坐标(从中心偏移-1.5个像素)将初始采样点从4x4的中心移到左上角第一个像素中心。
    float2 startCoord = texcoord - float2(1.5 * pixelSize.x, 1.5 * pixelSize.y);
   
    // 采样4x4区域的16个像素
    float minVal = 1e6;     // 初始化为很大的值,支持scRGB/HDR(可能超过1000尼特)
    float maxVal = 0.0;     // 初始化为很小的值
   
    for (int y = 0; y < 4; y++)     // 这个循环用来遍历4x4块采样。
    {
        for (int x = 0; x < 4; x++)
        {
            float2 sampleCoord = startCoord + float2(x * pixelSize.x, y * pixelSize.y);
            // 确保采样坐标在有效范围内
            // sampleCoord = clamp(sampleCoord, pixelSize * 0.5, 1.0 - pixelSize * 0.5);注释掉因为这个clamp似乎并不必要
            float4 sampleVal = tex2D(inputSampler, sampleCoord);
           
            minVal = min(minVal, sampleVal.r);
            maxVal = max(maxVal, sampleVal.g);
        }
    }
   
    // 存储结果:R通道存最小值,G通道存最大值
    return float4(minVal, maxVal, 0.0, 1.0);
}
// ============================================================================
// 纹理定义
// 固定5次归约:1024 -> 256 -> 64 -> 16 -> 4 -> 1
// ============================================================================
// 纹理0:1024x1024 - 存储下采样后的亮度值
texture2D TextureMip0 <
    pooled = true;
>
{
    Width = 1024;
    Height = 1024;
    Format = RGBA16F;
};
sampler2D SamplerMip0 {
    Texture = TextureMip0;
    MinFilter = Point;    // 缩小过滤:点过滤
    MagFilter = Point;    // 放大过滤:点过滤
    MipFilter = Point;    // Mipmap过滤:点过滤
    AddressU = Border;     // U方向寻址:边缘
    AddressV = Border;     // V方向寻址:边缘
};
// 纹理1:256x256 - 第一次4x4归约
texture2D TextureMip1 <
    pooled = true;
>
{
    Width = 256;
    Height = 256;
    Format = RGBA16F;
};
sampler2D SamplerMip1 {
    Texture = TextureMip1;
    MinFilter = Point;    // 缩小过滤:点过滤
    MagFilter = Point;    // 放大过滤:点过滤
    MipFilter = Point;    // Mipmap过滤:点过滤
    AddressU = Border;     // U方向寻址:边缘
    AddressV = Border;     // V方向寻址:边缘
};
// 纹理2:64x64 - 第二次4x4归约
texture2D TextureMip2 <
    pooled = true;
>
{
    Width = 64;
    Height = 64;
    Format = RGBA16F;
};
sampler2D SamplerMip2 {
    Texture = TextureMip2;
    MinFilter = Point;    // 缩小过滤:点过滤
    MagFilter = Point;    // 放大过滤:点过滤
    MipFilter = Point;    // Mipmap过滤:点过滤
    AddressU = Border;     // U方向寻址:边缘
    AddressV = Border;     // V方向寻址:边缘
};
// 纹理3:16x16 - 第三次4x4归约
texture2D TextureMip3 <
    pooled = true;
>
{
    Width = 16;
    Height = 16;
    Format = RGBA16F;
};
sampler2D SamplerMip3 {
    Texture = TextureMip3;
    MinFilter = Point;    // 缩小过滤:点过滤
    MagFilter = Point;    // 放大过滤:点过滤
    MipFilter = Point;    // Mipmap过滤:点过滤
    AddressU = Border;     // U方向寻址:边缘
    AddressV = Border;     // V方向寻址:边缘
};
// 纹理4:4x4 - 第四次4x4归约
texture2D TextureMip4 <
    pooled = true;
>
{
    Width = 4;
    Height = 4;
    Format = RGBA16F;
};
sampler2D SamplerMip4 {
    Texture = TextureMip4;
    MinFilter = Point;    // 缩小过滤:点过滤
    MagFilter = Point;    // 放大过滤:点过滤
    MipFilter = Point;    // Mipmap过滤:点过滤
    AddressU = Border;     // U方向寻址:边缘
    AddressV = Border;     // V方向寻址:边缘
};
// 纹理5:1x1 - 第五次4x4归约(最终结果)
texture2D TextureMip5 <
    pooled = true;
>
{
    Width = 1;
    Height = 1;
    Format = RGBA16F;
};
sampler2D SamplerMip5 {
    Texture = TextureMip5;
    MinFilter = Point;    // 缩小过滤:点过滤
    MagFilter = Point;    // 放大过滤:点过滤
    MipFilter = Point;    // Mipmap过滤:点过滤
    AddressU = Border;     // U方向寻址:边缘
    AddressV = Border;     // V方向寻址:边缘
};
// 纹理4_History:4x4 - 历史缓冲区(存储16帧历史的最大值和最小值)
texture2D TextureMip4_History<
    //storage = true;
>
{
    //storage2D = true;
    Width = 4;
    Height = 4;
    Format = RGBA16F;
};
sampler2D SamplerMip4_History {
    Texture = TextureMip4_History;
    MinFilter = Point;    // 缩小过滤:点过滤
    MagFilter = Point;    // 放大过滤:点过滤
    MipFilter = Point;    // Mipmap过滤:点过滤
    AddressU = Border;     // U方向寻址:边缘
    AddressV = Border;     // V方向寻址:边缘
};
// ============================================================================
// Pass着色器
// ============================================================================
// Pass 1:将后缓冲区采样到1024x1024并计算亮度
float4 Pass1_DownsampleTo1024(float4 position : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
    // 测试模式:输出测试图案以验证坐标映射
    // R通道:水平渐变(0到1)
    // G通道:垂直渐变(0到1)
    // B通道:固定0
    // 这样我们可以清楚地看到纹理是否覆盖整个区域
   
    // float2 testPattern = texcoord; // 直接使用texcoord作为渐变
   
    // 存储到TextureMip0(R通道存水平渐变,G通道存垂直渐变)
    // return float4(testPattern.x, testPattern.y, 0.0, 1.0);
   
    // 计算像素大小(用于边界检查)
    float2 pixelSize = 1.0 / float2(BUFFER_WIDTH, BUFFER_HEIGHT);
   
    // 根据采样模式计算采样坐标
    float2 sampleCoord;
    [branch]
    if (SamplingAera == 0) // 全屏模式
    {
        // 直接使用texcoord作为采样坐标
        sampleCoord = texcoord;
    }
    else // 自定义模式 (SamplingAera == 1)
    {
        // 采样区域
        float2 sampleSize = float2(1024*CustomAreaSize.x*pixelSize.x, 1024*CustomAreaSize.y*pixelSize.y);
       
        float2 sampleCenter = CustomAreaCenter;
       
        // 将1024x1024纹理坐标映射到自定义区域
        // 公式:中心 + (texcoord - 0.5) * 大小
        sampleCoord = sampleCenter + (texcoord - 0.5) * sampleSize;
    }
   
    // 注意:这里不需要clamp,因为AddressU = Border; AddressV = Border;
    // 允许采样坐标超过[0,1]范围,边缘模式会返回边界颜色
   
    // 从后缓冲区采样RGB值(使用Point过滤直接采样)
    float3 color = tex2D(ReShade::BackBuffer, sampleCoord).rgb;
   
    // UI滤除(如果启用)
    [branch]
    if (EnableUIFilter)
    {
        // 创建float3类型的滤除阈值
        float3 filterBlack = float3(UiFilterBlack, UiFilterBlack, UiFilterBlack);
       
        // 应用滤除:限制颜色在[filterBlack, +inf]范围内
        color = max(filterBlack, color);
       
        // 确保R、G、B通道使用相同的值(取亮度)
        float luminance = CalculateLuminance(color);
        color = float3(luminance, luminance, luminance);
    }
   
    // 计算亮度(单通道)
    float luminance = CalculateLuminance(color);
   
    // 存储到TextureMip0(R通道存亮度,G通道存相同值用于后续处理)
    return float4(luminance, luminance, 0.0, 1.0);
}
// Pass 2:第一次4x4归约(1024x1024 -> 256x256)
float4 Pass2_Reduction1(float4 position : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
    return ReductionPass(position, texcoord, SamplerMip0, 1.0 / 1024.0);
}
// Pass 3:第二次4x4归约(256x256 -> 64x64)
float4 Pass3_Reduction2(float4 position : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
    return ReductionPass(position, texcoord, SamplerMip1, 1.0 / 256.0);
}
// Pass 4:第三次4x4归约(64x64 -> 16x16)
float4 Pass4_Reduction3(float4 position : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
    return ReductionPass(position, texcoord, SamplerMip2, 1.0 / 64.0);
}
// Pass 5:第四次4x4归约(16x16 -> 4x4)
float4 Pass5_Reduction4(float4 position : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
    return ReductionPass(position, texcoord, SamplerMip3, 1.0 / 16.0);
}
// Pass 6:第五次4x4归约(4x4 -> 1x1)和历史平均值计算
float4 Pass6_Reduction5(float4 position : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
    // 执行正常的4x4归约
    float4 result = ReductionPass(position, texcoord, SamplerMip4, 1.0 / 4.0);
   
    // 如果启用历史平滑,计算历史平均值
    [branch]
    if (EnableHistorySmoothing)
    {
        // 从TextureMip4采样所有16个像素并计算历史值的平均值
        // TextureMip4的B通道存储历史最小值,A通道存储历史最大值
        float2 pixelSize = 1.0 / 4.0; // 4x4纹理的像素大小
        float2 startCoord = float2(0.5 * pixelSize.x, 0.5 * pixelSize.y); // 从第一个像素中心开始
       
        float historySumMin = 0.0;
        float historySumMax = 0.0;
       
        for (int y = 0; y < 4; y++)
        {
            for (int x = 0; x < 4; x++)
            {
                float2 sampleCoord = startCoord + float2(x * pixelSize.x, y * pixelSize.y);
                float4 mip4Value = tex2D(SamplerMip4, sampleCoord);
               
                // B通道存储历史最小值,A通道存储历史最大值
                historySumMin += mip4Value.b;
                historySumMax += mip4Value.a;
            }
        }
       
        // 添加当前帧值到总和中(result.r存储当前帧最小值,result.g存储当前帧最大值)
        // 现在总共有17个数据:16个历史值 + 1个当前帧值
        float totalSumMin = historySumMin + result.r;
        float totalSumMax = historySumMax + result.g;
       
        // 计算17个数据的平均值
        float totalAvgMin = totalSumMin / 17.0;
        float totalAvgMax = totalSumMax / 17.0;
       
        // 将17个数据的平均值存储在结果的B和A通道中
        result.b = totalAvgMin;
        result.a = totalAvgMax;
    }
   
    return result;
}
// Pass 7:将当前帧的1x1纹理值存储到历史纹理(0,0)
float4 Pass7_StoreCurrentToHistory(float4 position : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
    // 这个Pass只写入历史纹理的(0,0)位置
    if (texcoord.x == 0.125 && texcoord.y == 0.125)
    {
        // 从1x1纹理读取当前帧的最小值和最大值
        float4 currentFrame = tex2D(SamplerMip5, float2(0.5, 0.5));
       
        // 存储到历史纹理的(0,0)位置
        // R通道:当前帧最小值
        // G通道:当前帧最大值
        // B和A通道:保留为0(后续用于平均值)
        return float4(currentFrame.r, currentFrame.g, 0.0, 0.0);
    }
   
    // 其他位置返回0
    return float4(0.0, 0.0, 0.0, 0.0);
}
// Pass 8:将历史纹理RG通道复制到TextureMip4的BA通道
float4 Pass8_CopyHistoryToMip4(float4 position : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
    // 首先执行正常的4x4归约(从TextureMip4读取)
    float4 mip4Value = tex2D(SamplerMip4, texcoord);
   
    // 如果启用历史平滑,从历史纹理读取对应的历史值
    [branch]
    if (EnableHistorySmoothing)
    {
        // 从历史纹理读取对应位置的值
        float4 historyValue = tex2D(SamplerMip4_History, texcoord);
       
        // 将历史纹理的R和G通道(最小值和最大值)复制到B和A通道
        mip4Value.b = historyValue.r; // 历史最小值
        mip4Value.a = historyValue.g; // 历史最大值
    }
   
    return mip4Value;
}
// Pass 9:历史值移位
float4 Pass9_HistoryShift(float4 position : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
    // 这个Pass将历史纹理中的值向前移动一位
    // 使用4x4纹理作为16帧的循环缓冲区
    // 将二维坐标转换为一维[0,15]
   
    // 计算当前像素的行列索引(4x4纹理)
    uint col = uint(texcoord.x * 4.0);
    uint row = uint(texcoord.y * 4.0);
    uint pixelIndex = row * 4 + col;
   
    // 计算前一个索引(循环缓冲区)
    uint prevIndex;
    if (pixelIndex == 0)
    {
        prevIndex = 15; // 循环到最后一个位置
    }
    else
    {
        prevIndex = pixelIndex - 1;
    }
   
    // 将一维索引转换回二维纹理坐标
    uint prevCol = prevIndex % 4;
    uint prevRow = prevIndex / 4;
   
    // 计算前一个位置的纹理坐标(像素中心)
    float2 prevTexcoord = float2(
        prevCol * 0.25 + 0.125,
        prevRow * 0.25 + 0.125
    );
   
    // 读取前一个位置的值
    float4 prevValue = tex2D(SamplerMip4_History, prevTexcoord);
   
    return prevValue;
}
// Pass 10:最终颜色校准
float3 Pass10_FinalCalibration(float4 position : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
    // 检查校准模式
    [branch]
    if (CalibrationMode == 1 || CalibrationMode == 2)
    {
        // 显示校准图案
        return DrawCalibrationPattern(texcoord, CalibrationMode);
    }
   
    // 从后缓冲区采样
    float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb;
   
    // 将texcoord转换为像素坐标(用于调试视图)
    uint x = (uint)(texcoord.x * BUFFER_WIDTH);
    uint y = (uint)(texcoord.y * BUFFER_HEIGHT);
   
    // 获取统计结果
    float minLuminance = 0.0;
    float maxLuminance = 1000.0;
   
    if (EnableAutoStats)
    {
        // 从最终1x1纹理读取结果
        float4 finalStats = tex2D(SamplerMip5, float2(0.5, 0.5));
        minLuminance = finalStats.r;
        maxLuminance = finalStats.g;
       
        // 防止除零
        maxLuminance = max(maxLuminance, minLuminance + 0.001);
       
        // 调试视图 - 显示历史纹理和规约纹理
        [branch]
        if (EnableDebug)
        {
            // 左侧显示区域:显示3个历史相关纹理,每个占屏幕高度的1/3
            float leftDisplaySize = BUFFER_HEIGHT / 3.0;
            float leftDisplayWidth = leftDisplaySize;
            float leftDisplayHeight = leftDisplaySize;
           
            // 右侧显示区域:显示6个规约纹理,每个占屏幕高度的1/6
            float rightDisplaySize = BUFFER_HEIGHT / 6.0;
            float rightDisplayWidth = rightDisplaySize;
            float rightDisplayHeight = rightDisplaySize;
           
            // 检查当前像素是否在左侧显示区域内
            if (x < leftDisplayWidth)
            {
                // 计算在左侧显示区域内的相对位置
                uint displayX = x;
                uint displayY = y;
               
                // 计算当前像素属于哪个历史纹理(0-2)
                uint historyTextureIndex = displayY / (uint)leftDisplayHeight;
               
                // 确保纹理索引在0-2范围内
                if (historyTextureIndex < 3)
                {
                    // 计算在当前纹理显示区域内的相对位置(归一化到[0,1])
                    float localY = (displayY % (uint)leftDisplayHeight) / leftDisplayHeight;
                    float localX = displayX / leftDisplayWidth;
                   
                    // 根据纹理索引采样对应的历史纹理
                    float4 historyValue;
                    if (historyTextureIndex == 0)
                    {
                        // TextureMip4_History: 4x4 - 完整图像(RGBA)
                        float2 mipCoord = float2(localX, localY);
                        historyValue = tex2D(SamplerMip4_History, mipCoord);
                        // 显示完整RGBA:R通道为红色,G通道为绿色,B通道为蓝色
                        return float3(historyValue.r, historyValue.g, historyValue.b);
                    }
                    else if (historyTextureIndex == 1)
                    {
                        // TextureMip4_History: R通道(历史最小值)
                        float2 mipCoord = float2(localX, localY);
                        historyValue = tex2D(SamplerMip4_History, mipCoord);
                        // 只显示R通道(红色)
                        return float3(historyValue.r, 0.0, 0.0);
                    }
                    else // historyTextureIndex == 2
                    {
                        // TextureMip4_History: G通道(历史最大值)
                        float2 mipCoord = float2(localX, localY);
                        historyValue = tex2D(SamplerMip4_History, mipCoord);
                        // 只显示G通道(绿色)
                        return float3(0.0, historyValue.g, 0.0);
                    }
                }
            }
           
            // 检查当前像素是否在屏幕右侧的显示区域内
            if (x > BUFFER_WIDTH - rightDisplayWidth)
            {
                // 计算在显示区域内的相对位置
                uint displayX = x - (BUFFER_WIDTH - (uint)rightDisplayWidth);
                uint displayY = y;
               
                // 计算当前像素属于哪个纹理(0-5)
                uint textureIndex = displayY / (uint)rightDisplayHeight;
               
                // 确保纹理索引在0-5范围内
                if (textureIndex < 6)
                {
                    // 计算在当前纹理显示区域内的相对位置(归一化到[0,1])
                    float localY = (displayY % (uint)rightDisplayHeight) / rightDisplayHeight;
                    float localX = displayX / rightDisplayWidth;
                   
                    // 根据纹理索引采样对应的纹理
                    float4 mipValue;
                    if (textureIndex == 0)
                    {
                        // TextureMip0: 1024x1024
                        float2 mipCoord = float2(localX, localY);
                        mipValue = tex2D(SamplerMip0, mipCoord);
                    }
                    else if (textureIndex == 1)
                    {
                        // TextureMip1: 256x256
                        float2 mipCoord = float2(localX, localY);
                        mipValue = tex2D(SamplerMip1, mipCoord);
                    }
                    else if (textureIndex == 2)
                    {
                        // TextureMip2: 64x64
                        float2 mipCoord = float2(localX, localY);
                        mipValue = tex2D(SamplerMip2, mipCoord);
                    }
                    else if (textureIndex == 3)
                    {
                        // TextureMip3: 16x16
                        float2 mipCoord = float2(localX, localY);
                        mipValue = tex2D(SamplerMip3, mipCoord);
                    }
                    else if (textureIndex == 4)
                    {
                        // TextureMip4: 4x4
                        float2 mipCoord = float2(localX, localY);
                        mipValue = tex2D(SamplerMip4, mipCoord);
                    }
                    else // textureIndex == 5
                    {
                        // TextureMip5: 1x1 - 总是采样中心点
                        mipValue = tex2D(SamplerMip5, float2(0.5, 0.5));
                    }
                   
                    // R通道显示为红色,G通道显示为绿色(保持一致的显示风格)
                    return float3(mipValue.r, mipValue.g, 0.0);
                }
            }
        }
    }
   
    // 显示采样边界(如果启用)
    [branch]
    if (ShowSamplingBorder)
    {
        // 紫色边界颜色
        const float3 BORDER_COLOR = float3(1.0, 0.0, 1.0); // 紫色
       
        // 边界宽度(3像素)
        const float BORDER_WIDTH = 3.0;
       
        // 计算归一化的边界宽度
        float borderWidthX = BORDER_WIDTH / BUFFER_WIDTH;
        float borderWidthY = BORDER_WIDTH / BUFFER_HEIGHT;
       
        // 计算当前像素的归一化坐标
        float2 normalizedCoord = float2(x / float(BUFFER_WIDTH), y / float(BUFFER_HEIGHT));
       
        // 根据采样模式确定边界区域
        float2 borderMin, borderMax;
       
        if (SamplingAera == 0) // 全屏模式
        {
            // 整个屏幕的边界
            borderMin = float2(0.0, 0.0);
            borderMax = float2(1.0, 1.0);
        }
        else // 自定义模式
        {
            // 计算像素大小(与Pass1_DownsampleTo1024一致)
            float2 pixelSize = 1.0 / float2(BUFFER_WIDTH, BUFFER_HEIGHT);
           
            // 采样区域大小(与Pass1_DownsampleTo1024一致)
            float2 sampleSize = float2(1024*CustomAreaSize.x*pixelSize.x, 1024*CustomAreaSize.y*pixelSize.y);
            float2 sampleCenter = CustomAreaCenter;
           
            // 计算采样区域的边界
            float2 halfSize = sampleSize * 0.5;
            borderMin = sampleCenter - halfSize;
            borderMax = sampleCenter + halfSize;
           
            // 注意:这里不需要clamp,因为边界可以超过[0,1]范围
            // 边缘模式允许采样坐标超过[0,1]范围
        }
       
        // 检查当前像素是否在边界区域内(3像素宽)
        bool isInBorder = false;
       
        // 检查左边界
        if (normalizedCoord.x >= borderMin.x && normalizedCoord.x <= borderMin.x + borderWidthX &&
            normalizedCoord.y >= borderMin.y && normalizedCoord.y <= borderMax.y)
        {
            isInBorder = true;
        }
        // 检查右边界
        else if (normalizedCoord.x >= borderMax.x - borderWidthX && normalizedCoord.x <= borderMax.x &&
                normalizedCoord.y >= borderMin.y && normalizedCoord.y <= borderMax.y)
        {
            isInBorder = true;
        }
        // 检查上边界
        else if (normalizedCoord.y >= borderMin.y && normalizedCoord.y <= borderMin.y + borderWidthY &&
                normalizedCoord.x >= borderMin.x && normalizedCoord.x <= borderMax.x)
        {
            isInBorder = true;
        }
        // 检查下边界
        else if (normalizedCoord.y >= borderMax.y - borderWidthY && normalizedCoord.y <= borderMax.y &&
                normalizedCoord.x >= borderMin.x && normalizedCoord.x <= borderMax.x)
        {
            isInBorder = true;
        }
       
        // 如果在边界内,返回紫色
        if (isInBorder)
        {
            return BORDER_COLOR;
        }
    }
   
    // 应用颜色校准
    float3 minColor = float3(minLuminance, minLuminance, minLuminance);
    float3 maxColor = float3(maxLuminance, maxLuminance, maxLuminance);
    return ColorCalibration(color, RGB_offset, RGB_Gamma, RGB_Gain, RGB_Contrast, minColor, maxColor);
}
// ============================================================================
// 技术定义
// ============================================================================
technique ColorCalibration
{
    pass Pass1_Downsample
    {
        VertexShader = PostProcessVS;
        PixelShader = Pass1_DownsampleTo1024;
        RenderTarget = TextureMip0;
    }
   
    pass Pass2_Reduction1
    {
        VertexShader = PostProcessVS;
        PixelShader = Pass2_Reduction1;
        RenderTarget = TextureMip1;
    }
   
    pass Pass3_Reduction2
    {
        VertexShader = PostProcessVS;
        PixelShader = Pass3_Reduction2;
        RenderTarget = TextureMip2;
    }
   
    pass Pass4_Reduction3
    {
        VertexShader = PostProcessVS;
        PixelShader = Pass4_Reduction3;
        RenderTarget = TextureMip3;
    }
   
    pass Pass5_Reduction4
    {
        VertexShader = PostProcessVS;
        PixelShader = Pass5_Reduction4;
        RenderTarget = TextureMip4;
    }
   
    pass Pass6_Reduction5
    {
        VertexShader = PostProcessVS;
        PixelShader = Pass6_Reduction5;
        RenderTarget = TextureMip5;
    }
   
    pass Pass7_StoreCurrentToHistory
    {
        VertexShader = PostProcessVS;
        PixelShader = Pass7_StoreCurrentToHistory;
        RenderTarget = TextureMip4_History;
    }
   
    pass Pass8_CopyHistoryToMip4
    {
        VertexShader = PostProcessVS;
        PixelShader = Pass8_CopyHistoryToMip4;
        RenderTarget = TextureMip4;
    }
   
    pass Pass9_HistoryShift
    {
        VertexShader = PostProcessVS;
        PixelShader = Pass9_HistoryShift;
        RenderTarget = TextureMip4_History;
    }
   
    pass Pass10_Final
    {
        VertexShader = PostProcessVS;
        PixelShader = Pass10_FinalCalibration;
    }
}

Please Log in or Create an account to join the conversation.

  • BlueGary
  • Topic Author
More
5 days 18 hours ago #2 by BlueGary Replied by BlueGary on topic I want to know how to achieve persistent storage of textures.
I'm a fool! I didn't handle the return mechanism of pass7 properly......
 

Please Log in or Create an account to join the conversation.

We use cookies
We use cookies on our website. Some of them are essential for the operation of the forum. You can decide for yourself whether you want to allow cookies or not. Please note that if you reject them, you may not be able to use all the functionalities of the site.