New cars, static model rendering and stuff

This commit is contained in:
tovjemam 2026-01-19 18:10:24 +01:00
parent 899b0f990c
commit 7e1496bd70
15 changed files with 157 additions and 56 deletions

View File

@ -26,10 +26,14 @@ std::shared_ptr<const assets::Map> assets::Map::LoadFromFile(const std::string&
glm::vec3 angles; glm::vec3 angles;
iss >> obj.transform.position.x >> obj.transform.position.y >> obj.transform.position.z; auto trans = &obj.node.local;
iss >> trans->position.x >> trans->position.y >> trans->position.z;
iss >> angles.x >> angles.y >> angles.z; iss >> angles.x >> angles.y >> angles.z;
obj.transform.SetAngles(angles); trans->SetAngles(angles);
iss >> obj.transform.scale; iss >> trans->scale;
obj.node.UpdateMatrix();
std::string flag; std::string flag;
while (iss >> flag) while (iss >> flag)
@ -62,5 +66,22 @@ void assets::Map::Draw(gfx::DrawList& dlist) const
cmd.surface = &surface; cmd.surface = &surface;
dlist.AddSurface(cmd); dlist.AddSurface(cmd);
} }
for (const auto& obj : static_objects_)
{
if (!obj.model || !obj.model->GetMesh())
continue;
const auto& surfaces = obj.model->GetMesh()->surfaces;
for (const auto& surface : surfaces)
{
gfx::DrawSurfaceCmd cmd;
cmd.surface = &surface;
cmd.matrices = &obj.node.matrix;
// cmd.color_mod = glm::vec4(obj.color, 1.0f);
dlist.AddSurface(cmd);
}
}
} }
#endif // CLIENT #endif // CLIENT

View File

@ -4,7 +4,7 @@
#include <string> #include <string>
#include "model.hpp" #include "model.hpp"
#include "utils/transform.hpp" #include "game/transform_node.hpp"
#ifdef CLIENT #ifdef CLIENT
#include "gfx/draw_list.hpp" #include "gfx/draw_list.hpp"
@ -15,7 +15,7 @@ namespace assets
struct MapStaticObject struct MapStaticObject
{ {
Transform transform; game::TransformNode node;
std::shared_ptr<const Model> model; std::shared_ptr<const Model> model;
glm::vec3 color = glm::vec3(1.0f); glm::vec3 color = glm::vec3(1.0f);
}; };

View File

@ -76,14 +76,21 @@ std::shared_ptr<const assets::Model> assets::Model::LoadFromFile(const std::stri
{ {
CLIENT_ONLY(sflags |= gfx::SF_2SIDED;) CLIENT_ONLY(sflags |= gfx::SF_2SIDED;)
} }
else if (flag == "+transparent")
{
CLIENT_ONLY(sflags |= gfx::SF_TRANSPARENT;)
}
else if (flag == "+ocolor") else if (flag == "+ocolor")
{ {
CLIENT_ONLY(sflags |= gfx::SF_OBJECT_COLOR;) CLIENT_ONLY(sflags |= gfx::SF_OBJECT_COLOR;)
} }
else if (flag == "+blend")
{
std::string blend_str;
iss >> blend_str;
CLIENT_ONLY(
sflags |= gfx::SF_BLEND;
if (blend_str == "additive")
sflags |= gfx::SF_BLEND_ADDITIVE;
)
}
} }
CLIENT_ONLY( CLIENT_ONLY(
@ -128,7 +135,8 @@ std::shared_ptr<const assets::Model> assets::Model::LoadFromFile(const std::stri
// Optional but recommended // Optional but recommended
auto shape_hull = std::make_unique<btShapeHull>(temp_hull.get()); auto shape_hull = std::make_unique<btShapeHull>(temp_hull.get());
shape_hull->buildHull(temp_hull->getMargin()); // shape_hull->buildHull(temp_hull->getMargin());
shape_hull->buildHull(0.01f);
model->cshape_ = std::make_unique<btConvexHullShape>((btScalar*)shape_hull->getVertexPointer(), shape_hull->numVertices(), sizeof(btVector3)); model->cshape_ = std::make_unique<btConvexHullShape>((btScalar*)shape_hull->getVertexPointer(), shape_hull->numVertices(), sizeof(btVector3));
} }

View File

@ -69,7 +69,7 @@ void App::Frame()
float aspect = static_cast<float>(viewport_size_.x) / static_cast<float>(viewport_size_.y); float aspect = static_cast<float>(viewport_size_.x) / static_cast<float>(viewport_size_.y);
renderer_.Begin(viewport_size_.x, viewport_size_.y); renderer_.Begin(viewport_size_.x, viewport_size_.y);
renderer_.ClearColor(glm::vec3(0.3f, 0.9f, 1.0f)); renderer_.ClearColor(glm::vec3(0.5f, 0.7f, 1.0f));
renderer_.ClearDepth(); renderer_.ClearDepth();
dlist_.Clear(); dlist_.Clear();

View File

@ -15,7 +15,11 @@
#ifdef _WIN32 #ifdef _WIN32
#define NOMINMAX #define NOMINMAX
#pragma comment(lib, "ws2_32") #pragma comment(lib, "ws2_32")
#pragma comment(lib, "winmm.lib")
#include <WinSock2.h> #include <WinSock2.h>
#include <windows.h>
#include <chrono>
#include <thread>
#endif #endif
#include "app.hpp" #include "app.hpp"
@ -391,11 +395,26 @@ static void Main() {
emscripten_set_main_loop(Frame, 0, true); emscripten_set_main_loop(Frame, 0, true);
#else #else
#ifdef _WIN32
timeBeginPeriod(1);
#endif
SDL_GL_SetSwapInterval(0); SDL_GL_SetSwapInterval(0);
auto frame_dur = std::chrono::milliseconds(5);
while (!s_quit) while (!s_quit)
{ {
auto t_start = std::chrono::steady_clock::now();
Frame(); Frame();
auto t_next = t_start + frame_dur;
auto t_now = std::chrono::steady_clock::now();
if (t_now < t_next)
{
std::this_thread::sleep_for(t_next - t_now);
}
} }
s_app.reset(); s_app.reset();

View File

@ -38,7 +38,7 @@ void collision::DynamicsWorld::AddMapCollision()
// add static objects // add static objects
for (const auto& sobjs = map_->GetStaticObjects(); const auto& sobj : sobjs) for (const auto& sobjs = map_->GetStaticObjects(); const auto& sobj : sobjs)
{ {
AddModelInstance(*sobj.model, sobj.transform); AddModelInstance(*sobj.model, sobj.node.local);
} }
} }

View File

@ -3,7 +3,10 @@
#include "player.hpp" #include "player.hpp"
#include "vehicle.hpp" #include "vehicle.hpp"
game::OpenWorld::OpenWorld() : World("openworld") {} game::OpenWorld::OpenWorld() : World("openworld")
{
srand(time(NULL));
}
void game::OpenWorld::PlayerJoined(Player& player) void game::OpenWorld::PlayerJoined(Player& player)
{ {
@ -69,7 +72,7 @@ void game::OpenWorld::SpawnVehicle(Player& player)
// spawn him car // spawn him car
// random model // random model
const char* vehicles[] = {"pickup", "passat"}; const char* vehicles[] = {"pickup_hd", "passat", "twingo", "polskifiat"};
auto vehicle_name = vehicles[rand() % (sizeof(vehicles) / sizeof(vehicles[0]))]; auto vehicle_name = vehicles[rand() % (sizeof(vehicles) / sizeof(vehicles[0]))];
// ranodm color // ranodm color

View File

@ -67,7 +67,7 @@ void game::view::ClientSession::Update(const UpdateInfo& info)
glm::mat4 game::view::ClientSession::GetViewMatrix() const glm::mat4 game::view::ClientSession::GetViewMatrix() const
{ {
glm::vec3 center(0, 0, 3); glm::vec3 center(0.0f, 0.0f, 2.5f);
if (world_ && follow_ent_) if (world_ && follow_ent_)
{ {
@ -82,7 +82,7 @@ glm::mat4 game::view::ClientSession::GetViewMatrix() const
float pitch_sin = glm::sin(pitch_); float pitch_sin = glm::sin(pitch_);
glm::vec3 dir(yaw_sin * pitch_cos, yaw_cos * pitch_cos, pitch_sin); glm::vec3 dir(yaw_sin * pitch_cos, yaw_cos * pitch_cos, pitch_sin);
float distance = 10.0f; float distance = 8.0f;
auto eye = center - dir * distance; auto eye = center - dir * distance;

View File

@ -9,7 +9,8 @@
#include "client/gl.hpp" #include "client/gl.hpp"
#include "gfx/shader_sources.hpp" #include "shader_sources.hpp"
#include "shader_defs.hpp"
gfx::Renderer::Renderer() gfx::Renderer::Renderer()
{ {
@ -81,15 +82,15 @@ void gfx::Renderer::DrawSurfaceList(std::span<DrawSurfaceCmd> list, const DrawLi
const Surface* sa = a.surface; const Surface* sa = a.surface;
const Surface* sb = b.surface; const Surface* sb = b.surface;
const bool trans_a = sa->sflags & SF_TRANSPARENT; const bool blend_a = sa->sflags & SF_BLEND;
const bool trans_b = sb->sflags & SF_TRANSPARENT; const bool blend_b = sb->sflags & SF_BLEND;
if (trans_a != trans_b) if (blend_a != blend_b)
return trans_b; // opaque first return blend_b; // opaque first
if (trans_a) // both transparent if (blend_a) // both blended
{ {
return a.dist > b.dist; // do not optimize transparent, sort by distance instead return a.dist > b.dist; // do not optimize blended, sort by distance instead
} }
if (auto cmp = sa <=> sb; cmp != 0) if (auto cmp = sa <=> sb; cmp != 0)
@ -104,22 +105,28 @@ void gfx::Renderer::DrawSurfaceList(std::span<DrawSurfaceCmd> list, const DrawLi
return false; return false;
}); });
glEnable(GL_DEPTH_TEST); glActiveTexture(GL_TEXTURE0); // for all future bindings
glDepthFunc(GL_LESS);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glDisable(GL_BLEND);
InvalidateShaders();
// cache to eliminate fake state changes // cache to eliminate fake state changes
const gfx::Texture* last_texture = nullptr; const gfx::Texture* last_texture = nullptr;
const gfx::VertexArray* last_vao = nullptr; const gfx::VertexArray* last_vao = nullptr;
InvalidateShaders();
// enable depth test
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
// reset face culling
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
bool last_twosided = false; bool last_twosided = false;
glActiveTexture(GL_TEXTURE0); // for all future bindings // reset blending
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
bool last_blend = false;
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // set to opacity blending default
bool last_blend_additive = false;
for (const DrawSurfaceCmd& cmd : list) for (const DrawSurfaceCmd& cmd : list)
{ {
@ -129,7 +136,7 @@ void gfx::Renderer::DrawSurfaceList(std::span<DrawSurfaceCmd> list, const DrawLi
const bool skeletal_flag = surface->mflags & MF_SKELETAL; const bool skeletal_flag = surface->mflags & MF_SKELETAL;
// surface flags // surface flags
const bool twosided_flag = surface->sflags & SF_2SIDED; const bool twosided_flag = surface->sflags & SF_2SIDED;
const bool transparent_flag = surface->sflags & SF_TRANSPARENT; const bool blend_flag = surface->sflags & SF_BLEND;
const bool object_color_flag = surface->sflags & SF_OBJECT_COLOR; const bool object_color_flag = surface->sflags & SF_OBJECT_COLOR;
// sync 2sided // sync 2sided
@ -159,21 +166,56 @@ void gfx::Renderer::DrawSurfaceList(std::span<DrawSurfaceCmd> list, const DrawLi
} }
// set color // set color
bool cull_alpha = true; int shflags = SHF_CULL_ALPHA;
glm::vec4 color = glm::vec4(1.0f);
glm::vec4 color = glm::vec4(1.0f);
if (object_color_flag && cmd.color) if (object_color_flag && cmd.color)
{ {
// use object color and disable alpha cull // use object color and disable alpha cull
cull_alpha = false; shflags &= ~SHF_CULL_ALPHA;
shflags |= SHF_BACKGROUND;
color = glm::vec4(*cmd.color); color = glm::vec4(*cmd.color);
} }
// sync cull_alpha // sync blending
if (mshader.cull_alpha != cull_alpha) if (blend_flag != last_blend)
{ {
glUniform1i(mshader.shader->U(SU_CULL_ALPHA), cull_alpha ? 1 : 0); if (blend_flag)
mshader.cull_alpha = cull_alpha; {
glEnable(GL_BLEND);
glDepthMask(GL_FALSE);
}
else
{
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
}
last_blend = blend_flag;
}
// sync blending type
if (blend_flag)
{
shflags &= ~SHF_CULL_ALPHA;
const bool blend_additive = surface->sflags & SF_BLEND_ADDITIVE;
if (blend_additive != last_blend_additive)
{
if (blend_additive)
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
else
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
last_blend_additive = blend_additive;
}
// sync cull_alpha
if (mshader.flags != shflags)
{
glUniform1i(mshader.shader->U(SU_FLAGS), shflags);
mshader.flags = shflags;
} }
// sync color // sync color
@ -206,7 +248,8 @@ void gfx::Renderer::DrawSurfaceList(std::span<DrawSurfaceCmd> list, const DrawLi
(void*)(first_tri * 3U * sizeof(GLuint))); (void*)(first_tri * 3U * sizeof(GLuint)));
} }
// reset this as it is rare and other stuff might not reset this
glDepthMask(GL_TRUE);
} }

View File

@ -22,7 +22,7 @@ namespace gfx
// cached state to avoid redundant uniform updates which are expensive especially on WebGL // cached state to avoid redundant uniform updates which are expensive especially on WebGL
bool global_setup = false; bool global_setup = false;
glm::vec4 color = glm::vec4(-1.0f); // invalid to force initial setup glm::vec4 color = glm::vec4(-1.0f); // invalid to force initial setup
bool cull_alpha = false; int flags = 0;
}; };
class Renderer class Renderer

View File

@ -9,7 +9,7 @@ static const char* const s_uni_names[] = {
"u_view_proj", // SU_VIEW_PROJ "u_view_proj", // SU_VIEW_PROJ
"u_tex", // SU_TEX "u_tex", // SU_TEX
"u_color", // SU_COLOR "u_color", // SU_COLOR
"u_cull_alpha", // SU_COLOR "u_flags", // SU_FLAGS
}; };
// Vytvori shader z daneho zdroje // Vytvori shader z daneho zdroje

View File

@ -14,7 +14,7 @@ namespace gfx
SU_VIEW_PROJ, SU_VIEW_PROJ,
SU_TEX, SU_TEX,
SU_COLOR, SU_COLOR,
SU_CULL_ALPHA, SU_FLAGS,
SU_COUNT SU_COUNT
}; };

View File

@ -2,3 +2,6 @@
#define SD_MAX_LIGHTS 4 #define SD_MAX_LIGHTS 4
#define SD_MAX_BONES 256 #define SD_MAX_BONES 256
#define SHF_CULL_ALPHA 1
#define SHF_BACKGROUND 2

View File

@ -40,12 +40,12 @@
#define COMPUTE_LIGHTS_GLSL R"GLSL( #define COMPUTE_LIGHTS_GLSL R"GLSL(
// Example sun values (can later be uniforms) // Example sun values (can later be uniforms)
vec3 u_sun_direction = normalize(vec3(0.3, 0.5, -0.8)); // direction from which sunlight comes vec3 u_sun_direction = normalize(vec3(0.3, 0.5, -0.8)); // direction from which sunlight comes
vec3 u_sun_color = vec3(1.0, 0.95, 0.7); // warm sunlight color vec3 u_sun_color = vec3(1.0, 0.95, 0.7) * 0.9; // warm sunlight color
vec3 ComputeLights(in vec3 sector_pos, in vec3 sector_normal) vec3 ComputeLights(in vec3 sector_pos, in vec3 sector_normal)
{ {
// Base ambient // Base ambient
vec3 color = vec3(0.5, 0.5, 0.5); // u_ambient_light vec3 color = vec3(0.5, 0.5, 0.5) * 0.9; // u_ambient_light
// Sunlight contribution // Sunlight contribution
float sun_dot = max(dot(sector_normal, -u_sun_direction), 0.0); float sun_dot = max(dot(sector_normal, -u_sun_direction), 0.0);
@ -107,21 +107,24 @@ R"GLSL(
in vec2 v_uv; in vec2 v_uv;
in vec3 v_color; in vec3 v_color;
#define SHF_CULL_ALPHA 1
#define SHF_BACKGROUND 2
uniform sampler2D u_tex; uniform sampler2D u_tex;
uniform vec4 u_color; uniform vec4 u_color;
uniform bool u_cull_alpha; uniform int u_flags;
layout (location = 0) out vec4 o_color; layout (location = 0) out vec4 o_color;
void main() { void main() {
o_color = vec4(texture(u_tex, v_uv)); o_color = vec4(texture(u_tex, v_uv));
if (u_cull_alpha) if ((u_flags & SHF_CULL_ALPHA) > 0)
{ {
if (o_color.a < 0.5) if (o_color.a < 0.5)
discard; discard;
} }
else else if ((u_flags & SHF_BACKGROUND) > 0)
{ {
// blend with bg // blend with bg
o_color = mix(u_color, o_color, o_color.a); o_color = mix(u_color, o_color, o_color.a);

View File

@ -20,9 +20,10 @@ using SurfaceFlags = uint8_t;
enum SurfaceFlag : SurfaceFlags enum SurfaceFlag : SurfaceFlags
{ {
SF_NONE = 0x00, SF_NONE = 0x00,
SF_2SIDED = 0x01, SF_2SIDED = 0x01, // disable backface culling
SF_TRANSPARENT = 0x02, SF_BLEND = 0x02, // enable blending, disable depth write
SF_OBJECT_COLOR = 0x08, // use object level tint SF_BLEND_ADDITIVE = 0x04, // use additive blending instead of opacity
SF_OBJECT_COLOR = 0x08, // use object color for background instead of alpha culling
}; };
struct Surface struct Surface