LINUX.ORG.RU

Проблема с функцией textureProj при использовании Shadow Map

 ,


0

1

Добрый день. Отрабатываю освещение с тенями, получаемыми от карты теней (когда карта создается с помощью буфера глубины, получаемого при отрисовке сцены с позиции источника света).

Вот настройка сэмплера текстуры:

glGenSamplers(1,&ShadowMapSamplerId);
glBindSampler(ShadowMapSamplerUnit,ShadowMapSamplerId);

glSamplerParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glSamplerParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

glSamplerParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,GL_COMPARE_REF_TO_TEXTURE);
glSamplerParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);

glSamplerParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glSamplerParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

Два варианта кода фрагментного(пиксельного) шейдера:

1) Рекомендуемый OpenGL RedBook, с использованием функции textureProj (вроде как более эффективный с точки зрения использования аппаратных возможностей видеокарты)

#version 430 core
uniform sampler2DShadow ShadowMap;

vec4 clAmbient=vec4(0.2,0.2,0.2,1.0);
vec4 clSurface=vec4(0.0,0.0,1.0,1.0);

in vec3 clShadedFace;
in vec4 ShadowMapCoord;

vec4 clSaturation=vec4(1.0);
vec4 clResult;

void main(void)
{
  clResult=clSurface*(clAmbient+textureProj(ShadowMap,ShadowMapCoord)*vec4(clShadedFace,1.0));
  clResult=min(clResult,clSaturation);
  gl_FragColor = clResult;
}

В документации сказано, что при вызове textureProj для Sampler2DShadow будет возвращено либо 1.0 (если пиксель не скрыт от света) либо 0.0 если таки скрыт. На практике изображение получается таки с нужными тенями, НО освещенные части освещены очень-очень слабо, как если бы textureProj возвращала значения В ДИАПАЗОНЕ от 0 до 1, а не только краевые значения.

2)Слегка отличающийся код, призванный заменить использование textureProj на texture и ручную проверку принадлежности пикселя освещенной области

#version 430 core

uniform sampler2DShadow ShadowMap;

vec4 clAmbient=vec4(0.2,0.2,0.2,1.0);
vec4 clSurface=vec4(0.0,0.0,1.0,1.0);

in vec3 clShadedFace;
in vec4 ShadowMapCoord;

vec4 clSaturation=vec4(1.0);
vec4 clResult;

float visibility=1.0;


void main(void) 
{
  if(texture(ShadowMap,ShadowMapCoord.xyz)  < ShadowMapCoord.z)
    visibility=0.0;

  clResult=clSurface*(clAmbient+visibility*vec4(clShadedFace,1.0));
  clResult=min(clResult,clSaturation);
  gl_FragColor = clResult;
}

Вот этот вариант работает как надо: нужные тени и то , что освещено - освещено с нужной силой. Но как заставить работать первый вариант? Вроде как первый вариант чуть более быстродействен и эффективен, так как сравнение z координаты текущего пикселя и пикселя карты теней происходит на текстурном процессоре, а не в общем коде шейдера (ну или что-то в этом духе).

Только что заметил, что если заменить сторонний сэмплер на базовый (вместо glSamplerParameteri ставить glTexParameteri), то первый вариант работает как надо.Странно,сторонний сэмплер я правильно привязываю к шейдеру, проверял. Может дело в том, что GL_TEXTURE_COMPARE_MODE и GL_TEXTURE_COMPARE_FUNC можно настраивать только в сэмплере, выдаваемом текстуре по умолчанию?

Nerevarino ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.