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::tapDownStartPos = { 0, 0 };
Vector2f Environment::tapDownCurrentPos = { 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; float Environment::shipVelocity = 0.f;

View File

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

View File

@ -7,7 +7,8 @@
namespace ZL { namespace ZL {
static constexpr float PLANET_RADIUS = 20000.f; 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) --- // --- 1. Дальний диапазон (FAR) ---
static constexpr float FAR_Z_NEAR = 2000.0f; static constexpr float FAR_Z_NEAR = 2000.0f;
@ -17,19 +18,30 @@ namespace ZL {
static constexpr float TRANSITION_FAR_START = 3000.0f; static constexpr float TRANSITION_FAR_START = 3000.0f;
// --- 2. Средний диапазон (MIDDLE) --- // --- 2. Средний диапазон (MIDDLE) ---
static constexpr float MIDDLE_Z_NEAR = 200.f; static constexpr float MIDDLE_Z_NEAR = 500.f;
static constexpr float MIDDLE_Z_FAR = 20000.f; static constexpr float MIDDLE_Z_FAR = 50000.f;
// Дистанция, где ЗАВЕРШАЕТСЯ переход FAR -> MIDDLE и НАЧИНАЕТСЯ MIDDLE -> NEAR // Дистанция, где ЗАВЕРШАЕТСЯ переход FAR -> MIDDLE и НАЧИНАЕТСЯ MIDDLE -> NEAR
static constexpr float TRANSITION_MIDDLE_START = 500.f; static constexpr float TRANSITION_MIDDLE_START = 500.f;
// --- 3. Ближний диапазон (NEAR) --- // --- 3. Ближний диапазон (NEAR) ---
// Новые константы для максимальной точности // Новые константы для максимальной точности
static constexpr float NEAR_Z_NEAR = 5.0f; static constexpr float NEAR_Z_NEAR = 100.0f;
static constexpr float NEAR_Z_FAR = 5000.0f; static constexpr float NEAR_Z_FAR = 10000.0f;
// Дистанция, где ЗАВЕРШАЕТСЯ переход MIDDLE -> NEAR // Дистанция, где ЗАВЕРШАЕТСЯ переход 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) { 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; currentZNear = MIDDLE_Z_NEAR * (1.0f - alpha) + NEAR_Z_NEAR * alpha;
currentZFar = MIDDLE_Z_FAR * (1.0f - alpha) + NEAR_Z_FAR * 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 { else {
// Полностью ближний диапазон (distanceToPlanetSurface <= TRANSITION_NEAR_END) // Полностью ближний диапазон (distanceToPlanetSurface <= TRANSITION_NEAR_END)
currentZNear = NEAR_Z_NEAR; currentZNear = SUPER_NEAR_Z_NEAR;
currentZFar = NEAR_Z_FAR; currentZFar = SUPER_NEAR_Z_FAR;
} }
return { currentZNear, currentZFar }; return { currentZNear, currentZFar };
@ -118,6 +143,7 @@ namespace ZL {
int Y = (int)floor(y) & 255; int Y = (int)floor(y) & 255;
int Z = (int)floor(z) & 255; int Z = (int)floor(z) & 255;
x -= floor(x); x -= floor(x);
y -= floor(y); y -= floor(y);
z -= floor(z); z -= floor(z);
@ -139,6 +165,7 @@ namespace ZL {
// Частота шума (чем больше, тем больше "холмов") // Частота шума (чем больше, тем больше "холмов")
float frequency = 7.0f; float frequency = 7.0f;
// Получаем значение шума (обычно от -1 до 1) // Получаем значение шума (обычно от -1 до 1)
float noiseValue = noise(pos.v[0] * frequency, pos.v[1] * frequency, pos.v[2] * frequency); 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 // Масштабируем: хотим отклонение от 1.0 до 1.1
// Значит амплитуда = 0.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; return height;
} }
@ -193,17 +221,10 @@ namespace ZL {
sandTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/sand.png", "")); sandTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/sand.png", ""));
//sandTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/rock.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 = generateSphere(5);
planetAtmosphere.data.TexCoordData.clear(); planetAtmosphere.data.Scale(PLANET_RADIUS*1.03);
planetAtmosphere.data.ColorData.push_back({ 0,0.5,1 }); planetAtmosphere.data.Move(PLANET_CENTER_OFFSET);
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.RefreshVBO(); planetAtmosphere.RefreshVBO();
} }
@ -268,12 +289,15 @@ namespace ZL {
float dist = distanceToPlanetSurface(); float dist = distanceToPlanetSurface();
renderer.RenderUniform1f("uDistanceToPlanetSurface", dist); renderer.RenderUniform1f("uDistanceToPlanetSurface", dist);
renderer.RenderUniform1f("uCurrentZFar", currentZFar); renderer.RenderUniform1f("uCurrentZFar", currentZFar);
//glEnable(GL_BLEND);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE);// Аддитивное смешивание для эффекта свечения
glBindTexture(GL_TEXTURE_2D, sandTexture->getTexID()); glBindTexture(GL_TEXTURE_2D, sandTexture->getTexID());
renderer.DrawVertexRenderStruct(planetRenderStruct); renderer.DrawVertexRenderStruct(planetRenderStruct);
//glDisable(GL_BLEND);
CheckGlError(); CheckGlError();
@ -287,20 +311,21 @@ namespace ZL {
renderer.shaderManager.PopShader(); renderer.shaderManager.PopShader();
CheckGlError(); CheckGlError();
//drawAtmosphere(renderer); drawAtmosphere(renderer);
} }
void PlanetObject::drawAtmosphere(Renderer& renderer) { void PlanetObject::drawAtmosphere(Renderer& renderer) {
static const std::string defaultShaderName = "defaultAtmosphere"; static const std::string defaultShaderName = "defaultAtmosphere";
static const std::string vPositionName = "vPosition"; static const std::string vPositionName = "vPosition";
static const std::string vColorName = "vColor"; static const std::string vNormalName = "vNormal";
//glClear(GL_DEPTH_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT); glDepthMask(GL_FALSE);
renderer.shaderManager.PushShader(defaultShaderName); renderer.shaderManager.PushShader(defaultShaderName);
renderer.EnableVertexAttribArray(vPositionName); renderer.EnableVertexAttribArray(vPositionName);
renderer.EnableVertexAttribArray(vColorName); renderer.EnableVertexAttribArray(vNormalName);
const auto zRange = calculateZRange(Environment::shipPosition); const auto zRange = calculateZRange(Environment::shipPosition);
const float currentZNear = zRange.first; const float currentZNear = zRange.first;
@ -317,74 +342,27 @@ namespace ZL {
renderer.RotateMatrix(Environment::inverseShipMatrix); renderer.RotateMatrix(Environment::inverseShipMatrix);
renderer.TranslateMatrix(-Environment::shipPosition); renderer.TranslateMatrix(-Environment::shipPosition);
Matrix4f projMatrix = renderer.GetProjectionModelViewMatrix(); const Matrix4f viewMatrix = renderer.GetCurrentModelViewMatrix();
Matrix4f modelViewMatrix = renderer.GetCurrentModelViewMatrix();
Vector3f color = { 0.0, 0.5, 1.0 };
renderer.PopMatrix(); renderer.RenderUniform3fv("uColor", &color.v[0]);
renderer.PopProjectionMatrix();
renderer.PushProjectionMatrix((Environment::width), static_cast<float>(Environment::height), -1, 1); renderer.RenderUniformMatrix4fv("ModelViewMatrix", false, &viewMatrix.m[0]);
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]);
float dist = distanceToPlanetSurface();
renderer.RenderUniform1f("uDistanceToPlanetSurface", dist);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);// Аддитивное смешивание для эффекта свечения glBlendFunc(GL_SRC_ALPHA, GL_ONE);// Аддитивное смешивание для эффекта свечения
renderer.DrawVertexRenderStruct(planetAtmosphere); renderer.DrawVertexRenderStruct(planetAtmosphere);
glDisable(GL_BLEND); glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
renderer.PopMatrix(); renderer.PopMatrix();
renderer.PopProjectionMatrix(); renderer.PopProjectionMatrix();
renderer.DisableVertexAttribArray(vNormalName);
/*
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(vPositionName); renderer.DisableVertexAttribArray(vPositionName);
renderer.shaderManager.PopShader(); renderer.shaderManager.PopShader();
CheckGlError(); 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 varying vec3 vViewNormal;
const float FADE_WIDTH = 0.05; // Например, 5% от радиуса для плавного перехода varying vec3 vViewPosition;
void main() void main()
{ {
// 1. Расчет расстояния от фрагмента до центра // --- 1. Расчет плотности по Френелю (краевой эффект) ---
float distanceToCenter = length(vViewPosition - uCenterPos); vec3 viewVector = normalize(-vViewPosition);
float NdotV = dot(vViewNormal, viewVector);
float factor = 1.0 - abs(NdotV);
float atmosphereDensity = pow(factor, 5.0);
// 2. Расчет границ для плавного перехода // --- 2. Расчет коэффициента затухания по дистанции ---
// Начало спада (R)
float startRadius = uCenterRadius;
// Конец спада (R + dR)
float endRadius = uCenterRadius + FADE_WIDTH * uCenterRadius;
// 3. Расчет коэффициента прозрачности с помощью smoothstep float distanceFactor = 1.0;
// smoothstep(edge0, edge1, x) возвращает 0.0, если x < edge0,
// 1.0, если x > edge1, и плавно меняется между ними.
// Нам нужно, чтобы alpha была 0.5 при startRadius и 0.0 при endRadius. if (uDistanceToPlanetSurface > DIST_FOG_MAX)
// Если мы используем smoothstep(start, end, distance), то получим: {
// - 0.0, когда distance < start // Дистанция > 2000.0: Полностью видно (Factor = 1.0)
// - 1.0, когда distance > end distanceFactor = 1.0;
// Нам нужен обратный результат (1.0 - smoothstep), чтобы 0.5 было внутри, а 0.0 - снаружи. }
else if (uDistanceToPlanetSurface < DIST_FOG_MIN)
// Вычисляем множитель прозрачности (от 1.0 до 0.0) {
float fadeFactor = 1.0 - smoothstep(startRadius, endRadius, distanceToCenter); // Дистанция < 1000.0: Полностью не видно (Factor = 0.0)
distanceFactor = 0.0;
// 4. Применение нового alpha }
// Если fadeFactor = 1.0 (внутри R), alpha = 0.5 * 1.0 = 0.5 else
// Если fadeFactor = 0.0 (вне R+dR), alpha = 0.5 * 0.0 = 0.0 {
// Если между ними - плавная интерполяция. // Плавный переход (линейная интерполяция)
float finalAlpha = 0.5 * fadeFactor; // normalizedDistance: от 0.0 (на DIST_FOG_MIN) до 1.0 (на DIST_FOG_MAX)
float normalizedDistance = (uDistanceToPlanetSurface - DIST_FOG_MIN) / (DIST_FOG_MAX - DIST_FOG_MIN);
gl_FragColor = vec4(color, 0.5);
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 vPosition;
attribute vec3 vColor; attribute vec3 vNormal; // <-- Новый атрибут
uniform mat4 ProjectionModelViewMatrix; uniform mat4 ProjectionModelViewMatrix;
uniform mat4 ModelViewMatrix; uniform mat4 ModelViewMatrix;
varying vec3 color; // Выходные переменные (передаются во фрагментный шейдер)
varying vec3 vViewPosition; // Новая переменная: позиция вершины в пространстве вида varying vec3 vViewNormal;
varying vec3 vViewPosition;
void main() void main()
{ {
// Расчет позиции в пространстве отсечения (как у вас) // 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); gl_Position = ProjectionModelViewMatrix * vec4(vPosition.xyz, 1.0);
// Передача позиции в пространстве вида во фрагментный шейдер
vViewPosition = vec3(ModelViewMatrix * vec4(vPosition.xyz, 1.0));
//vViewPosition = vPosition.xyz;
color = vColor;
} }

View File

@ -9,6 +9,7 @@ varying vec3 color;
varying vec3 normal; varying vec3 normal;
varying vec2 TexCoord; varying vec2 TexCoord;
varying float viewZ; // <--- НОВОЕ: Z-координата в пространстве вида (View Space) varying float viewZ; // <--- НОВОЕ: Z-координата в пространстве вида (View Space)
varying vec3 pos;
uniform mat4 ProjectionModelViewMatrix; uniform mat4 ProjectionModelViewMatrix;
uniform mat4 ModelViewMatrix; // Нужна для преобразования vPosition в View Space uniform mat4 ModelViewMatrix; // Нужна для преобразования vPosition в View Space
@ -24,6 +25,8 @@ void main()
// удобнее использовать положительное значение. // удобнее использовать положительное значение.
viewZ = -viewPosition.z; viewZ = -viewPosition.z;
pos = vPosition.xyz;
gl_Position = ProjectionModelViewMatrix * vec4(vPosition.xyz, 1.0); gl_Position = ProjectionModelViewMatrix * vec4(vPosition.xyz, 1.0);
normal = normalize((ModelViewMatrix * vec4(vNormal, 0.0)).xyz); normal = normalize((ModelViewMatrix * vec4(vNormal, 0.0)).xyz);

View File

@ -4,6 +4,7 @@ varying vec3 color;
varying vec3 normal; varying vec3 normal;
varying vec2 TexCoord; varying vec2 TexCoord;
varying float viewZ; varying float viewZ;
varying vec3 pos;
uniform sampler2D Texture; uniform sampler2D Texture;
uniform vec3 uLightDirection; uniform vec3 uLightDirection;
@ -64,15 +65,26 @@ void main()
// гарантируя, что все, что подходит к границе uCurrentZFar, будет скрыто. // гарантируя, что все, что подходит к границе uCurrentZFar, будет скрыто.
// Точка начала тумана: 90% от uCurrentZFar // Точка начала тумана: 90% от uCurrentZFar
float farFogStart = 2000.0; float farFogStart = 2000.f;//uCurrentZFar * 0.7;
// Длина перехода тумана: 10% от uCurrentZFar // Длина перехода тумана: 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; float farFogFactor = 0.0;
if (depthRange > 0.0) { if (depthRange > 0.0) {
// Нормализация Z-глубины: 0.0f при farFogStart, 1.0f при farFogStart + depthRange // Нормализация 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. Объединение --- // --- 3.3. Объединение ---
@ -85,5 +97,9 @@ void main()
// 4. Смешивание цвета с туманом // 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);
} }