Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Opengl GLSL中的HDR、自适应色调映射和MSAA_Opengl_Glsl - Fatal编程技术网

Opengl GLSL中的HDR、自适应色调映射和MSAA

Opengl GLSL中的HDR、自适应色调映射和MSAA,opengl,glsl,Opengl,Glsl,为了努力自学OpenGL,我正在用自己的方式学习OpenGL 我目前正试图找出如何结合HDR和MSAA(如第9章所述) 对于HDR,这本书提出了一种自适应色调映射的方法,该方法基于计算每个片段5x5卷积滤波器的平均亮度 对于MSAA,使用的方法通过从样本距离计算的权重对所有样本进行平均 我尝试将这两种颜色结合在一起,可以在下面的pastebin中找到,将色调映射应用于每个样本,然后对它们进行平均,以计算最终的片段颜色 性能很糟糕(正如人们可能已经预料到的那样?):在每个样本25次查找的情况下,4

为了努力自学OpenGL,我正在用自己的方式学习OpenGL

我目前正试图找出如何结合HDR和MSAA(如第9章所述)

对于HDR,这本书提出了一种自适应色调映射的方法,该方法基于计算每个片段5x5卷积滤波器的平均亮度

对于MSAA,使用的方法通过从样本距离计算的权重对所有样本进行平均

我尝试将这两种颜色结合在一起,可以在下面的pastebin中找到,将色调映射应用于每个样本,然后对它们进行平均,以计算最终的片段颜色

性能很糟糕(正如人们可能已经预料到的那样?):在每个样本25次查找的情况下,4xMSAA的查找次数是4次,我猜GPU大部分时间都在查找我的FBO纹理。切换到由代码中的use_HDR uniform控制的代码路径会使简单场景的性能从400+fps下降到10以下

我的问题有两个:

  • 这是执行色调映射的明智方法吗?如果没有,你有什么建议

  • MSAA和基于卷积的滤波器应该如何组合?我猜对于任何需要查找相邻纹理的过滤器,例如几乎任何类似bloom、blur等的东西,我都会再次遇到这个问题

代码:

#版本330
在数据中
{
vec4位;
vec4正常;
vec4颜色;
vec2-texCoord;
mat4mvp;
mat4 mv;
}gdata;
输出vec4输出颜色;
均匀取样器2dms-tex;
均匀取样器1d-lum\u-to\u暴露;
均匀的缓冲重量;
统一整数抽样数;
统一布勒用途;
vec4色调映射(vec4颜色,浮点表达式)
{
返回1.0f-exp2(-color*exp);
}
常数ivec2 tc_偏移量[25]=ivec2[](ivec2(-2,-2),ivec2(-1,-2),ivec2(0,-2),ivec2(1,-2),ivec2(2,-2),
ivec2(-2,-1),ivec2(-1,-1),ivec2(0,-1),ivec2(1,-1),ivec2(2,-1),
ivec2(-2,0),ivec2(-1,0),ivec2(0,0),ivec2(1,0),ivec2(2,0),
ivec2(-2,1),ivec2(-1,1),ivec2(0,1),ivec2(1,1),ivec2(2,1),
ivec2(-2,2),ivec2(-1,2),ivec2(0,2),ivec2(1,2),ivec2(2,2));
void main()
{
ivec2 itexcoords=ivec2(地板(纹理尺寸(tex)*gdata.texCoord));
float tex_size_x=纹理尺寸(tex).x;
float tex_size_y=纹理化(tex).y;
outputColor=vec4(0.0f、0.0f、0.0f、1.0f);
//对于多样本缓冲区中的每个样本。。。
对于(int i=0;i
据我所知,从GLSL代码中,一个像素的所有样本的权重都是相等的。由此我得出结论,代码对每个像素的这些样本的总和感兴趣。总和是平均数乘以样本数。从这里至少可以看出两种优化技术。两者都使用一个中间的单采样纹理,您的代码应该从中采样,而不是原始的多采样纹理:

  • (精确到你正在做的事情)。使用着色器生成中间纹理,该着色器写入每个像素的平均采样数

  • (快速逼近)。让中间纹理恰好是已解析的原始纹理。可以通过调用
    glBlitFramebuffer()
    有效地完成。这将产生稍有不同的结果(因为采样位置不在网格上),但对于任务-HDR-来说,这不重要,因为这几乎是一个近似值:)


  • 祝你好运

    我没有《超级圣经》的副本,因此我不知道它们的确切主张,但这种方法似乎效率很低,而且不精确:您的5x5过滤器只访问每个texel的第I个样本,而完全忽略了其他样本

    对于过滤阶段,正如kvark已经建议的那样,我将使用
    glBlitFramebuffer
    在另一个纹理中进行解析,以在HDR中累积所有样本。在那之后,在另一个HDR纹理中进行过滤,可能使用a来获得性能,甚至使用GPU硬件来帮助进一步提高性能
    #version 330
    in Data
    {
        vec4 position;
        vec4 normal;
        vec4 color;
        vec2 texCoord;
        mat4 mvp;
        mat4 mv;
    } gdata;
    
    out vec4 outputColor;
    uniform sampler2DMS tex;
    uniform sampler1D lum_to_exposure;
    uniform samplerBuffer weights;
    uniform int samplecount;
    uniform bool use_HDR;
    
    vec4 tone_map(vec4 color, float exp)
    {
        return 1.0f - exp2(-color * exp);
    }
    
    const ivec2 tc_offset[25] = ivec2[](ivec2(-2, -2), ivec2(-1, -2), ivec2(0, -2), ivec2(1, -2), ivec2(2, -2),
                                        ivec2(-2, -1), ivec2(-1, -1), ivec2(0, -1), ivec2(1, -1), ivec2(2, -1),
                                        ivec2(-2,  0), ivec2(-1,  0), ivec2(0,  0), ivec2(1,  0), ivec2(2,  0),
                                        ivec2(-2,  1), ivec2(-1,  1), ivec2(0,  1), ivec2(1,  1), ivec2(2,  1),
                                        ivec2(-2,  2), ivec2(-1,  2), ivec2(0,  2), ivec2(1,  2), ivec2(2,  2));
    
    void main()
    {
        ivec2 itexcoords = ivec2(floor(textureSize(tex) * gdata.texCoord));
        float tex_size_x = textureSize(tex).x;
        float tex_size_y = textureSize(tex).y;
        outputColor = vec4(0.0f, 0.0f, 0.0f, 1.0f);
        // for each sample in the multi sample buffer...
        for (int i = 0; i < samplecount; i++)
        {
            // ... calculate exposure based on the corresponding sample of nearby texels
            vec4 sample;
            if (use_HDR)
            {
                sample = texelFetch(tex, itexcoords, i);
    
                // look up a 5x5 area around the current texel
                vec4 hdr_samples[25];
                for (int j = 0; j < 25; ++j)
                {
                    ivec2 coords = clamp(itexcoords + tc_offset[j], ivec2(0, 0), ivec2(tex_size_x, tex_size_y));
                    hdr_samples[j] = texelFetch(tex, coords, i);
                }
                // average the surrounding texels
                vec4 area_color = (
                         ( 1.0f * (hdr_samples[0] + hdr_samples[4] + hdr_samples[20] + hdr_samples[24])) +
                         ( 4.0f * (hdr_samples[1] + hdr_samples[3] + hdr_samples[5] + hdr_samples[9]
                                 + hdr_samples[15] + hdr_samples[19] + hdr_samples[21] + hdr_samples[23])) +
                         ( 7.0f * (hdr_samples[2] + hdr_samples[10] + hdr_samples[14] + hdr_samples[22])) +
                         (16.0f * (hdr_samples[6] + hdr_samples[8] + hdr_samples[16] + hdr_samples[18])) +
                         (26.0f * (hdr_samples[7] + hdr_samples[11] + hdr_samples[13] + hdr_samples[17])) +
                         (41.0f * (hdr_samples[12]))
                         ) / 273.0f;
                // RGB to luminance formula : lum = 0.3R + 0.59G + 0.11B
                float area_luminance = dot(area_color.rgb, vec3(0.3, 0.59, 0.11));
                float exposure = texture(lum_to_exposure, area_luminance/2.0).r;
                exposure = clamp(exposure, 0.02f, 20.0f);
    
    
                sample = tone_map(sample, exposure);
            }
            else
                sample = texelFetch(tex, itexcoords, i);
    
            // weight the sample based on its position
            float weight = texelFetch(weights, i).r;
            outputColor += sample * weight;
        }
    }