景物深度

时间:2018-09-01 17:28:09

标签: opengl image-processing glsl post-processing

我开始在应用程序中实现景深,但是遇到了一个问题。伪影以深度之间不平滑的过渡形式出现。

我通过以下方式进行景深:

  1. 使用主场景渲染,我将模糊值记录在Alpha通道中。我使用以下方法执行此操作:fragColor.a = clamp(abs(focalDepth + fragPos.z) / focalRange, 0.0, 1.0),其中focalDepth = 8focalRange = 20

  2. 此后,根据模糊值(我先前在alpha通道中记录的值)(以下阴影),应用具有动态大小和sigma的两步(水平和垂直)高斯模糊。

但是我有一个人工制品,在其中您可以看到深度之间的清晰过渡。

整个场景:the whole scene 而且规模越来越大:artifact

我的片段模糊着色器:

#version 330

precision mediump float;

#define BLOOM_KERNEL_SIZE 8
#define DOF_KERNEL_SIZE 8
/* ^^^ definitions ^^^ */

layout (location = 0) out vec4 bloomFragColor;
layout (location = 1) out vec4 dofFragColor;
in vec2 texCoords;

uniform sampler2D image; // bloom
uniform sampler2D image2; // dof
uniform bool isHorizontal;
uniform float kernel[BLOOM_KERNEL_SIZE];

float dof_kernel[DOF_KERNEL_SIZE];

vec4 tmp;
vec3 bloom_result;
vec3 dof_result;
float fdof;
float dofSigma;
int dofSize;

void makeDofKernel(int size, float sigma) {
    size = size * 2 - 1;
    float tmpKernel[DOF_KERNEL_SIZE * 2 - 1];
    int mean = size / 2;
    float sum = 0; // For accumulating the kernel values
    for (int x = 0; x < size; x++)  {
        tmpKernel[x] = exp(-0.5 * pow((x - mean) / sigma, 2.0));
        // Accumulate the kernel values
        sum += tmpKernel[x];
    }

    // Normalize the kernel
    for (int x = 0; x < size; x++) 
        tmpKernel[x] /= sum;

    // need center and right part
    for (int i = 0; i < mean + 1; i++) dof_kernel[i] = tmpKernel[size / 2 + i];
}

void main() {
    vec2 texOffset = 1.0 / textureSize(image, 0); // gets size of single texel
    tmp = texture(image2, texCoords);
    fdof = tmp.a;
    dofSize = clamp(int(tmp.a * DOF_KERNEL_SIZE), 1, DOF_KERNEL_SIZE);
    if (dofSize % 2 == 0) dofSize++;
    makeDofKernel(dofSize, 12.0 * fdof + 1);

    bloom_result = texture(image, texCoords).rgb * kernel[0]; // current fragment’s contribution
    dof_result = tmp.rgb * dof_kernel[0];

    if(isHorizontal) {
        for(int i = 1; i < kernel.length(); i++) {
            bloom_result += texture(image, texCoords + vec2(texOffset.x * i, 0.0)).rgb * kernel[i];
            bloom_result += texture(image, texCoords - vec2(texOffset.x * i, 0.0)).rgb * kernel[i];
        }

        for(int i = 1; i < dofSize; i++) {
            dof_result += texture(image2, texCoords + vec2(texOffset.x * i, 0.0)).rgb * dof_kernel[i];
            dof_result += texture(image2, texCoords - vec2(texOffset.x * i, 0.0)).rgb * dof_kernel[i];
        }
    } else {
        for(int i = 1; i < kernel.length(); i++) {
            bloom_result += texture(image, texCoords + vec2(0.0, texOffset.y * i)).rgb * kernel[i];
            bloom_result += texture(image, texCoords - vec2(0.0, texOffset.y * i)).rgb * kernel[i];
        }

        for(int i = 1; i < dofSize; i++) {
            dof_result += texture(image2, texCoords + vec2(0.0, texOffset.y * i)).rgb * dof_kernel[i];
            dof_result += texture(image2, texCoords - vec2(0.0, texOffset.y * i)).rgb * dof_kernel[i];
        }
    }

    bloomFragColor = vec4(bloom_result, 1.0);
    dofFragColor = vec4(dof_result, fdof);
}

以及DOF纹理的设置:glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, SCR_W, SCR_H, 0, GL_RGBA, GL_FLOAT, NULL)

着色器的优化我将在稍后进行,现在我非常关注此工件。如何消除呢?希望不改变景深的实现方式。但是,如果您知道更有效的方式-要求分享它。

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

问题已解决。我的错误是我更改了DOF模糊内核的大小,尽管我只需要更改sigma。更正了着色器代码:

#version 330

precision mediump float;

#define BLOOM_KERNEL_SIZE 8
#define DOF_KERNEL_SIZE 8
/* ^^^ definitions ^^^ */

layout (location = 0) out vec4 bloomFragColor;
layout (location = 1) out vec4 dofFragColor;

in vec2 texCoords;

uniform sampler2D image; // bloom
uniform sampler2D image2; // dof
uniform bool isHorizontal;

uniform float max_sigma = 12.0;
uniform float min_sigma = 0.0001;

uniform float kernel[BLOOM_KERNEL_SIZE];

float dof_kernel[DOF_KERNEL_SIZE];

vec4 tmp;
vec3 bloom_result;
vec3 dof_result;
float fdof;

const int DOF_LCR_SIZE = DOF_KERNEL_SIZE * 2 - 1; // left-center-right (lllcrrr)
const int DOF_MEAN = DOF_LCR_SIZE / 2;

void makeDofKernel(float sigma) {
    float sum = 0; // For accumulating the kernel values
    for (int x = DOF_MEAN; x < DOF_LCR_SIZE; x++)  {
        dof_kernel[x - DOF_MEAN] = exp(-0.5 * pow((x - DOF_MEAN) / sigma, 2.0));
        // Accumulate the kernel values
        sum += dof_kernel[x - DOF_MEAN];
    }

    sum += sum - dof_kernel[0];

    // Normalize the kernel
    for (int x = 0; x < DOF_KERNEL_SIZE; x++) dof_kernel[x] /= sum;
}

void main() {
    vec2 texOffset = 1.0 / textureSize(image, 0); // gets size of single texel
    tmp = texture(image2, texCoords);
    fdof = tmp.a;
    makeDofKernel(max_sigma * fdof + min_sigma);

    bloom_result = texture(image, texCoords).rgb * kernel[0]; // current fragment’s contribution
    dof_result = tmp.rgb * dof_kernel[0];

    if(isHorizontal) {
        for(int i = 1; i < BLOOM_KERNEL_SIZE; i++) {
            bloom_result += texture(image, texCoords + vec2(texOffset.x * i, 0.0)).rgb * kernel[i];
            bloom_result += texture(image, texCoords - vec2(texOffset.x * i, 0.0)).rgb * kernel[i];
        }

        for(int i = 1; i < DOF_KERNEL_SIZE; i++) {
            dof_result += texture(image2, texCoords + vec2(texOffset.x * i, 0.0)).rgb * dof_kernel[i];
            dof_result += texture(image2, texCoords - vec2(texOffset.x * i, 0.0)).rgb * dof_kernel[i];
        }
    } else {
        for(int i = 1; i < BLOOM_KERNEL_SIZE; i++) {
            bloom_result += texture(image, texCoords + vec2(0.0, texOffset.y * i)).rgb * kernel[i];
            bloom_result += texture(image, texCoords - vec2(0.0, texOffset.y * i)).rgb * kernel[i];
        }

        for(int i = 1; i < DOF_KERNEL_SIZE; i++) {
            dof_result += texture(image2, texCoords + vec2(0.0, texOffset.y * i)).rgb * dof_kernel[i];
            dof_result += texture(image2, texCoords - vec2(0.0, texOffset.y * i)).rgb * dof_kernel[i];
        }
    }

    bloomFragColor = vec4(bloom_result, 1.0);
    dofFragColor = vec4(dof_result, fdof);
}

结果:result result