Basic lightmap baking
This commit is contained in:
parent
c941ed9525
commit
be42793021
19
src/app.cpp
19
src/app.cpp
@ -16,13 +16,22 @@ App::App()
|
||||
|
||||
auto room001 = assets::SectorDef::LoadFromFile("data/room_001");
|
||||
|
||||
size_t s1 = world_.AddSector(room001);
|
||||
size_t s2 = world_.AddSector(room001);
|
||||
size_t s1i = world_.AddSector(room001);
|
||||
game::Sector& s1 = world_.GetSector(s1i);
|
||||
s1.AddLight(glm::vec3(0.0f, 0.0f, 1.8f), glm::vec3(0.0f, 1.0f, 1.0f), 5.0f);
|
||||
|
||||
size_t s2i = world_.AddSector(room001);
|
||||
game::Sector& s2 = world_.GetSector(s2i);
|
||||
s2.AddLight(glm::vec3(0.0f, 0.0f, 1.8f), glm::vec3(1.0f, 1.0f, 0.9f), 6.0f);
|
||||
|
||||
world_.LinkPortals(s1, "NDoor", s2, "WDoor");
|
||||
world_.LinkPortals(s2, "NDoor", s2, "SDoor");
|
||||
world_.LinkPortals(s1i, "NDoor", s2i, "WDoor", 0);
|
||||
world_.LinkPortals(s2i, "NDoor", s2i, "SDoor", 0);
|
||||
world_.LinkPortals(s2i, "EDoor", s2i, "EDoor", game::LINK_ROTATE180);
|
||||
|
||||
world_.Bake();
|
||||
|
||||
player_ = world_.Spawn<game::Player>(s1i, glm::vec3(0.0f, 0.0f, 1.0f));
|
||||
|
||||
player_ = world_.Spawn<game::Player>(s1, glm::vec3(0.0f, 0.0f, 1.0f));
|
||||
}
|
||||
|
||||
void App::Frame()
|
||||
|
||||
@ -8,9 +8,12 @@
|
||||
assets::Mesh::Mesh(std::span<MeshVertex> verts, std::span<MeshTriangle> tris, std::span<MeshMaterial> materials) :
|
||||
va_(gfx::VA_POSITION | gfx::VA_NORMAL | gfx::VA_UV | gfx::VA_LIGHTMAP_UV, gfx::VF_CREATE_EBO)
|
||||
{
|
||||
verts_.assign(verts.begin(), verts.end());
|
||||
tris_.assign(tris.begin(), tris.end());
|
||||
materials_.assign(materials.begin(), materials.end());
|
||||
|
||||
va_.SetVBOData(verts.data(), verts.size_bytes());
|
||||
va_.SetIndices(reinterpret_cast<const GLuint*>(tris.data()), tris.size() * 3);
|
||||
materials_.assign(materials.begin(), materials.end());
|
||||
}
|
||||
|
||||
std::shared_ptr<assets::Mesh> assets::Mesh::LoadFromFile(const std::string& filename, bool load_collision)
|
||||
|
||||
@ -34,8 +34,11 @@ namespace assets
|
||||
|
||||
class Mesh
|
||||
{
|
||||
gfx::VertexArray va_;
|
||||
std::vector<MeshVertex> verts_;
|
||||
std::vector<MeshTriangle> tris_;
|
||||
std::vector<MeshMaterial> materials_;
|
||||
|
||||
gfx::VertexArray va_;
|
||||
std::shared_ptr<collision::TriangleMesh> collision_mesh_;
|
||||
|
||||
public:
|
||||
@ -50,7 +53,10 @@ namespace assets
|
||||
}
|
||||
|
||||
const gfx::VertexArray& GetVA() { return va_; }
|
||||
const std::span<MeshMaterial> GetMaterials() { return materials_; }
|
||||
|
||||
std::span<const MeshVertex> GetVertices() const { return verts_; }
|
||||
std::span<const MeshTriangle> GetTriangles() const { return tris_; }
|
||||
std::span<const MeshMaterial> GetMaterials() const { return materials_; }
|
||||
|
||||
static std::shared_ptr<Mesh> LoadFromFile(const std::string& filename, bool load_collision);
|
||||
};
|
||||
|
||||
@ -9,7 +9,6 @@ namespace collision
|
||||
struct AABB
|
||||
{
|
||||
static constexpr float C_INFINITY = std::numeric_limits<float>::infinity();
|
||||
static constexpr float C_DEFAULT_MARGIN = 0.01f; // Margin for AABBs
|
||||
|
||||
using Vec = glm::vec<dim, float, glm::defaultp>;
|
||||
|
||||
@ -19,10 +18,10 @@ namespace collision
|
||||
AABB() = default;
|
||||
AABB(const Vec& min, const Vec& max) : min(min), max(max) {}
|
||||
|
||||
void AddPoint(const Vec& point, float margin = C_DEFAULT_MARGIN)
|
||||
void AddPoint(const Vec& point)
|
||||
{
|
||||
min = glm::min(min, point - margin);
|
||||
max = glm::max(max, point + margin);
|
||||
min = glm::min(min, point);
|
||||
max = glm::max(max, point);
|
||||
}
|
||||
|
||||
bool CollidesWith(const AABB<dim>& other) const;
|
||||
|
||||
@ -38,7 +38,6 @@ void game::Entity::Move(glm::vec3& velocity, float dt)
|
||||
|
||||
if (hit_portal != touching_portal_)
|
||||
{
|
||||
printf("Entity::Move: Touching portal changed from %p to %p\n", touching_portal_, hit_portal);
|
||||
touching_portal_ = hit_portal;
|
||||
|
||||
if (hit_portal)
|
||||
|
||||
@ -28,8 +28,6 @@ void game::Player::Rotate(float delta_yaw, float delta_pitch)
|
||||
|
||||
void game::Player::Update(float dt)
|
||||
{
|
||||
const glm::mat3& occu_basis = occu_->GetBasis();
|
||||
|
||||
float yaw_cos = glm::cos(yaw_);
|
||||
float yaw_sin = glm::sin(yaw_);
|
||||
float pitch_cos = glm::cos(pitch_);
|
||||
@ -101,7 +99,8 @@ void game::Player::Update(float dt)
|
||||
const glm::mat3& occu_basis = occu_->GetBasis();
|
||||
cam_forward_ = occu_basis * glm::vec3(yaw_sin * pitch_cos, yaw_cos * pitch_cos, pitch_sin);
|
||||
cam_up_ = occu_basis[2]; // Up vector is always the Z axis in sector space
|
||||
cam_right_ = glm::cross(cam_forward_, cam_up_);
|
||||
float scale = glm::length(cam_forward_);
|
||||
cam_right_ = glm::normalize(glm::cross(cam_forward_, cam_up_)) * scale;
|
||||
}
|
||||
|
||||
time_ += dt;
|
||||
@ -109,12 +108,10 @@ void game::Player::Update(float dt)
|
||||
|
||||
void game::Player::GetPOV(size_t& sector_idx, glm::vec3& position, glm::vec3& forward, glm::vec3& up) const
|
||||
{
|
||||
float scale = 1.0f;
|
||||
|
||||
sector_idx = occu_->GetSector().GetIndex();
|
||||
|
||||
glm::vec2 bobbing_offset = GetBobbingOffset(time_, 0.01f * current_speed_);
|
||||
glm::vec3 offset = ((cam_up_ * (0.7f + bobbing_offset.y)) + cam_right_ * bobbing_offset.x) * scale;
|
||||
glm::vec3 offset = cam_up_ * (0.7f + bobbing_offset.y) + cam_right_ * bobbing_offset.x;
|
||||
|
||||
position = occu_->GetPosition() + offset;
|
||||
|
||||
|
||||
@ -78,6 +78,15 @@ void game::Sector::ComputePortalVertex(Portal& portal, size_t idx, const glm::ve
|
||||
portal.verts[idx] = glm::vec3(portal.trans * glm::vec4(vert, 1.0f));
|
||||
}
|
||||
|
||||
void game::Sector::AddLight(const glm::vec3& position, const glm::vec3& color, float radius)
|
||||
{
|
||||
Light light;
|
||||
light.position = position;
|
||||
light.color = color;
|
||||
light.radius = radius;
|
||||
lights_.push_back(light);
|
||||
}
|
||||
|
||||
int game::Sector::GetPortalIndex(const std::string& name) const
|
||||
{
|
||||
auto it = portal_map_.find(name);
|
||||
@ -89,9 +98,15 @@ int game::Sector::GetPortalIndex(const std::string& name) const
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void LinkPortal(game::Portal& p1, game::Portal& p2) {
|
||||
static void LinkPortal(game::Portal& p1, game::Portal& p2, int flags) {
|
||||
// Calculate the traverse transformation
|
||||
glm::mat4 rotation = glm::rotate(glm::mat4(1.0f), glm::radians(180.0f), glm::vec3(0, 0, 1));
|
||||
|
||||
if (flags & game::LINK_ROTATE180)
|
||||
{
|
||||
rotation = glm::rotate(rotation, glm::radians(180.0f), glm::vec3(0, 1, 0));
|
||||
}
|
||||
|
||||
glm::mat4 p1_to_p2 = p2.trans * rotation * glm::inverse(p1.trans);
|
||||
|
||||
p1.link = &p2;
|
||||
@ -102,14 +117,14 @@ static void LinkPortal(game::Portal& p1, game::Portal& p2) {
|
||||
// Transforms directions from p1's sector space to p2's sector space
|
||||
p1.tr_basis = glm::mat3(p1.tr_position);
|
||||
|
||||
// get rid of scale
|
||||
for (size_t i = 0; i < 3 ; i++)
|
||||
p1.tr_basis[i] = glm::normalize(p1.tr_basis[i]);
|
||||
//// get rid of scale
|
||||
//for (size_t i = 0; i < 3 ; i++)
|
||||
// p1.tr_basis[i] = glm::normalize(p1.tr_basis[i]);
|
||||
|
||||
p1.tr_scale = p2.scale / p1.scale;
|
||||
}
|
||||
|
||||
void game::Sector::LinkPortals(Sector& s1, size_t idx1, Sector& s2, size_t idx2)
|
||||
void game::Sector::LinkPortals(Sector& s1, size_t idx1, Sector& s2, size_t idx2, int flags)
|
||||
{
|
||||
Portal& p1 = s1.portals_[idx1];
|
||||
Portal& p2 = s2.portals_[idx2];
|
||||
@ -119,11 +134,11 @@ void game::Sector::LinkPortals(Sector& s1, size_t idx1, Sector& s2, size_t idx2)
|
||||
throw std::runtime_error("One of the portals is already linked");
|
||||
}
|
||||
|
||||
LinkPortal(p1, p2);
|
||||
LinkPortal(p1, p2, flags);
|
||||
|
||||
if (&p1 != &p2)
|
||||
{
|
||||
LinkPortal(p2, p1);
|
||||
LinkPortal(p2, p1, flags);
|
||||
}
|
||||
|
||||
}
|
||||
@ -248,3 +263,154 @@ const game::Portal* game::Sector::TestPortalContact(btCapsuleShapeZ& capsule, co
|
||||
|
||||
return result_callback.portal;
|
||||
}
|
||||
|
||||
static bool PointIsOnRight(const glm::vec2& p0, const glm::vec2& p1, const glm::vec2& p)
|
||||
{
|
||||
// Check if point p is on the right side of the line segment p0 -> p1
|
||||
return (p1.x - p0.x) * (p.y - p0.y) - (p1.y - p0.y) * (p.x - p0.x) < 0.0f;
|
||||
}
|
||||
|
||||
static float SignedDistanceToLine(const glm::vec2& p0, const glm::vec2& p1, const glm::vec2& p)
|
||||
{
|
||||
// Calculate the signed distance from point p to the line segment p0 -> p1
|
||||
return (p1.x - p0.x) * (p.y - p0.y) - (p1.y - p0.y) * (p.x - p0.x);
|
||||
}
|
||||
|
||||
void game::Sector::BakeLightmap()
|
||||
{
|
||||
const size_t lightmap_size = 256;
|
||||
const glm::vec3 ambient_light(0.2f); // Ambient light color
|
||||
const float margin = 2.0f;
|
||||
|
||||
std::span<const assets::MeshVertex> mesh_verts = mesh_->GetVertices();
|
||||
std::span<const assets::MeshTriangle> mesh_tris = mesh_->GetTriangles();
|
||||
|
||||
struct LightmapTexel
|
||||
{
|
||||
bool used = false;
|
||||
glm::vec3 color = glm::vec3(0.0f);
|
||||
};
|
||||
|
||||
std::vector<LightmapTexel> lightmap(lightmap_size * lightmap_size);
|
||||
|
||||
for (const assets::MeshTriangle& tri : mesh_tris)
|
||||
{
|
||||
//const assets::MeshVertex* verts[3];
|
||||
glm::vec2 verts[3];
|
||||
glm::vec3 vert_pos[3];
|
||||
glm::vec3 vert_norm[3];
|
||||
|
||||
collision::AABB2 tri_aabb;
|
||||
|
||||
for (size_t i = 0; i < 3; ++i)
|
||||
{
|
||||
const assets::MeshVertex& vert = mesh_verts[tri.vert[i]];
|
||||
glm::vec2 pos_lightmap = vert.lightmap_uv * (float)lightmap_size;
|
||||
verts[i] = pos_lightmap;
|
||||
tri_aabb.AddPoint(pos_lightmap);
|
||||
|
||||
vert_pos[i] = vert.pos;
|
||||
vert_norm[i] = vert.normal;
|
||||
}
|
||||
|
||||
// Clamp to lightmap size
|
||||
int y0 = glm::max(0, (int)(tri_aabb.min.y - margin));
|
||||
int y1 = glm::min((int)lightmap_size, (int)(tri_aabb.max.y + 1.0f + margin));
|
||||
int x0 = glm::max(0, (int)(tri_aabb.min.x - margin));
|
||||
int x1 = glm::min((int)lightmap_size, (int)(tri_aabb.max.x + 1.0f + margin));
|
||||
|
||||
for (int y = y0; y < y1; ++y)
|
||||
{
|
||||
for (int x = x0; x < x1; ++x)
|
||||
{
|
||||
LightmapTexel& texel = lightmap[y * lightmap_size + x];
|
||||
|
||||
if (texel.used)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
glm::vec2 texel_pos((float)x + 0.5f, (float)y + 0.5f); // Center of the texel
|
||||
|
||||
//if (PointIsOnRight(verts[0], verts[1], texel_pos) ||
|
||||
// PointIsOnRight(verts[1], verts[2], texel_pos) ||
|
||||
// PointIsOnRight(verts[2], verts[0], texel_pos))
|
||||
//{
|
||||
// continue; // Texel is outside the triangle
|
||||
//}
|
||||
|
||||
float sd = SignedDistanceToLine(verts[0], verts[1], texel_pos);
|
||||
sd = glm::min(sd, SignedDistanceToLine(verts[1], verts[2], texel_pos));
|
||||
sd = glm::min(sd, SignedDistanceToLine(verts[2], verts[0], texel_pos));
|
||||
|
||||
if (sd > margin)
|
||||
{
|
||||
continue; // Texel is outside the triangle
|
||||
}
|
||||
|
||||
texel.used = sd < 0.0f;
|
||||
|
||||
// Compute barycentric coordinates
|
||||
glm::vec2 v0 = verts[1] - verts[0];
|
||||
glm::vec2 v1 = verts[2] - verts[0];
|
||||
glm::vec2 v2 = texel_pos - verts[0];
|
||||
float d00 = glm::dot(v0, v0);
|
||||
float d01 = glm::dot(v0, v1);
|
||||
float d11 = glm::dot(v1, v1);
|
||||
float d20 = glm::dot(v2, v0);
|
||||
float d21 = glm::dot(v2, v1);
|
||||
float denom = d00 * d11 - d01 * d01;
|
||||
if (denom == 0.0f)
|
||||
{
|
||||
continue; // Degenerate triangle, skip
|
||||
}
|
||||
|
||||
float v = (d11 * d20 - d01 * d21) / denom;
|
||||
float w = (d00 * d21 - d01 * d20) / denom;
|
||||
float u = 1.0f - v - w;
|
||||
|
||||
glm::vec3 texel_pos_ws = u * vert_pos[0] + v * vert_pos[1] + w * vert_pos[2];
|
||||
glm::vec3 texel_norm_ws = glm::normalize(u * vert_norm[0] + v * vert_norm[1] + w * vert_norm[2]);
|
||||
|
||||
glm::vec3 light_color = ambient_light;
|
||||
|
||||
for (const Light& light : lights_)
|
||||
{
|
||||
glm::vec3 light_dir = glm::normalize(light.position - texel_pos_ws);
|
||||
float dot = glm::dot(texel_norm_ws, light_dir);
|
||||
if (dot > 0.0f)
|
||||
{
|
||||
float dist = glm::length(light.position - texel_pos_ws);
|
||||
float attenuation = glm::clamp(1.0f - (dist / light.radius), 0.0f, 1.0f);
|
||||
light_color += light.color * dot * attenuation;
|
||||
}
|
||||
}
|
||||
|
||||
// Store the light color in the lightmap
|
||||
texel.color = light_color;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint8_t> lightmap_data(lightmap_size * lightmap_size * 3);
|
||||
for (size_t i = 0; i < lightmap.size(); ++i)
|
||||
{
|
||||
const LightmapTexel& texel = lightmap[i];
|
||||
glm::vec3 color = glm::clamp(texel.color * 0.5f, glm::vec3(0.0f), glm::vec3(1.0f));
|
||||
lightmap_data[i * 3 + 0] = static_cast<uint8_t>(color.r * 255.0f);
|
||||
lightmap_data[i * 3 + 1] = static_cast<uint8_t>(color.g * 255.0f);
|
||||
lightmap_data[i * 3 + 2] = static_cast<uint8_t>(color.b * 255.0f);
|
||||
}
|
||||
|
||||
|
||||
lightmap_ = std::make_shared<gfx::Texture>(
|
||||
lightmap_size, lightmap_size,
|
||||
lightmap_data.data(),
|
||||
GL_RGB,
|
||||
GL_RGB,
|
||||
GL_UNSIGNED_BYTE,
|
||||
GL_LINEAR
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@ -48,6 +48,18 @@ namespace game
|
||||
CollisionObjectData col_data;
|
||||
};
|
||||
|
||||
enum LinkPortalFlags
|
||||
{
|
||||
LINK_ROTATE180 = 1 << 0,
|
||||
};
|
||||
|
||||
struct Light
|
||||
{
|
||||
glm::vec3 position;
|
||||
glm::vec3 color;
|
||||
float radius;
|
||||
};
|
||||
|
||||
class Sector
|
||||
{
|
||||
World* world_;
|
||||
@ -56,6 +68,9 @@ namespace game
|
||||
|
||||
std::shared_ptr<assets::Mesh> mesh_;
|
||||
|
||||
std::vector<Light> lights_;
|
||||
std::shared_ptr<gfx::Texture> lightmap_;
|
||||
|
||||
std::vector<Portal> portals_;
|
||||
std::map<std::string, size_t> portal_map_; // Maps portal name to index in portals_
|
||||
|
||||
@ -73,14 +88,18 @@ namespace game
|
||||
void ComputePortalVertex(Portal& portal, size_t idx, const glm::vec2& base_vert);
|
||||
|
||||
public:
|
||||
|
||||
void AddLight(const glm::vec3& position, const glm::vec3& color, float radius);
|
||||
|
||||
size_t GetIndex() const { return idx_; }
|
||||
const std::shared_ptr<assets::Mesh>& GetMesh() const { return mesh_; }
|
||||
const std::shared_ptr<gfx::Texture>& GetLightmap() const { return lightmap_; }
|
||||
|
||||
int GetPortalIndex(const std::string& name) const;
|
||||
const Portal& GetPortal(size_t idx) const { return portals_[idx]; }
|
||||
const size_t GetNumPortals() const { return portals_.size(); }
|
||||
|
||||
static void LinkPortals(Sector& s1, size_t idx1, Sector& s2, size_t idx2);
|
||||
static void LinkPortals(Sector& s1, size_t idx1, Sector& s2, size_t idx2, int flags);
|
||||
|
||||
bool SweepCapsule(
|
||||
const btCapsuleShapeZ& capsule,
|
||||
@ -92,6 +111,7 @@ namespace game
|
||||
|
||||
const Portal* TestPortalContact(btCapsuleShapeZ& capsule, const glm::mat3& basis, const glm::vec3& pos);
|
||||
|
||||
void BakeLightmap();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ size_t game::World::AddSector(std::shared_ptr<assets::SectorDef> def)
|
||||
return idx;
|
||||
}
|
||||
|
||||
void game::World::LinkPortals(size_t sector1, const std::string& portal_name1, size_t sector2, const std::string& portal_name2)
|
||||
void game::World::LinkPortals(size_t sector1, const std::string& portal_name1, size_t sector2, const std::string& portal_name2, int flags)
|
||||
{
|
||||
Sector& s1 = *sectors_[sector1];
|
||||
Sector& s2 = *sectors_[sector2];
|
||||
@ -25,5 +25,13 @@ void game::World::LinkPortals(size_t sector1, const std::string& portal_name1, s
|
||||
throw std::runtime_error("Invalid portal names for linking");
|
||||
}
|
||||
|
||||
Sector::LinkPortals(s1, p1, s2, p2);
|
||||
Sector::LinkPortals(s1, p1, s2, p2, flags);
|
||||
}
|
||||
|
||||
void game::World::Bake()
|
||||
{
|
||||
for (auto& sector : sectors_)
|
||||
{
|
||||
sector->BakeLightmap();
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ namespace game
|
||||
size_t AddSector(std::shared_ptr<assets::SectorDef> def);
|
||||
|
||||
void LinkPortals(size_t sector1, const std::string& portal_name1,
|
||||
size_t sector2, const std::string& portal_name2);
|
||||
size_t sector2, const std::string& portal_name2, int flags);
|
||||
|
||||
template<class T, class... TArgs>
|
||||
T* Spawn(TArgs&&... args)
|
||||
@ -34,6 +34,8 @@ namespace game
|
||||
Sector& GetSector(size_t idx) { return *sectors_[idx]; }
|
||||
const Sector& GetSector(size_t idx) const { return *sectors_[idx]; }
|
||||
|
||||
void Bake();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@ -113,6 +113,18 @@ void gfx::Renderer::DrawSector(const DrawSectorParams& params)
|
||||
glUniformMatrix4fv(sector_shader_->U(gfx::SU_MODEL), 1, GL_FALSE, &model[0][0]);
|
||||
glUniform4fv(sector_shader_->U(gfx::SU_CLIP_PLANE), 1, ¶ms.clip_plane[0]);
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glUniform1i(sector_shader_->U(gfx::SU_LIGHTMAP_TEX), 1); // Bind lightmap to sampler
|
||||
const auto& lightmap = params.sector->GetLightmap();
|
||||
if (lightmap)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, lightmap->GetId());
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, 0); // No lightmap
|
||||
}
|
||||
|
||||
glBindVertexArray(mesh.GetVA().GetVAOId());
|
||||
for (auto mesh_materials = mesh.GetMaterials(); const auto& mat : mesh_materials) {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
@ -242,7 +254,7 @@ bool gfx::Renderer::ComputePortalScreenAABB(const game::Portal& portal, const gl
|
||||
glm::vec2 ndc = clip;
|
||||
ndc /= clip.w;
|
||||
|
||||
aabb.AddPoint(ndc, 0.0f);
|
||||
aabb.AddPoint(ndc);
|
||||
}
|
||||
|
||||
if (num_behind == 4)
|
||||
|
||||
@ -11,6 +11,7 @@ static const char* const s_uni_names[] = {
|
||||
"u_clip_plane", // SU_CLIP_PLANE
|
||||
"u_portal_size", // SU_PORTAL_SIZE
|
||||
"u_clear_depth", // SU_CLEAR_DEPTH
|
||||
"u_lightmap_tex", // SU_LIGHTMAP_TEX
|
||||
};
|
||||
|
||||
// Vytvori shader z daneho zdroje
|
||||
|
||||
@ -16,6 +16,7 @@ namespace gfx
|
||||
SU_CLIP_PLANE,
|
||||
SU_PORTAL_SIZE,
|
||||
SU_CLEAR_DEPTH,
|
||||
SU_LIGHTMAP_TEX,
|
||||
|
||||
SU_COUNT
|
||||
};
|
||||
|
||||
@ -20,12 +20,14 @@ R"GLSL(
|
||||
layout (location = 0) in vec3 a_pos;
|
||||
layout (location = 1) in vec3 a_normal;
|
||||
layout (location = 3) in vec2 a_uv;
|
||||
layout (location = 4) in vec2 a_lightmap_uv;
|
||||
|
||||
uniform mat4 u_model;
|
||||
uniform mat4 u_view_proj;
|
||||
uniform vec4 u_clip_plane;
|
||||
|
||||
out vec2 v_uv;
|
||||
out vec2 v_lightmap_uv;
|
||||
out float v_clip_distance;
|
||||
|
||||
void main() {
|
||||
@ -37,6 +39,7 @@ void main() {
|
||||
|
||||
//v_normal = mat3(u_model) * a_normal;
|
||||
v_uv = vec2(a_uv.x, 1.0 - a_uv.y);
|
||||
v_lightmap_uv = a_lightmap_uv;
|
||||
}
|
||||
)GLSL",
|
||||
|
||||
@ -44,9 +47,11 @@ void main() {
|
||||
GLSL_VERSION
|
||||
R"GLSL(
|
||||
in vec2 v_uv;
|
||||
in vec2 v_lightmap_uv;
|
||||
in float v_clip_distance;
|
||||
|
||||
uniform sampler2D u_tex;
|
||||
uniform sampler2D u_lightmap_tex;
|
||||
|
||||
layout (location = 0) out vec4 o_color;
|
||||
|
||||
@ -56,6 +61,7 @@ void main() {
|
||||
}
|
||||
|
||||
o_color = vec4(texture(u_tex, v_uv));
|
||||
o_color.rgb *= texture(u_lightmap_tex, v_lightmap_uv).rgb * 2.0; // Apply lightmap
|
||||
//o_color = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
|
||||
@ -16,8 +16,10 @@ gfx::Texture::Texture(GLuint width, GLuint height, const void* data, GLint inter
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
@ -37,7 +39,7 @@ std::shared_ptr<gfx::Texture> gfx::Texture::LoadFromFile(const std::string& file
|
||||
|
||||
std::shared_ptr<Texture> texture;
|
||||
try {
|
||||
texture = std::make_shared<Texture>(width, height, data, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR);
|
||||
texture = std::make_shared<Texture>(width, height, data, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR_MIPMAP_LINEAR);
|
||||
} catch (const std::exception& e) {
|
||||
stbi_image_free(data);
|
||||
throw; // Rethrow the exception after freeing the data
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user