Unity3d 需要着色器中纹理的平均值和最大值

Unity3d 需要着色器中纹理的平均值和最大值,unity3d,shader,Unity3d,Shader,我有一个RenderTexture,需要计算它的平均和最大像素值。RenderTexture是RFloat格式,因此只有一个组件。此外,它现在不使用mipmap。经过一些搜索后,似乎最好的方法是减少纹理,这意味着运行一个着色器,使其输入具有纹理大小,输出具有输入大小的一半。我们可以对4个相邻像素进行采样,计算最大值,并将值写入输出 sampler2D _MainTex; float4 _MainTex_ST; float4 _MainTex_TexelSize;

我有一个RenderTexture,需要计算它的平均和最大像素值。RenderTexture是RFloat格式,因此只有一个组件。此外,它现在不使用mipmap。

经过一些搜索后,似乎最好的方法是减少纹理,这意味着运行一个着色器,使其输入具有纹理大小,输出具有输入大小的一半。我们可以对4个相邻像素进行采样,计算最大值,并将值写入输出

    sampler2D _MainTex;
    float4 _MainTex_ST;
    float4 _MainTex_TexelSize;

    v2f vert(appdata v)
    {
        v2f o;
        o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
        o.uv = TRANSFORM_TEX(v.uv, _MainTex);
        return o;
    }
    float4 frag (v2f i) : SV_Target
    {
        float dx = _MainTex_TexelSize.x*0.5;
        float maximum = tex2D(_MainTex, i.uv + float2(-dx,-dx));
        maximum = max(maximum, tex2D(_MainTex, i.uv + float2(dx,-dx)));
        maximum = max(maximum, tex2D(_MainTex, i.uv + float2(-dx,dx)));
        maximum = max(maximum, tex2D(_MainTex, i.uv + float2(dx,dx)));
        return maximum;
    }
下一次迭代获得上一次迭代的输出,并写入一个rendertexture,该rendertexture是其输入的一半,即原始纹理的四分之一。所以尺寸大概是1024512256,。。。以此类推,直到1乘1纹理,这将给出最大值。以下是一些代码来显示CPU端:

        private RenderTexture Reduce(RenderTexture diff, Material mat)
    {
        int reductions = POT.GetPowerFromNum(diff.width);
        var rtList = new List<RenderTexture>();
        int smallRes = diff.width/2;
        var bigRT = diff;
        for (int i = 0; i < reductions; i++)
        {
            var smallRT = RenderTexture.GetTemporary(smallRes, smallRes, 0, diff.format);
            rtList.Add(smallRT);
            GpuUtils.Blit(bigRT,smallRT,mat);
            bigRT = smallRT;
            smallRes >>= 1;
        }
        for (int i = 0; i < reductions-1; i++)
        {
            RenderTexture.ReleaseTemporary(rtList[i]);
        }
        return rtList[reductions-1];
    }
private RenderTexture Reduce(RenderTexture diff,Material mat)
{
int reducements=POT.GetPowerFromNum(diff.width);
var rtList=新列表();
int smallRes=差异宽度/2;
var-bigRT=diff;
对于(int i=0;i>=1;
}
对于(int i=0;i<1;i++)
{
RenderTexture.ReleaseTemporary(rtList[i]);
}
返回rtList[减少-1];
}
这里的
diff
是原始渲染纹理,
GetPowerFromNum
计算1024的两个类似10的幂,mat是着色器的材质


对于average,可以对average着色器(而不是max)执行相同的操作,或者只是为渲染纹理启用mipmap并读取最高mipmap级别。

我不知道这是否是一个错误,或者是我的知识不够深入,但我将着色器中的最大值类型更改为float4。。。