Porting to web

This commit is contained in:
Vladislav Khorev 2026-01-07 15:14:13 +03:00
parent 6961152d34
commit 723b973c7f
16 changed files with 182 additions and 22 deletions

View File

@ -503,6 +503,7 @@ set_target_properties(space-game001 PROPERTIES
target_compile_definitions(space-game001 PRIVATE
PNG_ENABLED
SDL_MAIN_HANDLED
# SIMPLIFIED
)
# Линкуем с SDL2main, если он вообще установлен

View File

@ -154,6 +154,12 @@ emcc main.cpp Game.cpp Environment.cpp BoneAnimatedModel.cpp ZLMath.cpp Renderer
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/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 -I./thirdparty1/eigen-5.0.0 -I./src -I./thirdparty/libzip-1.11.3/build-emcmake/install/include -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
Code: MIT

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,8 @@
precision mediump float;
uniform samplerCube Texture;
varying vec3 dir;
void main(){
gl_FragColor = textureCube(Texture, normalize(dir));
}

View File

@ -0,0 +1,11 @@
attribute vec3 vPosition;
attribute vec2 vTexCoord;
varying vec2 texCoord;
uniform mat4 ProjectionModelViewMatrix;
void main()
{
gl_Position = ProjectionModelViewMatrix * vec4(vPosition.xyz, 1.0);
texCoord = vTexCoord;
}

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

View File

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

View File

@ -8,6 +8,7 @@
#include "TextModel.h"
#include <random>
#include <cmath>
#include <algorithm>
namespace ZL
{
@ -130,25 +131,40 @@ namespace ZL
// Initialize renderer
#ifdef EMSCRIPTEN
renderer.shaderManager.AddShaderFromFiles("default", "./shaders/default.vertex", "./shaders/default_web.fragment", CONST_ZIP_FILE);
/*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("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);
#else
#ifndef SIMPLIFIED
renderer.shaderManager.AddShaderFromFiles("default", "./shaders/default.vertex", "./shaders/default_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("defaultColor", "./shaders/defaultColor_fog.vertex", "./shaders/defaultColor_fog_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.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("defaultColor2", "./shaders/defaultColor_fog2.vertex", "./shaders/defaultColor_fog2_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("defaultColorStones", "./shaders/defaultColor_fog_stones.vertex", "./shaders/defaultColor_fog_stones_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);
#endif
#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>());
@ -187,6 +203,7 @@ namespace ZL
musicVolume = value;
Environment::shipVelocity = musicVolume * 20.0f;
});
#endif
cubemapTexture = std::make_shared<Texture>(
std::array<TextureDataStruct, 6>{
@ -223,10 +240,16 @@ namespace ZL
boxTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/box/box.png", CONST_ZIP_FILE));
boxBase = LoadFromTextFile02("./resources/box/box.txt", CONST_ZIP_FILE);
std::cout << "Init step 1 " << std::endl;
boxCoordsArr = generateRandomBoxCoords(50);
std::cout << "Init step 2 " << std::endl;
boxRenderArr.resize(boxCoordsArr.size());
std::cout << "Init step 3 " << std::endl;
for (int i = 0; i < boxCoordsArr.size(); i++)
{
boxRenderArr[i].AssignFrom(boxBase);
@ -234,10 +257,13 @@ namespace ZL
boxRenderArr[i].RefreshVBO();
}
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));
@ -296,14 +322,19 @@ namespace ZL
musicVolumeBarButton.data.TexCoordData.push_back({ 1,0 });
musicVolumeBarButton.RefreshVBO();*/
std::cout << "Init step 5 " << std::endl;
renderer.InitOpenGL();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
std::cout << "Init step 6 " << std::endl;
planetObject.init();
rockTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/rock.png", ""));
std::cout << "Init step 7 " << std::endl;
//rockTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/rock.png", CONST_ZIP_FILE));
std::cout << "Init step 8 " << std::endl;
}
void Game::drawCubemap(float skyPercent)
@ -403,9 +434,11 @@ namespace ZL
}
}
#ifndef SIMPLIFIED
sparkEmitter.draw(renderer, Environment::zoom, Environment::width, Environment::height);
projectileEmitter.draw(renderer, Environment::zoom, Environment::width, Environment::height);
#endif
renderer.PopMatrix();
renderer.PopProjectionMatrix();
renderer.DisableVertexAttribArray(vPositionName);
@ -568,8 +601,10 @@ namespace ZL
drawShip();
drawBoxes();
drawUI();
#ifndef SIMPLIFIED
drawUI();
#endif
CheckGlError();
}
@ -585,10 +620,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);
@ -622,6 +658,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);
@ -656,7 +693,7 @@ namespace ZL
sparkEmitter.update(static_cast<float>(delta));
projectileEmitter.update(static_cast<float>(delta));
#endif
lastTickCount = newTickCount;
}
}
@ -714,7 +751,7 @@ 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)) {
@ -722,7 +759,7 @@ namespace ZL
fireProjectiles();
}
}
#endif
for (const auto& button : uiManager.findButton("") ? std::vector<std::shared_ptr<UiButton>>{} : std::vector<std::shared_ptr<UiButton>>{}) {
(void)button;
}

View File

@ -47,7 +47,7 @@ namespace ZL {
size_t newTickCount;
size_t lastTickCount;
std::shared_ptr<Texture> rockTexture;
//std::shared_ptr<Texture> rockTexture;

View File

@ -51,9 +51,12 @@ namespace ZL {
planetMeshLods[i].Move(PLANET_CENTER_OFFSET);
}
#ifndef SIMPLIFIED
planetAtmosphereLod = generateSphere(5, 0);
planetAtmosphereLod.Scale(PLANET_RADIUS * 1.03);
planetAtmosphereLod.Move(PLANET_CENTER_OFFSET);
#endif
}
const LodLevel& PlanetData::getLodLevel(int level) const {

View File

@ -25,8 +25,12 @@ namespace ZL {
VertexID generateEdgeID(const VertexID& id1, const VertexID& id2);
#ifdef SIMPLIFIED
constexpr static int MAX_LOD_LEVELS = 1;
#else
constexpr static int MAX_LOD_LEVELS = 6;
//constexpr static int MAX_LOD_LEVELS = 2;
#endif
struct Triangle
{

View File

@ -5,8 +5,16 @@
#include "Environment.h"
#include "StoneObject.h"
namespace ZL {
#ifdef EMSCRIPTEN
using std::min;
using std::max;
#endif
extern const char* CONST_ZIP_FILE;
Matrix3f GetRotationForTriangle(const Triangle& tri) {
Vector3f vA = tri.data[0];
@ -66,16 +74,18 @@ namespace ZL {
planetRenderStruct.RefreshVBO();
sandTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/sand2.png", ""));
stoneTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/rock.png", ""));
sandTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/sand2.png", CONST_ZIP_FILE));
stoneTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/rock.png", CONST_ZIP_FILE));
#ifndef SIMPLIFIED
// Атмосфера
planetAtmosphereRenderStruct.data = planetData.getAtmosphereLod().vertexData;
if (planetAtmosphereRenderStruct.data.PositionData.size() > 0)
{
planetAtmosphereRenderStruct.RefreshVBO();
}
#endif
planetStones = CreateStoneGroupData(778, planetData.getLodLevel(lodIndex));
@ -195,6 +205,7 @@ namespace ZL {
void PlanetObject::draw(Renderer& renderer) {
#ifndef SIMPLIFIED
{
if (stoneMapFB == nullptr)
{
@ -210,6 +221,7 @@ namespace ZL {
stoneMapFB->GenerateMipmaps();
}
#endif
//bakeStoneTexture(renderer);
@ -220,7 +232,9 @@ namespace ZL {
drawPlanet(renderer);
drawStones(renderer);
#ifndef SIMPLIFIED
drawAtmosphere(renderer);
#endif
}
void PlanetObject::drawPlanet(Renderer& renderer)
@ -291,8 +305,10 @@ namespace ZL {
playerLightFactor = max(0.0f, (playerLightFactor + 0.2f) / 1.2f);
renderer.RenderUniform1f("uPlayerLightFactor", playerLightFactor);
#ifndef SIMPLIFIED
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, stoneMapFB->getTextureID());
#endif
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, sandTexture->getTexID());
@ -365,6 +381,7 @@ namespace ZL {
glBindTexture(GL_TEXTURE_2D, stoneTexture->getTexID());
for (int i : triangleIndicesToDraw)
//for (int i = 0; i < stonesToRender.size(); i++)
{
if (stonesToRender[i].data.PositionData.size() > 0)
{

View File

@ -9,20 +9,38 @@
namespace ZL {
#ifdef EMSCRIPTEN
using std::min;
using std::max;
#endif
#ifdef SIMPLIFIED
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 = 40;
//const int StoneParams::STONES_PER_TRIANGLE = 1;
// Вспомогательная функция для получения случайного числа в диапазоне [min, max]
float getRandomFloat(std::mt19937& gen, float min, float max) {
std::uniform_real_distribution<> distrib(min, max);

View File

@ -44,11 +44,19 @@ namespace ZL {
if (!vertexShaderCompiled)
{
#ifdef EMSCRIPTEN
std::cout << "Failed to compile vertex shader code!" << std::endl;
std::cout << infoLog << std::endl;
#endif
throw std::runtime_error("Failed to compile vertex shader code!");
}
if (!fragmentShaderCompiled)
{
#ifdef EMSCRIPTEN
std::cout << "Failed to compile fragment shader code!" << std::endl;
std::cout << infoLog2 << std::endl;
#endif
throw std::runtime_error("Failed to compile fragment shader code!");
}
@ -67,6 +75,10 @@ namespace ZL {
if (!programLinked)
{
#ifdef EMSCRIPTEN
std::cout << "Failed to link shader program!" << std::endl;
std::cout << infoLog << std::endl;
#endif
shaderProgram = 0;
throw std::runtime_error("Failed to link shader program!");
}
@ -202,7 +214,7 @@ namespace ZL {
ShaderSetter::ShaderSetter(ShaderManager& inShaderManager, const std::string& shaderName)
: shaderManager(shaderManager)
: shaderManager(inShaderManager)
{
shaderManager.PushShader(shaderName);
}

View File

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