Everywhere: Work towards lighting support
This commit is contained in:
@@ -1,7 +1,10 @@
|
|||||||
#version 450 core
|
#version 450 core
|
||||||
|
|
||||||
layout(location = 0) out vec4 color;
|
layout(location = 0) out vec4 albedoSpec; // RGB diffuse color
|
||||||
|
layout(location = 1) out vec4 position;
|
||||||
|
layout(location = 2) out vec4 normal;
|
||||||
|
|
||||||
|
in vec3 v_position;
|
||||||
in vec3 v_normal;
|
in vec3 v_normal;
|
||||||
in vec4 v_color;
|
in vec4 v_color;
|
||||||
in vec2 v_textureCoordinates;
|
in vec2 v_textureCoordinates;
|
||||||
@@ -46,5 +49,9 @@ void main()
|
|||||||
case 30: textureColor *= texture(u_textures[30], v_textureCoordinates); break;
|
case 30: textureColor *= texture(u_textures[30], v_textureCoordinates); break;
|
||||||
case 31: textureColor *= texture(u_textures[31], v_textureCoordinates); break;
|
case 31: textureColor *= texture(u_textures[31], v_textureCoordinates); break;
|
||||||
}
|
}
|
||||||
color = textureColor;
|
|
||||||
|
albedoSpec.rgb = textureColor.rgb;
|
||||||
|
albedoSpec.a = 1.0; // TODO: read specular from model material
|
||||||
|
position = vec4(v_position, 1.0f);
|
||||||
|
normal = vec4(normalize(v_normal), 1.0f);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ layout(location = 2) in vec4 a_color;
|
|||||||
layout(location = 3) in vec2 a_textureCoordinates;
|
layout(location = 3) in vec2 a_textureCoordinates;
|
||||||
layout(location = 4) in uint a_textureIndex;
|
layout(location = 4) in uint a_textureIndex;
|
||||||
|
|
||||||
|
out vec3 v_position;
|
||||||
out vec3 v_normal;
|
out vec3 v_normal;
|
||||||
out vec4 v_color;
|
out vec4 v_color;
|
||||||
out vec2 v_textureCoordinates;
|
out vec2 v_textureCoordinates;
|
||||||
@@ -14,10 +15,12 @@ out flat uint v_textureIndex;
|
|||||||
layout(std140, binding = 0) uniform Camera
|
layout(std140, binding = 0) uniform Camera
|
||||||
{
|
{
|
||||||
mat4 u_projectionView;
|
mat4 u_projectionView;
|
||||||
|
vec3 u_position;
|
||||||
};
|
};
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
v_position = a_position;
|
||||||
v_normal = a_normal;
|
v_normal = a_normal;
|
||||||
v_color = a_color;
|
v_color = a_color;
|
||||||
v_textureCoordinates = a_textureCoordinates;
|
v_textureCoordinates = a_textureCoordinates;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ out vec4 v_color;
|
|||||||
out vec3 v_textureCoordinates;
|
out vec3 v_textureCoordinates;
|
||||||
out flat uint v_textureIndex;
|
out flat uint v_textureIndex;
|
||||||
|
|
||||||
uniform mat4 u_projectionView;
|
uniform mat4 u_projectionView2;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
@@ -16,5 +16,5 @@ void main()
|
|||||||
v_textureCoordinates = a_position;
|
v_textureCoordinates = a_position;
|
||||||
v_textureIndex = a_textureIndex;
|
v_textureIndex = a_textureIndex;
|
||||||
// Vclip = Camera projection * Camera view * Model transform * Vlocal
|
// Vclip = Camera projection * Camera view * Model transform * Vlocal
|
||||||
gl_Position = u_projectionView * vec4(a_position, 1.0f);
|
gl_Position = u_projectionView2 * vec4(a_position, 1.0f);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#version 450 core
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 color;
|
||||||
|
|
||||||
|
in vec4 v_color;
|
||||||
|
in vec3 v_textureCoordinates;
|
||||||
|
in flat uint v_textureIndex;
|
||||||
|
|
||||||
|
uniform samplerCube u_textures[32];
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
color = v_color;
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
#version 450 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 a_position;
|
||||||
|
layout(location = 1) in vec4 a_color;
|
||||||
|
layout(location = 2) in uint a_textureIndex;
|
||||||
|
|
||||||
|
out vec4 v_color;
|
||||||
|
out vec3 v_textureCoordinates;
|
||||||
|
out flat uint v_textureIndex;
|
||||||
|
|
||||||
|
layout(std140, binding = 0) uniform Camera
|
||||||
|
{
|
||||||
|
mat4 u_projectionView;
|
||||||
|
vec3 u_position;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
v_color = a_color;
|
||||||
|
v_textureCoordinates = a_position;
|
||||||
|
v_textureIndex = a_textureIndex;
|
||||||
|
// Vclip = Camera projection * Camera view * Model transform * Vlocal
|
||||||
|
gl_Position = u_projectionView * vec4(a_position, 1.0f);
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
#version 450 core
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 color;
|
||||||
|
|
||||||
|
in vec4 v_color;
|
||||||
|
in vec2 v_textureCoordinates;
|
||||||
|
in flat uint v_textureIndex;
|
||||||
|
|
||||||
|
uniform sampler2D u_textures[32];
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
layout(std140, binding = 0) uniform Camera {
|
||||||
|
mat4 u_projectionView;
|
||||||
|
vec3 u_position;
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
struct DirectionalLight {
|
||||||
|
vec3 direction;
|
||||||
|
|
||||||
|
vec3 ambient;
|
||||||
|
vec3 diffuse;
|
||||||
|
vec3 specular;
|
||||||
|
};
|
||||||
|
|
||||||
|
const int MAX_DIRECTIONAL_LIGHTS = 32;
|
||||||
|
layout(std140, binding = 1) uniform DirectionalLights {
|
||||||
|
DirectionalLight u_directionalLight[MAX_DIRECTIONAL_LIGHTS];
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
float isObject = texture(u_textures[v_textureIndex + 1], v_textureCoordinates).a;
|
||||||
|
if (isObject == 0.0f) {
|
||||||
|
color = vec4(0,0,0,0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 albedo = texture(u_textures[v_textureIndex + 0], v_textureCoordinates).rgb;
|
||||||
|
float specular = texture(u_textures[v_textureIndex + 0], v_textureCoordinates).a;
|
||||||
|
vec3 position = texture(u_textures[v_textureIndex + 1], v_textureCoordinates).rgb;
|
||||||
|
vec3 normal = texture(u_textures[v_textureIndex + 2], v_textureCoordinates).rgb;
|
||||||
|
|
||||||
|
|
||||||
|
vec3 lighting = vec3(0.0f, 0.0f, 0.0f);//albedo * v_color.xyz;
|
||||||
|
vec3 viewDirection = normalize(u_position - position);
|
||||||
|
|
||||||
|
// Loop through all directional lights
|
||||||
|
for (int i = 0; i < MAX_DIRECTIONAL_LIGHTS; ++i) {
|
||||||
|
// Diffuse
|
||||||
|
vec3 lightDirection = normalize(-u_directionalLight[i].direction);
|
||||||
|
float diffuse = max(dot(normal, lightDirection), 0.0f);
|
||||||
|
|
||||||
|
// Specular
|
||||||
|
vec3 reflectionDirection = reflect(-lightDirection, normal);
|
||||||
|
float specular = pow(max(dot(viewDirection, reflectionDirection), 0.0f), 32);
|
||||||
|
|
||||||
|
lighting +=
|
||||||
|
(albedo * u_directionalLight[i].ambient) +
|
||||||
|
(albedo * diffuse * u_directionalLight[i].diffuse) +
|
||||||
|
(specular * u_directionalLight[i].specular);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop through all point lights
|
||||||
|
// TODO
|
||||||
|
// vec3 lightDirection = normalize(lightPosition - position);
|
||||||
|
// float diffuse = max(dot(normal, lightDirection), 0.0f);
|
||||||
|
// lighting += diffuse * albedo * u_lightColor;
|
||||||
|
|
||||||
|
// Loop through all spot lights
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
color = vec4(lighting, 1.0f);
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#version 450 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 a_position;
|
||||||
|
layout(location = 1) in vec4 a_color;
|
||||||
|
layout(location = 2) in vec2 a_textureCoordinates;
|
||||||
|
layout(location = 3) in uint a_textureIndex;
|
||||||
|
|
||||||
|
out vec4 v_color;
|
||||||
|
out vec2 v_textureCoordinates;
|
||||||
|
out flat uint v_textureIndex;
|
||||||
|
|
||||||
|
layout(std140, binding = 0) uniform Camera
|
||||||
|
{
|
||||||
|
mat4 u_projectionView;
|
||||||
|
vec3 u_position;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
v_color = a_color;
|
||||||
|
v_textureCoordinates = a_textureCoordinates;
|
||||||
|
v_textureIndex = a_textureIndex;
|
||||||
|
// Vclip = Model transform * Vlocal
|
||||||
|
gl_Position = vec4(a_position, 1.0f);
|
||||||
|
}
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "inferno/render/context.h"
|
#include "inferno/render/context.h"
|
||||||
#include "inferno/render/framebuffer.h"
|
#include "inferno/render/framebuffer.h"
|
||||||
#include "inferno/render/uniformbuffer.h"
|
#include "inferno/render/uniformbuffer.h"
|
||||||
|
#include "inferno/system/rendersystem.h"
|
||||||
// #include "inferno/render/gltf.h"
|
// #include "inferno/render/gltf.h"
|
||||||
#include "inferno/asset/shader.h"
|
#include "inferno/asset/shader.h"
|
||||||
#include "inferno/asset/texture.h"
|
#include "inferno/asset/texture.h"
|
||||||
@@ -53,27 +54,7 @@ Application::Application()
|
|||||||
|
|
||||||
Input::initialize();
|
Input::initialize();
|
||||||
RenderCommand::initialize();
|
RenderCommand::initialize();
|
||||||
|
RenderSystem::the().initialize(m_window->getWidth(), m_window->getHeight());
|
||||||
m_framebuffer = Framebuffer::create({
|
|
||||||
.attachments = { Framebuffer::Type::Color, Framebuffer::Type::Depth },
|
|
||||||
.width = m_window->getWidth(),
|
|
||||||
.height = m_window->getHeight(),
|
|
||||||
.clearColor = { 0.2f, 0.3f, 0.3f, 1.0f },
|
|
||||||
.clearBit = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT,
|
|
||||||
});
|
|
||||||
|
|
||||||
m_screenFramebuffer = Framebuffer::create({
|
|
||||||
.renderToScreen = true,
|
|
||||||
.clearColor = { 1.0f, 1.0f, 1.0f, 1.0f },
|
|
||||||
.clearBit = GL_COLOR_BUFFER_BIT,
|
|
||||||
});
|
|
||||||
|
|
||||||
Uniformbuffer::the().setLayout(
|
|
||||||
"Camera", 0,
|
|
||||||
{
|
|
||||||
{ BufferElementType::Mat4, "u_projectionView" },
|
|
||||||
});
|
|
||||||
Uniformbuffer::the().create("Camera");
|
|
||||||
|
|
||||||
m_scene = std::make_shared<Scene>();
|
m_scene = std::make_shared<Scene>();
|
||||||
m_scene->initialize();
|
m_scene->initialize();
|
||||||
@@ -104,6 +85,8 @@ Application::~Application()
|
|||||||
Renderer2D::destroy();
|
Renderer2D::destroy();
|
||||||
Renderer3D::destroy();
|
Renderer3D::destroy();
|
||||||
RendererCubemap::destroy();
|
RendererCubemap::destroy();
|
||||||
|
RendererPostProcess::destroy();
|
||||||
|
RendererLightCube::destroy();
|
||||||
RenderCommand::destroy();
|
RenderCommand::destroy();
|
||||||
AssetManager::destroy();
|
AssetManager::destroy();
|
||||||
// Input::destroy();
|
// Input::destroy();
|
||||||
@@ -167,10 +150,6 @@ int Application::run()
|
|||||||
// offset
|
// offset
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
constexpr glm::vec4 vectorOne { 1.0f, 1.0f, 1.0f, 1.0f };
|
|
||||||
constexpr glm::mat4 matIdentity { 1.0f };
|
|
||||||
constexpr TransformComponent transformIdentity;
|
|
||||||
|
|
||||||
double gametime = 0;
|
double gametime = 0;
|
||||||
uint64_t frames = 0;
|
uint64_t frames = 0;
|
||||||
|
|
||||||
@@ -196,33 +175,7 @@ int Application::run()
|
|||||||
// ---------------------------------
|
// ---------------------------------
|
||||||
// Render
|
// Render
|
||||||
|
|
||||||
m_framebuffer->bind();
|
|
||||||
|
|
||||||
RenderCommand::clearColor(m_framebuffer->clearColor());
|
|
||||||
RenderCommand::clearBit(m_framebuffer->clearBit());
|
|
||||||
|
|
||||||
render();
|
|
||||||
|
|
||||||
m_scene->render();
|
m_scene->render();
|
||||||
// RendererCharacter::the().drawCharacter(character, f->texture());
|
|
||||||
|
|
||||||
m_framebuffer->unbind();
|
|
||||||
|
|
||||||
// ---------------------------------
|
|
||||||
// Framebuffer
|
|
||||||
|
|
||||||
m_screenFramebuffer->bind();
|
|
||||||
|
|
||||||
RenderCommand::clearColor(m_screenFramebuffer->clearColor());
|
|
||||||
RenderCommand::clearBit(m_screenFramebuffer->clearBit());
|
|
||||||
|
|
||||||
Renderer2D::the().setEnableDepthBuffer(false);
|
|
||||||
Uniformbuffer::the().setValue("Camera", "u_projectionView", matIdentity);
|
|
||||||
Renderer2D::the().drawQuad(transformIdentity, vectorOne, m_framebuffer->texture(0));
|
|
||||||
Renderer2D::the().endScene();
|
|
||||||
Renderer2D::the().setEnableDepthBuffer(true);
|
|
||||||
|
|
||||||
m_screenFramebuffer->unbind();
|
|
||||||
|
|
||||||
m_window->render();
|
m_window->render();
|
||||||
}
|
}
|
||||||
@@ -259,8 +212,7 @@ bool Application::onWindowResize(WindowResizeEvent& e)
|
|||||||
{
|
{
|
||||||
ruc::info("WindowResizeEvent {}x{}", e.getWidth(), e.getHeight());
|
ruc::info("WindowResizeEvent {}x{}", e.getWidth(), e.getHeight());
|
||||||
|
|
||||||
RenderCommand::setViewport(0, 0, e.getWidth(), e.getHeight());
|
RenderSystem::the().resize(e.getWidth(), e.getHeight());
|
||||||
m_framebuffer->resize(e.getWidth(), e.getHeight());
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,8 +51,6 @@ private:
|
|||||||
float m_lastFrameTime { 0.0f };
|
float m_lastFrameTime { 0.0f };
|
||||||
|
|
||||||
std::unique_ptr<Window> m_window;
|
std::unique_ptr<Window> m_window;
|
||||||
std::shared_ptr<Framebuffer> m_framebuffer;
|
|
||||||
std::shared_ptr<Framebuffer> m_screenFramebuffer;
|
|
||||||
std::shared_ptr<Scene> m_scene;
|
std::shared_ptr<Scene> m_scene;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ void fromJson(const ruc::Json& json, CubemapComponent& value)
|
|||||||
if (json.exists("texture") && json.at("texture").type() == ruc::Json::Type::String) {
|
if (json.exists("texture") && json.at("texture").type() == ruc::Json::Type::String) {
|
||||||
value.texture = AssetManager::the().load<TextureCubemap>(json.at("texture").asString());
|
value.texture = AssetManager::the().load<TextureCubemap>(json.at("texture").asString());
|
||||||
}
|
}
|
||||||
|
if (json.exists("isLight")) {
|
||||||
|
json.at("isLight").getTo(value.isLight);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Inferno
|
} // namespace Inferno
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ namespace Inferno {
|
|||||||
struct CubemapComponent {
|
struct CubemapComponent {
|
||||||
glm::vec4 color { 1.0f };
|
glm::vec4 color { 1.0f };
|
||||||
std::shared_ptr<Texture> texture;
|
std::shared_ptr<Texture> texture;
|
||||||
|
bool isLight { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
void fromJson(const ruc::Json& json, CubemapComponent& value);
|
void fromJson(const ruc::Json& json, CubemapComponent& value);
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#include <cstdint> // int32_t, uint8_t, uint32_t
|
#include <cstdint> // int32_t, uint8_t, uint32_t
|
||||||
#include <memory> // std::shared_ptr
|
#include <memory> // std::shared_ptr
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility> // std::pair
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Inferno {
|
namespace Inferno {
|
||||||
|
|||||||
@@ -36,6 +36,14 @@ Framebuffer::~Framebuffer()
|
|||||||
glDeleteFramebuffers(1, &m_id);
|
glDeleteFramebuffers(1, &m_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Framebuffer::copyBuffer(std::shared_ptr<Framebuffer> from, std::shared_ptr<Framebuffer> to, uint32_t bits, uint32_t filter)
|
||||||
|
{
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, from->m_id);
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); // write to default framebuffer
|
||||||
|
glBlitFramebuffer(0, 0, from->m_width, from->m_height, 0, 0, to->m_width, to->m_height, bits, filter);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
void Framebuffer::bind() const
|
void Framebuffer::bind() const
|
||||||
@@ -86,22 +94,47 @@ void Framebuffer::createTextures()
|
|||||||
bind();
|
bind();
|
||||||
|
|
||||||
auto it = m_attachments.begin();
|
auto it = m_attachments.begin();
|
||||||
uint8_t color_attachment = 0;
|
m_colorAttachmentCount = 0;
|
||||||
|
|
||||||
size_t size = m_attachments.size();
|
size_t size = m_attachments.size();
|
||||||
m_textures.resize(size);
|
m_textures.resize(size);
|
||||||
for (size_t i = 0; i < size; ++i) {
|
for (size_t i = 0; i < size; ++i) {
|
||||||
TypeProperties type = *(it + i);
|
TypeProperties type = *(it + i);
|
||||||
|
|
||||||
if (type.type == Type::Color) {
|
if (type.type == Type::RGB8) {
|
||||||
// Set color attachment 0 out of 32
|
// Set color attachment 0 out of 32
|
||||||
m_textures[i] = (TextureFramebuffer::create(
|
m_textures[i] = TextureFramebuffer::create("", m_width, m_height, GL_RGB8, GL_RGB);
|
||||||
"", m_width, m_height, GL_RGB, GL_RGB));
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + m_colorAttachmentCount, GL_TEXTURE_2D, m_textures[i]->id(), 0);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + color_attachment, GL_TEXTURE_2D, m_textures[i]->id(), 0);
|
m_colorAttachmentCount++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.type == Type::RGBA8) { // Color
|
||||||
|
// Set color attachment 0 out of 32
|
||||||
|
m_textures[i] = TextureFramebuffer::create("", m_width, m_height, GL_RGBA8, GL_RGBA);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + m_colorAttachmentCount, GL_TEXTURE_2D, m_textures[i]->id(), 0);
|
||||||
|
m_colorAttachmentCount++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.type == Type::RGBA16F) {
|
||||||
|
// Set color attachment 0 out of 32
|
||||||
|
m_textures[i] = TextureFramebuffer::create("", m_width, m_height, GL_RGBA16F, GL_RGBA, GL_FLOAT);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + m_colorAttachmentCount, GL_TEXTURE_2D, m_textures[i]->id(), 0);
|
||||||
|
m_colorAttachmentCount++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.type == Type::RGBA32F) {
|
||||||
|
// Set color attachment 0 out of 32
|
||||||
|
m_textures[i] = TextureFramebuffer::create("", m_width, m_height, GL_RGBA32F, GL_RGBA, GL_FLOAT);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + m_colorAttachmentCount, GL_TEXTURE_2D, m_textures[i]->id(), 0);
|
||||||
|
m_colorAttachmentCount++;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This combined texture is required for older GPUs
|
// This combined texture is required for older GPUs
|
||||||
if (type.type == Type::Depth24Stencil8) {
|
if (type.type == Type::Depth24Stencil8) { // Depth
|
||||||
m_textures[i] = (TextureFramebuffer::create(
|
m_textures[i] = (TextureFramebuffer::create(
|
||||||
"", m_width, m_height, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8));
|
"", m_width, m_height, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8));
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_textures[i]->id(), 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_textures[i]->id(), 0);
|
||||||
@@ -117,7 +150,7 @@ void Framebuffer::createTextures()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VERIFY(color_attachment <= 32, "maximum color attachments was exceeded: {}/32", color_attachment);
|
VERIFY(m_colorAttachmentCount <= 32, "maximum color attachments was exceeded: {}/32", m_colorAttachmentCount);
|
||||||
check();
|
check();
|
||||||
|
|
||||||
unbind();
|
unbind();
|
||||||
|
|||||||
@@ -24,11 +24,14 @@ public:
|
|||||||
None = 0,
|
None = 0,
|
||||||
|
|
||||||
// Color
|
// Color
|
||||||
RGBA8 = 1,
|
RGB8 = 1,
|
||||||
|
RGBA8 = 2,
|
||||||
|
RGBA16F = 3,
|
||||||
|
RGBA32F = 4,
|
||||||
|
|
||||||
// Depth/stencil
|
// Depth/stencil
|
||||||
Depth32F = 2,
|
Depth24Stencil8 = 5,
|
||||||
Depth24Stencil8 = 3,
|
Depth32F = 6,
|
||||||
|
|
||||||
// Defaults
|
// Defaults
|
||||||
Color = RGBA8,
|
Color = RGBA8,
|
||||||
@@ -59,12 +62,14 @@ public:
|
|||||||
|
|
||||||
// Factory function
|
// Factory function
|
||||||
static std::shared_ptr<Framebuffer> create(const Properties& properties);
|
static std::shared_ptr<Framebuffer> create(const Properties& properties);
|
||||||
|
static void copyBuffer(std::shared_ptr<Framebuffer> from, std::shared_ptr<Framebuffer> to, uint32_t bits, uint32_t filter);
|
||||||
|
|
||||||
void bind() const;
|
void bind() const;
|
||||||
void unbind() const;
|
void unbind() const;
|
||||||
bool check() const;
|
bool check() const;
|
||||||
void resize(uint32_t width, uint32_t height);
|
void resize(uint32_t width, uint32_t height);
|
||||||
|
|
||||||
|
uint8_t colorAttachmentCount() const { return m_colorAttachmentCount; }
|
||||||
uint32_t id() const { return m_id; }
|
uint32_t id() const { return m_id; }
|
||||||
uint32_t width() const { return m_width; }
|
uint32_t width() const { return m_width; }
|
||||||
uint32_t height() const { return m_height; }
|
uint32_t height() const { return m_height; }
|
||||||
@@ -87,6 +92,7 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_renderToScreen { false };
|
bool m_renderToScreen { false };
|
||||||
|
uint8_t m_colorAttachmentCount { 1 };
|
||||||
uint32_t m_id { 0 };
|
uint32_t m_id { 0 };
|
||||||
uint32_t m_width { 0 };
|
uint32_t m_width { 0 };
|
||||||
uint32_t m_height { 0 };
|
uint32_t m_height { 0 };
|
||||||
|
|||||||
@@ -4,10 +4,12 @@
|
|||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <cstdint> // int32_t, uint32_t
|
||||||
#include <memory> // std::shared_ptr
|
#include <memory> // std::shared_ptr
|
||||||
|
|
||||||
#include "glad/glad.h"
|
#include "glad/glad.h"
|
||||||
#include "ruc/format/log.h"
|
#include "ruc/format/log.h"
|
||||||
|
#include "ruc/meta/assert.h"
|
||||||
|
|
||||||
#include "inferno/render/buffer.h"
|
#include "inferno/render/buffer.h"
|
||||||
#include "inferno/render/render-command.h"
|
#include "inferno/render/render-command.h"
|
||||||
@@ -57,6 +59,26 @@ void RenderCommand::setDepthTest(bool enabled)
|
|||||||
enabled ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST);
|
enabled ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderCommand::setColorAttachmentCount(uint32_t count)
|
||||||
|
{
|
||||||
|
static constexpr uint32_t colorAttachments[] = {
|
||||||
|
GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2,
|
||||||
|
GL_COLOR_ATTACHMENT3, GL_COLOR_ATTACHMENT4, GL_COLOR_ATTACHMENT5,
|
||||||
|
GL_COLOR_ATTACHMENT6, GL_COLOR_ATTACHMENT7, GL_COLOR_ATTACHMENT8,
|
||||||
|
GL_COLOR_ATTACHMENT9, GL_COLOR_ATTACHMENT10, GL_COLOR_ATTACHMENT11,
|
||||||
|
GL_COLOR_ATTACHMENT12, GL_COLOR_ATTACHMENT13, GL_COLOR_ATTACHMENT14,
|
||||||
|
GL_COLOR_ATTACHMENT15, GL_COLOR_ATTACHMENT16, GL_COLOR_ATTACHMENT17,
|
||||||
|
GL_COLOR_ATTACHMENT18, GL_COLOR_ATTACHMENT19, GL_COLOR_ATTACHMENT20,
|
||||||
|
GL_COLOR_ATTACHMENT21, GL_COLOR_ATTACHMENT22, GL_COLOR_ATTACHMENT23,
|
||||||
|
GL_COLOR_ATTACHMENT24, GL_COLOR_ATTACHMENT25, GL_COLOR_ATTACHMENT26,
|
||||||
|
GL_COLOR_ATTACHMENT27, GL_COLOR_ATTACHMENT28, GL_COLOR_ATTACHMENT29,
|
||||||
|
GL_COLOR_ATTACHMENT30, GL_COLOR_ATTACHMENT31
|
||||||
|
};
|
||||||
|
static constexpr uint32_t maxCount = sizeof(colorAttachments) / sizeof(colorAttachments[0]);
|
||||||
|
VERIFY(count > 0 && count <= maxCount, "incorrect colorbuffer count: {}/{}", count, maxCount);
|
||||||
|
glDrawBuffers(static_cast<int32_t>(count), colorAttachments); // Multiple Render Targets (MRT)
|
||||||
|
}
|
||||||
|
|
||||||
bool RenderCommand::depthTest()
|
bool RenderCommand::depthTest()
|
||||||
{
|
{
|
||||||
unsigned char depthTest = GL_FALSE;
|
unsigned char depthTest = GL_FALSE;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint> // int32_t, uint32_t
|
||||||
#include <memory> // std::shadred_ptr
|
#include <memory> // std::shadred_ptr
|
||||||
|
|
||||||
#include "glm/ext/vector_float4.hpp" // glm::vec4
|
#include "glm/ext/vector_float4.hpp" // glm::vec4
|
||||||
@@ -25,6 +26,7 @@ public:
|
|||||||
|
|
||||||
static void setViewport(int32_t x, int32_t y, uint32_t width, uint32_t height);
|
static void setViewport(int32_t x, int32_t y, uint32_t width, uint32_t height);
|
||||||
static void setDepthTest(bool enabled);
|
static void setDepthTest(bool enabled);
|
||||||
|
static void setColorAttachmentCount(uint32_t count);
|
||||||
|
|
||||||
static bool depthTest();
|
static bool depthTest();
|
||||||
static int32_t textureUnitAmount();
|
static int32_t textureUnitAmount();
|
||||||
|
|||||||
@@ -171,6 +171,7 @@ void Renderer<T>::flush()
|
|||||||
// Render
|
// Render
|
||||||
bool depthTest = RenderCommand::depthTest();
|
bool depthTest = RenderCommand::depthTest();
|
||||||
RenderCommand::setDepthTest(m_enableDepthBuffer);
|
RenderCommand::setDepthTest(m_enableDepthBuffer);
|
||||||
|
RenderCommand::setColorAttachmentCount(m_colorAttachmentCount);
|
||||||
RenderCommand::drawIndexed(m_vertexArray, m_elementIndex);
|
RenderCommand::drawIndexed(m_vertexArray, m_elementIndex);
|
||||||
RenderCommand::setDepthTest(depthTest);
|
RenderCommand::setDepthTest(depthTest);
|
||||||
|
|
||||||
@@ -197,6 +198,11 @@ void Renderer<T>::nextBatch()
|
|||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
Renderer2D::Renderer2D(s)
|
Renderer2D::Renderer2D(s)
|
||||||
|
{
|
||||||
|
Renderer2D::initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer2D::initialize()
|
||||||
{
|
{
|
||||||
Renderer::initialize();
|
Renderer::initialize();
|
||||||
|
|
||||||
@@ -216,6 +222,8 @@ Renderer2D::Renderer2D(s)
|
|||||||
// ---------------------------------
|
// ---------------------------------
|
||||||
// GPU
|
// GPU
|
||||||
|
|
||||||
|
m_enableDepthBuffer = false;
|
||||||
|
|
||||||
// Create vertex buffer
|
// Create vertex buffer
|
||||||
auto vertexBuffer = std::make_shared<VertexBuffer>(sizeof(QuadVertex) * maxVertices);
|
auto vertexBuffer = std::make_shared<VertexBuffer>(sizeof(QuadVertex) * maxVertices);
|
||||||
vertexBuffer->setLayout({
|
vertexBuffer->setLayout({
|
||||||
@@ -275,12 +283,17 @@ void Renderer2D::drawQuad(const TransformComponent& transform, glm::mat4 color,
|
|||||||
|
|
||||||
void Renderer2D::loadShader()
|
void Renderer2D::loadShader()
|
||||||
{
|
{
|
||||||
m_shader = AssetManager::the().load<Shader>("assets/glsl/batch-2d");
|
m_shader = AssetManager::the().load<Shader>("assets/glsl/post-process");
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
RendererCubemap::RendererCubemap(s)
|
RendererCubemap::RendererCubemap(s)
|
||||||
|
{
|
||||||
|
RendererCubemap::initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RendererCubemap::initialize()
|
||||||
{
|
{
|
||||||
Renderer::initialize();
|
Renderer::initialize();
|
||||||
|
|
||||||
@@ -354,10 +367,10 @@ void RendererCubemap::beginScene(glm::mat4 cameraProjection, glm::mat4 cameraVie
|
|||||||
// x x x 0
|
// x x x 0
|
||||||
// x x x 0
|
// x x x 0
|
||||||
// 0 0 0 1
|
// 0 0 0 1
|
||||||
cameraView = glm::mat4(glm::mat3(cameraView));
|
// cameraView = glm::mat4(glm::mat3(cameraView));
|
||||||
|
|
||||||
m_shader->bind();
|
m_shader->bind();
|
||||||
m_shader->setFloat("u_projectionView", cameraProjection * cameraView);
|
m_shader->setFloat("u_projectionView2", cameraProjection * cameraView);
|
||||||
m_shader->unbind();
|
m_shader->unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,6 +495,7 @@ Renderer3D::Renderer3D(s)
|
|||||||
// GPU
|
// GPU
|
||||||
|
|
||||||
m_enableDepthBuffer = true;
|
m_enableDepthBuffer = true;
|
||||||
|
m_colorAttachmentCount = 3;
|
||||||
|
|
||||||
// Create vertex buffer
|
// Create vertex buffer
|
||||||
auto vertexBuffer = std::make_shared<VertexBuffer>(sizeof(Vertex) * maxVertices);
|
auto vertexBuffer = std::make_shared<VertexBuffer>(sizeof(Vertex) * maxVertices);
|
||||||
@@ -501,8 +515,8 @@ void Renderer3D::drawModel(std::span<const Vertex> vertices, std::span<const uin
|
|||||||
{
|
{
|
||||||
// ruc::error("drawModel");
|
// ruc::error("drawModel");
|
||||||
|
|
||||||
VERIFY(vertices.size() <= maxVertices, "model vertices too big for buffer");
|
VERIFY(vertices.size() <= maxVertices, "model vertices too big for buffer, {}/{}", vertices.size(), maxVertices);
|
||||||
VERIFY(elements.size() <= maxElements, "model elements too big for buffer");
|
VERIFY(elements.size() <= maxElements, "model elements too big for buffer, {}/{}", elements.size(), maxElements);
|
||||||
|
|
||||||
// Create a new batch if the quad limit has been reached
|
// Create a new batch if the quad limit has been reached
|
||||||
if (m_vertexIndex + vertices.size() > maxVertices || m_elementIndex + elements.size() > maxElements) {
|
if (m_vertexIndex + vertices.size() > maxVertices || m_elementIndex + elements.size() > maxElements) {
|
||||||
@@ -512,9 +526,10 @@ void Renderer3D::drawModel(std::span<const Vertex> vertices, std::span<const uin
|
|||||||
uint32_t textureUnitIndex = addTextureUnit(texture);
|
uint32_t textureUnitIndex = addTextureUnit(texture);
|
||||||
|
|
||||||
// Add the vertices
|
// Add the vertices
|
||||||
|
glm::mat3 normalMatrix = glm::mat3(glm::transpose(glm::inverse(transform.transform)));
|
||||||
for (const auto& vertex : vertices) {
|
for (const auto& vertex : vertices) {
|
||||||
m_vertexBufferPtr->position = transform.transform * glm::vec4(vertex.position, 1.0f);
|
m_vertexBufferPtr->position = transform.transform * glm::vec4(vertex.position, 1.0f);
|
||||||
m_vertexBufferPtr->normal = vertex.normal;
|
m_vertexBufferPtr->normal = normalMatrix * vertex.normal; // take non-uniform scaling into consideration
|
||||||
m_vertexBufferPtr->color = color;
|
m_vertexBufferPtr->color = color;
|
||||||
m_vertexBufferPtr->textureCoordinates = vertex.textureCoordinates;
|
m_vertexBufferPtr->textureCoordinates = vertex.textureCoordinates;
|
||||||
m_vertexBufferPtr->textureIndex = textureUnitIndex;
|
m_vertexBufferPtr->textureIndex = textureUnitIndex;
|
||||||
@@ -565,4 +580,46 @@ void Renderer3D::startBatch()
|
|||||||
m_elementBufferPtr = m_elementBufferBase;
|
m_elementBufferPtr = m_elementBufferBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
void RendererPostProcess::drawQuad(const TransformComponent& transform, std::shared_ptr<Texture> albedo, std::shared_ptr<Texture> position, std::shared_ptr<Texture> normal)
|
||||||
|
{
|
||||||
|
nextBatch();
|
||||||
|
|
||||||
|
constexpr glm::vec2 textureCoordinates[] = {
|
||||||
|
{ 0.0f, 0.0f },
|
||||||
|
{ 1.0f, 0.0f },
|
||||||
|
{ 1.0f, 1.0f },
|
||||||
|
{ 0.0f, 1.0f }
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t textureUnitIndex = addTextureUnit(albedo);
|
||||||
|
addTextureUnit(position);
|
||||||
|
addTextureUnit(normal);
|
||||||
|
|
||||||
|
// Add the quads 4 vertices
|
||||||
|
for (uint32_t i = 0; i < vertexPerQuad; i++) {
|
||||||
|
m_vertexBufferPtr->position = transform.transform * m_vertexPositions[i];
|
||||||
|
m_vertexBufferPtr->textureCoordinates = textureCoordinates[i];
|
||||||
|
m_vertexBufferPtr->textureIndex = textureUnitIndex;
|
||||||
|
m_vertexBufferPtr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_vertexIndex += vertexPerQuad;
|
||||||
|
m_elementIndex += elementPerQuad;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RendererPostProcess::loadShader()
|
||||||
|
{
|
||||||
|
ruc::error("POSTPROCESSING!");
|
||||||
|
m_shader = AssetManager::the().load<Shader>("assets/glsl/post-process");
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
void RendererLightCube::loadShader()
|
||||||
|
{
|
||||||
|
m_shader = AssetManager::the().load<Shader>("assets/glsl/lightsource");
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Inferno
|
} // namespace Inferno
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ protected:
|
|||||||
|
|
||||||
// GPU objects
|
// GPU objects
|
||||||
bool m_enableDepthBuffer { true };
|
bool m_enableDepthBuffer { true };
|
||||||
|
uint32_t m_colorAttachmentCount { 1 };
|
||||||
std::shared_ptr<Shader> m_shader;
|
std::shared_ptr<Shader> m_shader;
|
||||||
std::shared_ptr<VertexArray> m_vertexArray;
|
std::shared_ptr<VertexArray> m_vertexArray;
|
||||||
};
|
};
|
||||||
@@ -124,7 +125,7 @@ protected:
|
|||||||
|
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
|
|
||||||
class Renderer2D final
|
class Renderer2D
|
||||||
: public Renderer<QuadVertex>
|
: public Renderer<QuadVertex>
|
||||||
, public ruc::Singleton<Renderer2D> {
|
, public ruc::Singleton<Renderer2D> {
|
||||||
public:
|
public:
|
||||||
@@ -138,15 +139,20 @@ public:
|
|||||||
void drawQuad(const TransformComponent& transform, glm::vec4 color, std::shared_ptr<Texture> texture);
|
void drawQuad(const TransformComponent& transform, glm::vec4 color, std::shared_ptr<Texture> texture);
|
||||||
void drawQuad(const TransformComponent& transform, glm::mat4 color, std::shared_ptr<Texture> texture);
|
void drawQuad(const TransformComponent& transform, glm::mat4 color, std::shared_ptr<Texture> texture);
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
void loadShader() override;
|
Renderer2D() { Renderer2D::initialize(); } // Needed for derived classes
|
||||||
|
|
||||||
|
void initialize();
|
||||||
|
|
||||||
// Default quad vertex positions
|
// Default quad vertex positions
|
||||||
glm::vec4 m_vertexPositions[vertexPerQuad];
|
glm::vec4 m_vertexPositions[vertexPerQuad];
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void loadShader() override;
|
||||||
};
|
};
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
|
|
||||||
class RendererCubemap final
|
class RendererCubemap
|
||||||
: public Renderer<CubemapVertex>
|
: public Renderer<CubemapVertex>
|
||||||
, public ruc::Singleton<RendererCubemap> {
|
, public ruc::Singleton<RendererCubemap> {
|
||||||
public:
|
public:
|
||||||
@@ -163,8 +169,13 @@ public:
|
|||||||
void drawCubemap(const TransformComponent& transform, glm::vec4 color, std::shared_ptr<Texture> texture);
|
void drawCubemap(const TransformComponent& transform, glm::vec4 color, std::shared_ptr<Texture> texture);
|
||||||
void drawCubemap(const TransformComponent& transform, glm::mat4 color, std::shared_ptr<Texture> texture);
|
void drawCubemap(const TransformComponent& transform, glm::mat4 color, std::shared_ptr<Texture> texture);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
RendererCubemap() { RendererCubemap::initialize(); } // Needed for derived classes
|
||||||
|
|
||||||
|
void initialize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void loadShader() override;
|
virtual void loadShader() override;
|
||||||
|
|
||||||
// Default cubemap vertex positions
|
// Default cubemap vertex positions
|
||||||
glm::vec4 m_vertexPositions[vertexPerQuad * quadPerCube];
|
glm::vec4 m_vertexPositions[vertexPerQuad * quadPerCube];
|
||||||
@@ -212,4 +223,47 @@ private:
|
|||||||
uint32_t* m_elementBufferPtr { nullptr };
|
uint32_t* m_elementBufferPtr { nullptr };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
class RendererPostProcess final
|
||||||
|
: public Renderer2D
|
||||||
|
, public ruc::Singleton<RendererPostProcess> {
|
||||||
|
public:
|
||||||
|
RendererPostProcess(ruc::Singleton<RendererPostProcess>::s)
|
||||||
|
: Renderer2D()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
virtual ~RendererPostProcess() = default;
|
||||||
|
|
||||||
|
using Singleton<RendererPostProcess>::the;
|
||||||
|
using Singleton<RendererPostProcess>::destroy;
|
||||||
|
|
||||||
|
void drawQuad(const TransformComponent& transform, std::shared_ptr<Texture> albedo, std::shared_ptr<Texture> position, std::shared_ptr<Texture> normal);
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void loadShader() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
class RendererLightCube final
|
||||||
|
: public RendererCubemap
|
||||||
|
, public ruc::Singleton<RendererLightCube> {
|
||||||
|
public:
|
||||||
|
RendererLightCube(ruc::Singleton<RendererLightCube>::s)
|
||||||
|
: RendererCubemap()
|
||||||
|
{
|
||||||
|
m_enableDepthBuffer = true;
|
||||||
|
}
|
||||||
|
virtual ~RendererLightCube() = default;
|
||||||
|
|
||||||
|
using Singleton<RendererLightCube>::the;
|
||||||
|
using Singleton<RendererLightCube>::destroy;
|
||||||
|
|
||||||
|
void beginScene(glm::mat4, glm::mat4) override {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void loadShader() override;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Inferno
|
} // namespace Inferno
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "glad/glad.h"
|
#include "glad/glad.h"
|
||||||
#include "glm/ext/matrix_float2x2.hpp" // glm::mat2
|
#include "glm/ext/matrix_float2x2.hpp" // glm::mat2
|
||||||
#include "glm/ext/matrix_float3x3.hpp" // glm::mat3
|
#include "glm/ext/matrix_float3x3.hpp" // glm::mat3
|
||||||
|
#include "glm/ext/vector_float3.hpp" // glm::vec3
|
||||||
#include "ruc/singleton.h"
|
#include "ruc/singleton.h"
|
||||||
|
|
||||||
#include "inferno/render/buffer.h"
|
#include "inferno/render/buffer.h"
|
||||||
@@ -25,6 +26,23 @@
|
|||||||
|
|
||||||
namespace Inferno {
|
namespace Inferno {
|
||||||
|
|
||||||
|
// Uniform block layouts, using std140 memory layout rules
|
||||||
|
|
||||||
|
#define MAX_DIRECTIONAL_LIGHTS 32
|
||||||
|
struct UniformDirectionalLight {
|
||||||
|
glm::vec3 direction { 0 };
|
||||||
|
float __padding0 { 0 };
|
||||||
|
|
||||||
|
glm::vec3 ambient { 0 };
|
||||||
|
float __padding1 { 0 };
|
||||||
|
glm::vec3 diffuse { 0 };
|
||||||
|
float __padding2 { 0 };
|
||||||
|
glm::vec3 specular { 0 };
|
||||||
|
float __padding3 { 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
struct UniformbufferBlock {
|
struct UniformbufferBlock {
|
||||||
uint32_t id { 0 };
|
uint32_t id { 0 };
|
||||||
uint32_t size { 0 };
|
uint32_t size { 0 };
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include <limits> // std::numeric_limits
|
#include <limits> // std::numeric_limits
|
||||||
#include <utility> // std::pair
|
#include <utility> // std::pair
|
||||||
|
|
||||||
#include "entt/entity/entity.hpp" // ent::entity
|
#include "entt/entity/fwd.hpp" // ent::entity
|
||||||
#include "ruc/file.h"
|
#include "ruc/file.h"
|
||||||
#include "ruc/format/log.h"
|
#include "ruc/format/log.h"
|
||||||
#include "ruc/json/json.h"
|
#include "ruc/json/json.h"
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
#include "inferno/component/tagcomponent.h"
|
#include "inferno/component/tagcomponent.h"
|
||||||
#include "inferno/component/textareacomponent.h"
|
#include "inferno/component/textareacomponent.h"
|
||||||
#include "inferno/component/transformcomponent.h"
|
#include "inferno/component/transformcomponent.h"
|
||||||
|
#include "inferno/render/renderer.h"
|
||||||
#include "inferno/render/uniformbuffer.h"
|
#include "inferno/render/uniformbuffer.h"
|
||||||
#include "inferno/scene/scene.h"
|
#include "inferno/scene/scene.h"
|
||||||
#include "inferno/script/nativescript.h"
|
#include "inferno/script/nativescript.h"
|
||||||
@@ -84,17 +85,7 @@ void Scene::update(float deltaTime)
|
|||||||
|
|
||||||
void Scene::render()
|
void Scene::render()
|
||||||
{
|
{
|
||||||
auto [projection, view] = CameraSystem::the().projectionView();
|
|
||||||
Uniformbuffer::the().setValue("Camera", "u_projectionView", projection * view);
|
|
||||||
RendererCubemap::the().beginScene(projection, view); // camera, lights, environment
|
|
||||||
|
|
||||||
RenderSystem::the().render();
|
RenderSystem::the().render();
|
||||||
TextAreaSystem::the().render();
|
|
||||||
|
|
||||||
RendererCubemap::the().endScene();
|
|
||||||
Renderer3D::the().endScene();
|
|
||||||
Renderer2D::the().endScene();
|
|
||||||
RendererFont::the().endScene();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::destroy()
|
void Scene::destroy()
|
||||||
|
|||||||
@@ -53,10 +53,23 @@ std::pair<glm::mat4, glm::mat4> CameraSystem::projectionView()
|
|||||||
}
|
}
|
||||||
|
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::vec3 CameraSystem::translate()
|
||||||
|
{
|
||||||
|
auto view = m_registry->view<TransformComponent, CameraComponent>();
|
||||||
|
|
||||||
|
for (auto [entity, transform, camera] : view.each()) {
|
||||||
|
return transform.translate;
|
||||||
|
}
|
||||||
|
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
void CameraSystem::updateOrthographic(TransformComponent& transform, CameraComponent& camera)
|
void CameraSystem::updateOrthographic(TransformComponent& transform, CameraComponent& camera)
|
||||||
{
|
{
|
||||||
// Update camera matrix
|
// Update camera matrix
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ public:
|
|||||||
* @brief Return a pair from the camera component: { projection, view }
|
* @brief Return a pair from the camera component: { projection, view }
|
||||||
*/
|
*/
|
||||||
std::pair<glm::mat4, glm::mat4> projectionView();
|
std::pair<glm::mat4, glm::mat4> projectionView();
|
||||||
|
glm::vec3 translate();
|
||||||
|
|
||||||
void setRegistry(std::shared_ptr<entt::registry> registry) { m_registry = registry; };
|
void setRegistry(std::shared_ptr<entt::registry> registry) { m_registry = registry; };
|
||||||
|
|
||||||
|
|||||||
@@ -4,42 +4,149 @@
|
|||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "glm/ext/matrix_transform.hpp" // glm::translate, glm::rotate, glm::scale, glm::radians
|
#include <cstdint> // int32_t
|
||||||
#include "inferno/component/model-component.h"
|
|
||||||
|
#include "glad/glad.h"
|
||||||
#include "ruc/format/log.h"
|
#include "ruc/format/log.h"
|
||||||
|
|
||||||
#include "inferno/component/cubemap-component.h"
|
#include "inferno/component/cubemap-component.h"
|
||||||
#include "inferno/component/model-component.h"
|
#include "inferno/component/model-component.h"
|
||||||
#include "inferno/component/spritecomponent.h"
|
#include "inferno/component/spritecomponent.h"
|
||||||
#include "inferno/component/transformcomponent.h"
|
#include "inferno/component/transformcomponent.h"
|
||||||
|
#include "inferno/render/framebuffer.h"
|
||||||
|
#include "inferno/render/render-command.h"
|
||||||
#include "inferno/render/renderer.h"
|
#include "inferno/render/renderer.h"
|
||||||
|
#include "inferno/render/uniformbuffer.h"
|
||||||
|
#include "inferno/system/camerasystem.h"
|
||||||
#include "inferno/system/rendersystem.h"
|
#include "inferno/system/rendersystem.h"
|
||||||
|
#include "inferno/system/textareasystem.h"
|
||||||
|
|
||||||
namespace Inferno {
|
namespace Inferno {
|
||||||
|
|
||||||
RenderSystem::RenderSystem(s)
|
RenderSystem::RenderSystem(s)
|
||||||
{
|
{
|
||||||
ruc::info("RenderSystem initialized");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderSystem::~RenderSystem()
|
RenderSystem::~RenderSystem()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
void RenderSystem::initialize(uint32_t width, uint32_t height)
|
||||||
|
{
|
||||||
|
m_framebuffer = Framebuffer::create({
|
||||||
|
.attachments = { Framebuffer::Type::Color, Framebuffer::Type::RGBA16F, Framebuffer::Type::RGBA16F, Framebuffer::Type::Depth },
|
||||||
|
.width = width,
|
||||||
|
.height = height,
|
||||||
|
.clearColor = { 0.0f, 0.0f, 0.0f, 0.0f },
|
||||||
|
.clearBit = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT,
|
||||||
|
});
|
||||||
|
|
||||||
|
m_screenFramebuffer = Framebuffer::create({
|
||||||
|
.renderToScreen = true,
|
||||||
|
.clearColor = { 1.0f, 1.0f, 1.0f, 1.0f },
|
||||||
|
.clearBit = GL_COLOR_BUFFER_BIT,
|
||||||
|
});
|
||||||
|
|
||||||
|
Uniformbuffer::the().setLayout(
|
||||||
|
"Camera", 0,
|
||||||
|
{
|
||||||
|
{ BufferElementType::Mat4, "u_projectionView" },
|
||||||
|
{ BufferElementType::Vec3, "u_position" },
|
||||||
|
});
|
||||||
|
Uniformbuffer::the().create("Camera");
|
||||||
|
|
||||||
|
Uniformbuffer::the().setLayout(
|
||||||
|
"DirectionalLights",
|
||||||
|
{
|
||||||
|
.size = sizeof(UniformDirectionalLight) * MAX_DIRECTIONAL_LIGHTS,
|
||||||
|
.bindingPoint = 1,
|
||||||
|
.uniformLocations = {
|
||||||
|
{ "u_directionalLight", 0 },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
Uniformbuffer::the().create("DirectionalLights");
|
||||||
|
|
||||||
|
ruc::info("RenderSystem initialized");
|
||||||
|
}
|
||||||
|
|
||||||
void RenderSystem::render()
|
void RenderSystem::render()
|
||||||
{
|
{
|
||||||
auto quadView = m_registry->view<TransformComponent, SpriteComponent>();
|
static constexpr TransformComponent transformIdentity;
|
||||||
|
|
||||||
for (auto [entity, transform, sprite] : quadView.each()) {
|
// ---------------------------------
|
||||||
Renderer2D::the().drawQuad(transform, sprite.color, sprite.texture);
|
// Deferred rendering to a framebuffer
|
||||||
|
|
||||||
|
framebufferSetup(m_framebuffer);
|
||||||
|
|
||||||
|
renderGeometry();
|
||||||
|
|
||||||
|
framebufferTeardown(m_framebuffer);
|
||||||
|
|
||||||
|
// ---------------------------------
|
||||||
|
// Forward rendering to the screen
|
||||||
|
|
||||||
|
framebufferSetup(m_screenFramebuffer);
|
||||||
|
|
||||||
|
renderSkybox();
|
||||||
|
|
||||||
|
// Render 3D geometry post-processing
|
||||||
|
RendererPostProcess::the().drawQuad(transformIdentity, m_framebuffer->texture(0), m_framebuffer->texture(1), m_framebuffer->texture(2));
|
||||||
|
RendererPostProcess::the().endScene();
|
||||||
|
|
||||||
|
// Visual representation of light sources
|
||||||
|
Framebuffer::copyBuffer(m_framebuffer, m_screenFramebuffer, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
||||||
|
renderLightCubes();
|
||||||
|
|
||||||
|
// Render 2D, UI
|
||||||
|
renderOverlay();
|
||||||
|
|
||||||
|
framebufferTeardown(m_screenFramebuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto cubemapView = m_registry->view<TransformComponent, CubemapComponent>();
|
void RenderSystem::resize(int32_t width, int32_t height)
|
||||||
|
{
|
||||||
for (auto [entity, transform, cubemap] : cubemapView.each()) {
|
RenderCommand::setViewport(0, 0, width, height);
|
||||||
RendererCubemap::the().drawCubemap(transform, cubemap.color, cubemap.texture);
|
m_framebuffer->resize(width, height);
|
||||||
|
m_screenFramebuffer->resize(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
void RenderSystem::framebufferSetup(std::shared_ptr<Framebuffer> framebuffer)
|
||||||
|
{
|
||||||
|
framebuffer->bind();
|
||||||
|
|
||||||
|
RenderCommand::setColorAttachmentCount(framebuffer->colorAttachmentCount());
|
||||||
|
RenderCommand::clearColor(framebuffer->clearColor());
|
||||||
|
RenderCommand::clearBit(framebuffer->clearBit());
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderSystem::framebufferTeardown(std::shared_ptr<Framebuffer> framebuffer)
|
||||||
|
{
|
||||||
|
framebuffer->unbind();
|
||||||
|
|
||||||
|
RenderCommand::setColorAttachmentCount(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderSystem::renderGeometry()
|
||||||
|
{
|
||||||
|
auto [projection, view] = CameraSystem::the().projectionView();
|
||||||
|
auto translate = CameraSystem::the().translate();
|
||||||
|
Uniformbuffer::the().setValue("Camera", "u_projectionView", projection * view);
|
||||||
|
Uniformbuffer::the().setValue("Camera", "u_position", translate);
|
||||||
|
|
||||||
|
static UniformDirectionalLight directionalLights[1] = {
|
||||||
|
{
|
||||||
|
.direction = { -8.0f, -8.0f, -8.0f },
|
||||||
|
.ambient = { 0.1f, 0.1f, 0.1f },
|
||||||
|
.diffuse = { 1.0f, 1.0f, 1.0f },
|
||||||
|
.specular = { 1.0f, 1.0f, 1.0f },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
Uniformbuffer::the().setValue("DirectionalLights", "u_directionalLight", directionalLights);
|
||||||
|
|
||||||
auto modelView = m_registry->view<TransformComponent, ModelComponent>();
|
auto modelView = m_registry->view<TransformComponent, ModelComponent>();
|
||||||
|
|
||||||
for (auto [entity, transform, model] : modelView.each()) {
|
for (auto [entity, transform, model] : modelView.each()) {
|
||||||
@@ -49,6 +156,54 @@ void RenderSystem::render()
|
|||||||
model.color,
|
model.color,
|
||||||
model.model->texture() ? model.model->texture() : model.texture);
|
model.model->texture() ? model.model->texture() : model.texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Renderer3D::the().endScene();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderSystem::renderSkybox()
|
||||||
|
{
|
||||||
|
auto [projection, view] = CameraSystem::the().projectionView();
|
||||||
|
RendererCubemap::the().beginScene(projection, view); // camera, lights, environment
|
||||||
|
|
||||||
|
auto cubemapView = m_registry->view<TransformComponent, CubemapComponent>();
|
||||||
|
|
||||||
|
for (auto [entity, transform, cubemap] : cubemapView.each()) {
|
||||||
|
if (!cubemap.isLight) {
|
||||||
|
RendererCubemap::the().drawCubemap(transform, cubemap.color, cubemap.texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RendererCubemap::the().endScene();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderSystem::renderLightCubes()
|
||||||
|
{
|
||||||
|
auto [projection, view] = CameraSystem::the().projectionView();
|
||||||
|
RendererLightCube::the().beginScene(projection, view); // camera, lights, environment
|
||||||
|
|
||||||
|
auto cubemapView = m_registry->view<TransformComponent, CubemapComponent>();
|
||||||
|
|
||||||
|
for (auto [entity, transform, cubemap] : cubemapView.each()) {
|
||||||
|
if (cubemap.isLight) {
|
||||||
|
RendererLightCube::the().drawCubemap(transform, cubemap.color, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RendererLightCube::the().endScene();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderSystem::renderOverlay()
|
||||||
|
{
|
||||||
|
auto quadView = m_registry->view<TransformComponent, SpriteComponent>();
|
||||||
|
|
||||||
|
for (auto [entity, transform, sprite] : quadView.each()) {
|
||||||
|
Renderer2D::the().drawQuad(transform, sprite.color, sprite.texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer2D::the().endScene();
|
||||||
|
|
||||||
|
TextAreaSystem::the().render();
|
||||||
|
RendererFont::the().endScene();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Inferno
|
} // namespace Inferno
|
||||||
|
|||||||
@@ -6,25 +6,39 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint> // int32_t, uint32_t
|
||||||
#include <memory> //std::shared_ptr
|
#include <memory> //std::shared_ptr
|
||||||
|
|
||||||
#include "entt/entity/registry.hpp" // entt::entity, entt::registry
|
#include "entt/entity/fwd.hpp" // entt::registry
|
||||||
|
|
||||||
#include "ruc/singleton.h"
|
#include "ruc/singleton.h"
|
||||||
|
|
||||||
#include "inferno/render/renderer.h"
|
|
||||||
|
|
||||||
namespace Inferno {
|
namespace Inferno {
|
||||||
|
|
||||||
|
class Framebuffer;
|
||||||
|
|
||||||
class RenderSystem final : public ruc::Singleton<RenderSystem> {
|
class RenderSystem final : public ruc::Singleton<RenderSystem> {
|
||||||
public:
|
public:
|
||||||
RenderSystem(s);
|
RenderSystem(s);
|
||||||
virtual ~RenderSystem();
|
virtual ~RenderSystem();
|
||||||
|
|
||||||
|
void initialize(uint32_t width, uint32_t height);
|
||||||
void render();
|
void render();
|
||||||
|
|
||||||
|
void resize(int32_t width, int32_t height);
|
||||||
|
|
||||||
void setRegistry(std::shared_ptr<entt::registry> registry) { m_registry = registry; };
|
void setRegistry(std::shared_ptr<entt::registry> registry) { m_registry = registry; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void framebufferSetup(std::shared_ptr<Framebuffer> framebuffer);
|
||||||
|
void framebufferTeardown(std::shared_ptr<Framebuffer> framebuffer);
|
||||||
|
void renderGeometry();
|
||||||
|
void renderSkybox();
|
||||||
|
void renderLightCubes();
|
||||||
|
void renderOverlay();
|
||||||
|
|
||||||
|
std::shared_ptr<Framebuffer> m_framebuffer;
|
||||||
|
std::shared_ptr<Framebuffer> m_screenFramebuffer;
|
||||||
std::shared_ptr<entt::registry> m_registry;
|
std::shared_ptr<entt::registry> m_registry;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user