Отложенный артефакт MSAA

Это процесс, который я прохожу, чтобы визуализировать сцену:

  • Привязать MSAA x4 GBuffer (4 цветовых вложения, положение, нормальный, цвет и неосвещенный цвет (только для скайбокса. У меня также есть компонент глубины / текстура).
  • Нарисуйте SkyBox
  • Draw Geo
  • Объедините все компоненты цвета и глубины в один образец FBO
  • Применить освещение (я использую текстуру глубины, чтобы проверить, должна ли она светиться, проверив, если значение текстуры глубины меньше 1).
  • Render Quad

И вот что происходит:

Single-Sample Multi-Sample

Как видите, я получаю эти белые и черные артефакты по краю, а не по гладкому краю. (Приятно отметить, что если я уберу освещение и просто рендеринг текстуры без освещения, я не получу это, и он будет сглаживаться правильно).

Вот мой шейдер (реализован SSAO, но, похоже, это не влияет).

#version 410 core
in vec2 Texcoord;
out vec4 outColor;
uniform sampler2D texFramebuffer;
uniform sampler2D ssaoTex;

uniform sampler2D gPosition;
uniform sampler2D gNormal;
uniform sampler2D gAlbedo;
uniform sampler2D gAlbedoUnlit;
uniform sampler2D gDepth;

uniform mat4 View;
struct Light {
vec3 Pos;
vec3 Color;
float Linear;
float Quadratic;
float Radius;
};

const int MAX_LIGHTS = 32;
uniform Light lights[MAX_LIGHTS];
uniform vec3 viewPos;

uniform bool SSAO;

void main()
{
vec3 color = texture(gAlbedo, Texcoord).rgb;
vec3 colorUnlit = texture(gAlbedoUnlit, Texcoord).rgb;
vec3 pos = texture(gPosition, Texcoord).rgb;
vec3 norm = normalize(texture( gNormal, Texcoord)).rgb;
vec3 depth = texture(gDepth, Texcoord).rgb;
float ssaoValue = texture(ssaoTex, Texcoord).r;

// then calculate lighting as usual
vec3 lighting;
if(SSAO)
{
lighting = vec3(0.3 * color.rgb * ssaoValue); // hard-coded ambient component
}
else
{
lighting = vec3(0.3 * color.rgb); // hard-coded ambient component
}
vec3 posWorld = pos.rgb;

vec3 viewDir = normalize(viewPos - posWorld);

for(int i = 0; i < MAX_LIGHTS; ++i)
{

vec4 lightPos = View * vec4(lights[i].Pos,1.0);
vec3 normLight = normalize(lightPos.xyz);
float distance = length(lightPos.xyz - posWorld);
if(distance < lights[i].Radius)
{
// diffuse
vec3 lightDir = normalize(lightPos.xyz - posWorld);
vec3 diffuse = max(dot(norm.rgb, lightDir), 0.0) * color.rgb *
lights[i].Color;

float attenuation = 1.0 / (1.0 + lights[i].Linear * distance + lights[i].Quadratic * distance * distance);
lighting += (diffuse*attenuation);
}
}

if(depth.r >= 1)
{
outColor = vec4(colorUnlit, 1.0);
}
else
{
outColor = vec4(lighting, 1.0);
}

}

Таким образом, последний оператор if проверяет, находится ли он в текстуре глубины, затем применяет освещение, а если нет, то просто рисует скайбокс (это значит, что освещение не применяется к скайбоксу).

Я потратил несколько дней, пытаясь решить эту проблему, изменив способы проверки того, должен ли он быть легким, сравнив нормали, положение и глубину, изменив формат на более высокое разрешение (например, используя RGB16F вместо RGB8 и т. Д.), Но я могу Выяснить, что является причиной этого, и сделать освещение для каждого сэмпла (используя выборку текселей) было бы слишком интенсивно.

Есть идеи?

3

Решение

Этот вопрос уже немного устарел, но я подумал, что скажу, как я решил свою проблему.

Я запускаю базовый фильтр Собела в своем шейдере, который я использую для контуров экранного пространства, но кроме того, я также проверяю, включен ли MSAA и, если да, то вычисляю освещение на пиксель вокруг краевых пикселей!

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]