diff --git a/Game.cpp b/Game.cpp index 658d41e..cac9e95 100755 --- a/Game.cpp +++ b/Game.cpp @@ -469,7 +469,7 @@ namespace ZL float skyPercent = 0.0; float distance = planetObject.distanceToPlanetSurface(); - if (distance > 2000.f) + if (distance > 1900.f) { skyPercent = 0.0f; } @@ -479,7 +479,7 @@ namespace ZL } else { - skyPercent = (2000.f - distance) / 1000.f; + skyPercent = (1900.f - distance) / 900.f; } drawCubemap(skyPercent); diff --git a/PlanetObject.cpp b/PlanetObject.cpp index 1c6eab5..e1fe455 100644 --- a/PlanetObject.cpp +++ b/PlanetObject.cpp @@ -19,7 +19,7 @@ namespace ZL { // --- 2. Средний диапазон (MIDDLE) --- static constexpr float MIDDLE_Z_NEAR = 500.f; - static constexpr float MIDDLE_Z_FAR = 50000.f; + static constexpr float MIDDLE_Z_FAR = 100000.f; // Дистанция, где ЗАВЕРШАЕТСЯ переход FAR -> MIDDLE и НАЧИНАЕТСЯ MIDDLE -> NEAR @@ -28,7 +28,7 @@ namespace ZL { // --- 3. Ближний диапазон (NEAR) --- // Новые константы для максимальной точности static constexpr float NEAR_Z_NEAR = 100.0f; - static constexpr float NEAR_Z_FAR = 10000.0f; + static constexpr float NEAR_Z_FAR = 20000.0f; // Дистанция, где ЗАВЕРШАЕТСЯ переход MIDDLE -> NEAR @@ -36,12 +36,12 @@ namespace ZL { // --- 3. Ближний диапазон (NEAR) --- // Новые константы для максимальной точности - static constexpr float SUPER_NEAR_Z_NEAR = 5.0f; - static constexpr float SUPER_NEAR_Z_FAR = 5000.0f; + static constexpr float SUPER_NEAR_Z_NEAR = 30.0f; + static constexpr float SUPER_NEAR_Z_FAR = 6000.0f; // Дистанция, где ЗАВЕРШАЕТСЯ переход MIDDLE -> NEAR - static constexpr float TRANSITION_SUPER_NEAR_END = 10.f; + static constexpr float TRANSITION_SUPER_NEAR_END = 30.f; VertexID generateEdgeID(const VertexID& id1, const VertexID& id2) { @@ -70,44 +70,35 @@ namespace ZL { // Плавный переход от FAR к MIDDLE const float transitionLength = TRANSITION_FAR_START - TRANSITION_MIDDLE_START; - // Нормализация расстояния, 0 при TRANSITION_FAR_START (Далеко), 1 при TRANSITION_MIDDLE_START (Близко) float normalizedDist = (dToPlanetSurface - TRANSITION_MIDDLE_START) / transitionLength; alpha = 1.0f - normalizedDist; // alpha = 0 (Далеко) ... 1 (Близко) - // Интерполяция: FAR * (1-alpha) + MIDDLE * alpha currentZNear = FAR_Z_NEAR * (1.0f - alpha) + MIDDLE_Z_NEAR * alpha; currentZFar = FAR_Z_FAR * (1.0f - alpha) + MIDDLE_Z_FAR * alpha; - // Диапазон II: Средне (MIDDLE) -> Близко (NEAR) } else if (dToPlanetSurface > TRANSITION_NEAR_END) { - // Плавный переход от MIDDLE к NEAR const float transitionLength = TRANSITION_MIDDLE_START - TRANSITION_NEAR_END; - // Нормализация расстояния, 0 при TRANSITION_MIDDLE_START (Далеко), 1 при TRANSITION_NEAR_END (Близко) float normalizedDist = (dToPlanetSurface - TRANSITION_NEAR_END) / transitionLength; alpha = 1.0f - normalizedDist; // alpha = 0 (Далеко) ... 1 (Близко) - // Интерполяция: MIDDLE * (1-alpha) + NEAR * alpha currentZNear = MIDDLE_Z_NEAR * (1.0f - alpha) + NEAR_Z_NEAR * alpha; currentZFar = MIDDLE_Z_FAR * (1.0f - alpha) + NEAR_Z_FAR * alpha; } else if (dToPlanetSurface > 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 = (dToPlanetSurface - 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 { - // Полностью ближний диапазон (distancdToPlanetSurfaceeToPlanetSurface <= TRANSITION_NEAR_END) currentZNear = SUPER_NEAR_Z_NEAR; currentZFar = SUPER_NEAR_Z_FAR; } @@ -165,7 +156,7 @@ namespace ZL { lerp(u, grad(p[AB + 1], x, y - 1, z - 1), grad(p[BB + 1], x - 1, y - 1, z - 1)))); } - float PerlinNoise::getSurfaceHeight(Vector3f pos) { + float PerlinNoise::getSurfaceHeight(Vector3f pos, float noiseCoeff) { // Частота шума (чем больше, тем больше "холмов") float frequency = 7.0f; @@ -179,7 +170,7 @@ namespace ZL { // Масштабируем: хотим отклонение от 1.0 до 1.1 // Значит амплитуда = 0.1 //float height = 1.0f; // * 0.2 даст вариацию высоты - float height = 1.0f - (noiseValue * 0.02f); // * 0.2 даст вариацию высоты + float height = 1.0f + (noiseValue * noiseCoeff); // * 0.2 даст вариацию высоты return height; } @@ -224,6 +215,7 @@ namespace ZL { // Используем максимальный LOD для наивысшей точности std::vector targetTriangles = triangleUnderCamera(currentLod); + if (targetTriangles.empty()) { // Если не удалось найти треугольник (например, ошибка в triangleUnderCamera // или корабль очень далеко от сетки), возвращаем старую оценку. @@ -283,7 +275,7 @@ namespace ZL { void PlanetObject::init() { for (int i = 0; i < planetMeshLods.size(); i++) { - planetMeshLods[i] = generateSphere(i); + planetMeshLods[i] = generateSphere(i, 0.02f); planetMeshLods[i].vertexData.Scale(PLANET_RADIUS); planetMeshLods[i].vertexData.Move(PLANET_CENTER_OFFSET); } @@ -294,12 +286,14 @@ namespace ZL { sandTexture = std::make_unique(CreateTextureDataFromPng("./resources/sand.png", "")); //sandTexture = std::make_unique(CreateTextureDataFromPng("./resources/rock.png", "")); - /* - planetAtmosphere.data = generateSphereOld(5); + + planetAtmosphereLod = generateSphere(5, 0); + + planetAtmosphere.data = planetAtmosphereLod.vertexData; planetAtmosphere.data.Scale(PLANET_RADIUS*1.03); planetAtmosphere.data.Move(PLANET_CENTER_OFFSET); - planetAtmosphere.RefreshVBO();*/ + planetAtmosphere.RefreshVBO(); } void PlanetObject::prepareDrawData() { @@ -389,13 +383,14 @@ namespace ZL { glClear(GL_DEPTH_BUFFER_BIT); //-------------------------- - +/* if (planetRenderRedStruct.data.PositionData.size() > 0) { renderer.shaderManager.PushShader(defaultShaderName2); renderer.RenderUniform1i(textureUniformName, 0); renderer.EnableVertexAttribArray(vPositionName); + renderer.EnableVertexAttribArray(vTexCoordName); // 2. Применяем динамическую матрицу проекции @@ -407,8 +402,14 @@ namespace ZL { renderer.LoadIdentity(); renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom }); renderer.RotateMatrix(Environment::inverseShipMatrix); + renderer.TranslateMatrix(-Environment::shipPosition); + + + renderer.RenderUniform1f("uDistanceToPlanetSurface", dist); + renderer.RenderUniform1f("uCurrentZFar", currentZFar); + glBindTexture(GL_TEXTURE_2D, sandTexture->getTexID()); Vector3f color1 = { 1.0, 0.0, 0.0 }; @@ -416,6 +417,8 @@ namespace ZL { renderer.RenderUniform3fv("uColor", &color1.v[0]); renderer.DrawVertexRenderStruct(planetRenderRedStruct); + glBindTexture(GL_TEXTURE_2D, sandTexture->getTexID()); + renderer.RenderUniform3fv("uColor", &color2.v[0]); renderer.DrawVertexRenderStruct(planetRenderYellowStruct); //glDisable(GL_BLEND); @@ -424,13 +427,15 @@ namespace ZL { renderer.PopMatrix(); renderer.PopProjectionMatrix(); + renderer.DisableVertexAttribArray(vTexCoordName); + renderer.DisableVertexAttribArray(vPositionName); renderer.shaderManager.PopShader(); CheckGlError(); - } + }*/ - //drawAtmosphere(renderer); + drawAtmosphere(renderer); } void PlanetObject::drawAtmosphere(Renderer& renderer) { @@ -445,7 +450,6 @@ namespace ZL { renderer.EnableVertexAttribArray(vNormalName); - const auto zRange = calculateZRange(Environment::shipPosition); const float currentZNear = zRange.first; const float currentZFar = zRange.second; @@ -501,6 +505,9 @@ namespace ZL { planetRenderRedStruct.data.PositionData.push_back(planetMeshLods[currentLod].vertexData.PositionData[i * 3]); planetRenderRedStruct.data.PositionData.push_back(planetMeshLods[currentLod].vertexData.PositionData[i * 3 + 1]); planetRenderRedStruct.data.PositionData.push_back(planetMeshLods[currentLod].vertexData.PositionData[i * 3 + 2]); + planetRenderRedStruct.data.TexCoordData.push_back(planetMeshLods[currentLod].vertexData.TexCoordData[i * 3]); + planetRenderRedStruct.data.TexCoordData.push_back(planetMeshLods[currentLod].vertexData.TexCoordData[i * 3 + 1]); + planetRenderRedStruct.data.TexCoordData.push_back(planetMeshLods[currentLod].vertexData.TexCoordData[i * 3 + 2]); usedYellow.insert(i); } @@ -518,6 +525,9 @@ namespace ZL { planetRenderYellowStruct.data.PositionData.push_back(planetMeshLods[currentLod].vertexData.PositionData[n * 3]); planetRenderYellowStruct.data.PositionData.push_back(planetMeshLods[currentLod].vertexData.PositionData[n * 3 + 1]); planetRenderYellowStruct.data.PositionData.push_back(planetMeshLods[currentLod].vertexData.PositionData[n * 3 + 2]); + planetRenderYellowStruct.data.TexCoordData.push_back(planetMeshLods[currentLod].vertexData.TexCoordData[n * 3]); + planetRenderYellowStruct.data.TexCoordData.push_back(planetMeshLods[currentLod].vertexData.TexCoordData[n * 3 + 1]); + planetRenderYellowStruct.data.TexCoordData.push_back(planetMeshLods[currentLod].vertexData.TexCoordData[n * 3 + 2]); } } @@ -558,7 +568,7 @@ namespace ZL { return output; } - Vector3f PlanetObject::calculateSurfaceNormal(Vector3f p_sphere) { + Vector3f PlanetObject::calculateSurfaceNormal(Vector3f p_sphere, float noiseCoeff) { // p_sphere - это нормализованный вектор (точка на идеальной сфере) float theta = 0.01f; // Шаг для "щупанья" соседей (epsilon) @@ -581,9 +591,9 @@ namespace ZL { // Реальные точки на искаженной поверхности // p = dir * height(dir) - Vector3f p0 = p0_dir * perlin.getSurfaceHeight(p0_dir); - Vector3f p1 = p1_dir * perlin.getSurfaceHeight(p1_dir); - Vector3f p2 = p2_dir * perlin.getSurfaceHeight(p2_dir); + Vector3f p0 = p0_dir * perlin.getSurfaceHeight(p0_dir, noiseCoeff); + Vector3f p1 = p1_dir * perlin.getSurfaceHeight(p1_dir, noiseCoeff); + Vector3f p2 = p2_dir * perlin.getSurfaceHeight(p2_dir, noiseCoeff); // Вектора от центральной точки к соседям Vector3f v1 = p1 - p0; @@ -629,7 +639,7 @@ namespace ZL { } - LodLevel PlanetObject::generateSphere(int subdivisions) { + LodLevel PlanetObject::generateSphere(int subdivisions, float noiseCoeff) { // 1. Исходный октаэдр и присвоение ID std::vector geometry = { {{ 0.0f, 1.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}, { 1.0f, 0.0f, 0.0f}}, // 0 @@ -689,7 +699,7 @@ namespace ZL { // ВОССТАНОВИМ ШАГ 2, но для финальной геометрии: for (size_t i = 0; i < lodLevel.vertexData.PositionData.size(); i++) { Vector3f dir = lodLevel.vertexData.PositionData[i].normalized(); - lodLevel.vertexData.PositionData[i] = dir * perlin.getSurfaceHeight(dir); + lodLevel.vertexData.PositionData[i] = dir * perlin.getSurfaceHeight(dir, noiseCoeff); // Обратите внимание: NormalData остается (dir), как в вашем коде lodLevel.vertexData.NormalData[i] = dir; } @@ -738,6 +748,8 @@ namespace ZL { return lodLevel; } + + std::vector PlanetObject::findNeighbors(int index, int lod) { // Проверка lod опущена для краткости... diff --git a/PlanetObject.h b/PlanetObject.h index 8951429..fad53b1 100644 --- a/PlanetObject.h +++ b/PlanetObject.h @@ -57,7 +57,7 @@ namespace ZL { float noise(float x, float y, float z); - float getSurfaceHeight(Vector3f pos); + float getSurfaceHeight(Vector3f pos, float noiseCoeff); }; @@ -73,6 +73,7 @@ namespace ZL { VertexRenderStruct planetRenderRedStruct; VertexRenderStruct planetRenderYellowStruct; + LodLevel planetAtmosphereLod; VertexRenderStruct planetAtmosphere; std::shared_ptr sandTexture; @@ -106,9 +107,9 @@ namespace ZL { int currentLod = planetMeshLods.size()-1; std::vector subdivideTriangles(const std::vector& inputTriangles); - Vector3f calculateSurfaceNormal(Vector3f p_sphere); + Vector3f calculateSurfaceNormal(Vector3f p_sphere, float noiseCoeff); LodLevel trianglesToVertices(const std::vector& triangles); - LodLevel generateSphere(int subdivisions); + LodLevel generateSphere(int subdivisions, float noiseCoeff); std::pair calculateZRange(const Vector3f& shipPosition); std::vector triangleUnderCamera(int lod); diff --git a/shaders/defaultColor_fog2_desktop.fragment b/shaders/defaultColor_fog2_desktop.fragment index 915d8de..aec32f5 100644 --- a/shaders/defaultColor_fog2_desktop.fragment +++ b/shaders/defaultColor_fog2_desktop.fragment @@ -12,6 +12,7 @@ uniform float uDistanceToPlanetSurface; uniform float uCurrentZFar; // Константы для тумана: +//const vec4 FOG_COLOR = vec4(0.0, 0.3, 0.3, 1.0); // Синий туман const vec4 FOG_COLOR = vec4(0.0, 0.5, 1.0, 1.0); // Синий туман // Параметры "Distance Fog" @@ -29,7 +30,7 @@ void main() { // ... (1. Получаем цвет и 2. Расчет освещения) vec4 textureColor = texture2D(Texture, TexCoord); - vec3 finalColor = textureColor.rgb * color; + vec3 finalColor = textureColor.rgb; float diffuse = max(0.0, dot(normal, uLightDirection)); float ambient = 0.2; @@ -65,20 +66,10 @@ void main() // гарантируя, что все, что подходит к границе uCurrentZFar, будет скрыто. // Точка начала тумана: 90% от uCurrentZFar - float farFogStart = 2000.f;//uCurrentZFar * 0.7; + float farFogStart = uCurrentZFar * 0.075; // Длина перехода тумана: 10% от uCurrentZFar - float depthRange = 2000.f;//uCurrentZFar * 0.25; + float depthRange = uCurrentZFar * 0.1; - 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; @@ -99,8 +90,8 @@ void main() // 4. Смешивание цвета с туманом //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 = mix(vec4(uColor* finalColor.rgb, 1.0), 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); - gl_FragColor = vec4(uColor*textureColor.rgb, 1.0); + //gl_FragColor = vec4(uColor*textureColor.rgb, 1.0); } \ No newline at end of file diff --git a/shaders/defaultColor_fog_desktop.fragment b/shaders/defaultColor_fog_desktop.fragment index 60b9592..c817811 100644 --- a/shaders/defaultColor_fog_desktop.fragment +++ b/shaders/defaultColor_fog_desktop.fragment @@ -12,6 +12,7 @@ uniform float uDistanceToPlanetSurface; uniform float uCurrentZFar; // Константы для тумана: +//const vec4 FOG_COLOR = vec4(0.0, 0.5, 0.5, 1.0); // Синий туман const vec4 FOG_COLOR = vec4(0.0, 0.5, 1.0, 1.0); // Синий туман // Параметры "Distance Fog" @@ -20,9 +21,9 @@ const float DIST_FOG_MIN = 1000.0; // Параметры "Z-Far Fog" // Насколько близко к Zfar должен начинаться туман (например, 10% от Zfar) -const float Z_FOG_START_RATIO = 0.9; +const float Z_FOG_START_RATIO = 0.8; // Какую долю от Zfar должен покрывать туман (например, 10% от Zfar) -const float Z_FOG_RANGE_RATIO = 0.1; +const float Z_FOG_RANGE_RATIO = 0.15; void main() @@ -65,20 +66,10 @@ void main() // гарантируя, что все, что подходит к границе uCurrentZFar, будет скрыто. // Точка начала тумана: 90% от uCurrentZFar - float farFogStart = 2000.f;//uCurrentZFar * 0.7; + float farFogStart = uCurrentZFar * 0.075; // Длина перехода тумана: 10% от uCurrentZFar - float depthRange = 2000.f;//uCurrentZFar * 0.25; + float depthRange = uCurrentZFar * 0.1; - 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; @@ -99,7 +90,7 @@ void main() // 4. Смешивание цвета с туманом //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 = 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(finalColor.rgb, 1.0); + //gl_FragColor = vec4(finalColor.rgb, 1.0); } \ No newline at end of file