Compare commits
17 Commits
c6d83c1b51
...
07108956b9
| Author | SHA1 | Date | |
|---|---|---|---|
| 07108956b9 | |||
| eb4b3bc78f | |||
| 8434ee8633 | |||
| 2d10e22a99 | |||
| 103fdcaa26 | |||
| 9e3bc4790b | |||
| 4bc74d0d2c | |||
| 3cca0b5c87 | |||
| bb4a2c926e | |||
| 808fad3001 | |||
| 73da0d79f5 | |||
| 788a302d75 | |||
| e36a599d68 | |||
| 9591ad403b | |||
| 51ace4a800 | |||
| 577336b5b7 | |||
| 9b26cf909b |
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -69,6 +69,7 @@
|
|||||||
"regex": "cpp",
|
"regex": "cpp",
|
||||||
"semaphore": "cpp",
|
"semaphore": "cpp",
|
||||||
"shared_mutex": "cpp",
|
"shared_mutex": "cpp",
|
||||||
"stop_token": "cpp"
|
"stop_token": "cpp",
|
||||||
|
"filesystem": "cpp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
103
engine/include/engine/3d/array.hpp
Normal file
103
engine/include/engine/3d/array.hpp
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
#ifndef CORE_ARRAY_H_
|
||||||
|
#define CORE_ARRAY_H_
|
||||||
|
|
||||||
|
#define ARRAY_INITIAL_CAPACITY 2
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
|
||||||
|
template<typename Item, typename Size = unsigned int>
|
||||||
|
class Array {
|
||||||
|
public:
|
||||||
|
Array() {
|
||||||
|
m_size = 0;
|
||||||
|
m_capacity = ARRAY_INITIAL_CAPACITY;
|
||||||
|
m_items = static_cast<Item*>(::operator new[](m_capacity * sizeof(Item)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Array(Size initialCapacity) {
|
||||||
|
m_size = 0;
|
||||||
|
m_capacity = initialCapacity;
|
||||||
|
m_items = static_cast<Item*>(::operator new[](m_capacity * sizeof(Item)));
|
||||||
|
}
|
||||||
|
|
||||||
|
~Array() {
|
||||||
|
for (unsigned int i = 0; i < m_size; ++i) {
|
||||||
|
m_items[i].~Item();
|
||||||
|
}
|
||||||
|
delete m_items;
|
||||||
|
}
|
||||||
|
|
||||||
|
Array(Array&& other) {
|
||||||
|
m_capacity = other.m_capacity;
|
||||||
|
m_size = other.m_size;
|
||||||
|
m_items = other.m_items;
|
||||||
|
|
||||||
|
other.m_size = 0;
|
||||||
|
other.m_capacity = 0;
|
||||||
|
other.m_items = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Array(const Array&) = delete;
|
||||||
|
public:
|
||||||
|
inline const Size GetSize() const noexcept { return m_size; }
|
||||||
|
|
||||||
|
Item* Begin() { return m_items; }
|
||||||
|
const Item* Begin() const { return m_items; }
|
||||||
|
|
||||||
|
Item& Back() { assert(m_size > 0 && "Calling back() on empty array!"); return m_items[m_size - 1]; }
|
||||||
|
const Item& Back() const { assert(m_size > 0 && "Calling back() on empty array!"); return m_items[m_size - 1]; }
|
||||||
|
|
||||||
|
Item* End() { return m_items + m_size; }
|
||||||
|
const Item* End() const { return m_items + m_size; }
|
||||||
|
|
||||||
|
inline const bool Empty() const { return m_size == 0; }
|
||||||
|
public:
|
||||||
|
template<typename... Args>
|
||||||
|
void EmplaceBack(Args&&... args) {
|
||||||
|
_ensureSize(m_size + 1);
|
||||||
|
new (&m_items[m_size++]) Item(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PushBack(const Item& item) {
|
||||||
|
_ensureSize(m_size + 1);
|
||||||
|
new (&m_items[m_size++]) Item(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PushBack(Item&& item) {
|
||||||
|
_ensureSize(m_size + 1);
|
||||||
|
new (&m_items[m_size++]) Item(std::move(item));
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
void _ensureSize(Size size) {
|
||||||
|
if (size > m_capacity) {
|
||||||
|
_extend(static_cast<Size>(m_capacity + (m_capacity / 2)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _extend(Size newSize) {
|
||||||
|
auto newItems = static_cast<Item*>(::operator new[](newSize * sizeof(Item)));
|
||||||
|
|
||||||
|
std::uninitialized_move(
|
||||||
|
std::make_move_iterator(m_items),
|
||||||
|
std::make_move_iterator(m_items + m_capacity),
|
||||||
|
newItems
|
||||||
|
);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < m_capacity; ++i) {
|
||||||
|
m_items[i].~Item();
|
||||||
|
}
|
||||||
|
|
||||||
|
::operator delete[](m_items);
|
||||||
|
|
||||||
|
m_items = newItems;
|
||||||
|
m_capacity = newSize;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
Item* m_items;
|
||||||
|
Size m_size;
|
||||||
|
Size m_capacity;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CORE_ARRAY_H_
|
||||||
64
engine/include/engine/3d/material.hpp
Normal file
64
engine/include/engine/3d/material.hpp
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#ifndef MATERIAL_H_
|
||||||
|
#define MATERIAL_H_
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "engine/renderer/texture.h"
|
||||||
|
|
||||||
|
#ifndef DEFAULT_MATERIAL_NAME
|
||||||
|
#define DEFAULT_MATERIAL_NAME "__default_material"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
|
||||||
|
typedef std::string MaterialID;
|
||||||
|
|
||||||
|
class Material {
|
||||||
|
public:
|
||||||
|
Material(const std::string& name) : m_id(name) {}
|
||||||
|
|
||||||
|
Material() : Material(DEFAULT_MATERIAL_NAME) {}
|
||||||
|
|
||||||
|
// Material(const Material&) = default;
|
||||||
|
public:
|
||||||
|
static Material Default() {
|
||||||
|
Material material;
|
||||||
|
material.SetAmbientColor(glm::vec3(0.52f, 0.52f, 0.52f));
|
||||||
|
return material;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
inline const MaterialID GetID() const { return m_id; }
|
||||||
|
|
||||||
|
inline const glm::vec3 GetAmbientColor() const { return m_ambient; }
|
||||||
|
inline const glm::vec3 GetDiffuseColor() const { return m_diffuse; }
|
||||||
|
inline const glm::vec3 GetSpecularColor() const { return m_specular; }
|
||||||
|
inline const float GetSpecularWeight() const { return m_shininess; }
|
||||||
|
inline const bool HasDiffuseTexture() const { return m_diffuse_tex != nullptr; }
|
||||||
|
inline const Texture* GetDiffuseTexture() const { return m_diffuse_tex; }
|
||||||
|
inline const float GetOpacity() const { return m_opacity; }
|
||||||
|
inline const int GetIllumination() const { return m_illum; }
|
||||||
|
public:
|
||||||
|
inline void SetAmbientColor(glm::vec3 ambient) { m_ambient = ambient; }
|
||||||
|
inline void SetDiffuseColor(glm::vec3 diffuse) { m_diffuse = diffuse; }
|
||||||
|
inline void SetSpecularColor(glm::vec3 specular) { m_specular = specular; }
|
||||||
|
inline void SetSpecularWeight(float weight) { m_shininess = weight; }
|
||||||
|
inline void SetDiffuseTexture(Texture* texture) { m_diffuse_tex = texture; }
|
||||||
|
inline void SetOpacity(float opacity) { m_opacity = opacity; }
|
||||||
|
inline void SetIllumination(float illum) { m_illum = illum; }
|
||||||
|
private:
|
||||||
|
glm::vec3 m_ambient { 0.2f, 0.2f, 0.2f };
|
||||||
|
glm::vec3 m_diffuse { 0.8f, 0.8f, 0.8f };
|
||||||
|
glm::vec3 m_specular { 1.0f, 1.0f, 1.0f };
|
||||||
|
float m_shininess { 32.0f };
|
||||||
|
float m_opacity { 1.0f };
|
||||||
|
int m_illum { 2 };
|
||||||
|
|
||||||
|
MaterialID m_id { 0 };
|
||||||
|
|
||||||
|
Texture* m_diffuse_tex { nullptr };
|
||||||
|
}; // class Material
|
||||||
|
|
||||||
|
} // namespace Core
|
||||||
|
|
||||||
|
#endif // MATERIAL_H_
|
||||||
85
engine/include/engine/3d/mesh.hpp
Normal file
85
engine/include/engine/3d/mesh.hpp
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "engine/3d/array.hpp"
|
||||||
|
#include "engine/3d/vertex.hpp"
|
||||||
|
#include "engine/3d/material.hpp"
|
||||||
|
|
||||||
|
#include "engine/export.h"
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
|
||||||
|
class ENGINE_API Mesh {
|
||||||
|
public:
|
||||||
|
Mesh() = default;
|
||||||
|
Mesh(const Material& material) : m_material(material) {}
|
||||||
|
|
||||||
|
Mesh(const Mesh&) = delete;
|
||||||
|
Mesh(Mesh&&) = default;
|
||||||
|
public:
|
||||||
|
template<typename... Args>
|
||||||
|
uint32_t EmplaceVertex(Args&&... args) {
|
||||||
|
Vertex v(std::forward<Args>(args)...);
|
||||||
|
auto it = m_vti.find(v);
|
||||||
|
if (it != m_vti.end()) return it->second;
|
||||||
|
uint32_t newIndex = static_cast<uint32_t>(m_vertices.GetSize());
|
||||||
|
m_vertices.PushBack(std::move(v));
|
||||||
|
m_vti.emplace(m_vertices.Back(), newIndex);
|
||||||
|
return newIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PushVertex(const Vertex& vertex) {
|
||||||
|
auto it = m_vti.find(vertex);
|
||||||
|
if (it != m_vti.end()) return it->second;
|
||||||
|
uint32_t newIndex = static_cast<uint32_t>(m_vertices.GetSize());
|
||||||
|
m_vertices.PushBack(vertex);
|
||||||
|
m_vti.emplace(m_vertices.Back(), newIndex);
|
||||||
|
return newIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PushTriangle(uint32_t a, uint32_t b, uint32_t c) {
|
||||||
|
m_indices.PushBack(a);
|
||||||
|
m_indices.PushBack(b);
|
||||||
|
m_indices.PushBack(c);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
inline const Material& GetMaterial() const { return m_material; }
|
||||||
|
private:
|
||||||
|
Array<Vertex> m_vertices { VERTICES_INITIAL_CAPACITY };
|
||||||
|
Array<uint32_t> m_indices { INDICES_INITIAL_CAPACITY };
|
||||||
|
|
||||||
|
Material m_material;
|
||||||
|
|
||||||
|
std::unordered_map<Vertex, uint32_t, VertexHash> m_vti;
|
||||||
|
}; // class Mesh
|
||||||
|
|
||||||
|
// Right now it's just a list of meshes connected to each other.
|
||||||
|
// In future we might want to add support for global material
|
||||||
|
// that can affect all sub materials, aka this class
|
||||||
|
// will act like Parent Mesh that contains Child Meshes
|
||||||
|
class ENGINE_API MeshGroup : public Array<Mesh> {
|
||||||
|
public:
|
||||||
|
MeshGroup() {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline Mesh* FindMeshByMaterial(const Material& material) {
|
||||||
|
for (auto it = Begin(); it != End(); ++it) {
|
||||||
|
if (it->GetMaterial().GetID() == material.GetID()) {
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return End();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Mesh* FindMeshByMaterial(const Material* material) {
|
||||||
|
for (auto it = Begin(); it != End(); ++it) {
|
||||||
|
if (it->GetMaterial().GetID() == material->GetID()) {
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return End();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Core
|
||||||
63
engine/include/engine/3d/vertex.hpp
Normal file
63
engine/include/engine/3d/vertex.hpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#define VERTICES_INITIAL_CAPACITY 256
|
||||||
|
#define INDICES_INITIAL_CAPACITY 512
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
|
||||||
|
struct Vertex {
|
||||||
|
public:
|
||||||
|
Vertex(glm::vec3 position, glm::vec3 normal, glm::vec2 uv)
|
||||||
|
: position(position), normal(normal), uv(uv) {}
|
||||||
|
Vertex()
|
||||||
|
: position(glm::vec3()), normal(glm::vec3()), uv(glm::vec2()) {}
|
||||||
|
|
||||||
|
Vertex(const Vertex&) noexcept = default;
|
||||||
|
Vertex(Vertex&&) noexcept = default;
|
||||||
|
|
||||||
|
bool operator ==(Vertex const& o) const noexcept {
|
||||||
|
return o.position == position
|
||||||
|
&& o.normal == normal
|
||||||
|
&& o.uv == uv;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
glm::vec3 position;
|
||||||
|
glm::vec3 normal;
|
||||||
|
glm::vec2 uv;
|
||||||
|
|
||||||
|
friend class VertexHash;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VertexHash {
|
||||||
|
size_t operator()(Vertex const& v) const noexcept {
|
||||||
|
auto h = [](float f) -> size_t {
|
||||||
|
uint32_t b;
|
||||||
|
static_assert(sizeof(float) == sizeof(uint32_t));
|
||||||
|
std::memcpy(&b, &f, sizeof(float));
|
||||||
|
// splitmix64-like mixing (simple)
|
||||||
|
uint64_t x = b;
|
||||||
|
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL;
|
||||||
|
x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL;
|
||||||
|
x ^= x >> 31;
|
||||||
|
return static_cast<size_t>(x);
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t res = 1469598103934665603ULL;
|
||||||
|
res ^= h(v.position.x) + 0x9e3779b97f4a7c15ULL + (res<<6) + (res>>2);
|
||||||
|
res ^= h(v.position.y) + 0x9e3779b97f4a7c15ULL + (res<<6) + (res>>2);
|
||||||
|
res ^= h(v.position.z) + 0x9e3779b97f4a7c15ULL + (res<<6) + (res>>2);
|
||||||
|
|
||||||
|
res ^= h(v.normal.x) + 0x9e3779b97f4a7c15ULL + (res<<6) + (res>>2);
|
||||||
|
res ^= h(v.normal.y) + 0x9e3779b97f4a7c15ULL + (res<<6) + (res>>2);
|
||||||
|
res ^= h(v.normal.z) + 0x9e3779b97f4a7c15ULL + (res<<6) + (res>>2);
|
||||||
|
|
||||||
|
res ^= h(v.uv.x) + 0x9e3779b97f4a7c15ULL + (res<<6) + (res>>2);
|
||||||
|
res ^= h(v.uv.y) + 0x9e3779b97f4a7c15ULL + (res<<6) + (res>>2);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@ -29,7 +29,7 @@ private:
|
|||||||
unsigned int m_instance_count { 0 };
|
unsigned int m_instance_count { 0 };
|
||||||
|
|
||||||
// TODO: use static draw when possible
|
// TODO: use static draw when possible
|
||||||
std::unique_ptr<OpenGL::InstanceBuffer> m_instanceBuffer = nullptr;
|
OpenGL::InstanceBuffer* m_instanceBuffer = nullptr;
|
||||||
private:
|
private:
|
||||||
friend class Renderer;
|
friend class Renderer;
|
||||||
void prepare(glm::mat4 *instances, unsigned int count);
|
void prepare(glm::mat4 *instances, unsigned int count);
|
||||||
|
|||||||
@ -20,21 +20,28 @@ namespace OpenGL {
|
|||||||
~Buffer();
|
~Buffer();
|
||||||
|
|
||||||
inline const BufferID GetID() const { return m_buffer; }
|
inline const BufferID GetID() const { return m_buffer; }
|
||||||
protected:
|
inline const BufferTarget GetTarget() const { return m_target; }
|
||||||
void Data(void* data, size_t size);
|
public:
|
||||||
void SubData(void *data, size_t size, size_t offset);
|
static inline const bool IsBound(const Buffer& buffer) { return m_bound == buffer.GetID(); }
|
||||||
|
static inline const bool IsBound(const Buffer* buffer) { return buffer && m_bound == buffer->GetID(); }
|
||||||
|
// static inline void Bind(const Buffer& buffer) { glBindBuffer(buffer.GetTarget(), buffer.GetID()); }
|
||||||
|
static inline void Bind(const Buffer* buffer) { glBindBuffer(buffer->GetTarget(), buffer->GetID()); m_bound = buffer->GetID(); }
|
||||||
|
static inline void Unbind(const Buffer* buffer) { glBindBuffer(buffer->GetTarget(), 0); m_bound = 0; }
|
||||||
|
|
||||||
|
static void Data(const Buffer* buffer, const void* data, size_t size);
|
||||||
|
static void SubData(const Buffer* buffer, const void *data, size_t size, size_t offset);
|
||||||
|
protected:
|
||||||
void BindBuffer(unsigned int index) const;
|
void BindBuffer(unsigned int index) const;
|
||||||
void BindBufferRanged(unsigned int index, size_t offset, size_t size) const;
|
void BindBufferRanged(unsigned int index, size_t offset, size_t size) const;
|
||||||
protected:
|
|
||||||
void Bind() const;
|
|
||||||
void Unbind() const;
|
|
||||||
private:
|
private:
|
||||||
BufferID m_buffer;
|
BufferID m_buffer;
|
||||||
BufferTarget m_target;
|
BufferTarget m_target;
|
||||||
BufferUsage m_usage;
|
BufferUsage m_usage;
|
||||||
|
private:
|
||||||
|
static BufferID m_bound;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: Implement custom fields structuring via ordered_map?
|
||||||
class ENGINE_API UniformBuffer : public Buffer {
|
class ENGINE_API UniformBuffer : public Buffer {
|
||||||
public:
|
public:
|
||||||
UniformBuffer(size_t size, unsigned int index);
|
UniformBuffer(size_t size, unsigned int index);
|
||||||
@ -43,7 +50,7 @@ namespace OpenGL {
|
|||||||
|
|
||||||
template<typename T, typename S = size_t>
|
template<typename T, typename S = size_t>
|
||||||
void UpdateUniform(void* data, S offset) {
|
void UpdateUniform(void* data, S offset) {
|
||||||
SubData(data, sizeof(T), offset);
|
SubData(this, data, sizeof(T), offset);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
unsigned int m_uniformBinding;
|
unsigned int m_uniformBinding;
|
||||||
@ -60,16 +67,24 @@ namespace OpenGL {
|
|||||||
public:
|
public:
|
||||||
InstanceBuffer(BufferUsage usage);
|
InstanceBuffer(BufferUsage usage);
|
||||||
|
|
||||||
void Data(void *data, size_t size) {
|
inline void StartConfigure() const { Buffer::Bind(this); }
|
||||||
Buffer::Data(data, size);
|
inline void EndConfigure() const { Buffer::Unbind(this); }
|
||||||
}
|
};
|
||||||
|
|
||||||
void SubData(void *data, size_t size, size_t offset) {
|
class ENGINE_API VertexArray {
|
||||||
Buffer::SubData(data, size, offset);
|
public:
|
||||||
}
|
VertexArray();
|
||||||
|
~VertexArray();
|
||||||
|
|
||||||
inline void StartConfigure() const { Bind(); }
|
void Bind();
|
||||||
inline void EndConfigure() const { Unbind(); }
|
void Unbind();
|
||||||
|
|
||||||
|
void SetupVertexBuffer(BufferUsage usage);
|
||||||
|
public:
|
||||||
|
void VertexBufferData(size_t size, const void* data);
|
||||||
|
private:
|
||||||
|
unsigned int m_id { 0 };
|
||||||
|
ArrayBuffer* m_vbo { nullptr };
|
||||||
};
|
};
|
||||||
} // namespace OpenGL
|
} // namespace OpenGL
|
||||||
|
|
||||||
|
|||||||
@ -1,21 +0,0 @@
|
|||||||
#ifndef RENDERER_BASICS_H
|
|
||||||
#define RENDERER_BASICS_H
|
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
|
|
||||||
class Vertex {
|
|
||||||
friend class Mesh;
|
|
||||||
private:
|
|
||||||
glm::vec3 m_position;
|
|
||||||
glm::vec3 m_normal;
|
|
||||||
glm::vec2 m_texCoord;
|
|
||||||
public:
|
|
||||||
Vertex(glm::vec3 position, glm::vec3 normal, glm::vec2 texCoord)
|
|
||||||
: m_position(position), m_normal(normal), m_texCoord(texCoord) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // RENDERER_BASICS_H
|
|
||||||
@ -5,25 +5,29 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
|
|
||||||
#include "engine/renderer/basics.h"
|
#include "engine/3d/vertex.hpp"
|
||||||
|
#include "engine/opengl/buffers.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
class Mesh {
|
class Mesh : public OpenGL::VertexArray {
|
||||||
public: // TODO: abstract away
|
public: // TODO: abstract away
|
||||||
unsigned int m_vao, m_vbo, m_ebo;
|
unsigned int m_ebo;
|
||||||
std::vector<Vertex> m_vertexBuffer;
|
std::vector<Vertex> m_vertexBuffer;
|
||||||
std::vector<unsigned int> m_indexBuffer;
|
std::vector<unsigned int> m_indexBuffer;
|
||||||
public: // TODO: abstract away
|
|
||||||
void Bind() const { glBindVertexArray(m_vao); }
|
|
||||||
void Unbind() { glBindVertexArray(0); }
|
|
||||||
void Upload() const;
|
|
||||||
public:
|
public:
|
||||||
std::string materialName;
|
Mesh(const std::string& name);
|
||||||
|
|
||||||
|
Mesh(const Mesh& other) = delete;
|
||||||
|
Mesh(Mesh&& other) noexcept
|
||||||
|
: m_ebo(other.m_ebo), m_vertexBuffer(std::move(other.m_vertexBuffer)), m_indexBuffer(std::move(other.m_indexBuffer)), m_materialName(std::move(other.m_materialName)) {}
|
||||||
public:
|
public:
|
||||||
Mesh();
|
inline const std::string& GetMaterialName() const { return m_materialName; }
|
||||||
|
void Upload();
|
||||||
public:
|
public:
|
||||||
void Render(unsigned int count);
|
void Render(unsigned int count);
|
||||||
|
private:
|
||||||
|
std::string m_materialName;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ namespace Core {
|
|||||||
class Texture {
|
class Texture {
|
||||||
public:
|
public:
|
||||||
Texture() : m_id(0) {}
|
Texture() : m_id(0) {}
|
||||||
static std::unique_ptr<Texture> LoadFile(const std::string& filename);
|
static Texture* LoadFile(const std::string& filename);
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] unsigned int GetID() const { return m_id; }
|
[[nodiscard]] unsigned int GetID() const { return m_id; }
|
||||||
private:
|
private:
|
||||||
|
|||||||
@ -9,8 +9,7 @@
|
|||||||
|
|
||||||
#include "engine/renderer/shader.h"
|
#include "engine/renderer/shader.h"
|
||||||
#include "engine/renderer/renderer.h"
|
#include "engine/renderer/renderer.h"
|
||||||
#include "engine/renderer/material.h"
|
#include "engine/3d/mesh.hpp"
|
||||||
#include "engine/renderer/mesh.h"
|
|
||||||
#include "engine/opengl/buffers.h"
|
#include "engine/opengl/buffers.h"
|
||||||
|
|
||||||
#include "engine/export.h"
|
#include "engine/export.h"
|
||||||
@ -20,40 +19,44 @@ namespace Core {
|
|||||||
enum ObjElement { OHASH, MTLLIB, USEMTL, O, V, VN, VT, F, OUNKNOWN };
|
enum ObjElement { OHASH, MTLLIB, USEMTL, O, V, VN, VT, F, OUNKNOWN };
|
||||||
enum MtlElement { MHASH, NEWMTL, NS, KA, KS, KD, NI, D, ILLUM, MAP_KD, MAP_KA, MUNKNOWN };
|
enum MtlElement { MHASH, NEWMTL, NS, KA, KS, KD, NI, D, ILLUM, MAP_KD, MAP_KA, MUNKNOWN };
|
||||||
|
|
||||||
class ENGINE_API Object {
|
class ENGINE_API Object : public MeshGroup {
|
||||||
friend class Renderer;
|
friend class Renderer;
|
||||||
private:
|
private:
|
||||||
static inline int NormalizeIndex(int idx, int baseCount);
|
static inline int NormalizeIndex(int idx, int baseCount);
|
||||||
|
|
||||||
private:
|
|
||||||
Object();
|
Object();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~Object() = default;
|
~Object() = default;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Object* LoadFile(const std::string& filename);
|
static Object* LoadFile(const std::string& filename);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void LoadMaterials(const std::filesystem::path& filename);
|
void LoadMTL(const std::filesystem::path& filename);
|
||||||
private:
|
|
||||||
void AddMaterial(std::string name, std::shared_ptr<Material> material);
|
|
||||||
std::shared_ptr<Material> GetMaterial(std::string name);
|
|
||||||
private:
|
private:
|
||||||
|
void CreateNewMesh();
|
||||||
|
void CreateNewMesh(const Material& material);
|
||||||
Mesh& GetLastMesh();
|
Mesh& GetLastMesh();
|
||||||
void CreateNewMesh(const std::string& materialName);
|
|
||||||
|
void AddMaterial(MaterialID id, const Material& material);
|
||||||
|
Material* GetMaterial(const MaterialID& id);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Render(Shader& shader, unsigned int count);
|
void Render(Shader& shader, unsigned int count);
|
||||||
[[nodiscard]] inline const std::string Name() const { return m_name; }
|
[[nodiscard]] inline const std::string Name() const { return m_name; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void EnableBatch(const OpenGL::InstanceBuffer* instanceBuffer);
|
void EnableBatch(const OpenGL::InstanceBuffer* instanceBuffer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
std::vector<glm::vec3> m_vertices;
|
std::vector<glm::vec3> m_vertices;
|
||||||
std::vector<glm::vec3> m_normals;
|
std::vector<glm::vec3> m_normals;
|
||||||
std::vector<glm::vec2> m_texCoords;
|
std::vector<glm::vec2> m_texCoords;
|
||||||
|
|
||||||
std::vector<Mesh> m_meshes;
|
std::unordered_map<MaterialID, Material> m_materials;
|
||||||
|
|
||||||
std::unordered_map<std::string, std::shared_ptr<Material>> m_materials;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,18 +12,22 @@ batch::batch() {
|
|||||||
|
|
||||||
void batch::prepare(glm::mat4 *instances, unsigned int count) {
|
void batch::prepare(glm::mat4 *instances, unsigned int count) {
|
||||||
if (!m_instanceBuffer) {
|
if (!m_instanceBuffer) {
|
||||||
m_instanceBuffer = std::make_unique<OpenGL::InstanceBuffer>(GL_DYNAMIC_DRAW);
|
m_instanceBuffer = new OpenGL::InstanceBuffer(GL_DYNAMIC_DRAW);
|
||||||
m_instanceBuffer->Data(nullptr, sizeof(glm::mat4) * count);
|
OpenGL::Buffer::Bind(m_instanceBuffer);
|
||||||
|
OpenGL::Buffer::Data(m_instanceBuffer, nullptr, sizeof(glm::mat4) * count);
|
||||||
|
OpenGL::Buffer::Unbind(m_instanceBuffer);
|
||||||
m_instance_count = count;
|
m_instance_count = count;
|
||||||
} else if (count > m_instance_count) {
|
} else if (count > m_instance_count) {
|
||||||
// Optional: reallocate only if you *really* have more instances than before
|
// Optional: reallocate only if you *really* have more instances than before
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, m_instance_vbo);
|
glBindBuffer(GL_ARRAY_BUFFER, m_instance_vbo);
|
||||||
m_instanceBuffer->Data(nullptr, sizeof(glm::mat4) * count);
|
OpenGL::Buffer::Bind(m_instanceBuffer);
|
||||||
|
OpenGL::Buffer::Data(m_instanceBuffer, nullptr, sizeof(glm::mat4) * count);
|
||||||
|
OpenGL::Buffer::Unbind(m_instanceBuffer);
|
||||||
m_instance_count = count;
|
m_instance_count = count;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Just update the data region — much cheaper
|
// Just update the data region — much cheaper
|
||||||
m_instanceBuffer->SubData(instances, sizeof(glm::mat4) * count, 0);
|
OpenGL::Buffer::SubData(m_instanceBuffer, instances, sizeof(glm::mat4) * count, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,17 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <cassert>
|
||||||
#include "engine/opengl/buffers.h"
|
#include "engine/opengl/buffers.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
namespace OpenGL {
|
namespace OpenGL {
|
||||||
|
|
||||||
|
BufferID Buffer::m_bound = 0;
|
||||||
|
|
||||||
Buffer::Buffer(BufferTarget target, BufferUsage usage)
|
Buffer::Buffer(BufferTarget target, BufferUsage usage)
|
||||||
: m_target(target), m_usage(usage)
|
: m_target(target), m_usage(usage)
|
||||||
{
|
{
|
||||||
glGenBuffers(1, &m_buffer);
|
glGenBuffers(1, &m_buffer);
|
||||||
Bind();
|
|
||||||
Data(nullptr, 0);
|
|
||||||
Unbind();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Buffer::Buffer(BufferTarget target)
|
Buffer::Buffer(BufferTarget target)
|
||||||
@ -20,36 +21,26 @@ namespace OpenGL {
|
|||||||
glDeleteBuffers(1, &m_buffer);
|
glDeleteBuffers(1, &m_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Buffer::Bind() const {
|
void Buffer::Data(const Buffer* buffer, const void *data, size_t size) {
|
||||||
glBindBuffer(m_target, m_buffer);
|
if (!IsBound(buffer)) Bind(buffer);
|
||||||
|
glBufferData(buffer->m_target, size, data, buffer->m_usage);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Buffer::Unbind() const {
|
void Buffer::SubData(const Buffer* buffer, const void *data, size_t size, size_t offset) {
|
||||||
glBindBuffer(m_target, 0);
|
if (!IsBound(buffer)) Bind(buffer);
|
||||||
}
|
glBufferSubData(buffer->m_target, offset, size, data);
|
||||||
|
|
||||||
void Buffer::Data(void *data, size_t size) {
|
|
||||||
Bind();
|
|
||||||
glBufferData(m_target, size, data, m_usage);
|
|
||||||
Unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Buffer::SubData(void *data, size_t size, size_t offset) {
|
|
||||||
Bind();
|
|
||||||
glBufferSubData(m_target, offset, size, data);
|
|
||||||
Unbind();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Buffer::BindBuffer(unsigned int index) const {
|
void Buffer::BindBuffer(unsigned int index) const {
|
||||||
Bind();
|
Buffer::Bind(this);
|
||||||
glBindBufferBase(m_target, index, m_buffer);
|
glBindBufferBase(m_target, index, m_buffer);
|
||||||
Unbind();
|
Buffer::Unbind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Buffer::BindBufferRanged(unsigned int index, size_t offset, size_t size) const {
|
void Buffer::BindBufferRanged(unsigned int index, size_t offset, size_t size) const {
|
||||||
Bind();
|
Buffer::Bind(this);
|
||||||
glBindBufferRange(m_target, index, m_buffer, offset, size);
|
glBindBufferRange(m_target, index, m_buffer, offset, size);
|
||||||
Unbind();
|
Buffer::Unbind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int UniformBuffer::s_bufferNextId = 1;
|
unsigned int UniformBuffer::s_bufferNextId = 1;
|
||||||
@ -57,7 +48,9 @@ namespace OpenGL {
|
|||||||
UniformBuffer::UniformBuffer(size_t size, unsigned int index)
|
UniformBuffer::UniformBuffer(size_t size, unsigned int index)
|
||||||
: Buffer(GL_UNIFORM_BUFFER, GL_STATIC_DRAW), m_uniformBinding(s_bufferNextId++)
|
: Buffer(GL_UNIFORM_BUFFER, GL_STATIC_DRAW), m_uniformBinding(s_bufferNextId++)
|
||||||
{
|
{
|
||||||
Data(nullptr, size);
|
Buffer::Bind(this);
|
||||||
|
Data(this, nullptr, size);
|
||||||
|
Buffer::Unbind(this);
|
||||||
|
|
||||||
BindBuffer(m_uniformBinding);
|
BindBuffer(m_uniformBinding);
|
||||||
}
|
}
|
||||||
@ -73,6 +66,55 @@ namespace OpenGL {
|
|||||||
InstanceBuffer::InstanceBuffer(BufferUsage usage)
|
InstanceBuffer::InstanceBuffer(BufferUsage usage)
|
||||||
: ArrayBuffer(usage) {}
|
: ArrayBuffer(usage) {}
|
||||||
|
|
||||||
|
VertexArray::VertexArray() : m_id(0) {
|
||||||
|
std::cout << "Vertex Array init" << std::endl;
|
||||||
|
glGenVertexArrays(1, &m_id);
|
||||||
|
std::cout << "m_id: " << m_id << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
VertexArray::~VertexArray() {
|
||||||
|
// if (m_vbo) {
|
||||||
|
// delete m_vbo;
|
||||||
|
// }
|
||||||
|
|
||||||
|
glDeleteVertexArrays(1, &m_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VertexArray::Bind() {
|
||||||
|
std::cout << "Binding VAO" << std::endl;
|
||||||
|
assert(m_id != 0 && "Vertex Array wasn't initialized.");
|
||||||
|
|
||||||
|
glBindVertexArray(m_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VertexArray::Unbind() {
|
||||||
|
assert(m_id != 0 && "Vertex Array wasn't initialized.");
|
||||||
|
|
||||||
|
// TODO: Add EBO as well
|
||||||
|
if (Buffer::IsBound(m_vbo)) {
|
||||||
|
Buffer::Unbind(m_vbo);
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VertexArray::SetupVertexBuffer(BufferUsage usage) {
|
||||||
|
if (m_vbo) {
|
||||||
|
delete m_vbo;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_vbo = new ArrayBuffer(usage);
|
||||||
|
Buffer::Bind(m_vbo);
|
||||||
|
Buffer::Data(m_vbo, nullptr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VertexArray::VertexBufferData(size_t size, const void* data) {
|
||||||
|
assert(m_vbo != nullptr && "Trying to upload vertex buffer data to nullptr");
|
||||||
|
|
||||||
|
Buffer::Bind(m_vbo);
|
||||||
|
Buffer::Data(m_vbo, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace OpenGL
|
} // namespace OpenGL
|
||||||
|
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
@ -1,53 +1,56 @@
|
|||||||
|
#include <iostream>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
#include "engine/renderer/mesh.h"
|
#include "engine/renderer/mesh.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
Mesh::Mesh() {
|
Mesh::Mesh(const std::string& name) : m_materialName(name.c_str()) {
|
||||||
m_vao = 0;
|
std::cout << "Mesh init" << std::endl;
|
||||||
m_vbo = 0;
|
|
||||||
|
// m_vao = 0;
|
||||||
|
// m_vbo = 0;
|
||||||
m_ebo = 0;
|
m_ebo = 0;
|
||||||
|
|
||||||
glGenVertexArrays(1, &m_vao);
|
// glGenVertexArrays(1, &m_vao);
|
||||||
glGenBuffers(1, &m_vbo);
|
// glGenBuffers(1, &m_vbo);
|
||||||
glGenBuffers(1, &m_ebo);
|
glGenBuffers(1, &m_ebo);
|
||||||
|
|
||||||
glBindVertexArray(m_vao);
|
Bind();
|
||||||
|
|
||||||
// VBO (vertex buffer)
|
SetupVertexBuffer(GL_DYNAMIC_DRAW);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);
|
|
||||||
|
|
||||||
// EBO (index buffer)
|
// EBO (index buffer)
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ebo);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ebo);
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
// attributes
|
// attributes
|
||||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<const void*>(offsetof(Vertex, m_position)));
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<const void*>(offsetof(Vertex, position)));
|
||||||
glEnableVertexAttribArray(0);
|
glEnableVertexAttribArray(0);
|
||||||
|
|
||||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<const void*>(offsetof(Vertex, m_normal)));
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<const void*>(offsetof(Vertex, normal)));
|
||||||
glEnableVertexAttribArray(1);
|
glEnableVertexAttribArray(1);
|
||||||
|
|
||||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<const void*>(offsetof(Vertex, m_texCoord)));
|
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<const void*>(offsetof(Vertex, uv)));
|
||||||
glEnableVertexAttribArray(2);
|
glEnableVertexAttribArray(2);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
// TODO: delete after ebo moved in VertexArray
|
||||||
glBindVertexArray(0);
|
// glBindBuffer(GL_DYNAMIC_DRAW, 0);
|
||||||
|
Unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mesh::Upload() const {
|
void Mesh::Upload() {
|
||||||
glBindVertexArray(m_vao);
|
Bind();
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
|
VertexBufferData(m_vertexBuffer.size() * sizeof(Vertex), m_vertexBuffer.data());
|
||||||
glBufferData(GL_ARRAY_BUFFER, m_vertexBuffer.size() * sizeof(Vertex), m_vertexBuffer.data(), GL_DYNAMIC_DRAW);
|
|
||||||
|
|
||||||
// Upload indices
|
// Upload indices
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ebo);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ebo);
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffer.size() * sizeof(unsigned int), m_indexBuffer.data(), GL_DYNAMIC_DRAW);
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffer.size() * sizeof(unsigned int), m_indexBuffer.data(), GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
glBindVertexArray(0);
|
// TODO: delete after ebo moved in VertexArray
|
||||||
|
// glBindBuffer(GL_DYNAMIC_DRAW, 0);
|
||||||
|
Unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mesh::Render(unsigned int count)
|
void Mesh::Render(unsigned int count)
|
||||||
|
|||||||
@ -170,7 +170,7 @@ void Renderer::RenderScene(Shader &shader) {
|
|||||||
b.prepare(models.data(), models.size());
|
b.prepare(models.data(), models.size());
|
||||||
if (!prevState) {
|
if (!prevState) {
|
||||||
std::cout << "[DEBUG] enabling batch" << std::endl;
|
std::cout << "[DEBUG] enabling batch" << std::endl;
|
||||||
m.object->EnableBatch(b.m_instanceBuffer.get());
|
m.object->EnableBatch(b.m_instanceBuffer);
|
||||||
}
|
}
|
||||||
m.object->Render(shader, batchItems.size());
|
m.object->Render(shader, batchItems.size());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,8 +9,8 @@
|
|||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
std::unique_ptr<Texture> Texture::LoadFile(const std::string& filename) {
|
Texture* Texture::LoadFile(const std::string& filename) {
|
||||||
auto texture = std::make_unique<Texture>();
|
auto texture = new Texture();
|
||||||
|
|
||||||
int w, h, c;
|
int w, h, c;
|
||||||
unsigned char *data = stbi_load(filename.c_str(), &w, &h, &c, 4);
|
unsigned char *data = stbi_load(filename.c_str(), &w, &h, &c, 4);
|
||||||
@ -19,8 +19,8 @@ std::unique_ptr<Texture> Texture::LoadFile(const std::string& filename) {
|
|||||||
std::exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
glGenTextures(1, &texture.get()->m_id);
|
glGenTextures(1, &texture->m_id);
|
||||||
glBindTexture(GL_TEXTURE_2D, texture.get()->m_id);
|
glBindTexture(GL_TEXTURE_2D, texture->m_id);
|
||||||
|
|
||||||
// TODO: configure properly
|
// TODO: configure properly
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
@ -34,7 +34,7 @@ std::unique_ptr<Texture> Texture::LoadFile(const std::string& filename) {
|
|||||||
std::cout << "Loaded texture under '" << filename << "' with size of " << sizeof(data) << " bytes" << std::endl;
|
std::cout << "Loaded texture under '" << filename << "' with size of " << sizeof(data) << " bytes" << std::endl;
|
||||||
stbi_image_free(data);
|
stbi_image_free(data);
|
||||||
|
|
||||||
return std::move(texture);
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,24 +8,10 @@
|
|||||||
#include "engine/renderer/wavefront.h"
|
#include "engine/renderer/wavefront.h"
|
||||||
|
|
||||||
#include "engine/IO/parser.h"
|
#include "engine/IO/parser.h"
|
||||||
#include "engine/renderer/mesh.h"
|
#include "engine/3d/mesh.hpp"
|
||||||
|
|
||||||
#define DEFAULT_MATERIAL_NAME "default"
|
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
// ObjElement toElement(const std::string &s) {
|
|
||||||
// if (s == "#") return ObjElement::OHASH;
|
|
||||||
// if (s == "mtllib") return ObjElement::MTLLIB;
|
|
||||||
// if (s == "usemtl") return ObjElement::USEMTL;
|
|
||||||
// if (s == "o") return ObjElement::O;
|
|
||||||
// if (s == "v") return ObjElement::V;
|
|
||||||
// if (s == "vn") return ObjElement::VN;
|
|
||||||
// if (s == "vt") return ObjElement::VT;
|
|
||||||
// if (s == "f") return ObjElement::F;
|
|
||||||
// return ObjElement::OUNKNOWN;
|
|
||||||
// }
|
|
||||||
|
|
||||||
inline ObjElement toElement(const char* s) {
|
inline ObjElement toElement(const char* s) {
|
||||||
switch (s[0]) {
|
switch (s[0]) {
|
||||||
case '#': return ObjElement::OHASH;
|
case '#': return ObjElement::OHASH;
|
||||||
@ -42,22 +28,6 @@ inline ObjElement toElement(const char* s) {
|
|||||||
return ObjElement::OUNKNOWN;
|
return ObjElement::OUNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
// MtlElement toMtlElement(const std::string &s) {
|
|
||||||
// if (s == "#") return MtlElement::MHASH;
|
|
||||||
// if (s == "newmtl") return MtlElement::NEWMTL;
|
|
||||||
// if (s == "Ns") return MtlElement::NS;
|
|
||||||
// if (s == "Ka") return MtlElement::KA;
|
|
||||||
// if (s == "Ks") return MtlElement::KS;
|
|
||||||
// if (s == "Kd") return MtlElement::KD;
|
|
||||||
// if (s == "Ni") return MtlElement::NI;
|
|
||||||
// if (s == "d") return MtlElement::D;
|
|
||||||
// if (s == "illum") return MtlElement::ILLUM;
|
|
||||||
// if (s == "map_Kd") return MtlElement::MAP_KD;
|
|
||||||
// if (s == "map_Ka") return MtlElement::MAP_KA;
|
|
||||||
// // if (s == "map_Ke") return MtlElement::MAP_KE;
|
|
||||||
// return MtlElement::MUNKNOWN;
|
|
||||||
// }
|
|
||||||
|
|
||||||
inline MtlElement toMtlElement(const char* s) {
|
inline MtlElement toMtlElement(const char* s) {
|
||||||
switch (s[0]) {
|
switch (s[0]) {
|
||||||
case '#': return MtlElement::MHASH;
|
case '#': return MtlElement::MHASH;
|
||||||
@ -104,7 +74,11 @@ Object::Object() {
|
|||||||
m_texCoords = std::vector<glm::vec2>();
|
m_texCoords = std::vector<glm::vec2>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::LoadMaterials(const std::filesystem::path& filename) {
|
void Object::AddMaterial(MaterialID id, const Material& material) {
|
||||||
|
m_materials.insert(std::make_pair(id, material));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::LoadMTL(const std::filesystem::path& filename) {
|
||||||
std::ifstream file(filename);
|
std::ifstream file(filename);
|
||||||
if (!file.is_open()) {
|
if (!file.is_open()) {
|
||||||
std::cerr << "Failed to open MTL file: " << filename << std::endl;
|
std::cerr << "Failed to open MTL file: " << filename << std::endl;
|
||||||
@ -112,7 +86,8 @@ void Object::LoadMaterials(const std::filesystem::path& filename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string currentMaterialName;
|
std::string currentMaterialName;
|
||||||
std::shared_ptr<Material> currentMaterial;
|
Material currentMaterial;
|
||||||
|
bool hasCurrent = false;
|
||||||
|
|
||||||
char line[1024]; // buffer per line
|
char line[1024]; // buffer per line
|
||||||
|
|
||||||
@ -128,15 +103,15 @@ void Object::LoadMaterials(const std::filesystem::path& filename) {
|
|||||||
case MtlElement::NEWMTL:
|
case MtlElement::NEWMTL:
|
||||||
{
|
{
|
||||||
// If a material was being built, commit it first
|
// If a material was being built, commit it first
|
||||||
if (currentMaterial) {
|
if (hasCurrent) {
|
||||||
AddMaterial(currentMaterialName, std::move(currentMaterial));
|
AddMaterial(currentMaterialName, currentMaterial);
|
||||||
currentMaterial = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char* materialName = p.TakeWord();
|
char* materialName = p.TakeWord();
|
||||||
if (materialName) {
|
if (materialName) {
|
||||||
currentMaterialName = materialName;
|
currentMaterialName = materialName;
|
||||||
currentMaterial = std::make_shared<Material>();
|
currentMaterial = Material(currentMaterialName);
|
||||||
|
hasCurrent = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -144,7 +119,7 @@ void Object::LoadMaterials(const std::filesystem::path& filename) {
|
|||||||
case MtlElement::NS: // specular weight
|
case MtlElement::NS: // specular weight
|
||||||
{
|
{
|
||||||
float weight = p.TakeFloat();
|
float weight = p.TakeFloat();
|
||||||
if (currentMaterial) currentMaterial->SetSpecularWeight(weight);
|
if (hasCurrent) currentMaterial.SetSpecularWeight(weight);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,7 +128,7 @@ void Object::LoadMaterials(const std::filesystem::path& filename) {
|
|||||||
float r = p.TakeFloat();
|
float r = p.TakeFloat();
|
||||||
float g = p.TakeFloat();
|
float g = p.TakeFloat();
|
||||||
float b = p.TakeFloat();
|
float b = p.TakeFloat();
|
||||||
if (currentMaterial) currentMaterial->SetAmbientColor(glm::vec3(r, g, b));
|
if (hasCurrent) currentMaterial.SetAmbientColor(glm::vec3(r, g, b));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,7 +137,7 @@ void Object::LoadMaterials(const std::filesystem::path& filename) {
|
|||||||
float r = p.TakeFloat();
|
float r = p.TakeFloat();
|
||||||
float g = p.TakeFloat();
|
float g = p.TakeFloat();
|
||||||
float b = p.TakeFloat();
|
float b = p.TakeFloat();
|
||||||
if (currentMaterial) currentMaterial->SetSpecularColor(glm::vec3(r, g, b));
|
if (hasCurrent) currentMaterial.SetSpecularColor(glm::vec3(r, g, b));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,21 +146,21 @@ void Object::LoadMaterials(const std::filesystem::path& filename) {
|
|||||||
float r = p.TakeFloat();
|
float r = p.TakeFloat();
|
||||||
float g = p.TakeFloat();
|
float g = p.TakeFloat();
|
||||||
float b = p.TakeFloat();
|
float b = p.TakeFloat();
|
||||||
if (currentMaterial) currentMaterial->SetDiffuseColor(glm::vec3(r, g, b));
|
if (hasCurrent) currentMaterial.SetDiffuseColor(glm::vec3(r, g, b));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case MtlElement::D: // opacity
|
case MtlElement::D: // opacity
|
||||||
{
|
{
|
||||||
float d = p.TakeFloat();
|
float d = p.TakeFloat();
|
||||||
if (currentMaterial) currentMaterial->SetOpacity(d);
|
if (hasCurrent) currentMaterial.SetOpacity(d);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case MtlElement::ILLUM: // illumination model
|
case MtlElement::ILLUM: // illumination model
|
||||||
{
|
{
|
||||||
int illum = p.TakeInt();
|
int illum = p.TakeInt();
|
||||||
if (currentMaterial) currentMaterial->SetIllumination(illum);
|
if (hasCurrent) currentMaterial.SetIllumination(illum);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,7 +168,7 @@ void Object::LoadMaterials(const std::filesystem::path& filename) {
|
|||||||
{
|
{
|
||||||
// take rest of line as texture path (can contain spaces)
|
// take rest of line as texture path (can contain spaces)
|
||||||
char* texPath = p.TakeUntil('\0');
|
char* texPath = p.TakeUntil('\0');
|
||||||
if (texPath && currentMaterial) {
|
if (texPath && hasCurrent) {
|
||||||
// trim trailing spaces
|
// trim trailing spaces
|
||||||
size_t len = std::strlen(texPath);
|
size_t len = std::strlen(texPath);
|
||||||
while (len > 0 && (texPath[len - 1] == ' ' || texPath[len - 1] == '\t'))
|
while (len > 0 && (texPath[len - 1] == ' ' || texPath[len - 1] == '\t'))
|
||||||
@ -201,7 +176,7 @@ void Object::LoadMaterials(const std::filesystem::path& filename) {
|
|||||||
|
|
||||||
std::filesystem::path texturePath = filename.parent_path() / texPath;
|
std::filesystem::path texturePath = filename.parent_path() / texPath;
|
||||||
|
|
||||||
currentMaterial->SetDiffuseTexture(Texture::LoadFile(texturePath.string()));
|
currentMaterial.SetDiffuseTexture(Texture::LoadFile(texturePath.string()));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -209,13 +184,13 @@ void Object::LoadMaterials(const std::filesystem::path& filename) {
|
|||||||
case MtlElement::MAP_KA: // ambient texture map
|
case MtlElement::MAP_KA: // ambient texture map
|
||||||
{
|
{
|
||||||
char* texPath = p.TakeUntil('\0');
|
char* texPath = p.TakeUntil('\0');
|
||||||
if (texPath && currentMaterial) {
|
if (texPath && hasCurrent) {
|
||||||
size_t len = std::strlen(texPath);
|
size_t len = std::strlen(texPath);
|
||||||
while (len > 0 && (texPath[len - 1] == ' ' || texPath[len - 1] == '\t'))
|
while (len > 0 && (texPath[len - 1] == ' ' || texPath[len - 1] == '\t'))
|
||||||
texPath[--len] = '\0';
|
texPath[--len] = '\0';
|
||||||
|
|
||||||
// optional: handle ambient texture
|
// optional: handle ambient texture
|
||||||
// currentMaterial->SetAmbientTexture(Texture::LoadFile(texPath));
|
// currentMaterial.SetAmbientTexture(Texture::LoadFile(texPath));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -227,41 +202,36 @@ void Object::LoadMaterials(const std::filesystem::path& filename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Commit last material if pending
|
// Commit last material if pending
|
||||||
if (currentMaterial) {
|
if (hasCurrent) {
|
||||||
AddMaterial(currentMaterialName, std::move(currentMaterial));
|
AddMaterial(currentMaterialName, currentMaterial);
|
||||||
}
|
}
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::AddMaterial(std::string name, std::shared_ptr<Material> material)
|
Material* Object::GetMaterial(const MaterialID& id)
|
||||||
{
|
{
|
||||||
m_materials.insert(std::make_pair(std::move(name), std::move(material)));
|
auto material = m_materials.find(id);
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<Material> Object::GetMaterial(std::string name)
|
|
||||||
{
|
|
||||||
auto material = m_materials.find(name);
|
|
||||||
if (material == m_materials.end()) return nullptr;
|
if (material == m_materials.end()) return nullptr;
|
||||||
return material->second;
|
return &material->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::CreateNewMesh(const std::string& materialName)
|
void Object::CreateNewMesh(const Material& material)
|
||||||
{
|
{
|
||||||
Mesh mesh;
|
EmplaceBack(material);
|
||||||
mesh.materialName = materialName;
|
}
|
||||||
m_meshes.push_back(mesh);
|
|
||||||
|
void Object::CreateNewMesh()
|
||||||
|
{
|
||||||
|
EmplaceBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
Mesh& Object::GetLastMesh()
|
Mesh& Object::GetLastMesh()
|
||||||
{
|
{
|
||||||
if (m_meshes.empty()) {
|
if (Empty()) {
|
||||||
auto material = std::make_shared<Material>();
|
CreateNewMesh(Material::Default());
|
||||||
material->SetAmbientColor(glm::vec3(0.52f, 0.52f, 0.52f));
|
|
||||||
AddMaterial(DEFAULT_MATERIAL_NAME, std::move(material));
|
|
||||||
CreateNewMesh(DEFAULT_MATERIAL_NAME);
|
|
||||||
}
|
}
|
||||||
return m_meshes.back();
|
return Back();
|
||||||
}
|
}
|
||||||
|
|
||||||
Object* Object::LoadFile(const std::string& filename) {
|
Object* Object::LoadFile(const std::string& filename) {
|
||||||
@ -289,7 +259,7 @@ Object* Object::LoadFile(const std::string& filename) {
|
|||||||
if (mtlFile) {
|
if (mtlFile) {
|
||||||
std::filesystem::path fullPath = filename;
|
std::filesystem::path fullPath = filename;
|
||||||
std::filesystem::path mtlPath = fullPath.replace_filename(mtlFile);
|
std::filesystem::path mtlPath = fullPath.replace_filename(mtlFile);
|
||||||
obj->LoadMaterials(mtlPath);
|
obj->LoadMTL(mtlPath);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -298,11 +268,16 @@ Object* Object::LoadFile(const std::string& filename) {
|
|||||||
{
|
{
|
||||||
char* materialName = p.TakeWord();
|
char* materialName = p.TakeWord();
|
||||||
if (materialName) {
|
if (materialName) {
|
||||||
auto& mesh = obj->GetLastMesh();
|
auto material = obj->GetMaterial(materialName);
|
||||||
if (mesh.materialName != materialName) {
|
if (!material) {
|
||||||
Mesh newMesh;
|
// Not defined material being used.
|
||||||
newMesh.materialName = materialName;
|
std::cerr << "[WARN] WavefrontError: use of undefined material '"
|
||||||
obj->m_meshes.push_back(newMesh);
|
<< materialName << "'" << std::endl;
|
||||||
|
material = new Material();
|
||||||
|
}
|
||||||
|
auto mesh = obj->FindMeshByMaterial(material);
|
||||||
|
if (mesh == obj->End()) {
|
||||||
|
obj->CreateNewMesh(*material);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -349,8 +324,11 @@ Object* Object::LoadFile(const std::string& filename) {
|
|||||||
case ObjElement::F: // face
|
case ObjElement::F: // face
|
||||||
{
|
{
|
||||||
auto& mesh = obj->GetLastMesh();
|
auto& mesh = obj->GetLastMesh();
|
||||||
int raw_vi, raw_ti, raw_ni;
|
|
||||||
|
|
||||||
|
std::vector<uint32_t> faceIndices;
|
||||||
|
faceIndices.reserve(8);
|
||||||
|
|
||||||
|
int raw_vi, raw_ti, raw_ni;
|
||||||
while (p.TakeFaceIndices(raw_vi, raw_ti, raw_ni)) {
|
while (p.TakeFaceIndices(raw_vi, raw_ti, raw_ni)) {
|
||||||
// Convert raw OBJ indices to 0-based / -1 sentinel
|
// Convert raw OBJ indices to 0-based / -1 sentinel
|
||||||
int vi = Object::NormalizeIndex(raw_vi, (int)obj->m_vertices.size());
|
int vi = Object::NormalizeIndex(raw_vi, (int)obj->m_vertices.size());
|
||||||
@ -362,15 +340,22 @@ Object* Object::LoadFile(const std::string& filename) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 vert = obj->m_vertices[vi];
|
Vertex v;
|
||||||
glm::vec3 norm(0.0f);
|
v.position = obj->m_vertices[vi];
|
||||||
glm::vec2 texCoord(0.0f);
|
v.normal = (ni >= 0) ? obj->m_normals[ni] : glm::vec3(0.0f);
|
||||||
|
v.uv = (ti >= 0) ? obj->m_texCoords[ti] : glm::vec3(0.0f);
|
||||||
|
|
||||||
if (ni >= 0) norm = obj->m_normals[ni];
|
uint32_t idx = mesh.PushVertex(v);
|
||||||
if (ti >= 0) texCoord = obj->m_texCoords[ti];
|
faceIndices.push_back(idx);
|
||||||
|
// mesh.m_vertexBuffer.emplace_back(vert, norm, texCoord);
|
||||||
|
// mesh.m_indexBuffer.push_back(mesh.m_vertexBuffer.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
mesh.m_vertexBuffer.emplace_back(vert, norm, texCoord);
|
// triangulate polygon (fan)
|
||||||
mesh.m_indexBuffer.push_back(mesh.m_vertexBuffer.size() - 1);
|
if (faceIndices.size() >= 3) {
|
||||||
|
for (size_t i = 1; i + 1 < faceIndices.size(); ++i) {
|
||||||
|
mesh.PushTriangle(faceIndices[0], faceIndices[i], faceIndices[i+1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -385,130 +370,108 @@ Object* Object::LoadFile(const std::string& filename) {
|
|||||||
std::cout << "Vertices count: " << obj->m_vertices.size() << std::endl;
|
std::cout << "Vertices count: " << obj->m_vertices.size() << std::endl;
|
||||||
std::cout << "Normals count: " << obj->m_normals.size() << std::endl;
|
std::cout << "Normals count: " << obj->m_normals.size() << std::endl;
|
||||||
std::cout << "TexCoords count: " << obj->m_texCoords.size() << std::endl;
|
std::cout << "TexCoords count: " << obj->m_texCoords.size() << std::endl;
|
||||||
std::cout << "Meshes count: " << obj->m_meshes.size() << std::endl;
|
std::cout << "Meshes count: " << obj->GetSize() << std::endl;
|
||||||
std::cout << "Materials count: " << obj->m_materials.size() << std::endl;
|
std::cout << "Materials count: " << obj->m_materials.size() << std::endl;
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
for (auto &mesh : obj->m_meshes) {
|
// FIXME:
|
||||||
mesh.Upload();
|
|
||||||
}
|
// for (auto it = obj->Begin(); it != obj->End(); ++it) {
|
||||||
|
// it->Upload();
|
||||||
|
// }
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::EnableBatch(const OpenGL::InstanceBuffer* instanceBuffer) {
|
void Object::EnableBatch(const OpenGL::InstanceBuffer* instanceBuffer) {
|
||||||
for (auto &mesh : m_meshes) {
|
// FIXME:
|
||||||
mesh.Bind();
|
|
||||||
|
|
||||||
instanceBuffer->StartConfigure();
|
|
||||||
std::size_t vec4Size = sizeof(glm::vec4);
|
|
||||||
for (int i = 0; i < 4; ++i) {
|
|
||||||
glEnableVertexAttribArray(3 + i); // use locations 3,4,5,6 for instance matrix
|
|
||||||
glVertexAttribPointer(3 + i, 4, GL_FLOAT, GL_FALSE,
|
|
||||||
sizeof(glm::mat4), (void*)(i * vec4Size));
|
|
||||||
glVertexAttribDivisor(3 + i, 1); // IMPORTANT: one per instance, not per vertex
|
|
||||||
}
|
|
||||||
instanceBuffer->EndConfigure();
|
|
||||||
|
|
||||||
mesh.Unbind();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// void Object::Render(Shader& shader)
|
|
||||||
// {
|
|
||||||
// for (auto &mesh : m_meshes) {
|
// for (auto &mesh : m_meshes) {
|
||||||
// auto material = GetMaterial(mesh.materialName);
|
// mesh.Bind();
|
||||||
|
|
||||||
// shader.setFloat("ambientStrength", 0.2f);
|
// instanceBuffer->StartConfigure();
|
||||||
// shader.setFloat("shininess", material->GetSpecularWeight());
|
// std::size_t vec4Size = sizeof(glm::vec4);
|
||||||
// shader.setFloat("opacity", material->GetOpacity());
|
// for (int i = 0; i < 4; ++i) {
|
||||||
// shader.setBool("useSpecular", material->GetIllumination() >= 2);
|
// glEnableVertexAttribArray(3 + i); // use locations 3,4,5,6 for instance matrix
|
||||||
// shader.setFloat("specularStrength", 1.0f);
|
// glVertexAttribPointer(3 + i, 4, GL_FLOAT, GL_FALSE,
|
||||||
// shader.setVec3("ambientColor", material->GetAmbientColor());
|
// sizeof(glm::mat4), (void*)(i * vec4Size));
|
||||||
// shader.setVec3("diffuseColor", material->GetDiffuseColor());
|
// glVertexAttribDivisor(3 + i, 1); // IMPORTANT: one per instance, not per vertex
|
||||||
// shader.setVec3("specularColor", material->GetSpecularColor());
|
// }
|
||||||
|
// instanceBuffer->EndConfigure();
|
||||||
|
|
||||||
// if (material->HasDiffuseTexture()) {
|
// mesh.Unbind();
|
||||||
// shader.setBool("useTexture", true);
|
|
||||||
// glActiveTexture(GL_TEXTURE0);
|
|
||||||
// glBindTexture(GL_TEXTURE_2D, material->GetDiffuseTexture()->GetID());
|
|
||||||
// shader.setInt("diffuseTex", 0);
|
|
||||||
// } else {
|
|
||||||
// shader.setBool("useTexture", false);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// mesh.Render();
|
|
||||||
// }
|
|
||||||
// }
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
void Object::Render(Shader& shader, unsigned int count)
|
void Object::Render(Shader& shader, unsigned int count)
|
||||||
{
|
{
|
||||||
for (auto &mesh : m_meshes)
|
// FIXME:
|
||||||
{
|
|
||||||
auto material = GetMaterial(mesh.materialName);
|
|
||||||
|
|
||||||
// --- Basic material properties ---
|
// for (auto &mesh : m_meshes)
|
||||||
shader.setFloat("opacity", material->GetOpacity());
|
// {
|
||||||
|
// auto material = GetMaterial(mesh.GetMaterialName());
|
||||||
|
|
||||||
// Albedo (base color)
|
// // --- Basic material properties ---
|
||||||
shader.setVec3("albedo", material->GetDiffuseColor());
|
// shader.setFloat("opacity", material->GetOpacity());
|
||||||
|
|
||||||
// Metallic and roughness (defaults)
|
// // Albedo (base color)
|
||||||
shader.setFloat("metallic", 0.8f);
|
// shader.setVec3("albedo", material->GetDiffuseColor());
|
||||||
shader.setFloat("roughness", 0.5f);
|
|
||||||
shader.setFloat("ao", 1.0f); // default ambient occlusion if none
|
|
||||||
|
|
||||||
// --- Optional textures ---
|
// // Metallic and roughness (defaults)
|
||||||
int texUnit = 0;
|
// shader.setFloat("metallic", 0.8f);
|
||||||
|
// shader.setFloat("roughness", 0.5f);
|
||||||
|
// shader.setFloat("ao", 1.0f); // default ambient occlusion if none
|
||||||
|
|
||||||
// Albedo texture
|
// // --- Optional textures ---
|
||||||
if (material->HasDiffuseTexture()) {
|
// int texUnit = 0;
|
||||||
shader.setBool("useAlbedoMap", true);
|
|
||||||
glActiveTexture(GL_TEXTURE0 + texUnit);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, material->GetDiffuseTexture()->GetID());
|
|
||||||
shader.setInt("albedoTex", texUnit++);
|
|
||||||
} else {
|
|
||||||
shader.setBool("useAlbedoMap", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Metallic texture
|
// // Albedo texture
|
||||||
// if (material->HasMetallicTexture()) {
|
// if (material->HasDiffuseTexture()) {
|
||||||
if (false) {
|
// shader.setBool("useAlbedoMap", true);
|
||||||
shader.setBool("useMetallicMap", true);
|
// glActiveTexture(GL_TEXTURE0 + texUnit);
|
||||||
glActiveTexture(GL_TEXTURE0 + texUnit);
|
// glBindTexture(GL_TEXTURE_2D, material->GetDiffuseTexture()->GetID());
|
||||||
// glBindTexture(GL_TEXTURE_2D, material->GetMetallicTexture()->GetID());
|
// shader.setInt("albedoTex", texUnit++);
|
||||||
shader.setInt("metallicTex", texUnit++);
|
// } else {
|
||||||
} else {
|
// shader.setBool("useAlbedoMap", false);
|
||||||
shader.setBool("useMetallicMap", false);
|
// }
|
||||||
}
|
|
||||||
|
|
||||||
// Roughness texture
|
// // Metallic texture
|
||||||
// if (material->HasRoughnessTexture()) {
|
// // if (material->HasMetallicTexture()) {
|
||||||
if (false) {
|
// if (false) {
|
||||||
shader.setBool("useRoughnessMap", true);
|
// shader.setBool("useMetallicMap", true);
|
||||||
glActiveTexture(GL_TEXTURE0 + texUnit);
|
// glActiveTexture(GL_TEXTURE0 + texUnit);
|
||||||
// glBindTexture(GL_TEXTURE_2D, material->GetRoughnessTexture()->GetID());
|
// // glBindTexture(GL_TEXTURE_2D, material->GetMetallicTexture()->GetID());
|
||||||
shader.setInt("roughnessTex", texUnit++);
|
// shader.setInt("metallicTex", texUnit++);
|
||||||
} else {
|
// } else {
|
||||||
shader.setBool("useRoughnessMap", false);
|
// shader.setBool("useMetallicMap", false);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// AO texture
|
// // Roughness texture
|
||||||
// if (material->HasAoTexture()) {
|
// // if (material->HasRoughnessTexture()) {
|
||||||
if (false) {
|
// if (false) {
|
||||||
shader.setBool("useAoMap", true);
|
// shader.setBool("useRoughnessMap", true);
|
||||||
glActiveTexture(GL_TEXTURE0 + texUnit);
|
// glActiveTexture(GL_TEXTURE0 + texUnit);
|
||||||
// glBindTexture(GL_TEXTURE_2D, material->GetAoTexture()->GetID());
|
// // glBindTexture(GL_TEXTURE_2D, material->GetRoughnessTexture()->GetID());
|
||||||
shader.setInt("aoTex", texUnit++);
|
// shader.setInt("roughnessTex", texUnit++);
|
||||||
} else {
|
// } else {
|
||||||
shader.setBool("useAoMap", false);
|
// shader.setBool("useRoughnessMap", false);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// --- Render mesh ---
|
// // AO texture
|
||||||
mesh.Render(count);
|
// // if (material->HasAoTexture()) {
|
||||||
}
|
// if (false) {
|
||||||
|
// shader.setBool("useAoMap", true);
|
||||||
|
// glActiveTexture(GL_TEXTURE0 + texUnit);
|
||||||
|
// // glBindTexture(GL_TEXTURE_2D, material->GetAoTexture()->GetID());
|
||||||
|
// shader.setInt("aoTex", texUnit++);
|
||||||
|
// } else {
|
||||||
|
// shader.setBool("useAoMap", false);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // --- Render mesh ---
|
||||||
|
// mesh.Render(count);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -63,7 +63,7 @@ public:
|
|||||||
assert(batchEntt.HasComponent<batch>() && "batch doesn't have any batch component!");
|
assert(batchEntt.HasComponent<batch>() && "batch doesn't have any batch component!");
|
||||||
assert(batchEntt.HasComponent<mesh>() && "batch doesn't have any mesh component!");
|
assert(batchEntt.HasComponent<mesh>() && "batch doesn't have any mesh component!");
|
||||||
// Generate 1000 random cubes
|
// Generate 1000 random cubes
|
||||||
for (int i = 0; i < 10000; ++i) {
|
for (int i = 0; i < 100; ++i) {
|
||||||
auto cubeEntity = scene->CreateEntity();
|
auto cubeEntity = scene->CreateEntity();
|
||||||
|
|
||||||
float x = static_cast<float>(rand()) / RAND_MAX * 200.f - 100.f; // range [-100, 100]
|
float x = static_cast<float>(rand()) / RAND_MAX * 200.f - 100.f; // range [-100, 100]
|
||||||
|
|||||||
Reference in New Issue
Block a user