diff --git a/shaders/lighting.frag b/shaders/lighting.frag index 6908e7f..5197ef5 100644 --- a/shaders/lighting.frag +++ b/shaders/lighting.frag @@ -59,9 +59,11 @@ void main() float acosA; // Косинус между вектором от поверхности к источнику и обратным направлением источника float intensity; // Интенсивность для прожектора vec3 fragPosLightSpace; // Фрагмент в пространстве источника - float closestDepth; // Значение глубины из буфера тени float shadowValue; // Значение затененности - + vec2 texelSize = 1.0 / textureSize(sunShadowDepth, 0); // Размер текселя текстуры теней + int x, y; // Счетчик для PCF + float pcfDepth; // Глубина PCF + // Фоновая освещенность color = vec4(ka, 1); @@ -74,10 +76,17 @@ void main() fragPosLightSpace = (fragPosLightSpace + vec3(1.0)) / 2; // Сдвиг для решения проблемы акне fragPosLightSpace.z -= max(0.05 * (1.0 - dot(N, sun.direction)), 0.005); - // Получим значение ближайшей глубины к источнику - closestDepth = texture(sunShadowDepth, fragPosLightSpace.xy).r; - // Проверим, что рассматриваемый фрагмент ближе чем значение глубины - shadowValue = fragPosLightSpace.z > closestDepth ? 1.0 : 0.0; + // Проверка PCF + shadowValue = 0.0; + for(x = -1; x <= 1; ++x) + { + for(y = -1; y <= 1; ++y) + { + pcfDepth = texture(sunShadowDepth, fragPosLightSpace.xy + vec2(x, y) * texelSize).r; + shadowValue += fragPosLightSpace.z > pcfDepth ? 1.0 : 0.0; + } + } + shadowValue /= 9; // Рассчитываем освещенность, если значение тени меньше 1 if (shadowValue < 1.0) { @@ -91,8 +100,8 @@ void main() // Зеркальная составляющая specular = pow(max(dot(H, N), 0.0), p*4); // скалярное произведение с отсеканием значений < 0 в степени p // Результирующий цвет с учетом солнца - color += vec4(sun.color*kd*diffuse, 1) - + vec4(sun.color*ks*specular, 1); + color += ( vec4(sun.color*kd*diffuse, 1) + + vec4(sun.color*ks*specular, 1) ) * (1.0 - shadowValue); } }