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;
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;
obj.transform.SetAngles(angles);
iss >> obj.transform.scale;
trans->SetAngles(angles);
iss >> trans->scale;
obj.node.UpdateMatrix();
std::string flag;
while (iss >> flag)
@ -62,5 +66,22 @@ void assets::Map::Draw(gfx::DrawList& dlist) const
cmd.surface = &surface;
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

View File

@ -4,7 +4,7 @@
#include <string>
#include "model.hpp"
#include "utils/transform.hpp"
#include "game/transform_node.hpp"
#ifdef CLIENT
#include "gfx/draw_list.hpp"
@ -15,7 +15,7 @@ namespace assets
struct MapStaticObject
{
Transform transform;
game::TransformNode node;
std::shared_ptr<const Model> model;
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;)
}
else if (flag == "+transparent")
{
CLIENT_ONLY(sflags |= gfx::SF_TRANSPARENT;)
}
else if (flag == "+ocolor")
{
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(
@ -128,7 +135,8 @@ std::shared_ptr<const assets::Model> assets::Model::LoadFromFile(const std::stri
// Optional but recommended
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));
}

View File

@ -69,7 +69,7 @@ void App::Frame()
float aspect = static_cast<float>(viewport_size_.x) / static_cast<float>(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();
dlist_.Clear();

View File

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

View File

@ -38,7 +38,7 @@ void collision::DynamicsWorld::AddMapCollision()
// add static objects
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 "vehicle.hpp"
game::OpenWorld::OpenWorld() : World("openworld") {}
game::OpenWorld::OpenWorld() : World("openworld")
{
srand(time(NULL));
}
void game::OpenWorld::PlayerJoined(Player& player)
{
@ -69,7 +72,7 @@ void game::OpenWorld::SpawnVehicle(Player& player)
// spawn him car
// 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]))];
// ranodm color

View File

@ -67,7 +67,7 @@ void game::view::ClientSession::Update(const UpdateInfo& info)
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_)
{
@ -82,7 +82,7 @@ glm::mat4 game::view::ClientSession::GetViewMatrix() const
float pitch_sin = glm::sin(pitch_);
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;

View File

@ -9,7 +9,8 @@
#include "client/gl.hpp"
#include "gfx/shader_sources.hpp"
#include "shader_sources.hpp"
#include "shader_defs.hpp"
gfx::Renderer::Renderer()
{
@ -81,15 +82,15 @@ void gfx::Renderer::DrawSurfaceList(std::span<DrawSurfaceCmd> list, const DrawLi
const Surface* sa = a.surface;
const Surface* sb = b.surface;
const bool trans_a = sa->sflags & SF_TRANSPARENT;
const bool trans_b = sb->sflags & SF_TRANSPARENT;
const bool blend_a = sa->sflags & SF_BLEND;
const bool blend_b = sb->sflags & SF_BLEND;
if (trans_a != trans_b)
return trans_b; // opaque first
if (blend_a != blend_b)
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)
@ -103,24 +104,30 @@ void gfx::Renderer::DrawSurfaceList(std::span<DrawSurfaceCmd> list, const DrawLi
return false;
});
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glDisable(GL_BLEND);
InvalidateShaders();
glActiveTexture(GL_TEXTURE0); // for all future bindings
// cache to eliminate fake state changes
const gfx::Texture* last_texture = 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;
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)
{
const Surface* surface = cmd.surface;
@ -129,7 +136,7 @@ void gfx::Renderer::DrawSurfaceList(std::span<DrawSurfaceCmd> list, const DrawLi
const bool skeletal_flag = surface->mflags & MF_SKELETAL;
// surface flags
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;
// sync 2sided
@ -159,21 +166,56 @@ void gfx::Renderer::DrawSurfaceList(std::span<DrawSurfaceCmd> list, const DrawLi
}
// set color
bool cull_alpha = true;
glm::vec4 color = glm::vec4(1.0f);
int shflags = SHF_CULL_ALPHA;
glm::vec4 color = glm::vec4(1.0f);
if (object_color_flag && cmd.color)
{
// use object color and disable alpha cull
cull_alpha = false;
shflags &= ~SHF_CULL_ALPHA;
shflags |= SHF_BACKGROUND;
color = glm::vec4(*cmd.color);
}
// sync blending
if (blend_flag != last_blend)
{
if (blend_flag)
{
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.cull_alpha != cull_alpha)
if (mshader.flags != shflags)
{
glUniform1i(mshader.shader->U(SU_CULL_ALPHA), cull_alpha ? 1 : 0);
mshader.cull_alpha = cull_alpha;
glUniform1i(mshader.shader->U(SU_FLAGS), shflags);
mshader.flags = shflags;
}
// sync color
@ -206,7 +248,8 @@ void gfx::Renderer::DrawSurfaceList(std::span<DrawSurfaceCmd> list, const DrawLi
(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
bool global_setup = false;
glm::vec4 color = glm::vec4(-1.0f); // invalid to force initial setup
bool cull_alpha = false;
int flags = 0;
};
class Renderer

View File

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

View File

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

View File

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

View File

@ -27,7 +27,7 @@
#define MESH_MATRICES_GLSL R"GLSL(
uniform mat4 u_view_proj;
uniform mat4 u_model; // Transform matrix
uniform mat4 u_model; // Transform matrix
)GLSL"
#define LIGHT_MATRICES_GLSL R"GLSL(
@ -40,12 +40,12 @@
#define COMPUTE_LIGHTS_GLSL R"GLSL(
// 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_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)
{
// 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
float sun_dot = max(dot(sector_normal, -u_sun_direction), 0.0);
@ -107,21 +107,24 @@ R"GLSL(
in vec2 v_uv;
in vec3 v_color;
#define SHF_CULL_ALPHA 1
#define SHF_BACKGROUND 2
uniform sampler2D u_tex;
uniform vec4 u_color;
uniform bool u_cull_alpha;
uniform int u_flags;
layout (location = 0) out vec4 o_color;
void main() {
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)
discard;
discard;
}
else
else if ((u_flags & SHF_BACKGROUND) > 0)
{
// blend with bg
o_color = mix(u_color, o_color, o_color.a);

View File

@ -20,9 +20,10 @@ using SurfaceFlags = uint8_t;
enum SurfaceFlag : SurfaceFlags
{
SF_NONE = 0x00,
SF_2SIDED = 0x01,
SF_TRANSPARENT = 0x02,
SF_OBJECT_COLOR = 0x08, // use object level tint
SF_2SIDED = 0x01, // disable backface culling
SF_BLEND = 0x02, // enable blending, disable depth write
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