Добрый день. Отрабатываю освещение с тенями, получаемыми от карты теней (когда карта создается с помощью буфера глубины, получаемого при отрисовке сцены с позиции источника света).
Вот настройка сэмплера текстуры:
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 координаты текущего пикселя и пикселя карты теней происходит на текстурном процессоре, а не в общем коде шейдера (ну или что-то в этом духе).