Глубина полевых артефактов - PullRequest
0 голосов
/ 01 сентября 2018

Я начал реализовывать глубину резкости в своем приложении, но столкнулся с проблемой. Артефакты появляются в виде негладкого перехода между глубинами.

Я делаю глубину резкости следующим образом:

  1. При рендеринге основной сцены я записываю значение размытия в альфа-канале. Я делаю это, используя это: fragColor.a = clamp(abs(focalDepth + fragPos.z) / focalRange, 0.0, 1.0), где focalDepth = 8, focalRange = 20.

  2. После этого я применяю двухступенчатое (по горизонтали и вертикали) размытие по Гауссу с динамическим размером и сигмой, в зависимости от значения размытия (которое я ранее записал в альфа-канале) (шейдер ниже)

Но у меня есть артефакт, где вы видите четкий переход между глубинами.

Вся сцена: 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 голосов
/ 02 сентября 2018

Проблема решена. Моя ошибка состояла в том, что я изменил размер ядра размытия DOF, хотя мне пришлось изменить только сигму. Исправленный код шейдера:

#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);
}

Результат: resultresult

...