Направленное отображение теней в отложенном затенении - PullRequest
0 голосов
/ 24 мая 2018

Я реализую направленное отображение теней в отложенном затенении.

Сначала я рендерил карту глубины из светлого вида (ортогональная проекция).

Результат:result

Я собираюсь сделать VSM, поэтому над буфером находится R32G32, хранящий глубину и глубину * глубина.

Затем для полноэкранного прохода затенения для тени (послепроход освещения), я пишу следующий пиксельный шейдер:

    #version 330

    in vec2 texCoord; // screen coordinate
    out vec3 fragColor; // output color on the screen

    uniform mat4 lightViewProjMat; // lightView * lightProjection (ortho)

    uniform sampler2D sceneTexture; // lit scene with one directional light
    uniform sampler2D shadowMapTexture;
    uniform sampler2D scenePosTexture; // store fragment's 3D position

    void main() {
      vec3 fragPos = texture(scenePosTexture, texCoord).xyz; // get 3D position of pixel
      vec4 fragPosLightSpace = lightViewProjMat * vec4(fragPos, 1.0); // project it to light-space view: lightView * lightProjection

      // projective texture mapping
      vec3 coord = fragPosLightSpace.xyz / fragPosLightSpace.w;
      coord = coord * 0.5 + 0.5;

      float lightViewDepth; // depth value in the depth buffer - the maximum depth that light can see
      float currentDepth; // depth of screen pixel, maybe not visible to the light, that's how shadow mapping works
      vec2 moments; // depth and depth * depth for later variance shadow mapping

      moments = texture(shadowMapTexture, coord.xy).xy;
      lightViewDepth = moments.x;
      currentDepth = fragPosLightSpace.z;

      float lit_factor = 0;
      if (currentDepth <= lightViewDepth)
        lit_factor = 1; // pixel is visible to the light
      else
        lit_factor = 0; // the light doesn't see this pixel

      // I don't do VSM yet, just want to see black or full-color pixels
      fragColor = texture(sceneTexture, texCoord).rgb * lit_factor;
}

Полученный результат - черный экран, но если я жестко закодировал lit_factor, чтобы быть 1, результат будет:

result

По сути, именно так выглядит sceneTexture.

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

Мой код генерации карты теней:

// vertex shader
#version 330 compatibility

uniform mat4 lightViewMat; // lightView
uniform mat4 lightViewProjMat; // lightView * lightProj

in vec3 in_vertex;
out float depth;

void main() {
  vec4 vert = vec4(in_vertex, 1.0);
  depth = (lightViewMat * vert).z / (500 * 0.2); // 500 is far value, this line tunes the depth precision
  gl_Position = lightViewProjMat * vert;
}

// pixel shader
#version 330

in float depth;
out vec2 out_depth;

void main() {
  out_depth = vec2(depth, depth * depth);
}

Ответы [ 2 ]

0 голосов
/ 24 мая 2018

Компонент z фрагментного шейдера, встроенного в переменную gl_FragCoord, содержит значение глубины в диапазоне [0.0, 1.0].Это значение, которое вы должны сохранить на карте глубины:

out_depth = vec2(gl_FragCoord.z, depth * depth);

После вычисления

vec3 fragPos = texture(scenePosTexture, texCoord).xyz; // get 3D position of pixel
vec4 fragPosLightSpace = lightViewProjMat * vec4(fragPos, 1.0); // project it to light-space view: lightView * lightProjection
vec3 ndc_coord = fragPosLightSpace.xyz / fragPosLightSpace.w;

переменная ndc_coord содержит нормализованную координату устройства, где все компоненты находятся вдиапазон [-1,0, 1,0].

Компонент z нормализованного координаты устройства может быть преобразован в значение глубины (если диапазон глубины равен [0,0, 1,0]),на

float currentDepth = ndc_coord.z * 0.5 + 0.5;

Это значение можно сравнить со значением из карты глубины, поскольку currentDepth и lightViewDepth вычисляются с использованием одной и той же матрицы вида и матрицы проекции:

moments = texture(shadowMapTexture, coord.xy).xy;
lightViewDepth = moments.x;

if (currentDepth <= lightViewDepth)
    lit_factor = 1; // pixel is visible to the light
else
    lit_factor = 0; // the light doesn't see this pixel
0 голосов
/ 24 мая 2018

Это глубина, которую вы храните на теневой карте:

depth = (lightViewMat * vert).z / (500 * 0.2);

Это глубина, с которой вы сравниваете значение считанного возврата с:

vec4 fragPosLightSpace = lightViewProjMat * vec4(fragPos, 1.0);
currentDepth = fragPosLightSpace.z;

Если fragPos находится вмировое пространство тогда я предполагаю lightViewMat * vert == fragPos.Вы сжимаете глубину путем деления на 500 * 0.2, но это не равно fragPosLightSpace.z.

Подсказка: запишите значение currentDepth в одном канале и значение из карты теней в другом канале.затем можете сравнить их визуально или в RenderDoc или аналогичном.

...