Compare commits
2 Commits
8b8ad35d01
...
ecba8247bf
Author | SHA1 | Date | |
---|---|---|---|
ecba8247bf | |||
fa9076b834 |
@ -21,6 +21,7 @@ protected:
|
||||
private:
|
||||
unsigned int m_id;
|
||||
unsigned int m_instance_vbo { 0 };
|
||||
unsigned int m_instance_count { 0 };
|
||||
private:
|
||||
void prepare(glm::mat4 *instances, unsigned int count);
|
||||
};
|
||||
|
@ -23,6 +23,7 @@ private:
|
||||
unsigned int shadowMap;
|
||||
unsigned int fbo;
|
||||
glm::mat4 lightSpace;
|
||||
int shadowRes{1024};
|
||||
};
|
||||
|
||||
#endif // COMPONENTS_LIGHT_H_
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "engine/renderer/shader.h"
|
||||
#include "engine/export.h"
|
||||
#include "engine/components/light.h"
|
||||
|
||||
// TODO: make static or singleton
|
||||
class ENGINE_API Renderer {
|
||||
@ -21,6 +22,7 @@ private:
|
||||
void ApplyLights(Shader &shader);
|
||||
void UpdateView();
|
||||
void RenderScene(Shader &shader);
|
||||
void EnsureShadowResources(light& l);
|
||||
private:
|
||||
Shader m_shader;
|
||||
Shader m_depthShader;
|
||||
|
@ -11,9 +11,20 @@ batch::batch() {
|
||||
void batch::prepare(glm::mat4 *instances, unsigned int count) {
|
||||
if (m_instance_vbo == 0) {
|
||||
glGenBuffers(1, &m_instance_vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_instance_vbo);
|
||||
// Allocate *once*, no data yet — just reserve space
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * count, nullptr, GL_DYNAMIC_DRAW);
|
||||
m_instance_count = count;
|
||||
} else if (count > m_instance_count) {
|
||||
// Optional: reallocate only if you *really* have more instances than before
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_instance_vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * count, nullptr, GL_DYNAMIC_DRAW);
|
||||
m_instance_count = count;
|
||||
} else {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_instance_vbo);
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_instance_vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * count, reinterpret_cast<void*>(instances), GL_DYNAMIC_DRAW);
|
||||
// Just update the data region — much cheaper
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(glm::mat4) * count, instances);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
@ -86,6 +86,32 @@ void Renderer::ApplyLights(Shader &shader) {
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::EnsureShadowResources(light& l) {
|
||||
if (l.fbo != 0 && l.shadowMap != 0) return; // already created
|
||||
|
||||
glGenFramebuffers(1, &l.fbo);
|
||||
glGenTextures(1, &l.shadowMap);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, l.shadowMap);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24,
|
||||
l.shadowRes, l.shadowRes, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
|
||||
|
||||
// NEAREST is fine to start; switch to LINEAR + PCF later if you want
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
const float borderColor[] = {1.f, 1.f, 1.f, 1.f};
|
||||
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, l.fbo);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, l.shadowMap, 0);
|
||||
glDrawBuffer(GL_NONE);
|
||||
glReadBuffer(GL_NONE);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void Renderer::UpdateView() {
|
||||
auto cam = m_registry.view<transform, camera>().back();
|
||||
auto camTransform = m_registry.get<transform>(cam);
|
||||
@ -165,53 +191,31 @@ void Renderer::RenderScene(Shader &shader) {
|
||||
}
|
||||
|
||||
void Renderer::GenerateShadowMaps() {
|
||||
const unsigned int SHADOW_WIDTH = 1024, SHADOW_HEIGHT = 1024;
|
||||
|
||||
m_depthShader.use();
|
||||
|
||||
auto lights = m_registry.view<light>();
|
||||
|
||||
for (auto [lEntt, l] : lights.each()) {
|
||||
for (auto [_, l] : lights.each()) {
|
||||
// TODO: support other light types when ready
|
||||
if (l.type != light::LightType::DIRECTIONAL) return;
|
||||
|
||||
glGenFramebuffers(1, &l.fbo);
|
||||
glGenTextures(1, &l.shadowMap);
|
||||
glBindTexture(GL_TEXTURE_2D, l.shadowMap);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24,
|
||||
SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
|
||||
float borderColor[] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, l.fbo);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, l.shadowMap, 0);
|
||||
glDrawBuffer(GL_NONE);
|
||||
glReadBuffer(GL_NONE);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
if (l.type != light::LightType::DIRECTIONAL) continue;
|
||||
EnsureShadowResources(l);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::Render() {
|
||||
const unsigned int SHADOW_WIDTH = 1024, SHADOW_HEIGHT = 1024;
|
||||
|
||||
m_depthShader.use();
|
||||
|
||||
auto lights = m_registry.view<light, transform>();
|
||||
glCullFace(GL_FRONT);
|
||||
|
||||
for (auto [lEntt, l, t] : lights.each()) {
|
||||
const auto lights = m_registry.view<light, transform>();
|
||||
|
||||
for (auto [_, l, t] : lights.each()) {
|
||||
// TODO: support other light types when ready
|
||||
if (l.type != light::LightType::DIRECTIONAL) return;
|
||||
if (l.type != light::LightType::DIRECTIONAL) continue;
|
||||
|
||||
glClearColor(0x18/255.0f, 0x18/255.0f, 0x18/255.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
EnsureShadowResources(l);
|
||||
|
||||
float near_plane = 0.1f, far_plane = 50.0f;
|
||||
// float near_plane = 0.1f, far_plane = 50.0f;
|
||||
glm::vec3 target = glm::vec3(0.0f, 0.5f, 0.0f);
|
||||
glm::mat4 lightView = glm::lookAt(t.position, target, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
glm::mat4 lightProjection = glm::ortho(-6.0f, 6.0f, -6.0f, 6.0f, 1.0f, 20.0f);
|
||||
@ -220,26 +224,30 @@ void Renderer::Render() {
|
||||
m_depthShader.setMat4("u_lightSpace", lightSpaceMatrix);
|
||||
l.lightSpace = lightSpaceMatrix;
|
||||
|
||||
glCullFace(GL_FRONT);
|
||||
glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
|
||||
glViewport(0, 0, l.shadowRes, l.shadowRes);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, l.fbo);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Optional: further stabilize acne
|
||||
// glEnable(GL_POLYGON_OFFSET_FILL);
|
||||
// glPolygonOffset(2.0f, 4.0f);
|
||||
|
||||
RenderScene(m_depthShader);
|
||||
|
||||
// glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glCullFace(GL_BACK);
|
||||
}
|
||||
|
||||
// actual rendering
|
||||
glCullFace(GL_BACK);
|
||||
|
||||
// ---- MAIN PASS -----
|
||||
glViewport(0, 0, Window::GetWidth(), Window::GetHeight());
|
||||
|
||||
glClearColor(0x18/255.0f, 0x18/255.0f, 0x18/255.0f, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
m_shader.use();
|
||||
|
||||
ApplyLights(m_shader);
|
||||
UpdateView();
|
||||
|
||||
RenderScene(m_shader);
|
||||
}
|
@ -196,10 +196,9 @@ void Object::LoadMaterials(const std::filesystem::path& filename) {
|
||||
while (len > 0 && (texPath[len - 1] == ' ' || texPath[len - 1] == '\t'))
|
||||
texPath[--len] = '\0';
|
||||
|
||||
std::filesystem::path fullPath = filename;
|
||||
std::filesystem::path texturePath = fullPath.parent_path() / texPath;
|
||||
std::filesystem::path texturePath = filename.parent_path() / texPath;
|
||||
|
||||
currentMaterial->SetDiffuseTexture(Texture::LoadFile(texturePath));
|
||||
currentMaterial->SetDiffuseTexture(Texture::LoadFile(texturePath.string()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -35,10 +35,11 @@ public:
|
||||
m_registry.emplace<transform>(cameraEntity, glm::vec3(0.f, 2.f, 2.f));
|
||||
m_registry.emplace<camera>(cameraEntity);
|
||||
|
||||
Object* targetObj = Object::LoadFile("./assets/wizard/wizard.obj");
|
||||
Object* targetObj = Object::LoadFile("./assets/car/car.obj");
|
||||
const auto targetEntity = m_registry.create();
|
||||
m_registry.emplace<transform>(targetEntity, glm::vec3(0.f, 0.0f, 0.f));
|
||||
m_registry.emplace<mesh>(targetEntity, std::shared_ptr<Object>(targetObj));
|
||||
m_registry.emplace<rotate>(targetEntity);
|
||||
|
||||
Object* grass = Object::LoadFile("./assets/common/cube/cube.obj");
|
||||
const auto cubeEntity = m_registry.create();
|
||||
|
Reference in New Issue
Block a user