ПрограммированиеФорумГрафика

Проблемы с Variance Shadow Map (смотреть 19 пост)

Страницы: 1 2 Следующая »
#0
0:40, 16 дек 2013

Сделал наконец Shadow Map. Но как и у всех, наверно, возникли артефакты: не затеняется обратная сторона ножа (на первом скрине) и полоски (на втором скрине). Пробовал разный bias, где-то помогает, но где-то тени вообще пропадают. Сейчас Shadow Map сделан с использованием автоматического сравнения и sampler2DShadow. Но хотелось бы это исправить и сделать все самому в шейдере. Пробовал разные функции (дальше закомментированы), но тени почему-то не появляются.

2 | Проблемы с Variance Shadow Map (смотреть 19 пост)
3 | Проблемы с Variance Shadow Map (смотреть 19 пост)

Создание ShadowMap:

  glGenTextures(1, &light->shadowMap);
  glBindTexture(GL_TEXTURE_2D, light->shadowMap);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
  glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 2048, 2048, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);

Вершинный шейдер Shadow Map:

  #version 130

  in vec3 vertex_position;
  uniform mat4 model_matrix;
  uniform mat4 light_matrix;

  void main(void) {
    gl_Position = light_matrix * (model_matrix * vec4(vertex_position, 1.0));
  }

Фрагментный шейдер Shadow Map:

  #version 130

  void main(void) {
  }

Расчет теней и освещения в шейдере:

float PCF(in sampler2DShadow shadowMap, in vec4 smtexcoord) {
    float res = 0.0;

    res += textureProj(shadowMap, smtexcoord + vec4(0.0, -0.015, 0.0, 0.0));
    res += textureProj(shadowMap, smtexcoord + vec4(0.0, 0.015, 0.0, 0.0));
    res += textureProj(shadowMap, smtexcoord + vec4(0.015, -0.015, 0.0, 0.0));
    res += textureProj(shadowMap, smtexcoord + vec4(0.015, 0.0, 0.0, 0.0));
    res += textureProj(shadowMap, smtexcoord + vec4(0.015, 0.015, 0.0, 0.0));
    res += textureProj(shadowMap, smtexcoord + vec4(-0.015, -0.015, 0.0, 0.0));
    res += textureProj(shadowMap, smtexcoord + vec4(-0.015, 0.0, 0.0, 0.0));
    res += textureProj(shadowMap, smtexcoord + vec4(-0.015, 0.015, 0.0, 0.0));

    return (res/8.0);
}

.....

for(int i=0; i<MAXLIGHTSPOT; i++) {
    vec3 lightDir = normalize(fragment_lightspot_dir[i]);
    float shadow = 1.0;
    //if(texture(lightspot_shadowMap[i], (fragment_lightspot_smtexcoord[i].xy/fragment_lightspot_smtexcoord[i].w)).z < (fragment_lightspot_smtexcoord[i].z)/fragment_lightspot_smtexcoord[i].w) {
    //if(textureProj(lightspot_shadowMap[i], fragment_lightspot_smtexcoord[i].xyzw) < (fragment_lightspot_smtexcoord[i].z)/fragment_lightspot_smtexcoord[i].w) {
    //if(shadow2D(lightspot_shadowMap[i], fragment_lightspot_smtexcoord[i]).x == 0) {
        shadow = PCF(lightspot_shadowMap[i], fragment_lightspot_smtexcoord[i]);
    //if(shadow == 0.0) { continue; }
    //continue;
    //}
    float spotEffect = dot(lightspot_direction[i], -lightDir);
    float spot = float(lightspot_cutoff[i]);
    spotEffect = max(pow(spotEffect, lightspot_exponent[i]), 0.0);
    float attenuation = spot * spotEffect / (lightspot_attenuation[i].x + lightspot_attenuation[i].y * fragment_lightspot_distance[i] + lightspot_attenuation[i].z * fragment_lightspot_distance[i] * fragment_lightspot_distance[i]);
    color += (material_ambient * lightspot_ambient[i]) * attenuation;
    color += (material_diffuse * lightspot_diffuse[i]) * attenuation;
    color += (((material_specular * lightspot_specular[i]) * max(pow(dot(reflect(lightDir, normal), viewDir), material_shininess), 0.0))) * attenuation;
    color *= shadow;
}

FragColor = vec4(color, material_alpha);\n"

Так как 8 выборок считаются для каждого пикселя, то при 3 динамических источниках света уже заметны подтормаживания, что конечно плохо.
Если вместо закомментированного кода вставить следующее:

    if(textureProj(lightspot_shadowMap[i], fragment_lightspot_smtexcoord[i].xyzw) < (fragment_lightspot_smtexcoord[i].z)/fragment_lightspot_smtexcoord[i].w) {
        continue;
    }

то тормозов нет и заметен даже прирост производительности (т.к. не рассчитывается свет для пикселей в тени), но тени по краям становятся резкими, что выглядит некрасиво.
Существует ли способ размыть края тени, отбрасывая при этом пиксели в тени? Если нет, хотелось бы услышать советы по улучшению/оптимизации.

Правка: добавлены скрины

#1
5:55, 16 дек 2013

Рисуй только задние грани геометрии.

#2
7:42, 16 дек 2013

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

#3
9:27, 16 дек 2013

ialexbr
> Если вместо закомментированного кода вставить следующее:
> то тормозов нет и заметен даже прирост производительности (т.к. не
> рассчитывается свет для пикселей в тени),

Налицо укорения через DFC.

> Существует ли способ размыть края тени, отбрасывая при этом пиксели в тени?
> Если нет, хотелось бы услышать советы по улучшению/оптимизации.

Техники есть, например, сделать цепочку mix/max mips. Более сложенее динамический подгонять веса.
Если железо новое можно ускорить выборку через gather

И тд, и тп ... у тебя вся жизнь впереди :)

#4
11:20, 16 дек 2013

innuendo
> mix/max mips
чёто посмотрел ту нвидийную демку с ними - а там 20 фпс (если зазумиться чтобы модель и тень от неё примерно весь экран занимали).
неюзабельно.

ialexbr
> не затеняется обратная сторона ножа
нужно dot(нормаль, направление света) добавить

ialexbr
> Существует ли способ размыть края тени, отбрасывая при этом пиксели в тени?
> Если нет, хотелось бы услышать советы по улучшению/оптимизации.
Вроде в доке по какой то игре читал про такой трюк: посчитать тени без сглаживания в очень лоуресный рендертаргет (типа там 160х120), картинка при этом должна быть просто белым цветом с черными тенями. Необязательно рендерить сцену повторно, можно реюзать глубину сцены, если она уже посчитана перед наложением теней. Применяешь дальше к этой текстуре фильтр, которые находит края теней и расширяет их на несколько пикселей и сужает вовнутрь тоже на несколько и пишет, в результате, такую лоуресную маску, которая должна как раз собой покрыть мягкие края теней, но не взлезть ни внутрь, ни наружу.
Юзаешь дальше эту маску в затенении конечной сцены, там где её нет - делаешь одну грубую выборку, где есть - со сглаживанием.

#5
11:30, 16 дек 2013

Mr F
> чёто посмотрел ту нвидийную демку с ними - а там 20 фпс (если зазумиться чтобы
> модель и тень от неё примерно весь экран занимали).
> неюзабельно

1. Там две точности.
2. Там не самый оптимальный шейдер.

#6
11:33, 16 дек 2013

innuendo
> 1. Там две точности.
в смысле?

в любом случае, тормозит хуже чем VSM+SAT, который выглядел ничуть не хуже чем тут accurate версия, а шёл в 250 фпс у меня.

#7
11:45, 16 дек 2013

Mr F
> > 1. Там две точности.
> в смысле?

аккуратная и нет :)

> в любом случае, тормозит хуже чем VSM+SAT
Не уверен. Есть графики\картинки ?

#8
11:48, 16 дек 2013

innuendo
> Не уверен. Есть графики\картинки ?
какие графики?
есть то, что я запускал и то и другое и смотрел на фпс)

#9
11:49, 16 дек 2013

Mr F
> > Не уверен. Есть графики\картинки ?
> какие графики?

Сравнений :)

> есть то, что я запускал и то и другое и смотрел на фпс)

Это хорошо. Но можно же и код шейдера посмотреть ? :)

#10
12:01, 16 дек 2013

innuendo
> Но можно же и код шейдера посмотреть ? :)
шейдер самопальный с кучей костылей, говнокода и ограничений, так что я лучше его придержу)
но он работал, я уже постил демку: http://ndotl.wordpress.com/2013/09/05/penumbra-shadows/

#11
12:05, 16 дек 2013

Mr F
> шейдер самопальный с кучей костылей,

я имел ввиду шейдер той самой тормознутой демки :)
можно подумать, что SAT быстро считается ?

#12
12:10, 16 дек 2013

innuendo
> я имел ввиду шейдер той самой тормознутой демки
ну дак он в самой демке на сайте нвидии

innuendo
> можно подумать, что SAT быстро считается ?
нихрена не быстро, но при некоторых условиях можно соптимизировать, как я делал: рендерить каждый кастер в свой кусок атласа, тогда кол-во препассов SAT потребуется только для размера максимального квадратика в атласе, неважно что их много.
но это всё конечно неуниверсальное и геморрой... но хотя бы в некоторых ситуациях работает.
минмакс мипы пока не видел чтобы хоть в какой-то работали.

#13
12:15, 16 дек 2013

Mr F
> ну дак он в самой демке на сайте нвидии

Да. Думаешь, он очень оптимально написан ?

#14
12:20, 16 дек 2013

innuendo
> Да. Думаешь, он очень оптимально написа
я хз, других демок не видел.
если есть ещё какие - кинь)

Страницы: 1 2 Следующая »
ПрограммированиеФорумГрафика

Тема в архиве.