102 lines
3.8 KiB
Plaintext
102 lines
3.8 KiB
Plaintext
// planetStone фрагментный шейдер
|
|
|
|
varying vec2 TexCoord;
|
|
varying vec3 worldPosition;
|
|
varying vec3 vWorldNormal;
|
|
|
|
uniform sampler2D Texture;
|
|
uniform float uDistanceToPlanetSurface;
|
|
uniform vec3 uViewPos;
|
|
uniform vec3 uLightDirWorld;
|
|
uniform float uPlayerLightFactor;
|
|
|
|
void main()
|
|
{
|
|
// --- 1. Подготовка векторов ---
|
|
vec3 normal = normalize(vWorldNormal);
|
|
vec3 lightToSource = normalize(-uLightDirWorld);
|
|
|
|
// Вектор от центра планеты к камню (нормаль самой поверхности планеты под камнем)
|
|
// Предполагаем, что центр планеты в (0,0,0)
|
|
vec3 surfaceNormal = normalize(worldPosition);
|
|
|
|
// --- 2. Расчет Shadow Mask ---
|
|
// Проверяем, освещена ли точка планеты, на которой стоит камень
|
|
float shadowMask = clamp(dot(surfaceNormal, lightToSource) * 5.0, 0.0, 1.0);
|
|
// Коэффициент 5.0 делает переход на терминаторе более четким
|
|
|
|
// --- 3. Освещение камня ---
|
|
float diff = max(dot(normal, lightToSource), 0.0);
|
|
|
|
// Применяем shadowMask к диффузной составляющей
|
|
// Если точка на планете в тени, то прямой свет (diff) обнуляется
|
|
float ambient = 0.3;
|
|
float lightIntensity = (diff * shadowMask);
|
|
|
|
lightIntensity *= mix(0.2, 1.0, shadowMask);
|
|
|
|
lightIntensity += ambient;
|
|
|
|
// --- 4. Остальная логика (цвета и туман) ---
|
|
vec3 dayFog = vec3(0.0, 0.5, 1.0);
|
|
vec3 nightFog = vec3(0.01, 0.01, 0.04);
|
|
vec3 dynamicFogColor = mix(nightFog, dayFog, uPlayerLightFactor);
|
|
|
|
vec4 textureColor = texture2D(Texture, TexCoord);
|
|
vec3 litColor = textureColor.rgb * lightIntensity;
|
|
|
|
float realDist = distance(worldPosition, uViewPos);
|
|
float h = uDistanceToPlanetSurface;
|
|
float alphaFactor = clamp((2000.0 - realDist) / 500.0, 0.0, 1.0);
|
|
|
|
float fogStart, fogEnd;
|
|
|
|
// --- Логика расчета границ тумана ---
|
|
|
|
if (h >= 1000.0) {
|
|
gl_FragColor = vec4(litColor, alphaFactor);
|
|
}
|
|
else
|
|
{
|
|
if (h > 100.0) {
|
|
// Нормализуем высоту от 100 до 1000 (t: 0 -> 1)
|
|
float t = (h - 100.0) / 900.0;
|
|
|
|
// На высоте 100 туман начинается со 100.
|
|
// К высоте 1000 он плавно "убегает" к границе 2500, где объект исчезает.
|
|
fogStart = mix(1500.0, 15000.0, t);
|
|
|
|
// Держим ширину зоны тумана в пределах 400-600 единиц
|
|
float fogRange = mix(1000.0, 6000.0, t);
|
|
fogEnd = fogStart + fogRange;
|
|
}
|
|
else if (h > 40.0) {
|
|
float t = (h - 40.0) / 60.0;
|
|
|
|
// На высоте 100 туман начинается со 100.
|
|
// К высоте 1000 он плавно "убегает" к границе 2500, где объект исчезает.
|
|
fogStart = mix(800.0, 1500.0, t);
|
|
|
|
fogEnd = mix(1000.0, 2500.0, t);
|
|
}
|
|
else if (h > 20.0) {
|
|
float t = (h - 20.0) / 20.0;
|
|
fogStart = mix(200.0, 800.0, t);
|
|
fogEnd = mix(500.0, 1000.0, t);
|
|
}
|
|
else {
|
|
// Минимумы при h = 0: start 25, end 125
|
|
float t = clamp(h / 20.0, 0.0, 1.0);
|
|
fogStart = mix(100.0, 200.0, t);
|
|
fogEnd = mix(250.0, 500.0, t);
|
|
}
|
|
|
|
// Расчет фактора тумана
|
|
float fogRange = max(fogEnd - fogStart, 1.0);
|
|
float fogFactor = clamp((realDist - fogStart) / fogRange, 0.0, 1.0);
|
|
|
|
// Смешивание освещенного камня с динамическим туманом
|
|
vec3 mixedColor = mix(litColor, dynamicFogColor, fogFactor);
|
|
gl_FragColor = vec4(mixedColor, alphaFactor);
|
|
}
|
|
} |