Somehow planet is working

This commit is contained in:
Vladislav Khorev 2025-12-14 13:00:39 +03:00
parent af550f56a7
commit 7a1961b5d1
7 changed files with 146 additions and 134 deletions

View File

@ -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;

View File

@ -488,7 +488,7 @@ namespace ZL
glClear(GL_DEPTH_BUFFER_BIT);
}
drawShip();
drawBoxes();
//drawBoxes();
drawUI();

View File

@ -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<float, float> 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<Texture>(CreateTextureDataFromPng("./resources/sand.png", ""));
//sandTexture = std::make_unique<Texture>(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<float>(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<float>(screenX), static_cast<float>(screenY), 0.0f);
renderer.TranslateMatrix(centerPos);
renderer.RenderUniform1f("uCenterRadius", 0.f);
renderer.RenderUniform3fv("uCenterPos", &centerPos.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<float>(Environment::width) / static_cast<float>(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", &centerPos.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();

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}