refactoring

This commit is contained in:
Vladislav Khorev committed 2026-01-09 22:33:46 +03:00
1 parent 9fc0adf210
commit d1cab1f3b3
2082 files changed
+13644 -161518

No files matched your search

+11
View File
@@ -0,0 +1,11 @@
attribute vec3 vPosition;
attribute vec2 vTexCoord;
varying vec2 texCoord;
uniform mat4 ProjectionModelViewMatrix;
void main()
{
gl_Position = ProjectionModelViewMatrix * vec4(vPosition.xyz, 1.0);
texCoord = vTexCoord;
}
@@ -0,0 +1,17 @@
// Вершинный шейдер:
attribute vec3 vPosition;
attribute vec3 vNormal;
uniform mat4 ProjectionModelViewMatrix;
uniform mat4 ModelViewMatrix;
varying vec3 vWorldNormal;
varying vec3 vViewNormal;
varying vec3 vViewPosition;
void main() {
vWorldNormal = vPosition; // Локальная позиция вершины на сфере радиуса 1.0
vViewPosition = (ModelViewMatrix * vec4(vPosition, 1.0)).xyz;
vViewNormal = normalize((ModelViewMatrix * vec4(vNormal, 0.0)).xyz);
gl_Position = ProjectionModelViewMatrix * vec4(vPosition, 1.0);
}
@@ -0,0 +1,125 @@
precision highp float;
// Фрагментный шейдер:
uniform vec3 uColor;
uniform float uDistanceToPlanetSurface; // Расстояние корабля до поверхности
// Константы затухания, определенные прямо в шейдере
const float DIST_FOG_MAX = 2000.0;
const float DIST_FOG_MIN = 1000.0;
varying vec3 vWorldNormal;
varying vec3 vViewNormal;
varying vec3 vViewPosition;
// Добавь эти uniform-ы
//uniform float uTime;
uniform vec3 uLightDirView;
uniform vec3 uPlayerDirWorld;
// Простая функция псевдослучайного шума
float hash(float n) { return fract(sin(n) * 43758.5453123); }
float noise(vec3 x) {
vec3 p = floor(x);
vec3 f = fract(x);
f = f * f * (3.0 - 2.0 * f);
float n = p.x + p.y * 57.0 + 113.0 * p.z;
return mix(mix(mix(hash(n + 0.0), hash(n + 1.0), f.x),
mix(hash(n + 57.0), hash(n + 58.0), f.x), f.y),
mix(mix(hash(n + 113.0), hash(n + 114.0), f.x),
mix(hash(n + 170.0), hash(n + 171.0), f.x), f.y), f.z);
}
// Fractal Brownian Motion для "кучевости" облаков
float fbm(vec3 p) {
float f = 0.5000 * noise(p); p *= 2.02;
f += 0.2500 * noise(p); p *= 2.03;
f += 0.1250 * noise(p);
return f;
}
void main()
{
//gl_FragColor = vec4(1.0, 0.0, 0.0, 0.5);
vec3 normal = normalize(vViewNormal);
vec3 viewVector = normalize(-vViewPosition);
float NdotV = dot(normal, viewVector);
// Вектор направления от центра планеты к текущему фрагменту атмосферы (Мировой)
vec3 fragmentDir = normalize(vWorldNormal);
// Вектор направления от центра планеты к игроку (нужно передать как uniform)
// Передай его в C++: renderer.RenderUniform3fv("uPlayerDirWorld", playerDirWorld.data());
// --- 1. Плавное отсечение за горизонтом (Horizon Mask) ---
// Считаем косинус угла между игроком и точкой атмосферы
float cosAngle = dot(fragmentDir, uPlayerDirWorld);
// Плавно затухаем от 0.0 (горизонт) до 0.2 (над головой)
//float horizonMask = smoothstep(0.0, 0.4, cosAngle);
float horizonMask = smoothstep(0.93, 1.0, cosAngle);
// --- 2. Плавный переход при прохождении сквозь слой (Transition Mask) ---
// Определяем "высоту" игрока относительно слоя (напр. слой на 1.03 * R)
// uDistanceToPlanetSurface уже вычислен в PlanetData
float layerHeight = 600.0; // Примерная толщина слоя атмосферы (3% от 20000)
// Делаем прозрачным при приближении к границе (dist около layerHeight)
// и снова видимым, когда спустились ниже
float distToLayer = abs(uDistanceToPlanetSurface - layerHeight);
float transitionMask = smoothstep(0.0, 200.0, distToLayer);
// --- 3. Освещение и облака ---
float diff = max(dot(normal, uLightDirView), 0.0);
if (uDistanceToPlanetSurface < layerHeight) {
diff = max(dot(-normal, uLightDirView), 0.0); // Инверсия для взгляда снизу
}
float lightIntensity = diff + 0.05;
vec3 cloudCoord = fragmentDir * 6.0;
//cloudCoord.x += uTime * 0.03;
float n = fbm(cloudCoord);
float cloudMask = smoothstep(0.4, 0.65, n);
// --- 4. Финальный расчет альфы ---
float atmosphereDensity = pow(1.0 - abs(NdotV), 5.0);
float distanceFactor = clamp((uDistanceToPlanetSurface - DIST_FOG_MIN) / (DIST_FOG_MAX - DIST_FOG_MIN), 0.0, 1.0);
// Базовая прозрачность облаков
float cloudAlpha = cloudMask * 0.8;
// Применяем маски:
// В космосе важен distanceFactor, на планете важен horizonMask
float finalCloudAlpha = cloudAlpha * transitionMask;
if (uDistanceToPlanetSurface < layerHeight) {
finalCloudAlpha *= horizonMask; // На планете скрываем то, что под ногами
} else {
finalCloudAlpha *= distanceFactor; // В космосе скрываем по вашей старой логике
if (NdotV <=0.0)
{
//finalCloudAlpha = 0.0;
discard;
}
}
vec3 currentAtmo = mix(vec3(0.01, 0.02, 0.1), uColor, lightIntensity);
vec3 currentCloud = mix(vec3(0.1, 0.1, 0.15), vec3(1.0, 1.0, 1.0), lightIntensity);
vec3 finalRGB = mix(currentAtmo, currentCloud, cloudMask);
//vec3 finalRGB = currentAtmo;
// Для дымки (atmo) оставляем затухание при посадке
float atmoAlpha = atmosphereDensity * distanceFactor;
//float atmoAlpha = distanceFactor;
float finalAtmoAlpha = atmoAlpha;
if (uDistanceToPlanetSurface < layerHeight) {
finalCloudAlpha *= horizonMask;
finalAtmoAlpha *= horizonMask; // Принудительно гасим дымку под горизонтом
}
gl_FragColor = vec4(finalRGB, max(finalAtmoAlpha, finalCloudAlpha));
}
+23
View File
@@ -0,0 +1,23 @@
attribute vec3 vPosition;
attribute vec3 vColor;
attribute vec3 vNormal;
attribute vec2 vTexCoord; // <-- Обычные UV (если используются)
varying vec3 color;
varying vec3 normal;
varying vec2 TexCoord; // <-- Передаем UV
uniform mat4 ProjectionModelViewMatrix;
uniform mat4 ModelViewMatrix;
uniform vec3 uLightDirection;
void main()
{
gl_Position = ProjectionModelViewMatrix * vec4(vPosition.xyz, 1.0);
normal = normalize((ModelViewMatrix * vec4(vNormal, 0.0)).xyz);
color = vColor;
TexCoord = vTexCoord;
}
@@ -0,0 +1,9 @@
precision mediump float;
varying vec3 color;
void main()
{
//gl_FragColor = vec4(color, 1.0);
gl_FragColor = vec4(1.0, 1.0, 0.5, 1.0);
}
+12
View File
@@ -0,0 +1,12 @@
attribute vec3 vPosition;
uniform mat4 ProjectionModelViewMatrix;
varying vec3 dir;
void main(){
vec4 realVertexPos = vec4(vPosition.xyz, 1.0);
gl_Position = ProjectionModelViewMatrix * realVertexPos;
dir = vPosition;
}
@@ -0,0 +1,8 @@
precision mediump float;
uniform samplerCube Texture;
varying vec3 dir;
void main(){
gl_FragColor = textureCube(Texture, normalize(dir));
}
+11
View File
@@ -0,0 +1,11 @@
attribute vec3 vPosition;
attribute vec2 vTexCoord;
varying vec2 texCoord;
uniform mat4 ProjectionModelViewMatrix;
void main()
{
gl_Position = ProjectionModelViewMatrix * vec4(vPosition.xyz, 1.0);
texCoord = vTexCoord;
}
@@ -0,0 +1,9 @@
precision mediump float;
uniform sampler2D Texture;
varying vec2 texCoord;
void main()
{
vec4 color = texture2D(Texture,texCoord).rgba;
gl_FragColor = color;
}
+12
View File
@@ -0,0 +1,12 @@
precision mediump float;
uniform sampler2D Texture;
varying vec2 texCoord;
void main()
{
vec4 color = texture2D(Texture,texCoord).rgba;
//gl_FragColor = vec4(color.rgb*0.1 + vec3(0.9, 0.9, 0.9), 1.0);
gl_FragColor = color;
}
+9
View File
@@ -0,0 +1,9 @@
attribute vec3 vPosition;
uniform mat4 ProjectionModelViewMatrix;
varying vec3 vViewDir;
void main() {
gl_Position = ProjectionModelViewMatrix * vec4(vPosition, 1.0);
// Направление взгляда в пространстве вида (вершина куба относительно центра)
vViewDir = vPosition;
}
+37
View File
@@ -0,0 +1,37 @@
precision mediump float;
uniform samplerCube Texture;
uniform float skyPercent;
uniform float uPlayerLightFactor; // Глобальный фактор дня/ночи для позиции игрока
uniform vec3 uSkyColor;
varying vec3 vViewDir;
void main() {
vec3 viewDir = normalize(vViewDir);
// 1. Получаем звезды
vec4 starsColor = textureCube(Texture, viewDir);
// 2. Цвета атмосферы
vec3 dayColor = uSkyColor;
vec3 nightColor = vec3(0.01, 0.01, 0.04);
// 3. Теперь всё небо окрашивается одинаково в зависимости от положения игрока
// Мы плавно смешиваем ночной и дневной купол
vec3 atmosphericColor = mix(nightColor, dayColor, uPlayerLightFactor);
// 4. Логика видимости звезд
// Звезды видны в космосе (skyPercent=0)
// И в атмосфере, если сейчас ночь (uPlayerLightFactor -> 0)
float starsVisibility = (1.0 - skyPercent) + (skyPercent * (1.0 - uPlayerLightFactor));
// Делаем звезды чуть ярче на ночном небе
starsVisibility = pow(starsVisibility, 1.5);
// 5. Итоговый цвет
// Добавляем слой атмосферы к звездам
vec3 skyLayer = atmosphericColor * skyPercent;
vec3 finalColor = (starsColor.rgb * starsVisibility) + skyLayer;
gl_FragColor = vec4(finalColor, 1.0);
}
+31
View File
@@ -0,0 +1,31 @@
// Vertex Shader (Bake Stage)
attribute vec3 vPosition;
attribute vec2 vTexCoord;
varying vec2 TexCoord;
varying float vHeight;
// Данные о плоскости треугольника планеты
uniform vec3 uPlanePoint; // Любая вершина треугольника (например, tri.data[0])
uniform vec3 uPlaneNormal; // Нормаль треугольника планеты (ось Z из GetRotationForTriangle)
uniform float uMaxHeight; // Максимальный размер камня (BASE_SCALE)
uniform mat4 ProjectionModelViewMatrix;
void main()
{
// 1. Вычисляем вектор от плоскости до текущей вершины камня
vec3 vecToVertex = vPosition - uPlanePoint;
// 2. Проецируем этот вектор на нормаль плоскости (скалярное произведение)
// Это и есть кратчайшее расстояние от точки до плоскости
float distance = dot(vecToVertex, uPlaneNormal);
// 3. Нормализуем высоту для записи в текстуру (0.0 - уровень земли, 1.0 - пик)
// Clamp гарантирует, что значения не выйдут за пределы, если камень "утоплен"
vHeight = clamp(distance / uMaxHeight, 0.0, 1.0);
TexCoord = vTexCoord;
gl_Position = ProjectionModelViewMatrix * vec4(vPosition, 1.0);
}
@@ -0,0 +1,14 @@
precision mediump float;
varying vec2 TexCoord;
varying float vHeight;
uniform sampler2D Texture;
void main()
{
vec4 stoneColor = texture2D(Texture, TexCoord);
gl_FragColor = vec4(stoneColor.rgb, vHeight);
//gl_FragColor = vec4(vHeight, vHeight, vHeight, vHeight);
//gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);
}
+40
View File
@@ -0,0 +1,40 @@
attribute vec3 vPosition;
attribute vec2 vTexCoord;
attribute vec3 vNormal;
attribute vec3 vTangent; // Новые атрибуты
attribute vec3 vBinormal;
attribute vec3 vColor;
varying vec3 Color;
varying vec2 TexCoord;
varying vec3 vViewDirTangent;
varying vec3 worldPosition;
varying vec3 vWorldNormal;
uniform mat4 ProjectionModelViewMatrix;
uniform mat4 ModelViewMatrix;
uniform highp vec3 uViewPos;
void main() {
gl_Position = ProjectionModelViewMatrix * vec4(vPosition, 1.0);
TexCoord = vTexCoord;
vec3 viewDirWorld = normalize(uViewPos - vPosition);
// Строим матрицу перехода из атрибутов
// Так как базис ортонормирован, TBN^-1 == TBN_transpose
vViewDirTangent = vec3(
dot(viewDirWorld, vTangent),
dot(viewDirWorld, vBinormal),
dot(viewDirWorld, vNormal)
);
vec4 viewPosition = ModelViewMatrix * vec4(vPosition.xyz, 1.0);
worldPosition = vPosition;
vWorldNormal = vPosition;
Color = vColor;
}
+116
View File
@@ -0,0 +1,116 @@
precision highp float;
varying vec2 TexCoord;
varying vec3 vViewDirTangent;
varying vec3 Color;
varying vec3 worldPosition;
varying vec3 vWorldNormal;
uniform sampler2D Texture;
uniform sampler2D BakedTexture;
uniform float uHeightScale;
uniform float uDistanceToPlanetSurface;
uniform float uCurrentZFar;
uniform vec3 uViewPos;
const vec4 FOG_COLOR = vec4(0.0, 0.5, 1.0, 1.0); // Синий туман
uniform vec3 uLightDirWorld; // Направление ЛУЧЕЙ (1, -1, -1)
uniform float uPlayerLightFactor;
uniform vec3 uPlayerDirWorld;
void main() {
// --- 1. Расчет освещения поверхности ---
// Направление НА источник света
vec3 lightToSource = normalize(-uLightDirWorld);
vec3 fragmentDir = normalize(vWorldNormal);
// Используем vNormal (нормаль в мировом пространстве, так как vPosition тоже в мировом)
// Важно: если vNormal не нормализована в вершинном, делаем это здесь
vec3 normal = normalize(fragmentDir); // На планете-сфере нормаль совпадает с направлением от центра
float diff = max(dot(normal, lightToSource), 0.0);
float ambient = 0.3; // Базовая освещенность ночной стороны
float surfaceLightIntensity = diff + ambient;
// --- 2. Динамический цвет тумана ---
// Синхронизируем туман с атмосферой: днем голубой, ночью темно-синий
vec3 dayFog = vec3(0.0, 0.5, 1.0);
vec3 nightFog = vec3(0.01, 0.01, 0.04);
vec3 dynamicFogColor = mix(nightFog, dayFog, uPlayerLightFactor);
// --- 3. Основная логика текстур (твой код) ---
vec3 viewDir = normalize(vViewDirTangent);
float height = texture2D(Texture, TexCoord).a;
vec2 p = vec2(viewDir.x, -viewDir.y) * (height * uHeightScale);
vec2 finalTexCoord = TexCoord + p;
float realDist = distance(worldPosition, uViewPos);
float textureMixFactor = clamp((2000.0 - realDist) / 500.0, 0.0, 1.0);
vec4 bakedTextureColor = texture2D(BakedTexture, finalTexCoord);
vec4 textureColor = texture2D(Texture, TexCoord);
vec4 textureFlavoredColor = vec4(textureColor.rgb * Color, 1.0);
if (bakedTextureColor.x < 0.01 && bakedTextureColor.y < 0.01 && bakedTextureColor.z < 0.01) {
textureMixFactor = 1.0;
}
vec4 finalColor = textureMixFactor * textureFlavoredColor + (1.0 - textureMixFactor) * bakedTextureColor;
// --- 4. ПРИМЕНЕНИЕ ОСВЕЩЕНИЯ ---
// Умножаем результат текстурирования на освещенность
finalColor.rgb *= surfaceLightIntensity;
// --- 5. Расчет тумана (с использованием динамического цвета) ---
float h = uDistanceToPlanetSurface;
float fogStart, fogEnd;
if (h >= 1000.0) {
gl_FragColor = vec4(finalColor.rgb, 1.0);
}
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(finalColor.rgb, dynamicFogColor, fogFactor);
gl_FragColor = vec4(mixedColor, 1.0);
}
}
+36
View File
@@ -0,0 +1,36 @@
attribute vec3 vPosition;
attribute vec2 vTexCoord;
attribute vec3 vNormal;
attribute vec3 vTangent;
attribute vec3 vBinormal;
attribute vec3 vColor;
varying vec2 TexCoord;
varying vec3 Color;
varying vec3 vViewDirTangent;
varying vec3 worldPosition;
varying vec3 vWorldNormal;
uniform mat4 ProjectionModelViewMatrix;
uniform mat4 ModelViewMatrix;
uniform highp vec3 uViewPos;
void main() {
vWorldNormal = vNormal;
gl_Position = ProjectionModelViewMatrix * vec4(vPosition, 1.0);
TexCoord = vTexCoord;
vec3 viewDirWorld = normalize(uViewPos - vPosition);
// Строим матрицу перехода из атрибутов
// Так как базис ортонормирован, TBN^-1 == TBN_transpose
vViewDirTangent = vec3(
dot(viewDirWorld, vTangent),
dot(viewDirWorld, vBinormal),
dot(viewDirWorld, vNormal)
);
vec4 viewPosition = ModelViewMatrix * vec4(vPosition.xyz, 1.0);
worldPosition = vPosition;
}
+102
View File
@@ -0,0 +1,102 @@
precision highp float;
// 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);
}
}
+9
View File
@@ -0,0 +1,9 @@
precision mediump float;
uniform sampler2D Texture;
varying vec2 texCoord;
void main()
{
vec4 color = texture2D(Texture,texCoord).rgba;
gl_FragColor = color;
}
+11
View File
@@ -0,0 +1,11 @@
attribute vec3 vPosition;
attribute vec2 vTexCoord;
varying vec2 texCoord;
uniform mat4 ProjectionModelViewMatrix;
void main()
{
gl_Position = ProjectionModelViewMatrix * vec4(vPosition.xyz, 1.0);
texCoord = vTexCoord;
}