From 7a1961b5d1e024686124c7e9998f18924b9137d9 Mon Sep 17 00:00:00 2001 From: Vladislav Khorev Date: Sun, 14 Dec 2025 13:00:39 +0300 Subject: [PATCH] Somehow planet is working --- Environment.cpp | 2 +- Game.cpp | 2 +- PlanetObject.cpp | 144 +++++++++------------- shaders/defaultAtmosphere.fragment | 75 ++++++----- shaders/defaultAtmosphere.vertex | 30 +++-- shaders/defaultColor_fog.vertex | 3 + shaders/defaultColor_fog_desktop.fragment | 24 +++- 7 files changed, 146 insertions(+), 134 deletions(-) diff --git a/Environment.cpp b/Environment.cpp index 7e06bc4..8d6479d 100644 --- a/Environment.cpp +++ b/Environment.cpp @@ -31,7 +31,7 @@ bool Environment::tapDownHold = false; Vector2f Environment::tapDownStartPos = { 0, 0 }; Vector2f Environment::tapDownCurrentPos = { 0, 0 }; -Vector3f Environment::shipPosition = {0,0,0}; +Vector3f Environment::shipPosition = {0,0,45000.f}; float Environment::shipVelocity = 0.f; diff --git a/Game.cpp b/Game.cpp index 885ad64..dcc305c 100755 --- a/Game.cpp +++ b/Game.cpp @@ -488,7 +488,7 @@ namespace ZL glClear(GL_DEPTH_BUFFER_BIT); } drawShip(); - drawBoxes(); + //drawBoxes(); drawUI(); diff --git a/PlanetObject.cpp b/PlanetObject.cpp index a7e8bd1..22e368f 100644 --- a/PlanetObject.cpp +++ b/PlanetObject.cpp @@ -7,7 +7,8 @@ namespace ZL { static constexpr float PLANET_RADIUS = 20000.f; - static Vector3f PLANET_CENTER_OFFSET = Vector3f{ 0.f, 0.f, -45000.f }; + static Vector3f PLANET_CENTER_OFFSET = Vector3f{ 0.f, 0.f, 0.0f }; + //static Vector3f PLANET_CENTER_OFFSET = Vector3f{ 0.f, 0.f, -45000.f }; // --- 1. Дальний диапазон (FAR) --- static constexpr float FAR_Z_NEAR = 2000.0f; @@ -17,19 +18,30 @@ namespace ZL { static constexpr float TRANSITION_FAR_START = 3000.0f; // --- 2. Средний диапазон (MIDDLE) --- - static constexpr float MIDDLE_Z_NEAR = 200.f; - static constexpr float MIDDLE_Z_FAR = 20000.f; + static constexpr float MIDDLE_Z_NEAR = 500.f; + static constexpr float MIDDLE_Z_FAR = 50000.f; + // Дистанция, где ЗАВЕРШАЕТСЯ переход FAR -> MIDDLE и НАЧИНАЕТСЯ MIDDLE -> NEAR static constexpr float TRANSITION_MIDDLE_START = 500.f; // --- 3. Ближний диапазон (NEAR) --- // Новые константы для максимальной точности - static constexpr float NEAR_Z_NEAR = 5.0f; - static constexpr float NEAR_Z_FAR = 5000.0f; + static constexpr float NEAR_Z_NEAR = 100.0f; + static constexpr float NEAR_Z_FAR = 10000.0f; + // Дистанция, где ЗАВЕРШАЕТСЯ переход MIDDLE -> NEAR - static constexpr float TRANSITION_NEAR_END = 40.f; + static constexpr float TRANSITION_NEAR_END = 100.f; + + // --- 3. Ближний диапазон (NEAR) --- +// Новые константы для максимальной точности + static constexpr float SUPER_NEAR_Z_NEAR = 5.0f; + static constexpr float SUPER_NEAR_Z_FAR = 5000.0f; + + + // Дистанция, где ЗАВЕРШАЕТСЯ переход MIDDLE -> NEAR + static constexpr float TRANSITION_SUPER_NEAR_END = 10.f; std::pair calculateZRange(const Vector3f& shipPosition) { @@ -76,11 +88,24 @@ namespace ZL { currentZNear = MIDDLE_Z_NEAR * (1.0f - alpha) + NEAR_Z_NEAR * alpha; currentZFar = MIDDLE_Z_FAR * (1.0f - alpha) + NEAR_Z_FAR * alpha; + } + else if (distanceToPlanetSurface > TRANSITION_SUPER_NEAR_END) { + // Плавный переход от MIDDLE к NEAR + const float transitionLength = TRANSITION_NEAR_END - TRANSITION_SUPER_NEAR_END; + + // Нормализация расстояния, 0 при TRANSITION_MIDDLE_START (Далеко), 1 при TRANSITION_NEAR_END (Близко) + float normalizedDist = (distanceToPlanetSurface - TRANSITION_SUPER_NEAR_END) / transitionLength; + alpha = 1.0f - normalizedDist; // alpha = 0 (Далеко) ... 1 (Близко) + + // Интерполяция: MIDDLE * (1-alpha) + NEAR * alpha + currentZNear = NEAR_Z_NEAR * (1.0f - alpha) + SUPER_NEAR_Z_NEAR * alpha; + currentZFar = NEAR_Z_FAR * (1.0f - alpha) + SUPER_NEAR_Z_FAR * alpha; + } else { // Полностью ближний диапазон (distanceToPlanetSurface <= TRANSITION_NEAR_END) - currentZNear = NEAR_Z_NEAR; - currentZFar = NEAR_Z_FAR; + currentZNear = SUPER_NEAR_Z_NEAR; + currentZFar = SUPER_NEAR_Z_FAR; } return { currentZNear, currentZFar }; @@ -118,6 +143,7 @@ namespace ZL { int Y = (int)floor(y) & 255; int Z = (int)floor(z) & 255; + x -= floor(x); y -= floor(y); z -= floor(z); @@ -139,6 +165,7 @@ namespace ZL { // Частота шума (чем больше, тем больше "холмов") float frequency = 7.0f; + // Получаем значение шума (обычно от -1 до 1) float noiseValue = noise(pos.v[0] * frequency, pos.v[1] * frequency, pos.v[2] * frequency); @@ -147,7 +174,8 @@ namespace ZL { // Масштабируем: хотим отклонение от 1.0 до 1.1 // Значит амплитуда = 0.1 - float height = 1.0f + (noiseValue * 0.01f); // * 0.2 даст вариацию высоты + float height = 1.0f; // * 0.2 даст вариацию высоты + //float height = 1.0f - (noiseValue * 0.01f); // * 0.2 даст вариацию высоты return height; } @@ -171,7 +199,7 @@ namespace ZL { return distanceToPlanetSurface; } - + PlanetObject::PlanetObject() : perlin(77777) @@ -193,17 +221,10 @@ namespace ZL { sandTexture = std::make_unique(CreateTextureDataFromPng("./resources/sand.png", "")); //sandTexture = std::make_unique(CreateTextureDataFromPng("./resources/rock.png", "")); - planetAtmosphere.data = CreateRect2D({ 0.f, 0.f }, { 1.f, 1.f }, 0.f); - planetAtmosphere.data.TexCoordData.clear(); - planetAtmosphere.data.ColorData.push_back({ 0,0.5,1 }); - planetAtmosphere.data.ColorData.push_back({ 0,0.5,1 }); - planetAtmosphere.data.ColorData.push_back({ 0,0.5,1 }); - planetAtmosphere.data.ColorData.push_back({ 0,0.5,1 }); - planetAtmosphere.data.ColorData.push_back({ 0,0.5,1 }); - planetAtmosphere.data.ColorData.push_back({ 0,0.5,1 }); - planetAtmosphere.data.Scale(1000.f); - //planetAtmosphere.data.Scale(PLANET_RADIUS*1.25f); - //planetAtmosphere.data.Move(PLANET_CENTER_OFFSET); + planetAtmosphere.data = generateSphere(5); + planetAtmosphere.data.Scale(PLANET_RADIUS*1.03); + planetAtmosphere.data.Move(PLANET_CENTER_OFFSET); + planetAtmosphere.RefreshVBO(); } @@ -268,12 +289,15 @@ namespace ZL { float dist = distanceToPlanetSurface(); + renderer.RenderUniform1f("uDistanceToPlanetSurface", dist); renderer.RenderUniform1f("uCurrentZFar", currentZFar); + //glEnable(GL_BLEND); + //glBlendFunc(GL_SRC_ALPHA, GL_ONE);// Аддитивное смешивание для эффекта свечения glBindTexture(GL_TEXTURE_2D, sandTexture->getTexID()); renderer.DrawVertexRenderStruct(planetRenderStruct); - + //glDisable(GL_BLEND); CheckGlError(); @@ -287,20 +311,21 @@ namespace ZL { renderer.shaderManager.PopShader(); CheckGlError(); - //drawAtmosphere(renderer); + drawAtmosphere(renderer); } void PlanetObject::drawAtmosphere(Renderer& renderer) { static const std::string defaultShaderName = "defaultAtmosphere"; static const std::string vPositionName = "vPosition"; - static const std::string vColorName = "vColor"; - - glClear(GL_DEPTH_BUFFER_BIT); - + static const std::string vNormalName = "vNormal"; + //glClear(GL_DEPTH_BUFFER_BIT); + glDepthMask(GL_FALSE); renderer.shaderManager.PushShader(defaultShaderName); renderer.EnableVertexAttribArray(vPositionName); - renderer.EnableVertexAttribArray(vColorName); + renderer.EnableVertexAttribArray(vNormalName); + + const auto zRange = calculateZRange(Environment::shipPosition); const float currentZNear = zRange.first; @@ -317,74 +342,27 @@ namespace ZL { renderer.RotateMatrix(Environment::inverseShipMatrix); renderer.TranslateMatrix(-Environment::shipPosition); - Matrix4f projMatrix = renderer.GetProjectionModelViewMatrix(); - Matrix4f modelViewMatrix = renderer.GetCurrentModelViewMatrix(); + const Matrix4f viewMatrix = renderer.GetCurrentModelViewMatrix(); + Vector3f color = { 0.0, 0.5, 1.0 }; - renderer.PopMatrix(); - renderer.PopProjectionMatrix(); + renderer.RenderUniform3fv("uColor", &color.v[0]); - renderer.PushProjectionMatrix((Environment::width), static_cast(Environment::height), -1, 1); - renderer.PushMatrix(); - renderer.LoadIdentity(); - - // Преобразуем центр планеты в экранные координаты - int screenX = 0; - int screenY = 0; - worldToScreenCoordinates( - PLANET_CENTER_OFFSET, - projMatrix, - Environment::width, - Environment::height, - screenX, - screenY - ); - - // Позиция центра в пикселях - Vector3f centerPos = Vector3f(static_cast(screenX), static_cast(screenY), 0.0f); - - renderer.TranslateMatrix(centerPos); - renderer.RenderUniform1f("uCenterRadius", 0.f); - renderer.RenderUniform3fv("uCenterPos", ¢erPos.v[0]); + renderer.RenderUniformMatrix4fv("ModelViewMatrix", false, &viewMatrix.m[0]); + float dist = distanceToPlanetSurface(); + renderer.RenderUniform1f("uDistanceToPlanetSurface", dist); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE);// Аддитивное смешивание для эффекта свечения renderer.DrawVertexRenderStruct(planetAtmosphere); glDisable(GL_BLEND); + glDepthMask(GL_TRUE); renderer.PopMatrix(); renderer.PopProjectionMatrix(); - - /* - renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5, - static_cast(Environment::width) / static_cast(Environment::height), - currentZNear, currentZFar); - - renderer.PushMatrix(); - renderer.LoadIdentity(); - renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom }); - renderer.RotateMatrix(Environment::inverseShipMatrix); - renderer.TranslateMatrix(-Environment::shipPosition); - - float centerRadius = PLANET_RADIUS*1.2f; - - Vector3f centerPos = PLANET_CENTER_OFFSET; - - - renderer.RenderUniform1f("uCenterRadius", centerRadius); - renderer.RenderUniform3fv("uCenterPos", ¢erPos.v[0]); - - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE);// Аддитивное смешивание для эффекта свечения - - renderer.DrawVertexRenderStruct(planetAtmosphere); - glDisable(GL_BLEND); - renderer.PopMatrix(); - renderer.PopProjectionMatrix();*/ - renderer.DisableVertexAttribArray(vColorName); + renderer.DisableVertexAttribArray(vNormalName); renderer.DisableVertexAttribArray(vPositionName); renderer.shaderManager.PopShader(); CheckGlError(); diff --git a/shaders/defaultAtmosphere.fragment b/shaders/defaultAtmosphere.fragment index 324256f..04d43b2 100644 --- a/shaders/defaultAtmosphere.fragment +++ b/shaders/defaultAtmosphere.fragment @@ -1,41 +1,48 @@ -varying vec3 color; -varying vec3 vViewPosition; // Получаем позицию фрагмента в пространстве вида +// Фрагментный шейдер: +uniform vec3 uColor; +uniform float uDistanceToPlanetSurface; // Расстояние корабля до поверхности -uniform vec3 uCenterPos; // Центр планеты/атмосферы (в пространстве вида) -uniform float uCenterRadius; // Радиус атмосферы (точка, где прозрачность = 0.5) +// Константы затухания, определенные прямо в шейдере +const float DIST_FOG_MAX = 2000.0; +const float DIST_FOG_MIN = 1000.0; -// Определение зоны плавного спада alpha -const float FADE_WIDTH = 0.05; // Например, 5% от радиуса для плавного перехода +varying vec3 vViewNormal; +varying vec3 vViewPosition; void main() { - // 1. Расчет расстояния от фрагмента до центра - float distanceToCenter = length(vViewPosition - uCenterPos); - - // 2. Расчет границ для плавного перехода - // Начало спада (R) - float startRadius = uCenterRadius; - // Конец спада (R + dR) - float endRadius = uCenterRadius + FADE_WIDTH * uCenterRadius; + // --- 1. Расчет плотности по Френелю (краевой эффект) --- + vec3 viewVector = normalize(-vViewPosition); + float NdotV = dot(vViewNormal, viewVector); + float factor = 1.0 - abs(NdotV); + float atmosphereDensity = pow(factor, 5.0); - // 3. Расчет коэффициента прозрачности с помощью smoothstep - // smoothstep(edge0, edge1, x) возвращает 0.0, если x < edge0, - // 1.0, если x > edge1, и плавно меняется между ними. - - // Нам нужно, чтобы alpha была 0.5 при startRadius и 0.0 при endRadius. - // Если мы используем smoothstep(start, end, distance), то получим: - // - 0.0, когда distance < start - // - 1.0, когда distance > end - // Нам нужен обратный результат (1.0 - smoothstep), чтобы 0.5 было внутри, а 0.0 - снаружи. - - // Вычисляем множитель прозрачности (от 1.0 до 0.0) - float fadeFactor = 1.0 - smoothstep(startRadius, endRadius, distanceToCenter); - - // 4. Применение нового alpha - // Если fadeFactor = 1.0 (внутри R), alpha = 0.5 * 1.0 = 0.5 - // Если fadeFactor = 0.0 (вне R+dR), alpha = 0.5 * 0.0 = 0.0 - // Если между ними - плавная интерполяция. - float finalAlpha = 0.5 * fadeFactor; - - gl_FragColor = vec4(color, 0.5); + // --- 2. Расчет коэффициента затухания по дистанции --- + + float distanceFactor = 1.0; + + if (uDistanceToPlanetSurface > DIST_FOG_MAX) + { + // Дистанция > 2000.0: Полностью видно (Factor = 1.0) + distanceFactor = 1.0; + } + else if (uDistanceToPlanetSurface < DIST_FOG_MIN) + { + // Дистанция < 1000.0: Полностью не видно (Factor = 0.0) + distanceFactor = 0.0; + } + else + { + // Плавный переход (линейная интерполяция) + // normalizedDistance: от 0.0 (на DIST_FOG_MIN) до 1.0 (на DIST_FOG_MAX) + float normalizedDistance = (uDistanceToPlanetSurface - DIST_FOG_MIN) / (DIST_FOG_MAX - DIST_FOG_MIN); + + distanceFactor = clamp(normalizedDistance, 0.0, 1.0); + } + + // --- 3. Финальный цвет и прозрачность --- + + float finalAlpha = atmosphereDensity * distanceFactor; + + gl_FragColor = vec4(uColor, finalAlpha); } \ No newline at end of file diff --git a/shaders/defaultAtmosphere.vertex b/shaders/defaultAtmosphere.vertex index 629ebe8..2faba8b 100644 --- a/shaders/defaultAtmosphere.vertex +++ b/shaders/defaultAtmosphere.vertex @@ -1,20 +1,28 @@ +// Вершинный шейдер: attribute vec3 vPosition; -attribute vec3 vColor; +attribute vec3 vNormal; // <-- Новый атрибут uniform mat4 ProjectionModelViewMatrix; uniform mat4 ModelViewMatrix; -varying vec3 color; -varying vec3 vViewPosition; // Новая переменная: позиция вершины в пространстве вида +// Выходные переменные (передаются во фрагментный шейдер) +varying vec3 vViewNormal; +varying vec3 vViewPosition; void main() { - // Расчет позиции в пространстве отсечения (как у вас) - gl_Position = ProjectionModelViewMatrix * vec4(vPosition.xyz, 1.0); - - // Передача позиции в пространстве вида во фрагментный шейдер - vViewPosition = vec3(ModelViewMatrix * vec4(vPosition.xyz, 1.0)); - //vViewPosition = vPosition.xyz; - - color = vColor; + // 1. Позиция в пространстве вида (View Space) + vec4 positionView = ModelViewMatrix * vec4(vPosition, 1.0); + vViewPosition = positionView.xyz; + + // 2. Нормаль в пространстве вида (View Space) + // Преобразуем нормаль, используя ModelViewMatrix. Поскольку нормаль - это вектор, + // трансляционная часть (четвертый столбец) матрицы нам не нужна. + // Если бы было неединообразное масштабирование, потребовалась бы Inverse Transpose Matrix. + // В вашем случае, где есть только униформное масштабирование и вращение, + // достаточно просто умножить на ModelViewMatrix: + vViewNormal = normalize((ModelViewMatrix * vec4(vNormal, 0.0)).xyz); + // W=0.0 для векторов, чтобы игнорировать трансляцию + + gl_Position = ProjectionModelViewMatrix * vec4(vPosition.xyz, 1.0); } \ No newline at end of file diff --git a/shaders/defaultColor_fog.vertex b/shaders/defaultColor_fog.vertex index eadfe41..d34873f 100644 --- a/shaders/defaultColor_fog.vertex +++ b/shaders/defaultColor_fog.vertex @@ -9,6 +9,7 @@ varying vec3 color; varying vec3 normal; varying vec2 TexCoord; varying float viewZ; // <--- НОВОЕ: Z-координата в пространстве вида (View Space) +varying vec3 pos; uniform mat4 ProjectionModelViewMatrix; uniform mat4 ModelViewMatrix; // Нужна для преобразования vPosition в View Space @@ -23,6 +24,8 @@ void main() // в пространстве вида обычно отрицательна, но для расчета тумана // удобнее использовать положительное значение. viewZ = -viewPosition.z; + + pos = vPosition.xyz; gl_Position = ProjectionModelViewMatrix * vec4(vPosition.xyz, 1.0); diff --git a/shaders/defaultColor_fog_desktop.fragment b/shaders/defaultColor_fog_desktop.fragment index cc24c23..09bf95f 100644 --- a/shaders/defaultColor_fog_desktop.fragment +++ b/shaders/defaultColor_fog_desktop.fragment @@ -4,6 +4,7 @@ varying vec3 color; varying vec3 normal; varying vec2 TexCoord; varying float viewZ; +varying vec3 pos; uniform sampler2D Texture; uniform vec3 uLightDirection; @@ -64,15 +65,26 @@ void main() // гарантируя, что все, что подходит к границе uCurrentZFar, будет скрыто. // Точка начала тумана: 90% от uCurrentZFar - float farFogStart = 2000.0; + float farFogStart = 2000.f;//uCurrentZFar * 0.7; // Длина перехода тумана: 10% от uCurrentZFar - float depthRange = 2500.0; + float depthRange = 2000.f;//uCurrentZFar * 0.25; + + if (abs(uDistanceToPlanetSurface) < 410.f) + { + farFogStart = 1800.f * abs(uDistanceToPlanetSurface-10.f) * 0.0025 + 200.f; + depthRange = farFogStart; + } + if (abs(uDistanceToPlanetSurface) < 10.f) + { + farFogStart = 200.f; + depthRange = 200.f; + } float farFogFactor = 0.0; if (depthRange > 0.0) { // Нормализация Z-глубины: 0.0f при farFogStart, 1.0f при farFogStart + depthRange - farFogFactor = clamp((viewZ - farFogStart) / depthRange, 0.0, 1.0); + farFogFactor = clamp((abs(viewZ) - farFogStart) / depthRange, 0.0, 1.0); } // --- 3.3. Объединение --- @@ -85,5 +97,9 @@ void main() // 4. Смешивание цвета с туманом - gl_FragColor = mix(vec4(litColor, 1.0), FOG_COLOR, fogFactor); + + //vec3 mountainColor = vec3((length(pos+vec3(0.0,0.0,45000.0))-20000.0)/100.0, 0.5,0.0); + gl_FragColor = mix(vec4(finalColor.rgb, 0.5), FOG_COLOR, fogFactor); + //gl_FragColor = vec4((length(pos+vec3(0.0,0.0,45000.0))-20000.0)/100.0, 0.0,0.0, 1.0); + //gl_FragColor = vec4(fogFactor, 0.5,0.5, 1.0); } \ No newline at end of file