Compare commits

..

No commits in common. "9fc0adf210b0b1d798481af24e8d39f2238b5096" and "648acf8938a53ac1ebcfc2395dd13e7aac5f0078" have entirely different histories.

67 changed files with 30997 additions and 244 deletions

View File

@ -507,7 +507,7 @@ target_compile_definitions(space-game001 PRIVATE
WIN32_LEAN_AND_MEAN
PNG_ENABLED
SDL_MAIN_HANDLED
# SIMPLIFIED
SIMPLIFIED
)
# Линкуем с SDL2main, если он вообще установлен
@ -538,10 +538,6 @@ if (WIN32)
set(LIBZIP_DLL_SRC "$<IF:$<CONFIG:Debug>,${LIBZIP_BASE_DIR}-Debug/bin/zip.dll,${LIBZIP_BASE_DIR}-Release/bin/zip.dll>")
set(ZLIB_DLL_SRC "$<IF:$<CONFIG:Debug>,${ZLIB_INSTALL_DIR}/bin/zlibd.dll,${ZLIB_INSTALL_DIR}/bin/zlib.dll>")
set(ZLIB_DLL_DST "$<IF:$<CONFIG:Debug>,$<TARGET_FILE_DIR:space-game001>/zlibd.dll,$<TARGET_FILE_DIR:space-game001>/zlib.dll>")
add_custom_command(TARGET space-game001 POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo "Copying DLLs to output folder..."
@ -555,10 +551,6 @@ if (WIN32)
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${LIBZIP_DLL_SRC}"
"$<TARGET_FILE_DIR:space-game001>/zip.dll"
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${ZLIB_DLL_SRC}"
"${ZLIB_DLL_DST}"
)
endif()
@ -570,7 +562,6 @@ endif()
set(RUNTIME_RESOURCE_DIRS
"resources"
"shaders"
"config"
)
# Копируем ресурсы и шейдеры в папку exe и в корень build/

View File

@ -157,7 +157,7 @@ emrun --no_browser --port 8080 .
# Emscripten new
```
emcc src/main.cpp src/Game.cpp src/Environment.cpp src/BoneAnimatedModel.cpp src/TextModel.cpp src/Projectile.cpp src/SparkEmitter.cpp src/UiManager.cpp src/render/Renderer.cpp src/render/ShaderManager.cpp src/render/TextureManager.cpp src/render/FrameBuffer.cpp src/render/OpenGlExtensions.cpp src/utils/Utils.cpp src/utils/TaskManager.cpp src/utils/Perlin.cpp src/planet/PlanetData.cpp src/planet/PlanetObject.cpp src/planet/StoneObject.cpp -O2 -std=c++17 -pthread -sUSE_PTHREADS=1 -sPTHREAD_POOL_SIZE=4 -sTOTAL_MEMORY=4294967296 -sINITIAL_MEMORY=3221225472 -sMAXIMUM_MEMORY=4294967296 -sALLOW_MEMORY_GROWTH=1 -fexceptions -I./thirdparty1/eigen-5.0.0 -I./src -I./thirdparty/libzip-1.11.3/build-emcmake/install/include -IC:/Boost/include/boost-1_84 -L./thirdparty/libzip-1.11.3/build-emcmake/install/lib -lzip -lz -sUSE_SDL_IMAGE=2 -sUSE_SDL=2 -sUSE_LIBPNG=1 --preload-file space-game001.zip -o space-game001.html
emcc src/main.cpp src/Game.cpp src/Environment.cpp src/BoneAnimatedModel.cpp src/TextModel.cpp src/Projectile.cpp src/SparkEmitter.cpp src/UiManager.cpp src/render/Renderer.cpp src/render/ShaderManager.cpp src/render/TextureManager.cpp src/render/FrameBuffer.cpp src/render/OpenGlExtensions.cpp src/utils/Utils.cpp src/utils/TaskManager.cpp src/utils/Perlin.cpp src/planet/PlanetData.cpp src/planet/PlanetObject.cpp src/planet/StoneObject.cpp -O2 -std=c++17 -pthread -sUSE_PTHREADS=1 -sPTHREAD_POOL_SIZE=4 -sTOTAL_MEMORY=4294967296 -sINITIAL_MEMORY=3221225472 -sMAXIMUM_MEMORY=4294967296 -sALLOW_MEMORY_GROWTH=1 -fexceptions -I./thirdparty1/eigen-5.0.0 -I./src -I./thirdparty/libzip-1.11.3/build-emcmake/install/include -IC:/Boost/include/boost-1_84 -L./thirdparty/libzip-1.11.3/build-emcmake/install/lib -lzip -lz -sUSE_SDL_IMAGE=2 -sUSE_SDL=2 -sUSE_LIBPNG=1 -DSIMPLIFIED=1 --preload-file space-game001.zip -o space-game001.html
```
# License

View File

@ -1,14 +1,14 @@
{
"emissionRate": 100.0,
"maxParticles": 200,
"particleSize": 0.3,
"particleSize": 0.04,
"biasX": 0.3,
"emissionPoints": [
{
"position": [-1.3, 0, 0.0]
"position": [-2.1, 0.4, 5.0]
},
{
"position": [1.3, 0.0, 0.0]
"position": [2.1, 0.4, 5.0]
}
],
"speedRange": [0.5, 2.0],

View File

@ -2,7 +2,7 @@
"emissionPoints": [
{ "position": [0.0, 0.0, 0.0] }
],
"texture": "./resources/spark_white.png",
"texture": "./resources/sand.png",
"speedRange": [10.0, 30.0],
"zSpeedRange": [-1.0, 1.0],
"scaleRange": [0.5, 1.0],

View File

@ -1,38 +1,86 @@
{
"root": {
"type": "FrameLayout",
"x": 0,
"y": 0,
"width": 1280,
"height": 720,
"children": [
{
"type": "Slider",
"name": "velocitySlider",
"x": 1140,
"y": 100,
"width": 50,
"height": 500,
"value": 0.0,
"orientation": "vertical",
"textures": {
"track": "./resources/velocitySliderTexture.png",
"knob": "./resources/velocitySliderButton.png"
}
},
{
"type": "Button",
"name": "shootButton",
"x": 100,
"y": 100,
"width": 100,
"height": 100,
"textures": {
"normal": "./resources/shoot_normal.png",
"hover": "./resources/shoot_hover.png",
"pressed": "./resources/shoot_pressed.png"
}
}
]
}
"root": {
"type": "FrameLayout",
"x": 0,
"y": 0,
"width": 1280,
"height": 720,
"children": [
{
"type": "FrameLayout",
"name": "leftPanel",
"x": 100,
"y": 100,
"width": 320,
"height": 400,
"children": [
{
"type": "LinearLayout",
"name": "mainButtons",
"orientation": "vertical",
"spacing": 10,
"x": 0,
"y": 0,
"width": 300,
"height": 300,
"children": [
{
"type": "Button",
"name": "playButton",
"x": 100,
"y": 300,
"width": 200,
"height": 50,
"textures": {
"normal": "./resources/button.png",
"hover": "./resources/button.png",
"pressed": "./resources/button.png"
}
},
{
"type": "Button",
"name": "settingsButton",
"x": 100,
"y": 200,
"width": 200,
"height": 50,
"textures": {
"normal": "./resources/sand.png",
"hover": "./resources/sand.png",
"pressed": "./resources/sand.png"
}
},
{
"type": "Button",
"name": "exitButton",
"x": 100,
"y": 100,
"width": 200,
"height": 50,
"textures": {
"normal": "./resources/rock.png",
"hover": "./resources/rock.png",
"pressed": "./resources/rock.png"
}
}
]
}
]
},
{
"type": "Slider",
"name": "musicVolumeSlider",
"x": 1140,
"y": 100,
"width": 10,
"height": 500,
"value": 0.5,
"orientation": "vertical",
"textures": {
"track": "./resources/musicVolumeBarTexture.png",
"knob": "./resources/musicVolumeBarButton.png"
}
}
]
}
}

BIN
resources/DefaultMaterial_BaseColor.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
resources/box/box.png (Stored with Git LFS)

Binary file not shown.

BIN
resources/button.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resources/musicVolumeBarButton.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resources/musicVolumeBarTexture.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resources/rock.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resources/rockdark3.png (Stored with Git LFS)

Binary file not shown.

BIN
resources/rockx.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resources/sand.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resources/sand2.png (Stored with Git LFS)

Binary file not shown.

BIN
resources/sandx.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resources/shoot_hover.png (Stored with Git LFS)

Binary file not shown.

BIN
resources/shoot_normal.png (Stored with Git LFS)

Binary file not shown.

BIN
resources/shoot_pressed.png (Stored with Git LFS)

Binary file not shown.

BIN
resources/sky/space1.png (Stored with Git LFS)

Binary file not shown.

BIN
resources/sky/space_bk.bmp (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resources/sky/space_dn.bmp (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resources/sky/space_ft.bmp (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resources/sky/space_lf.bmp (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resources/sky/space_rt.bmp (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resources/sky/space_up.bmp (Stored with Git LFS) Normal file

Binary file not shown.

14508
resources/spaceship004.txt Normal file

File diff suppressed because it is too large Load Diff

15036
resources/spaceship005.txt Normal file

File diff suppressed because it is too large Load Diff

BIN
resources/spark_white.png (Stored with Git LFS)

Binary file not shown.

BIN
resources/sship001x.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resources/velocitySliderButton.png (Stored with Git LFS)

Binary file not shown.

BIN
resources/velocitySliderTexture.png (Stored with Git LFS)

Binary file not shown.

View File

@ -0,0 +1,118 @@
// Фрагментный шейдер:
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()
{
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 = 1.0 - smoothstep(0.9, 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)
{
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);
// Для дымки (atmo) оставляем затухание при посадке
float atmoAlpha = atmosphereDensity * distanceFactor;
float finalAtmoAlpha = atmoAlpha;
if (uDistanceToPlanetSurface < layerHeight) {
finalCloudAlpha *= horizonMask;
finalAtmoAlpha *= horizonMask; // Принудительно гасим дымку под горизонтом
}
gl_FragColor = vec4(finalRGB, max(finalAtmoAlpha, finalCloudAlpha));
}

View File

@ -0,0 +1,122 @@
// Фрагментный шейдер:
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()
{
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.9, 1.0, cosAngle);
gl_FragColor = vec4(horizonMask, 0.0, 0.0, 0.5);
return;
/*
// --- 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)
{
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);
// Для дымки (atmo) оставляем затухание при посадке
float atmoAlpha = atmosphereDensity * distanceFactor;
float finalAtmoAlpha = atmoAlpha;
if (uDistanceToPlanetSurface < layerHeight) {
finalCloudAlpha *= horizonMask;
finalAtmoAlpha *= horizonMask; // Принудительно гасим дымку под горизонтом
}
gl_FragColor = vec4(finalRGB, max(finalAtmoAlpha, finalCloudAlpha));*/
}

View File

@ -0,0 +1,118 @@
// Фрагментный шейдер:
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()
{
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)
{
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);
// Для дымки (atmo) оставляем затухание при посадке
float atmoAlpha = atmosphereDensity * distanceFactor;
float finalAtmoAlpha = atmoAlpha;
if (uDistanceToPlanetSurface < layerHeight) {
finalCloudAlpha *= horizonMask;
finalAtmoAlpha *= horizonMask; // Принудительно гасим дымку под горизонтом
}
gl_FragColor = vec4(finalRGB, max(finalAtmoAlpha, finalCloudAlpha));
}

View File

@ -0,0 +1,22 @@
varying vec3 color; // Цвет вершины (с шумом)
varying vec3 normal;
varying vec3 lightDirection_VS;
varying vec2 TexCoord; // UV-координаты
uniform sampler2D Texture;
uniform vec3 uLightDirection;
void main()
{
// 1. Получаем цвет из текстуры и смешиваем с цветовым шумом
vec4 textureColor = texture2D(Texture, TexCoord);
vec3 finalColor = textureColor.rgb * color;
// 3. Расчет освещения
float diffuse = max(0.0, dot(normal, uLightDirection));
float ambient = 0.2;
float lightingFactor = min(1.0, ambient + diffuse);
gl_FragColor = vec4(finalColor * lightingFactor, 1.0);
}

View File

@ -0,0 +1,35 @@
// Вершинный шейдер (Vertex Shader)
attribute vec3 vPosition;
attribute vec3 vColor;
attribute vec3 vNormal;
attribute vec2 vTexCoord;
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
uniform vec3 uLightDirection;
void main()
{
// Преобразование позиции в пространство вида (View Space)
vec4 viewPosition = ModelViewMatrix * vec4(vPosition.xyz, 1.0);
// Сохраняем отрицательную Z-координату. В OpenGL Z-координата (глубина)
// в пространстве вида обычно отрицательна, но для расчета тумана
// удобнее использовать положительное значение.
viewZ = -viewPosition.z;
pos = vPosition.xyz;
gl_Position = ProjectionModelViewMatrix * vec4(vPosition.xyz, 1.0);
normal = normalize((ModelViewMatrix * vec4(vNormal, 0.0)).xyz);
color = vColor;
TexCoord = vTexCoord;
}

View File

@ -0,0 +1,35 @@
// Вершинный шейдер (Vertex Shader)
attribute vec3 vPosition;
attribute vec3 vColor;
attribute vec3 vNormal;
attribute vec2 vTexCoord;
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
uniform vec3 uLightDirection;
void main()
{
// Преобразование позиции в пространство вида (View Space)
vec4 viewPosition = ModelViewMatrix * vec4(vPosition.xyz, 1.0);
// Сохраняем отрицательную Z-координату. В OpenGL Z-координата (глубина)
// в пространстве вида обычно отрицательна, но для расчета тумана
// удобнее использовать положительное значение.
viewZ = -viewPosition.z;
pos = vPosition.xyz;
gl_Position = ProjectionModelViewMatrix * vec4(vPosition.xyz, 1.0);
normal = normalize((ModelViewMatrix * vec4(vNormal, 0.0)).xyz);
color = vColor;
TexCoord = vTexCoord;
}

View File

@ -0,0 +1,97 @@
// ---Фрагментный шейдер (Fragment Shader)
varying vec3 color;
varying vec3 normal;
varying vec2 TexCoord;
varying float viewZ;
varying vec3 pos;
uniform sampler2D Texture;
uniform vec3 uLightDirection;
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"
const float DIST_FOG_MAX = 2000.0;
const float DIST_FOG_MIN = 1000.0;
// Параметры "Z-Far Fog"
// Насколько близко к Zfar должен начинаться туман (например, 10% от Zfar)
const float Z_FOG_START_RATIO = 0.9;
// Какую долю от Zfar должен покрывать туман (например, 10% от Zfar)
const float Z_FOG_RANGE_RATIO = 0.1;
uniform vec3 uColor;
void main()
{
// ... (1. Получаем цвет и 2. Расчет освещения)
vec4 textureColor = texture2D(Texture, TexCoord);
vec3 finalColor = textureColor.rgb;
float diffuse = max(0.0, dot(normal, uLightDirection));
float ambient = 0.2;
float lightingFactor = min(1.0, ambient + diffuse);
vec3 litColor = finalColor * lightingFactor;
// 3. Расчет коэффициента тумана (fogFactor)
float fogFactor = 0.0;
// --- 3.1. Расчет коэффициента тумана на основе расстояния до поверхности (Distance Fog) ---
// Этот туман работает на больших расстояниях и постепенно исчезает,
// уступая место Z-Far Fog при приближении к планете.
if (uDistanceToPlanetSurface >= DIST_FOG_MIN && uDistanceToPlanetSurface <DIST_FOG_MAX) {
// Нормализация: 0.0f при DIST_FOG_MAX, 1.0f при DIST_FOG_MIN
float distRange = DIST_FOG_MAX - DIST_FOG_MIN;
float distNormalized = clamp((uDistanceToPlanetSurface - DIST_FOG_MIN) / distRange, 0.0, 1.0);
// alpha = 0.0 (Далеко) ... 1.0 (Близко к 1000.f)
fogFactor = 1.0 - distNormalized;
}
if (uDistanceToPlanetSurface < DIST_FOG_MIN)
{
fogFactor = 1.0;
}
// Если uDistanceToPlanetSurface < 1000.0f, то fogFactor = 0.0f (пока не пересчитан ниже),
// что позволяет Z-Far Fog взять контроль.
// --- 3.2. Расчет коэффициента тумана на основе Z-глубины (Z-Far Fog) ---
// Этот туман работает всегда, но его эффект усиливается при уменьшении uCurrentZFar,
// гарантируя, что все, что подходит к границе uCurrentZFar, будет скрыто.
// Точка начала тумана: 90% от uCurrentZFar
float farFogStart = uCurrentZFar * 0.075;
// Длина перехода тумана: 10% от uCurrentZFar
float depthRange = uCurrentZFar * 0.1;
float farFogFactor = 0.0;
if (depthRange > 0.0) {
// Нормализация Z-глубины: 0.0f при farFogStart, 1.0f при farFogStart + depthRange
farFogFactor = clamp((abs(viewZ) - farFogStart) / depthRange, 0.0, 1.0);
}
// --- 3.3. Объединение ---
// Когда мы далеко (fogFactor > 0.0), Distance Fog доминирует.
// Когда мы близко (fogFactor = 0.0), Z-Far Fog берет управление.
// Если оба активны, берем максимум (например, когда фрагмент далек от игрока, но игрок все еще в зоне Distance Fog).
//fogFactor = max(fogFactor, farFogFactor);
fogFactor = fogFactor * farFogFactor;
// 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(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(textureColor.rgb, 1.0);
}

View File

@ -0,0 +1,97 @@
// ---Фрагментный шейдер (Fragment Shader)
varying vec3 color;
varying vec3 normal;
varying vec2 TexCoord;
varying float viewZ;
varying vec3 pos;
uniform sampler2D Texture;
uniform vec3 uLightDirection;
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"
const float DIST_FOG_MAX = 2000.0;
const float DIST_FOG_MIN = 1000.0;
// Параметры "Z-Far Fog"
// Насколько близко к Zfar должен начинаться туман (например, 10% от Zfar)
const float Z_FOG_START_RATIO = 0.8;
// Какую долю от Zfar должен покрывать туман (например, 10% от Zfar)
const float Z_FOG_RANGE_RATIO = 0.15;
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;
float lightingFactor = min(1.0, ambient + diffuse);
vec3 litColor = finalColor * lightingFactor;
// 3. Расчет коэффициента тумана (fogFactor)
float fogFactor = 0.0;
// --- 3.1. Расчет коэффициента тумана на основе расстояния до поверхности (Distance Fog) ---
// Этот туман работает на больших расстояниях и постепенно исчезает,
// уступая место Z-Far Fog при приближении к планете.
if (uDistanceToPlanetSurface >= DIST_FOG_MIN && uDistanceToPlanetSurface <DIST_FOG_MAX) {
// Нормализация: 0.0f при DIST_FOG_MAX, 1.0f при DIST_FOG_MIN
float distRange = DIST_FOG_MAX - DIST_FOG_MIN;
float distNormalized = clamp((uDistanceToPlanetSurface - DIST_FOG_MIN) / distRange, 0.0, 1.0);
// alpha = 0.0 (Далеко) ... 1.0 (Близко к 1000.f)
fogFactor = 1.0 - distNormalized;
}
if (uDistanceToPlanetSurface < DIST_FOG_MIN)
{
fogFactor = 1.0;
}
// Если uDistanceToPlanetSurface < 1000.0f, то fogFactor = 0.0f (пока не пересчитан ниже),
// что позволяет Z-Far Fog взять контроль.
// --- 3.2. Расчет коэффициента тумана на основе Z-глубины (Z-Far Fog) ---
// Этот туман работает всегда, но его эффект усиливается при уменьшении uCurrentZFar,
// гарантируя, что все, что подходит к границе uCurrentZFar, будет скрыто.
// Точка начала тумана: 90% от uCurrentZFar
float farFogStart = uCurrentZFar * 0.075;
// Длина перехода тумана: 10% от uCurrentZFar
float depthRange = uCurrentZFar * 0.1;
float farFogFactor = 0.0;
if (depthRange > 0.0) {
// Нормализация Z-глубины: 0.0f при farFogStart, 1.0f при farFogStart + depthRange
farFogFactor = clamp((abs(viewZ) - farFogStart) / depthRange, 0.0, 1.0);
}
// --- 3.3. Объединение ---
// Когда мы далеко (fogFactor > 0.0), Distance Fog доминирует.
// Когда мы близко (fogFactor = 0.0), Z-Far Fog берет управление.
// Если оба активны, берем максимум (например, когда фрагмент далек от игрока, но игрок все еще в зоне Distance Fog).
//fogFactor = max(fogFactor, farFogFactor);
fogFactor = fogFactor * farFogFactor;
// 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 = 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);
}

View File

@ -0,0 +1,26 @@
attribute vec3 vPosition;
attribute vec2 vTexCoord;
attribute vec3 vNormal;
attribute vec3 vTangent; // Новые атрибуты
attribute vec3 vBinormal;
varying vec2 TexCoord;
varying vec3 vViewDirTangent;
uniform mat4 ProjectionModelViewMatrix;
uniform 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)
);
}

View File

@ -0,0 +1,69 @@
/*varying vec2 TexCoord;
varying vec3 vViewDirTangent;
uniform sampler2D Texture; // Нам нужен только Alpha канал (высота)
uniform float uHeightScale;
void main() {
vec3 viewDir = normalize(vViewDirTangent);
float height = texture2D(Texture, TexCoord).a;
// Рассчитываем вектор смещения P
//vec2 p = viewDir.xy * (height * uHeightScale) / viewDir.z;
//vec2 p = vec2(viewDir.y, -viewDir.x) * (height * uHeightScale);
//vec2 p = viewDir.xy * (height * uHeightScale);
vec2 p = vec2(viewDir.x, -viewDir.y) * (height * uHeightScale);
vec2 finalTexCoord = TexCoord + p;
// 1. Визуализация сетки по смещенным координатам
// Если сетка кривая или ломается на стыках — значит T, B, N векторы не сошлись
vec2 grid = fract(finalTexCoord * 20.0); // 20 ячеек сетки
float line = (step(0.9, grid.x) + step(0.9, grid.y));
// 2. Визуализация вектора смещения через цвет
// Красный = смещение по U, Зеленый = смещение по V
vec3 offsetColor = vec3(p * 10.0 + 0.5, 0.0); // Умножаем на 10 для видимости
vec3 finalColor = mix(offsetColor, vec3(1.0), line); // Накладываем сетку поверх цвета
// 3. Подмешиваем карту высот, чтобы видеть "объемы"
gl_FragColor = vec4(finalColor * height, 1.0);
}*/
varying vec2 TexCoord;
varying vec3 vViewDirTangent;
uniform sampler2D Texture;
uniform float uHeightScale;
void main() {
vec3 viewDir = normalize(vViewDirTangent);
// Получаем высоту из альфа-канала запеченной текстуры
float height = texture2D(Texture, TexCoord).a;
// Смещение. Знак минус используется, если мы хотим "вдавить" камни
// Деление на viewDir.z помогает избежать сильных искажений под углом
//vec2 p = viewDir.xy * (height * uHeightScale) / viewDir.z;
vec2 p = vec2(viewDir.x, -viewDir.y) * (height * uHeightScale);
//vec2 p = vec2(0,0);
vec2 finalTexCoord = TexCoord + p;
gl_FragColor = texture2D(Texture, finalTexCoord);
}
/*
varying vec2 TexCoord;
varying vec3 vViewDirTangent; // Тот самый вектор из VS
void main() {
// 1. Нормализуем входящий вектор
vec3 v = normalize(vViewDirTangent);
// 2. Преобразуем компоненты из [-1, 1] в [0, 1] для визуализации
// X -> Red, Y -> Green, Z -> Blue
vec3 debugColor = v * 0.5 + 0.5;
gl_FragColor = vec4(debugColor, 1.0);
}*/

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.9 + vec3(0.1, 0.1, 0.1), 1.0);
gl_FragColor = color;
}

View File

@ -0,0 +1,8 @@
uniform samplerCube Texture;
varying vec3 dir;
void main(){
gl_FragColor = textureCube(Texture, normalize(dir));
}

View File

@ -0,0 +1,10 @@
//precision mediump float;
uniform sampler2D Texture;
varying vec2 texCoord;
void main()
{
vec4 color = texture2D(Texture,texCoord).rgba;
gl_FragColor = color;
}

13
shaders/env.fragment Normal file
View File

@ -0,0 +1,13 @@
uniform samplerCube Texture;
varying vec3 dir;
void main(){
gl_FragColor = textureCube(Texture, normalize(dir));
//if (dir.z < 0)
//{
// gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
//}
//gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

12
shaders/env.vertex Normal file
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;
}

View File

@ -0,0 +1,8 @@
uniform samplerCube Texture;
varying vec3 dir;
void main(){
gl_FragColor = textureCube(Texture, normalize(dir));
}

View File

@ -0,0 +1,36 @@
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);
}

7
shaders/env_web.fragment Normal file
View File

@ -0,0 +1,7 @@
precision mediump float;
uniform samplerCube Texture;
varying vec3 dir;
void main(){
gl_FragColor = textureCube(Texture, normalize(dir));
}

View File

@ -0,0 +1,13 @@
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);
}

View File

@ -0,0 +1,115 @@
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);
}
}

View File

@ -0,0 +1,14 @@
varying vec2 TexCoord;
varying vec3 vViewDirTangent; // Тот самый вектор из VS
void main() {
// 1. Нормализуем входящий вектор
vec3 v = normalize(vViewDirTangent);
// 2. Преобразуем компоненты из [-1, 1] в [0, 1] для визуализации
// X -> Red, Y -> Green, Z -> Blue
vec3 debugColor = v * 0.5 + 0.5;
gl_FragColor = vec4(debugColor, 1.0);
}

View File

@ -0,0 +1,32 @@
varying vec2 TexCoord;
varying vec3 vViewDirTangent;
uniform sampler2D Texture; // Нам нужен только Alpha канал (высота)
uniform float uHeightScale;
void main() {
vec3 viewDir = normalize(vViewDirTangent);
float height = texture2D(Texture, TexCoord).a;
// Рассчитываем вектор смещения P
//vec2 p = viewDir.xy * (height * uHeightScale) / viewDir.z;
//vec2 p = vec2(viewDir.y, -viewDir.x) * (height * uHeightScale);
//vec2 p = viewDir.xy * (height * uHeightScale);
vec2 p = vec2(viewDir.x, -viewDir.y) * (height * uHeightScale);
vec2 finalTexCoord = TexCoord + p;
// 1. Визуализация сетки по смещенным координатам
// Если сетка кривая или ломается на стыках — значит T, B, N векторы не сошлись
vec2 grid = fract(finalTexCoord * 20.0); // 20 ячеек сетки
float line = (step(0.9, grid.x) + step(0.9, grid.y));
// 2. Визуализация вектора смещения через цвет
// Красный = смещение по U, Зеленый = смещение по V
vec3 offsetColor = vec3(p * 10.0 + 0.5, 0.0); // Умножаем на 10 для видимости
vec3 finalColor = mix(offsetColor, vec3(1.0), line); // Накладываем сетку поверх цвета
// 3. Подмешиваем карту высот, чтобы видеть "объемы"
gl_FragColor = vec4(finalColor * height, 1.0);
}

View File

@ -0,0 +1,102 @@
// 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);
}
}

View File

@ -1,9 +1,12 @@
precision mediump float;
//precision mediump float;
uniform sampler2D Texture;
varying vec2 texCoord;
void main()
{
vec4 color = texture2D(Texture,texCoord).rgba;
//gl_FragColor = vec4(color.rgb*0.9 + vec3(0.1, 0.1, 0.1), 1.0);
gl_FragColor = color;
}

View File

@ -18,6 +18,8 @@ namespace ZL
const char* CONST_ZIP_FILE = "";
#endif
Eigen::Quaternionf generateRandomQuaternion(std::mt19937& gen)
{
@ -33,6 +35,7 @@ namespace ZL
return randomQuat.normalized();
}
std::vector<BoxCoords> generateRandomBoxCoords(int N)
{
const float MIN_DISTANCE = 3.0f;
@ -127,8 +130,13 @@ namespace ZL
// Initialize renderer
#ifndef SIMPLIFIED
#ifdef EMSCRIPTEN
/*renderer.shaderManager.AddShaderFromFiles("default", "./shaders/default.vertex", "./shaders/default_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("defaultColor", "./shaders/defaultColor.vertex", "./shaders/defaultColor_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("env", "./shaders/env.vertex", "./shaders/env_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("defaultAtmosphere", "./shaders/defaultAtmosphere.vertex", "./shaders/defaultAtmosphere.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("defaultColorPlanet", "./shaders/defaultColorPlanet.vertex", "./shaders/defaultColorPlanet_web.fragment", CONST_ZIP_FILE);
*/
renderer.shaderManager.AddShaderFromFiles("defaultColor", "./shaders/defaultColor.vertex", "./shaders/defaultColor_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("default", "./shaders/default.vertex", "./shaders/default_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("env_sky", "./shaders/env_sky.vertex", "./shaders/env_sky_web.fragment", CONST_ZIP_FILE);
@ -138,27 +146,42 @@ namespace ZL
renderer.shaderManager.AddShaderFromFiles("planetLand", "./shaders/planet_land.vertex", "./shaders/planet_land_web.fragment", CONST_ZIP_FILE);
#else
#ifndef SIMPLIFIED
renderer.shaderManager.AddShaderFromFiles("defaultColor", "./shaders/defaultColor.vertex", "./shaders/defaultColor_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("default", "./shaders/default.vertex", "./shaders/default_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("env_sky", "./shaders/env_sky.vertex", "./shaders/env_sky_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("defaultAtmosphere", "./shaders/defaultAtmosphere.vertex", "./shaders/defaultAtmosphere_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("planetBake", "./shaders/planet_bake.vertex", "./shaders/planet_bake_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("planetStone", "./shaders/planet_stone.vertex", "./shaders/planet_stone_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("planetLand", "./shaders/planet_land.vertex", "./shaders/planet_land_desktop.fragment", CONST_ZIP_FILE);
#else
/*renderer.shaderManager.AddShaderFromFiles("default", "./shaders/default.vertex", "./shaders/default_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("env_sky", "./shaders/default_env.vertex", "./shaders/default_env_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("defaultAtmosphere", "./shaders/default_texture.vertex", "./shaders/default_texture_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("planetBake", "./shaders/default_texture.vertex", "./shaders/default_texture_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("planetStone", "./shaders/default_texture.vertex", "./shaders/default_texture_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("planetLand", "./shaders/default_texture.vertex", "./shaders/default_texture_desktop.fragment", CONST_ZIP_FILE);
*/
renderer.shaderManager.AddShaderFromFiles("defaultColor", "./shaders/defaultColor.vertex", "./shaders/defaultColor_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("default", "./shaders/default.vertex", "./shaders/default_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("env_sky", "./shaders/default_env.vertex", "./shaders/default_env_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("defaultAtmosphere", "./shaders/default_texture.vertex", "./shaders/default_texture_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("planetBake", "./shaders/default_texture.vertex", "./shaders/default_texture_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("planetStone", "./shaders/default_texture.vertex", "./shaders/default_texture_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("planetLand", "./shaders/default_texture.vertex", "./shaders/default_texture_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("env_sky", "./shaders/env_sky.vertex", "./shaders/env_sky_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("defaultAtmosphere", "./shaders/defaultAtmosphere.vertex", "./shaders/defaultAtmosphere_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("planetBake", "./shaders/planet_bake.vertex", "./shaders/planet_bake_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("planetStone", "./shaders/planet_stone.vertex", "./shaders/planet_stone_web.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("planetLand", "./shaders/planet_land.vertex", "./shaders/planet_land_web.fragment", CONST_ZIP_FILE);
#endif
bool cfgLoaded = sparkEmitter.loadFromJsonFile("config/spark_config.json", renderer, CONST_ZIP_FILE);
bool projCfgLoaded = projectileEmitter.loadFromJsonFile("config/spark_projectile_config.json", renderer, CONST_ZIP_FILE);
#endif
#ifndef SIMPLIFIED
bool cfgLoaded = sparkEmitter.loadFromJsonFile("../config/spark_config.json", renderer, CONST_ZIP_FILE);
bool projCfgLoaded = projectileEmitter.loadFromJsonFile("../config/spark_projectile_config.json", renderer, CONST_ZIP_FILE);
projectileEmitter.setEmissionPoints(std::vector<Vector3f>());
uiManager.loadFromFile("config/ui.json", renderer, CONST_ZIP_FILE);
uiManager.loadFromFile("../config/ui.json", renderer, CONST_ZIP_FILE);
uiManager.setButtonCallback("shootButton", [this](const std::string& name) {
uint64_t now = SDL_GetTicks64();
if (now - lastProjectileFireTime >= static_cast<uint64_t>(projectileCooldownMs)) {
lastProjectileFireTime = now;
fireProjectiles();
}
});
/*
uiManager.setButtonCallback("playButton", [this](const std::string& name) {
std::cerr << "Play button pressed: " << name << std::endl;
});
@ -168,7 +191,7 @@ namespace ZL
});
uiManager.setButtonCallback("settingsButton", [this](const std::string& name) {
if (uiManager.pushMenuFromFile("config/settings.json", this->renderer, CONST_ZIP_FILE)) {
if (uiManager.pushMenuFromFile("../config/settings.json", this->renderer, CONST_ZIP_FILE)) {
uiManager.setButtonCallback("Opt1", [this](const std::string& n) {
std::cerr << "Opt1 pressed: " << n << std::endl;
@ -186,20 +209,22 @@ namespace ZL
std::cerr << "Failed to open settings menu" << std::endl;
}
});
*/
uiManager.setSliderCallback("velocitySlider", [this](const std::string& name, float value) {
Environment::shipVelocity = value * 1000.f;
});
uiManager.setSliderCallback("musicVolumeSlider", [this](const std::string& name, float value) {
std::cerr << "Music volume slider changed to: " << value << std::endl;
musicVolume = value;
Environment::shipVelocity = musicVolume * 20.0f;
});
#endif
cubemapTexture = std::make_shared<Texture>(
std::array<TextureDataStruct, 6>{
CreateTextureDataFromPng("./resources/sky/space1.png", CONST_ZIP_FILE),
CreateTextureDataFromPng("./resources/sky/space1.png", CONST_ZIP_FILE),
CreateTextureDataFromPng("./resources/sky/space1.png", CONST_ZIP_FILE),
CreateTextureDataFromPng("./resources/sky/space1.png", CONST_ZIP_FILE),
CreateTextureDataFromPng("./resources/sky/space1.png", CONST_ZIP_FILE),
CreateTextureDataFromPng("./resources/sky/space1.png", CONST_ZIP_FILE)
CreateTextureDataFromBmp24("./resources/sky/space_rt.bmp", CONST_ZIP_FILE),
CreateTextureDataFromBmp24("./resources/sky/space_lf.bmp", CONST_ZIP_FILE),
CreateTextureDataFromBmp24("./resources/sky/space_up.bmp", CONST_ZIP_FILE),
CreateTextureDataFromBmp24("./resources/sky/space_dn.bmp", CONST_ZIP_FILE),
CreateTextureDataFromBmp24("./resources/sky/space_bk.bmp", CONST_ZIP_FILE),
CreateTextureDataFromBmp24("./resources/sky/space_ft.bmp", CONST_ZIP_FILE)
});
@ -245,12 +270,12 @@ namespace ZL
}
std::cout << "Init step 4 " << std::endl;
#ifndef SIMPLIFIED
if (!cfgLoaded)
{
throw std::runtime_error("Failed to load spark emitter config file!");
}
#endif
/* buttonTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/button.png", CONST_ZIP_FILE));
@ -416,18 +441,18 @@ namespace ZL
renderer.TranslateMatrix({ 0, -Environment::zoom * 0.03f, 0 });
glBindTexture(GL_TEXTURE_2D, spaceshipTexture->getTexID());
renderer.DrawVertexRenderStruct(spaceship);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
for (const auto& p : projectiles) {
if (p && p->isActive()) {
p->draw(renderer);
}
}
#ifndef SIMPLIFIED
sparkEmitter.draw(renderer, Environment::zoom, Environment::width, Environment::height);
projectileEmitter.draw(renderer, Environment::zoom, Environment::width, Environment::height);
glDisable(GL_BLEND);
#endif
renderer.PopMatrix();
renderer.PopProjectionMatrix();
renderer.DisableVertexAttribArray(vPositionName);
@ -479,6 +504,37 @@ namespace ZL
renderer.shaderManager.PopShader();
CheckGlError();
}
/*void Game::UpdateVolumeKnob() {
float musicVolumeBarButtonButtonCenterY = volumeBarMinY + musicVolume * (volumeBarMaxY - volumeBarMinY);
auto& pos = musicVolumeBarButton.data.PositionData;
pos[0] = { musicVolumeBarButtonButtonCenterX - musicVolumeBarButtonButtonRadius, musicVolumeBarButtonButtonCenterY - musicVolumeBarButtonButtonRadius, 0 };
pos[1] = { musicVolumeBarButtonButtonCenterX - musicVolumeBarButtonButtonRadius, musicVolumeBarButtonButtonCenterY + musicVolumeBarButtonButtonRadius, 0 };
pos[2] = { musicVolumeBarButtonButtonCenterX + musicVolumeBarButtonButtonRadius, musicVolumeBarButtonButtonCenterY + musicVolumeBarButtonButtonRadius, 0 };
pos[3] = { musicVolumeBarButtonButtonCenterX - musicVolumeBarButtonButtonRadius, musicVolumeBarButtonButtonCenterY - musicVolumeBarButtonButtonRadius, 0 };
pos[4] = { musicVolumeBarButtonButtonCenterX + musicVolumeBarButtonButtonRadius, musicVolumeBarButtonButtonCenterY + musicVolumeBarButtonButtonRadius, 0 };
pos[5] = { musicVolumeBarButtonButtonCenterX + musicVolumeBarButtonButtonRadius, musicVolumeBarButtonButtonCenterY - musicVolumeBarButtonButtonRadius, 0 };
musicVolumeBarButton.RefreshVBO();
}
void Game::UpdateVolumeFromMouse(int mouseX, int mouseY) {
int uiX = mouseX;
int uiY = Environment::height - mouseY;
Environment::shipVelocity = (musicVolume) * (20.0);
if (uiY < volumeBarMinY || uiY > volumeBarMaxY)
{
return;
}
float t = (uiY - volumeBarMinY) / (volumeBarMaxY - volumeBarMinY);
if (t < 0.0f) t = 0.0f;
if (t > 1.0f) t = 1.0f;
musicVolume = t;
UpdateVolumeKnob();
}*/
void Game::drawUI()
{
@ -495,11 +551,27 @@ namespace ZL
renderer.EnableVertexAttribArray(vPositionName);
renderer.EnableVertexAttribArray(vTexCoordName);
//renderer.PushProjectionMatrix(Environment::width, Environment::height, -1, 1);
//renderer.PushMatrix();
//renderer.LoadIdentity();
//glBindTexture(GL_TEXTURE_2D, buttonTexture->getTexID());
//renderer.DrawVertexRenderStruct(button);
//glBindTexture(GL_TEXTURE_2D, musicVolumeBarTexture->getTexID());
//renderer.DrawVertexRenderStruct(musicVolumeBar);
//glBindTexture(GL_TEXTURE_2D, musicVolumeBarButtonTexture->getTexID());
//renderer.DrawVertexRenderStruct(musicVolumeBarButton);
//renderer.PopMatrix();
//renderer.PopProjectionMatrix();
renderer.DisableVertexAttribArray(vPositionName);
renderer.DisableVertexAttribArray(vTexCoordName);
glEnable(GL_BLEND);
uiManager.draw(renderer);
glDisable(GL_BLEND);
renderer.shaderManager.PopShader();
CheckGlError();
}
@ -543,7 +615,10 @@ namespace ZL
drawShip();
drawBoxes();
#ifndef SIMPLIFIED
drawUI();
#endif
CheckGlError();
}
@ -559,9 +634,11 @@ namespace ZL
size_t delta = (newTickCount - lastTickCount > CONST_MAX_TIME_INTERVAL) ?
CONST_MAX_TIME_INTERVAL : newTickCount - lastTickCount;
#ifndef SIMPLIFIED
//gameObjects.updateScene(delta);
sparkEmitter.update(static_cast<float>(delta));
#endif
planetObject.update(static_cast<float>(delta));
if (Environment::tapDownHold) {
float diffx = Environment::tapDownCurrentPos(0) - Environment::tapDownStartPos(0);
@ -595,6 +672,7 @@ namespace ZL
Environment::shipPosition = Environment::shipPosition + velocityDirectionAdjusted;
}
#ifndef SIMPLIFIED
for (auto& p : projectiles) {
if (p && p->isActive()) {
p->update(static_cast<float>(delta), renderer);
@ -629,6 +707,7 @@ namespace ZL
sparkEmitter.update(static_cast<float>(delta));
projectileEmitter.update(static_cast<float>(delta));
#endif
lastTickCount = newTickCount;
}
}
@ -648,7 +727,7 @@ namespace ZL
for (const auto& lo : localOffsets) {
Vector3f worldPos = Environment::shipPosition + Environment::shipMatrix * lo;
Vector3f worldVel = worldForward * (projectileSpeed + Environment::shipVelocity);
Vector3f worldVel = worldForward * projectileSpeed;
for (auto& p : projectiles) {
if (!p->isActive()) {
@ -686,16 +765,15 @@ namespace ZL
uiManager.onMouseDown(uiX, uiY);
bool uiHandled = false;
/*
#ifndef SIMPLIFIED
if (event.button.button == SDL_BUTTON_LEFT && !uiManager.isUiInteraction()) {
uint64_t now = SDL_GetTicks64();
if (now - lastProjectileFireTime >= static_cast<uint64_t>(projectileCooldownMs)) {
lastProjectileFireTime = now;
fireProjectiles();
}
}*/
}
#endif
for (const auto& button : uiManager.findButton("") ? std::vector<std::shared_ptr<UiButton>>{} : std::vector<std::shared_ptr<UiButton>>{}) {
(void)button;
}

View File

@ -68,12 +68,12 @@ namespace ZL {
//bool isDraggingVolume = false;
/*
float velocitySlider = 0.0f;
float musicVolume = 0.0f;
float volumeBarMinX = 1190.0f;
float volumeBarMaxX = 1200.0f;
float volumeBarMinY = 100.0f;
float volumeBarMaxY = 600.0f;*/
float volumeBarMaxY = 600.0f;
//float musicVolumeBarButtonButtonCenterX = 1195.0f;
//float musicVolumeBarButtonButtonRadius = 25.0f;
//void UpdateVolumeFromMouse(int mouseX, int mouseY);

View File

@ -7,13 +7,11 @@
#include <iostream>
#include "Environment.h"
#include <stdexcept>
#include "utils/Utils.h"
namespace ZL {
using json = nlohmann::json;
SparkEmitter::SparkEmitter()
: emissionRate(100.0f), isActive(true), drawDataDirty(true), maxParticles(200),
shaderProgramName("default"), particleSize(0.04f), biasX(0.3f), configured(false) {
@ -77,7 +75,7 @@ namespace ZL {
std::sort(sortedParticles.begin(), sortedParticles.end(),
[](const auto& a, const auto& b) {
return a.second < b.second;
return a.second > b.second;
});
for (const auto& [particlePtr, depth] : sortedParticles) {
@ -331,29 +329,15 @@ namespace ZL {
bool SparkEmitter::loadFromJsonFile(const std::string& path, Renderer& renderer, const std::string& zipFile) {
std::cout << "Loading spark config from: " << path << std::endl;
std::string content;
try {
if (zipFile.empty()) {
content = readTextFile(path);
}
else {
auto buf = readFileFromZIP(path, zipFile);
if (buf.empty()) {
std::cerr << "Failed to read JSON from zip: " << path << " in " << zipFile << std::endl;
throw std::runtime_error("Failed to load spark emitter config file!");
}
content.assign(buf.begin(), buf.end());
}
}
catch (const std::exception& e) {
std::cerr << "Failed to open JSON file: " << path << " : " << e.what() << std::endl;
std::ifstream in(path);
if (!in.is_open()) {
std::cerr << "Failed to open JSON file: " << path << std::endl;
throw std::runtime_error("Failed to load spark emitter config file!");
}
json j;
try {
j = json::parse(content);
in >> j;
std::cout << "JSON parsed successfully" << std::endl;
}
catch (const std::exception& e) {

View File

@ -152,28 +152,15 @@ namespace ZL {
}
void UiManager::loadFromFile(const std::string& path, Renderer& renderer, const std::string& zipFile) {
std::string content;
try {
if (zipFile.empty()) {
content = readTextFile(path);
}
else {
auto buf = readFileFromZIP(path, zipFile);
if (buf.empty()) {
std::cerr << "UiManager: failed to read " << path << " from zip " << zipFile << std::endl;
throw std::runtime_error("Failed to load UI file: " + path);
}
content.assign(buf.begin(), buf.end());
}
}
catch (const std::exception& e) {
std::cerr << "UiManager: failed to open " << path << " : " << e.what() << std::endl;
std::ifstream in(path);
if (!in.is_open()) {
std::cerr << "UiManager: failed to open " << path << std::endl;
throw std::runtime_error("Failed to load UI file: " + path);
}
json j;
try {
j = json::parse(content);
in >> j;
}
catch (const std::exception& e) {
std::cerr << "UiManager: json parse error: " << e.what() << std::endl;

View File

@ -32,7 +32,7 @@ namespace ZL {
, currentLod(0)
{
currentLod = planetMeshLods.size() - 1; // Start with max LOD
/*
initialVertexMap = {
{{ 0.0f, 1.0f, 0.0f}, "A"},
{{ 0.0f, -1.0f, 0.0f}, "B"},
@ -40,7 +40,7 @@ namespace ZL {
{{-1.0f, 0.0f, 0.0f}, "D"},
{{ 0.0f, 0.0f, 1.0f}, "E"},
{{ 0.0f, 0.0f, -1.0f}, "F"}
};*/
};
}
void PlanetData::init() {

View File

@ -25,7 +25,12 @@ namespace ZL {
VertexID generateEdgeID(const VertexID& id1, const VertexID& id2);
#ifdef SIMPLIFIED
constexpr static int MAX_LOD_LEVELS = 6;
#else
constexpr static int MAX_LOD_LEVELS = 6;
#endif
struct Triangle
{
@ -89,7 +94,7 @@ namespace ZL {
int currentLod; // Ëîãè÷åñêèé òåêóùèé óðîâåíü äåòàëèçàöèè
//std::map<Vector3f, VertexID, Vector3fComparator> initialVertexMap;
std::map<Vector3f, VertexID, Vector3fComparator> initialVertexMap;
// Âíóòðåííèå ìåòîäû ãåíåðàöèè
std::vector<Triangle> subdivideTriangles(const std::vector<Triangle>& inputTriangles, float noiseCoeff);

View File

@ -17,7 +17,6 @@ namespace ZL {
Matrix3f GetRotationForTriangle(const Triangle& tri) {
Vector3f vA = tri.data[0];
Vector3f vB = tri.data[1];
Vector3f vC = tri.data[2];
@ -76,7 +75,7 @@ namespace ZL {
sandTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/sand2.png", CONST_ZIP_FILE));
stoneTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/rockdark3.png", CONST_ZIP_FILE));
stoneTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/rock.png", CONST_ZIP_FILE));
// Атмосфера
planetAtmosphereRenderStruct.data = planetData.getAtmosphereLod().vertexData;

View File

@ -15,14 +15,37 @@ namespace ZL {
#endif
#ifdef SIMPLIFIED
const float StoneParams::BASE_SCALE = 10.0f; // Общий размер камня
const float StoneParams::MIN_AXIS_SCALE = 1.0f; // Минимальное растяжение/сжатие по оси
const float StoneParams::MAX_AXIS_SCALE = 1.0f; // Максимальное растяжение/сжатие по оси
const float StoneParams::MIN_PERTURBATION = 0.0f; // Минимальное радиальное возмущение вершины
const float StoneParams::MAX_PERTURBATION = 0.0f; // Максимальное радиальное возмущение вершины
const int StoneParams::STONES_PER_TRIANGLE = 40;
/*
const float StoneParams::BASE_SCALE = 1000.0f; // Общий размер камня
const float StoneParams::MIN_AXIS_SCALE = 1.0f; // Минимальное растяжение/сжатие по оси
const float StoneParams::MAX_AXIS_SCALE = 1.0f; // Максимальное растяжение/сжатие по оси
const float StoneParams::MIN_PERTURBATION = 0.0f; // Минимальное радиальное возмущение вершины
const float StoneParams::MAX_PERTURBATION = 0.0f; // Максимальное радиальное возмущение вершины
const int StoneParams::STONES_PER_TRIANGLE = 2;
*/
#else
const float StoneParams::BASE_SCALE = 10.0f; // Общий размер камня
const float StoneParams::MIN_AXIS_SCALE = 1.0f; // Минимальное растяжение/сжатие по оси
const float StoneParams::MAX_AXIS_SCALE = 1.0f; // Максимальное растяжение/сжатие по оси
const float StoneParams::MIN_PERTURBATION = 0.0f; // Минимальное радиальное возмущение вершины
const float StoneParams::MAX_PERTURBATION = 0.0f; // Максимальное радиальное возмущение вершины
const int StoneParams::STONES_PER_TRIANGLE = 40;
#endif
/*const float StoneParams::MIN_AXIS_SCALE = 0.5f; // Минимальное растяжение/сжатие по оси
const float StoneParams::MAX_AXIS_SCALE = 1.5f; // Максимальное растяжение/сжатие по оси
const float StoneParams::MIN_PERTURBATION = 0.05f; // Минимальное радиальное возмущение вершины
const float StoneParams::MAX_PERTURBATION = 0.25f; // Максимальное радиальное возмущение вершины
*/
//const int StoneParams::STONES_PER_TRIANGLE = 1;
// Вспомогательная функция для получения случайного числа в диапазоне [min, max]

View File

@ -27,11 +27,11 @@ namespace ZL
};
BitSize bitSize;
/*#ifdef SIMPLIFIED
#ifdef SIMPLIFIED
MipmapType mipmap = NONE; // Ïî óìîë÷àíèþ âêëþ÷åíî
#else*/
#else
MipmapType mipmap = GENERATE; // Ïî óìîë÷àíèþ âêëþ÷åíî
//#endif
#endif
};
class Texture
{

View File

@ -5,11 +5,9 @@
#include <iostream>
#include <algorithm>
#include <fstream>
#ifdef EMSCRIPTEN
#include <zip.h>
#include <cstdlib>
#include <filesystem>
#include <string>
#include <cctype>
#endif
namespace ZL
{
@ -36,7 +34,7 @@ namespace ZL
file.seekg(0, std::ios::beg);
std::vector<char> vec;
vec.reserve(static_cast<size_t>(fileSize));
vec.reserve(fileSize);
vec.insert(vec.begin(),
std::istream_iterator<char>(file),
@ -44,96 +42,47 @@ namespace ZL
return vec;
}
std::vector<char> readFileFromZIP(const std::string& filename, const std::string& zipfilename) {
#ifdef EMSCRIPTEN
const std::string zipPath = zipfilename;
int zipErr;
zip_t* archive = zip_open(zipPath.c_str(), ZIP_RDONLY, &zipErr);
if (!archive) {
throw std::runtime_error("?????? ???????? ZIP: " + zipPath);
throw std::runtime_error("Ошибка открытия ZIP: " + zipPath);
}
std::string cleanFilename = filename;
if (cleanFilename.rfind("./", 0) == 0) {
cleanFilename = cleanFilename.substr(2);
}
std::cout << "???? ? ZIP: " << cleanFilename << std::endl;
std::cout << "Ищем в ZIP: " << cleanFilename << std::endl;
zip_file_t* zipFile = zip_fopen(archive, cleanFilename.c_str(), 0);
if (!zipFile) {
zip_close(archive);
throw std::runtime_error("???? ?? ?????? ? ZIP: " + cleanFilename);
throw std::runtime_error("Файл не найден в ZIP: " + cleanFilename);
}
zip_stat_t fileStat;
if (zip_stat(archive, cleanFilename.c_str(), 0, &fileStat) != 0) {
zip_fclose(zipFile);
zip_close(archive);
throw std::runtime_error("?????? ?????? ZIP-??????????.");
throw std::runtime_error("Ошибка чтения ZIP-статистики.");
}
std::vector<char> fileData;
fileData.resize(fileStat.size);
zip_fread(zipFile, fileData.data(), fileData.size());
zip_fclose(zipFile);
zip_close(archive);
return fileData;
#else
// ???????
if (zipfilename.empty()) {
std::cerr << "readFileFromZIP: zipfilename empty" << std::endl;
return {};
}
int zipErr = 0;
zip_t* archive = zip_open(zipfilename.c_str(), ZIP_RDONLY, &zipErr);
if (!archive) {
std::cerr << "readFileFromZIP: zip_open failed for: " << zipfilename
<< " (error code " << zipErr << ")" << std::endl;
return {};
}
std::string cleanFilename = filename;
if (cleanFilename.rfind("./", 0) == 0) {
cleanFilename = cleanFilename.substr(2);
}
zip_stat_t fileStat;
if (zip_stat(archive, cleanFilename.c_str(), 0, &fileStat) != 0) {
std::cerr << "readFileFromZIP: file not found in ZIP: " << cleanFilename
<< " in " << zipfilename << std::endl;
zip_close(archive);
return {};
}
zip_file_t* zipFile = zip_fopen(archive, cleanFilename.c_str(), 0);
if (!zipFile) {
std::cerr << "readFileFromZIP: zip_fopen failed for " << cleanFilename << std::endl;
zip_close(archive);
return {};
}
std::vector<char> fileData;
fileData.resize(static_cast<size_t>(fileStat.size));
zip_int64_t readBytes = zip_fread(zipFile, fileData.data(), static_cast<zip_uint64_t>(fileData.size()));
if (readBytes < 0) {
std::cerr << "readFileFromZIP: zip_fread failed for " << cleanFilename << std::endl;
zip_fclose(zipFile);
zip_close(archive);
return {};
}
zip_fclose(zipFile);
zip_close(archive);
return fileData;
return {};
#endif
}
@ -153,4 +102,4 @@ namespace ZL
}
return false;
}
};
};