Compare commits
3
Commits
fd8973d10d
...
d01a4429ca
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d01a4429ca | ||
|
|
d22effdfa3 | ||
|
|
52611beeab |
@@ -23,6 +23,7 @@
|
|||||||
#include "inferno/render/context.h"
|
#include "inferno/render/context.h"
|
||||||
#include "inferno/render/font.h"
|
#include "inferno/render/font.h"
|
||||||
// #include "inferno/render/gltf.h"
|
// #include "inferno/render/gltf.h"
|
||||||
|
#include "inferno/render/render-command.h"
|
||||||
#include "inferno/render/renderer.h"
|
#include "inferno/render/renderer.h"
|
||||||
#include "inferno/render/shader.h"
|
#include "inferno/render/shader.h"
|
||||||
#include "inferno/render/texture.h"
|
#include "inferno/render/texture.h"
|
||||||
@@ -78,7 +79,7 @@ Application::~Application()
|
|||||||
m_scene->destroy();
|
m_scene->destroy();
|
||||||
|
|
||||||
FontManager::destroy();
|
FontManager::destroy();
|
||||||
RendererCharacter::destroy();
|
RendererFont::destroy();
|
||||||
Renderer2D::destroy();
|
Renderer2D::destroy();
|
||||||
RendererCubemap::destroy();
|
RendererCubemap::destroy();
|
||||||
RenderCommand::destroy();
|
RenderCommand::destroy();
|
||||||
@@ -170,14 +171,14 @@ int Application::run()
|
|||||||
std::pair<glm::mat4, glm::mat4> projectionView = m_scene->cameraProjectionView();
|
std::pair<glm::mat4, glm::mat4> projectionView = m_scene->cameraProjectionView();
|
||||||
RendererCubemap::the().beginScene(projectionView.first, projectionView.second); // camera, lights, environment
|
RendererCubemap::the().beginScene(projectionView.first, projectionView.second); // camera, lights, environment
|
||||||
Renderer2D::the().beginScene(projectionView.first, projectionView.second); // camera, lights, environment
|
Renderer2D::the().beginScene(projectionView.first, projectionView.second); // camera, lights, environment
|
||||||
RendererCharacter::the().beginScene();
|
RendererFont::the().beginScene(projectionView.first, projectionView.second); // camera, lights, environment
|
||||||
|
|
||||||
m_scene->render();
|
m_scene->render();
|
||||||
// RendererCharacter::the().drawCharacter(character, f->texture());
|
// RendererCharacter::the().drawCharacter(character, f->texture());
|
||||||
|
|
||||||
RendererCubemap::the().endScene();
|
RendererCubemap::the().endScene();
|
||||||
Renderer2D::the().endScene();
|
Renderer2D::the().endScene();
|
||||||
RendererCharacter::the().endScene();
|
RendererFont::the().endScene();
|
||||||
|
|
||||||
m_window->render();
|
m_window->render();
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-20
@@ -42,17 +42,17 @@ public:
|
|||||||
static uint32_t getTypeCount(const BufferElementType type);
|
static uint32_t getTypeCount(const BufferElementType type);
|
||||||
static uint32_t getTypeGL(const BufferElementType type);
|
static uint32_t getTypeGL(const BufferElementType type);
|
||||||
|
|
||||||
inline BufferElementType getType() const { return m_type; }
|
BufferElementType getType() const { return m_type; }
|
||||||
inline std::string getName() const { return m_name; }
|
std::string getName() const { return m_name; }
|
||||||
inline uint32_t getSize() const { return m_size; }
|
uint32_t getSize() const { return m_size; }
|
||||||
inline uint32_t getOffset() const { return m_offset; }
|
uint32_t getOffset() const { return m_offset; }
|
||||||
inline bool getNormalized() const { return m_normalized; }
|
bool getNormalized() const { return m_normalized; }
|
||||||
|
|
||||||
inline void setType(const BufferElementType& type) { m_type = type; }
|
void setType(const BufferElementType& type) { m_type = type; }
|
||||||
inline void setName(const std::string& name) { m_name = name; }
|
void setName(const std::string& name) { m_name = name; }
|
||||||
inline void setSize(const uint32_t& size) { m_size = size; }
|
void setSize(const uint32_t& size) { m_size = size; }
|
||||||
inline void setOffset(const uint32_t& offset) { m_offset = offset; }
|
void setOffset(const uint32_t& offset) { m_offset = offset; }
|
||||||
inline void setNormalized(const bool& normalized) { m_normalized = normalized; }
|
void setNormalized(const bool& normalized) { m_normalized = normalized; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BufferElementType m_type;
|
BufferElementType m_type;
|
||||||
@@ -70,14 +70,14 @@ public:
|
|||||||
BufferLayout() {}
|
BufferLayout() {}
|
||||||
BufferLayout(const std::initializer_list<BufferElement>& elements);
|
BufferLayout(const std::initializer_list<BufferElement>& elements);
|
||||||
|
|
||||||
inline const std::vector<BufferElement>& getElements() const { return m_elements; }
|
const std::vector<BufferElement>& getElements() const { return m_elements; }
|
||||||
inline uint32_t getStride() const { return m_stride; }
|
uint32_t getStride() const { return m_stride; }
|
||||||
|
|
||||||
// Iterators
|
// Iterators
|
||||||
inline std::vector<BufferElement>::iterator begin() { return m_elements.begin(); }
|
std::vector<BufferElement>::iterator begin() { return m_elements.begin(); }
|
||||||
inline std::vector<BufferElement>::iterator end() { return m_elements.end(); }
|
std::vector<BufferElement>::iterator end() { return m_elements.end(); }
|
||||||
inline std::vector<BufferElement>::const_iterator begin() const { return m_elements.begin(); }
|
std::vector<BufferElement>::const_iterator begin() const { return m_elements.begin(); }
|
||||||
inline std::vector<BufferElement>::const_iterator end() const { return m_elements.end(); }
|
std::vector<BufferElement>::const_iterator end() const { return m_elements.end(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void calculateOffsetsAndStride();
|
void calculateOffsetsAndStride();
|
||||||
@@ -101,7 +101,7 @@ public:
|
|||||||
|
|
||||||
void uploadData(const void* data, uint32_t size);
|
void uploadData(const void* data, uint32_t size);
|
||||||
|
|
||||||
inline const BufferLayout& getLayout() const { return m_layout; }
|
const BufferLayout& getLayout() const { return m_layout; }
|
||||||
|
|
||||||
inline void setLayout(const BufferLayout& layout) { m_layout = layout; }
|
inline void setLayout(const BufferLayout& layout) { m_layout = layout; }
|
||||||
|
|
||||||
@@ -121,7 +121,7 @@ public:
|
|||||||
void bind() const;
|
void bind() const;
|
||||||
void unbind() const;
|
void unbind() const;
|
||||||
|
|
||||||
inline uint32_t getCount() const { return m_count; }
|
uint32_t getCount() const { return m_count; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t m_id { 0 };
|
uint32_t m_id { 0 };
|
||||||
@@ -142,8 +142,8 @@ public:
|
|||||||
void addVertexBuffer(std::shared_ptr<VertexBuffer> vertexBuffer);
|
void addVertexBuffer(std::shared_ptr<VertexBuffer> vertexBuffer);
|
||||||
void setIndexBuffer(std::shared_ptr<IndexBuffer> indexBuffer);
|
void setIndexBuffer(std::shared_ptr<IndexBuffer> indexBuffer);
|
||||||
|
|
||||||
inline const std::vector<std::shared_ptr<VertexBuffer>>& getVertexBuffers() const { return m_vertexBuffers; }
|
std::shared_ptr<VertexBuffer> at(size_t i) const { return m_vertexBuffers.at(i); }
|
||||||
inline std::shared_ptr<IndexBuffer> getIndexBuffer() const { return m_indexBuffer; }
|
std::shared_ptr<IndexBuffer> getIndexBuffer() const { return m_indexBuffer; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t m_id { 0 };
|
uint32_t m_id { 0 };
|
||||||
|
|||||||
+11
-11
@@ -73,14 +73,14 @@ void Font::parseFont(const std::string& font)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Character
|
// Symbol
|
||||||
// ---------------------------------
|
// ---------------------------------
|
||||||
|
|
||||||
if (action.compare("char") == 0) {
|
if (action.compare("char") == 0) {
|
||||||
unsigned char id = convert<unsigned char>(findValue("id", columns));
|
auto id = convert<char>(findValue("id", columns));
|
||||||
uint32_t width = convert<uint32_t>(findValue("width", columns));
|
auto width = convert<uint32_t>(findValue("width", columns));
|
||||||
uint32_t height = convert<uint32_t>(findValue("height", columns));
|
auto height = convert<uint32_t>(findValue("height", columns));
|
||||||
Character character = {
|
Symbol symbol = {
|
||||||
.id = id,
|
.id = id,
|
||||||
.position = {
|
.position = {
|
||||||
convert<uint32_t>(findValue("x", columns)) + m_padding[Padding::Left],
|
convert<uint32_t>(findValue("x", columns)) + m_padding[Padding::Left],
|
||||||
@@ -97,7 +97,7 @@ void Font::parseFont(const std::string& font)
|
|||||||
.advance = convert<uint32_t>(findValue("xadvance", columns)) - m_padding[Padding::Left] - m_padding[Padding::Right]
|
.advance = convert<uint32_t>(findValue("xadvance", columns)) - m_padding[Padding::Left] - m_padding[Padding::Right]
|
||||||
};
|
};
|
||||||
|
|
||||||
m_characterList.emplace(id, std::make_shared<Character>(character));
|
m_symbolList.emplace(id, std::make_shared<Symbol>(symbol));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,10 +109,10 @@ void Font::parseFont(const std::string& font)
|
|||||||
unsigned char second = convert<unsigned char>(findValue("second", columns));
|
unsigned char second = convert<unsigned char>(findValue("second", columns));
|
||||||
char amount = convert<char>(findValue("amount", columns));
|
char amount = convert<char>(findValue("amount", columns));
|
||||||
|
|
||||||
// Add the kerning of the previous character to this character
|
// Add the kerning of the previous symbol to this symbol
|
||||||
if (m_characterList.find(second) != m_characterList.end()) {
|
if (m_symbolList.find(second) != m_symbolList.end()) {
|
||||||
auto character = m_characterList.at(second);
|
auto symbol = m_symbolList.at(second);
|
||||||
character->kernings.emplace(first, amount);
|
symbol->kernings.emplace(first, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -132,7 +132,7 @@ std::vector<std::string> Font::findColumns(const std::string& line) const
|
|||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
size_t find = 0;
|
size_t find = 0;
|
||||||
size_t findFirstNotOf = 0;
|
size_t findFirstNotOf = 0;
|
||||||
// Loop over line characters
|
// Loop over line symbols
|
||||||
while (find != std::string::npos) {
|
while (find != std::string::npos) {
|
||||||
find = line.find(" ", index);
|
find = line.find(" ", index);
|
||||||
findFirstNotOf = line.find_first_not_of(" ", index);
|
findFirstNotOf = line.find_first_not_of(" ", index);
|
||||||
|
|||||||
@@ -24,13 +24,13 @@ namespace Inferno {
|
|||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
struct Character {
|
struct Symbol {
|
||||||
char id; // Character
|
char id; // Symbol
|
||||||
glm::uvec2 position; // Position
|
glm::uvec2 position; // Position
|
||||||
glm::uvec2 size; // Width/height
|
glm::uvec2 size; // Width/height
|
||||||
glm::ivec2 offset; // Offset from baseline to left / top of glyph
|
glm::ivec2 offset; // Offset from baseline to left / top of glyph
|
||||||
uint32_t advance; // Amount to advance to next glyph
|
uint32_t advance; // Amount to advance to next glyph
|
||||||
std::unordered_map<unsigned char, char> kernings; // Kernings for characters that come before this one
|
std::unordered_map<unsigned char, char> kernings; // Kernings for symbols that come before this one
|
||||||
};
|
};
|
||||||
|
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
@@ -52,8 +52,8 @@ public:
|
|||||||
inline uint32_t lineSpacing() const { return m_lineSpacing; }
|
inline uint32_t lineSpacing() const { return m_lineSpacing; }
|
||||||
inline std::shared_ptr<Texture> texture() const { return m_texture; }
|
inline std::shared_ptr<Texture> texture() const { return m_texture; }
|
||||||
|
|
||||||
inline std::shared_ptr<Character> get(unsigned char c) const { return m_characterList.at(c); }
|
inline std::shared_ptr<Symbol> get(unsigned char c) const { return m_symbolList.at(c); }
|
||||||
inline std::shared_ptr<Character> operator[](unsigned char c) const { return m_characterList.at(c); }
|
inline std::shared_ptr<Symbol> operator[](unsigned char c) const { return m_symbolList.at(c); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void parseFont(const std::string& font);
|
void parseFont(const std::string& font);
|
||||||
@@ -66,7 +66,7 @@ private:
|
|||||||
uint32_t m_lineSpacing = { 0 };
|
uint32_t m_lineSpacing = { 0 };
|
||||||
std::array<uint32_t, 4> m_padding = { 0 };
|
std::array<uint32_t, 4> m_padding = { 0 };
|
||||||
std::shared_ptr<Texture> m_texture;
|
std::shared_ptr<Texture> m_texture;
|
||||||
std::unordered_map<unsigned char, std::shared_ptr<Character>> m_characterList;
|
std::unordered_map<unsigned char, std::shared_ptr<Symbol>> m_symbolList;
|
||||||
};
|
};
|
||||||
|
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
@@ -98,7 +98,7 @@ struct ruc::format::Formatter<glm::ivec2> : Formatter<std::vector<int32_t>> {
|
|||||||
// FontManager fm;
|
// FontManager fm;
|
||||||
// Font f = fm.load("path/to/font");
|
// Font f = fm.load("path/to/font");
|
||||||
// Font f2("path/to/font");
|
// Font f2("path/to/font");
|
||||||
// Character c = f['a'];
|
// Symbol c = f['a'];
|
||||||
|
|
||||||
// Look into using signed distance fields for texture map generation ? anti-aliasing for text
|
// Look into using signed distance fields for texture map generation ? anti-aliasing for text
|
||||||
// https://youtu.be/d8cfgcJR9Tk
|
// https://youtu.be/d8cfgcJR9Tk
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 Riyyi
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "glad/glad.h"
|
||||||
|
#include "ruc/format/log.h"
|
||||||
|
|
||||||
|
#include "inferno/render/buffer.h"
|
||||||
|
#include "inferno/render/render-command.h"
|
||||||
|
|
||||||
|
namespace Inferno {
|
||||||
|
|
||||||
|
void RenderCommand::initialize()
|
||||||
|
{
|
||||||
|
setDepthTest(true);
|
||||||
|
|
||||||
|
// Enable transparency
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
|
||||||
|
ruc::info("RenderCommand initialized");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderCommand::destroy()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderCommand::clear()
|
||||||
|
{
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderCommand::clearColor(const glm::vec4& color)
|
||||||
|
{
|
||||||
|
glClearColor(color.r, color.g, color.b, color.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderCommand::drawIndexed(const VertexArray& vertexArray, uint32_t indexCount)
|
||||||
|
{
|
||||||
|
uint32_t count = indexCount ? indexCount : vertexArray.getIndexBuffer()->getCount();
|
||||||
|
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderCommand::setViewport(int32_t x, int32_t y, uint32_t width, uint32_t height)
|
||||||
|
{
|
||||||
|
glViewport(x, y, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderCommand::setDepthTest(bool enabled)
|
||||||
|
{
|
||||||
|
// Set z-buffer / depth buffer
|
||||||
|
enabled ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RenderCommand::depthTest()
|
||||||
|
{
|
||||||
|
unsigned char depthTest = GL_FALSE;
|
||||||
|
glGetBooleanv(GL_DEPTH_TEST, &depthTest);
|
||||||
|
return depthTest == GL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t RenderCommand::textureUnitAmount()
|
||||||
|
{
|
||||||
|
int32_t amount = 0;
|
||||||
|
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &amount);
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Inferno
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 Riyyi
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "glm/ext/matrix_float4x4.hpp" // glm::mat4
|
||||||
|
|
||||||
|
namespace Inferno {
|
||||||
|
|
||||||
|
class VertexArray;
|
||||||
|
|
||||||
|
class RenderCommand {
|
||||||
|
public:
|
||||||
|
static void initialize();
|
||||||
|
static void destroy();
|
||||||
|
|
||||||
|
static void clear();
|
||||||
|
static void clearColor(const glm::vec4& color);
|
||||||
|
static void drawIndexed(const VertexArray& vertexArray, uint32_t indexCount = 0);
|
||||||
|
|
||||||
|
static void setViewport(int32_t x, int32_t y, uint32_t width, uint32_t height);
|
||||||
|
static void setDepthTest(bool enabled);
|
||||||
|
|
||||||
|
static bool depthTest();
|
||||||
|
static int32_t textureUnitAmount();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Inferno
|
||||||
+170
-339
@@ -10,176 +10,65 @@
|
|||||||
#include "glad/glad.h"
|
#include "glad/glad.h"
|
||||||
#include "ruc/format/log.h"
|
#include "ruc/format/log.h"
|
||||||
|
|
||||||
|
#include "inferno/component/transformcomponent.h"
|
||||||
#include "inferno/render/buffer.h"
|
#include "inferno/render/buffer.h"
|
||||||
|
#include "inferno/render/render-command.h"
|
||||||
#include "inferno/render/renderer.h"
|
#include "inferno/render/renderer.h"
|
||||||
#include "inferno/render/shader.h"
|
#include "inferno/render/shader.h"
|
||||||
#include "inferno/render/texture.h"
|
#include "inferno/render/texture.h"
|
||||||
|
|
||||||
namespace Inferno {
|
namespace Inferno {
|
||||||
|
|
||||||
void RenderCommand::initialize()
|
template<typename T>
|
||||||
{
|
void Renderer<T>::beginScene(glm::mat4, glm::mat4)
|
||||||
setDepthTest(true);
|
|
||||||
|
|
||||||
// Enable transparency
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
glEnable(GL_BLEND);
|
|
||||||
|
|
||||||
ruc::info("RenderCommand initialized");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderCommand::destroy()
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderCommand::clear()
|
template<typename T>
|
||||||
|
void Renderer<T>::endScene()
|
||||||
{
|
{
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
nextBatch();
|
||||||
}
|
|
||||||
|
|
||||||
void RenderCommand::clearColor(const glm::vec4& color)
|
|
||||||
{
|
|
||||||
glClearColor(color.r, color.g, color.b, color.a);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderCommand::drawIndexed(const VertexArray& vertexArray, uint32_t indexCount)
|
|
||||||
{
|
|
||||||
uint32_t count = indexCount ? indexCount : vertexArray.getIndexBuffer()->getCount();
|
|
||||||
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderCommand::setViewport(int32_t x, int32_t y, uint32_t width, uint32_t height)
|
|
||||||
{
|
|
||||||
glViewport(x, y, width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderCommand::setDepthTest(bool enabled)
|
|
||||||
{
|
|
||||||
// Set z-buffer / depth buffer
|
|
||||||
enabled ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RenderCommand::depthTest()
|
|
||||||
{
|
|
||||||
unsigned char depthTest = GL_FALSE;
|
|
||||||
glGetBooleanv(GL_DEPTH_TEST, &depthTest);
|
|
||||||
return depthTest == GL_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t RenderCommand::textureUnitAmount()
|
|
||||||
{
|
|
||||||
int32_t amount = 0;
|
|
||||||
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &amount);
|
|
||||||
return amount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
uint32_t Renderer::m_supportedTextureUnitPerBatch = 0;
|
template<typename T>
|
||||||
|
uint32_t Renderer<T>::m_maxSupportedTextureSlots = 0;
|
||||||
|
|
||||||
void Renderer::initialize()
|
template<typename T>
|
||||||
|
void Renderer<T>::initialize()
|
||||||
{
|
{
|
||||||
// Get amount of texture units supported by the GPU
|
// Get amount of texture units supported by the GPU
|
||||||
uint32_t constTextureUnitCount = textureUnitPerBatch;
|
|
||||||
uint32_t gpuTextureUnitCount = RenderCommand::textureUnitAmount();
|
uint32_t gpuTextureUnitCount = RenderCommand::textureUnitAmount();
|
||||||
m_supportedTextureUnitPerBatch = std::min(constTextureUnitCount, gpuTextureUnitCount);
|
m_maxSupportedTextureSlots = std::min(maxTextureSlots, gpuTextureUnitCount);
|
||||||
|
|
||||||
// Texture unit 0 is reserved for no texture
|
// Texture unit 0 is reserved for no texture
|
||||||
m_textureUnits[0] = nullptr;
|
m_textureSlots[0] = nullptr;
|
||||||
|
|
||||||
// Create texture unit samplers
|
// Create texture unit samplers
|
||||||
int32_t samplers[textureUnitPerBatch];
|
int32_t samplers[maxTextureSlots];
|
||||||
for (uint32_t i = 0; i < textureUnitPerBatch; i++) {
|
for (uint32_t i = 0; i < maxTextureSlots; i++) {
|
||||||
samplers[i] = i;
|
samplers[i] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create shader
|
// Create shader
|
||||||
loadShader();
|
loadShader();
|
||||||
m_shader->bind();
|
m_shader->bind();
|
||||||
m_shader->setInt("u_textures", samplers, textureUnitPerBatch);
|
m_shader->setInt("u_textures", samplers, maxTextureSlots);
|
||||||
m_shader->unbind();
|
m_shader->unbind();
|
||||||
|
|
||||||
// Create vertex array
|
// Create vertex array
|
||||||
m_vertexArray = std::make_shared<VertexArray>();
|
m_vertexArray = std::make_shared<VertexArray>();
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::destroy()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t Renderer::addTextureUnit(std::shared_ptr<Texture> texture)
|
|
||||||
{
|
|
||||||
if (texture == nullptr) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new batch if the texture unit limit has been reached
|
|
||||||
if (m_textureUnitIndex >= m_supportedTextureUnitPerBatch) {
|
|
||||||
nextBatch();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If texure was already added
|
|
||||||
for (uint32_t i = 1; i < m_textureUnitIndex; i++) {
|
|
||||||
if (m_textureUnits[i] == texture) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add texture
|
|
||||||
uint32_t textureUnitIndex = m_textureUnitIndex;
|
|
||||||
m_textureUnits[textureUnitIndex] = texture;
|
|
||||||
m_textureUnitIndex++;
|
|
||||||
|
|
||||||
return textureUnitIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::bind()
|
|
||||||
{
|
|
||||||
m_shader->bind();
|
|
||||||
|
|
||||||
for (uint32_t i = 1; i < m_textureUnitIndex; i++) {
|
|
||||||
m_textureUnits[i]->bind(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_vertexArray->bind();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::unbind()
|
|
||||||
{
|
|
||||||
m_vertexArray->unbind();
|
|
||||||
|
|
||||||
for (uint32_t i = 1; i < m_textureUnitIndex; i++) {
|
|
||||||
m_textureUnits[i]->unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_shader->unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
Renderer2D::Renderer2D(s)
|
|
||||||
{
|
|
||||||
Renderer::initialize();
|
|
||||||
|
|
||||||
// CPU
|
// CPU
|
||||||
// ---------------------------------
|
// ---------------------------------
|
||||||
|
|
||||||
// Create array for storing quads vertices
|
|
||||||
m_vertexBufferBase = std::make_unique<QuadVertex[]>(vertexCount);
|
|
||||||
m_vertexBufferPtr = m_vertexBufferBase.get();
|
|
||||||
|
|
||||||
// Set default quad vertex positions
|
|
||||||
m_vertexPositions[0] = { -0.5f, -0.5f, 0.0f, 1.0f };
|
|
||||||
m_vertexPositions[1] = { 0.5f, -0.5f, 0.0f, 1.0f };
|
|
||||||
m_vertexPositions[2] = { 0.5f, 0.5f, 0.0f, 1.0f };
|
|
||||||
m_vertexPositions[3] = { -0.5f, 0.5f, 0.0f, 1.0f };
|
|
||||||
|
|
||||||
// Generate indices
|
// Generate indices
|
||||||
|
|
||||||
uint32_t* indices = new uint32_t[indexCount];
|
uint32_t* indices = new uint32_t[maxIndices];
|
||||||
|
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
for (uint32_t i = 0; i < indexCount; i += indexPerQuad) {
|
for (uint32_t i = 0; i < maxIndices; i += indexPerQuad) {
|
||||||
indices[i + 0] = offset + 0;
|
indices[i + 0] = offset + 0;
|
||||||
indices[i + 1] = offset + 1;
|
indices[i + 1] = offset + 1;
|
||||||
indices[i + 2] = offset + 2;
|
indices[i + 2] = offset + 2;
|
||||||
@@ -193,8 +82,132 @@ Renderer2D::Renderer2D(s)
|
|||||||
// GPU
|
// GPU
|
||||||
// ---------------------------------
|
// ---------------------------------
|
||||||
|
|
||||||
|
// Create index buffer
|
||||||
|
auto indexBuffer = std::make_shared<IndexBuffer>(indices, sizeof(uint32_t) * maxIndices);
|
||||||
|
m_vertexArray->setIndexBuffer(indexBuffer);
|
||||||
|
delete[] indices;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void Renderer<T>::destroy()
|
||||||
|
{
|
||||||
|
delete[] m_vertexBufferBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
uint32_t Renderer<T>::addTextureUnit(std::shared_ptr<Texture> texture)
|
||||||
|
{
|
||||||
|
if (texture == nullptr) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new batch if the texture unit limit has been reached
|
||||||
|
if (m_textureSlotIndex >= m_maxSupportedTextureSlots) {
|
||||||
|
nextBatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If texure was already added
|
||||||
|
for (uint32_t i = 1; i < m_textureSlotIndex; i++) {
|
||||||
|
if (m_textureSlots[i] == texture) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add texture
|
||||||
|
uint32_t textureSlotIndex = m_textureSlotIndex;
|
||||||
|
m_textureSlots[textureSlotIndex] = texture;
|
||||||
|
m_textureSlotIndex++;
|
||||||
|
|
||||||
|
return textureSlotIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void Renderer<T>::bind()
|
||||||
|
{
|
||||||
|
m_shader->bind();
|
||||||
|
|
||||||
|
for (uint32_t i = 1; i < m_textureSlotIndex; i++) {
|
||||||
|
m_textureSlots[i]->bind(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_vertexArray->bind();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void Renderer<T>::unbind()
|
||||||
|
{
|
||||||
|
m_vertexArray->unbind();
|
||||||
|
|
||||||
|
for (uint32_t i = 1; i < m_textureSlotIndex; i++) {
|
||||||
|
m_textureSlots[i]->unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_shader->unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void Renderer<T>::flush()
|
||||||
|
{
|
||||||
|
if (m_quadIndex == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upload vertex data to GPU
|
||||||
|
m_vertexArray->at(0)->uploadData(
|
||||||
|
m_vertexBufferBase,
|
||||||
|
m_quadIndex * vertexPerQuad * sizeof(T));
|
||||||
|
|
||||||
|
bind();
|
||||||
|
|
||||||
|
// Render
|
||||||
|
bool depthTest = RenderCommand::depthTest();
|
||||||
|
RenderCommand::setDepthTest(m_enableDepthBuffer);
|
||||||
|
RenderCommand::drawIndexed(*m_vertexArray, m_quadIndex * indexPerQuad);
|
||||||
|
RenderCommand::setDepthTest(depthTest);
|
||||||
|
|
||||||
|
unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void Renderer<T>::startBatch()
|
||||||
|
{
|
||||||
|
m_quadIndex = 0;
|
||||||
|
m_vertexBufferPtr = m_vertexBufferBase;
|
||||||
|
|
||||||
|
m_textureSlotIndex = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void Renderer<T>::nextBatch()
|
||||||
|
{
|
||||||
|
flush();
|
||||||
|
startBatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
Renderer2D::Renderer2D(s)
|
||||||
|
{
|
||||||
|
Renderer::initialize();
|
||||||
|
|
||||||
|
// CPU
|
||||||
|
// ---------------------------------
|
||||||
|
|
||||||
|
// Create array for storing quads vertices
|
||||||
|
m_vertexBufferBase = new QuadVertex[maxVertices];
|
||||||
|
m_vertexBufferPtr = m_vertexBufferBase;
|
||||||
|
|
||||||
|
// Set default quad vertex positions
|
||||||
|
m_vertexPositions[0] = { -0.5f, -0.5f, 0.0f, 1.0f };
|
||||||
|
m_vertexPositions[1] = { 0.5f, -0.5f, 0.0f, 1.0f };
|
||||||
|
m_vertexPositions[2] = { 0.5f, 0.5f, 0.0f, 1.0f };
|
||||||
|
m_vertexPositions[3] = { -0.5f, 0.5f, 0.0f, 1.0f };
|
||||||
|
|
||||||
|
// GPU
|
||||||
|
// ---------------------------------
|
||||||
|
|
||||||
// Create vertex buffer
|
// Create vertex buffer
|
||||||
auto vertexBuffer = std::make_shared<VertexBuffer>(sizeof(QuadVertex) * vertexCount);
|
auto vertexBuffer = std::make_shared<VertexBuffer>(sizeof(QuadVertex) * maxVertices);
|
||||||
vertexBuffer->setLayout({
|
vertexBuffer->setLayout({
|
||||||
{ BufferElementType::Vec3, "a_position" },
|
{ BufferElementType::Vec3, "a_position" },
|
||||||
{ BufferElementType::Vec4, "a_color" },
|
{ BufferElementType::Vec4, "a_color" },
|
||||||
@@ -203,19 +216,9 @@ Renderer2D::Renderer2D(s)
|
|||||||
});
|
});
|
||||||
m_vertexArray->addVertexBuffer(vertexBuffer);
|
m_vertexArray->addVertexBuffer(vertexBuffer);
|
||||||
|
|
||||||
// Create index buffer
|
|
||||||
auto indexBuffer = std::make_shared<IndexBuffer>(indices, sizeof(uint32_t) * indexCount);
|
|
||||||
m_vertexArray->setIndexBuffer(indexBuffer);
|
|
||||||
delete[] indices;
|
|
||||||
|
|
||||||
ruc::info("Renderer2D initialized");
|
ruc::info("Renderer2D initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer2D::~Renderer2D()
|
|
||||||
{
|
|
||||||
Renderer::destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer2D::beginScene(glm::mat4 cameraProjection, glm::mat4 cameraView)
|
void Renderer2D::beginScene(glm::mat4 cameraProjection, glm::mat4 cameraView)
|
||||||
{
|
{
|
||||||
m_shader->bind();
|
m_shader->bind();
|
||||||
@@ -223,11 +226,6 @@ void Renderer2D::beginScene(glm::mat4 cameraProjection, glm::mat4 cameraView)
|
|||||||
m_shader->unbind();
|
m_shader->unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer2D::endScene()
|
|
||||||
{
|
|
||||||
nextBatch();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer2D::drawQuad(const TransformComponent& transform, glm::vec4 color)
|
void Renderer2D::drawQuad(const TransformComponent& transform, glm::vec4 color)
|
||||||
{
|
{
|
||||||
drawQuad(transform, color, nullptr);
|
drawQuad(transform, color, nullptr);
|
||||||
@@ -246,7 +244,7 @@ void Renderer2D::drawQuad(const TransformComponent& transform, glm::vec4 color,
|
|||||||
void Renderer2D::drawQuad(const TransformComponent& transform, glm::mat4 color, std::shared_ptr<Texture> texture)
|
void Renderer2D::drawQuad(const TransformComponent& transform, glm::mat4 color, std::shared_ptr<Texture> texture)
|
||||||
{
|
{
|
||||||
// Create a new batch if the quad limit has been reached
|
// Create a new batch if the quad limit has been reached
|
||||||
if (m_quadIndex >= quadCount) {
|
if (m_quadIndex >= maxQuads) {
|
||||||
nextBatch();
|
nextBatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,39 +274,6 @@ void Renderer2D::loadShader()
|
|||||||
m_shader = ShaderManager::the().load("assets/glsl/batch-quad");
|
m_shader = ShaderManager::the().load("assets/glsl/batch-quad");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer2D::flush()
|
|
||||||
{
|
|
||||||
if (m_quadIndex == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Upload vertex data to GPU
|
|
||||||
m_vertexArray->getVertexBuffers().at(0)->uploadData(
|
|
||||||
m_vertexBufferBase.get(),
|
|
||||||
m_quadIndex * vertexPerQuad * sizeof(QuadVertex));
|
|
||||||
|
|
||||||
bind();
|
|
||||||
|
|
||||||
// Render
|
|
||||||
RenderCommand::drawIndexed(*m_vertexArray, m_quadIndex * indexPerQuad);
|
|
||||||
|
|
||||||
unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer2D::startBatch()
|
|
||||||
{
|
|
||||||
m_quadIndex = 0;
|
|
||||||
m_vertexBufferPtr = m_vertexBufferBase.get();
|
|
||||||
|
|
||||||
m_textureUnitIndex = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer2D::nextBatch()
|
|
||||||
{
|
|
||||||
flush();
|
|
||||||
startBatch();
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
RendererCubemap::RendererCubemap(s)
|
RendererCubemap::RendererCubemap(s)
|
||||||
@@ -319,8 +284,8 @@ RendererCubemap::RendererCubemap(s)
|
|||||||
// ---------------------------------
|
// ---------------------------------
|
||||||
|
|
||||||
// Create array for storing quads vertices
|
// Create array for storing quads vertices
|
||||||
m_vertexBufferBase = std::make_unique<CubemapVertex[]>(vertexCount);
|
m_vertexBufferBase = new CubemapVertex[maxVertices];
|
||||||
m_vertexBufferPtr = m_vertexBufferBase.get();
|
m_vertexBufferPtr = m_vertexBufferBase;
|
||||||
|
|
||||||
// Set default cubemap vertex positions
|
// Set default cubemap vertex positions
|
||||||
|
|
||||||
@@ -360,27 +325,13 @@ RendererCubemap::RendererCubemap(s)
|
|||||||
m_vertexPositions[22] = { 0.5f, -0.5f, 0.5f, 1.0f };
|
m_vertexPositions[22] = { 0.5f, -0.5f, 0.5f, 1.0f };
|
||||||
m_vertexPositions[23] = { 0.5f, -0.5f, -0.5f, 1.0f };
|
m_vertexPositions[23] = { 0.5f, -0.5f, -0.5f, 1.0f };
|
||||||
|
|
||||||
// Generate indices
|
|
||||||
|
|
||||||
uint32_t* indices = new uint32_t[indexCount];
|
|
||||||
|
|
||||||
uint32_t offset = 0;
|
|
||||||
for (uint32_t i = 0; i < indexCount; i += indexPerQuad) {
|
|
||||||
indices[i + 0] = offset + 0;
|
|
||||||
indices[i + 1] = offset + 1;
|
|
||||||
indices[i + 2] = offset + 2;
|
|
||||||
indices[i + 3] = offset + 2;
|
|
||||||
indices[i + 4] = offset + 3;
|
|
||||||
indices[i + 5] = offset + 0;
|
|
||||||
|
|
||||||
offset += vertexPerQuad;
|
|
||||||
}
|
|
||||||
|
|
||||||
// GPU
|
// GPU
|
||||||
// ---------------------------------
|
// ---------------------------------
|
||||||
|
|
||||||
|
m_enableDepthBuffer = false;
|
||||||
|
|
||||||
// Create vertex buffer
|
// Create vertex buffer
|
||||||
auto vertexBuffer = std::make_shared<VertexBuffer>(sizeof(CubemapVertex) * vertexCount);
|
auto vertexBuffer = std::make_shared<VertexBuffer>(sizeof(CubemapVertex) * maxVertices);
|
||||||
vertexBuffer->setLayout({
|
vertexBuffer->setLayout({
|
||||||
{ BufferElementType::Vec3, "a_position" },
|
{ BufferElementType::Vec3, "a_position" },
|
||||||
{ BufferElementType::Vec4, "a_color" },
|
{ BufferElementType::Vec4, "a_color" },
|
||||||
@@ -388,19 +339,9 @@ RendererCubemap::RendererCubemap(s)
|
|||||||
});
|
});
|
||||||
m_vertexArray->addVertexBuffer(vertexBuffer);
|
m_vertexArray->addVertexBuffer(vertexBuffer);
|
||||||
|
|
||||||
// Create index buffer
|
|
||||||
auto indexBuffer = std::make_shared<IndexBuffer>(indices, sizeof(uint32_t) * indexCount);
|
|
||||||
m_vertexArray->setIndexBuffer(indexBuffer);
|
|
||||||
delete[] indices;
|
|
||||||
|
|
||||||
ruc::info("RendererCubemap initialized");
|
ruc::info("RendererCubemap initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
RendererCubemap::~RendererCubemap()
|
|
||||||
{
|
|
||||||
Renderer::destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RendererCubemap::beginScene(glm::mat4 cameraProjection, glm::mat4 cameraView)
|
void RendererCubemap::beginScene(glm::mat4 cameraProjection, glm::mat4 cameraView)
|
||||||
{
|
{
|
||||||
// We want the skybox fixed in position, so only retain the rotation and scale.
|
// We want the skybox fixed in position, so only retain the rotation and scale.
|
||||||
@@ -416,11 +357,6 @@ void RendererCubemap::beginScene(glm::mat4 cameraProjection, glm::mat4 cameraVie
|
|||||||
m_shader->unbind();
|
m_shader->unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererCubemap::endScene()
|
|
||||||
{
|
|
||||||
nextBatch();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RendererCubemap::drawCubemap(const TransformComponent& transform, glm::vec4 color, std::shared_ptr<Texture> texture)
|
void RendererCubemap::drawCubemap(const TransformComponent& transform, glm::vec4 color, std::shared_ptr<Texture> texture)
|
||||||
{
|
{
|
||||||
drawCubemap(transform, glm::mat4(color, color, color, color), texture);
|
drawCubemap(transform, glm::mat4(color, color, color, color), texture);
|
||||||
@@ -429,13 +365,13 @@ void RendererCubemap::drawCubemap(const TransformComponent& transform, glm::vec4
|
|||||||
void RendererCubemap::drawCubemap(const TransformComponent& transform, glm::mat4 color, std::shared_ptr<Texture> texture)
|
void RendererCubemap::drawCubemap(const TransformComponent& transform, glm::mat4 color, std::shared_ptr<Texture> texture)
|
||||||
{
|
{
|
||||||
// Create a new batch if the quad limit has been reached
|
// Create a new batch if the quad limit has been reached
|
||||||
if (m_quadIndex >= quadCount) {
|
if (m_quadIndex >= maxQuads) {
|
||||||
nextBatch();
|
nextBatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t textureUnitIndex = addTextureUnit(texture);
|
uint32_t textureUnitIndex = addTextureUnit(texture);
|
||||||
|
|
||||||
// Add the quads 4 vertices
|
// Add the quads 4 vertices, 6 times, once per cube side
|
||||||
for (uint32_t i = 0; i < vertexPerQuad * quadPerCube; i++) {
|
for (uint32_t i = 0; i < vertexPerQuad * quadPerCube; i++) {
|
||||||
m_vertexBufferPtr->position = transform.transform * m_vertexPositions[i];
|
m_vertexBufferPtr->position = transform.transform * m_vertexPositions[i];
|
||||||
m_vertexBufferPtr->color = color[i % 4];
|
m_vertexBufferPtr->color = color[i % 4];
|
||||||
@@ -451,45 +387,9 @@ void RendererCubemap::loadShader()
|
|||||||
m_shader = ShaderManager::the().load("assets/glsl/batch-cubemap");
|
m_shader = ShaderManager::the().load("assets/glsl/batch-cubemap");
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererCubemap::flush()
|
|
||||||
{
|
|
||||||
if (m_quadIndex == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Upload vertex data to GPU
|
|
||||||
m_vertexArray->getVertexBuffers().at(0)->uploadData(
|
|
||||||
m_vertexBufferBase.get(),
|
|
||||||
m_quadIndex * vertexPerQuad * sizeof(CubemapVertex));
|
|
||||||
|
|
||||||
bind();
|
|
||||||
|
|
||||||
// Render
|
|
||||||
bool depthTest = RenderCommand::depthTest();
|
|
||||||
RenderCommand::setDepthTest(false);
|
|
||||||
RenderCommand::drawIndexed(*m_vertexArray, m_quadIndex * indexPerQuad);
|
|
||||||
RenderCommand::setDepthTest(depthTest);
|
|
||||||
|
|
||||||
unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RendererCubemap::startBatch()
|
|
||||||
{
|
|
||||||
m_quadIndex = 0;
|
|
||||||
m_vertexBufferPtr = m_vertexBufferBase.get();
|
|
||||||
|
|
||||||
m_textureUnitIndex = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RendererCubemap::nextBatch()
|
|
||||||
{
|
|
||||||
flush();
|
|
||||||
startBatch();
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
RendererCharacter::RendererCharacter(s)
|
RendererFont::RendererFont(s)
|
||||||
{
|
{
|
||||||
Renderer::initialize();
|
Renderer::initialize();
|
||||||
|
|
||||||
@@ -497,30 +397,16 @@ RendererCharacter::RendererCharacter(s)
|
|||||||
// ---------------------------------
|
// ---------------------------------
|
||||||
|
|
||||||
// Create array for storing quads vertices
|
// Create array for storing quads vertices
|
||||||
m_vertexBufferBase = std::make_unique<CharacterVertex[]>(vertexCount);
|
m_vertexBufferBase = new SymbolVertex[maxVertices];
|
||||||
m_vertexBufferPtr = m_vertexBufferBase.get();
|
m_vertexBufferPtr = m_vertexBufferBase;
|
||||||
|
|
||||||
// Generate indices
|
|
||||||
|
|
||||||
uint32_t* indices = new uint32_t[indexCount];
|
|
||||||
|
|
||||||
uint32_t offset = 0;
|
|
||||||
for (uint32_t i = 0; i < indexCount; i += indexPerQuad) {
|
|
||||||
indices[i + 0] = offset + 0;
|
|
||||||
indices[i + 1] = offset + 1;
|
|
||||||
indices[i + 2] = offset + 2;
|
|
||||||
indices[i + 3] = offset + 2;
|
|
||||||
indices[i + 4] = offset + 3;
|
|
||||||
indices[i + 5] = offset + 0;
|
|
||||||
|
|
||||||
offset += vertexPerQuad;
|
|
||||||
}
|
|
||||||
|
|
||||||
// GPU
|
// GPU
|
||||||
// ---------------------------------
|
// ---------------------------------
|
||||||
|
|
||||||
|
m_enableDepthBuffer = false;
|
||||||
|
|
||||||
// Create vertex buffer
|
// Create vertex buffer
|
||||||
auto vertexBuffer = std::make_shared<VertexBuffer>(sizeof(CharacterVertex) * vertexCount);
|
auto vertexBuffer = std::make_shared<VertexBuffer>(sizeof(SymbolVertex) * maxVertices);
|
||||||
vertexBuffer->setLayout({
|
vertexBuffer->setLayout({
|
||||||
{ BufferElementType::Vec3, "a_position" },
|
{ BufferElementType::Vec3, "a_position" },
|
||||||
{ BufferElementType::Vec4, "a_color" },
|
{ BufferElementType::Vec4, "a_color" },
|
||||||
@@ -535,32 +421,13 @@ RendererCharacter::RendererCharacter(s)
|
|||||||
});
|
});
|
||||||
m_vertexArray->addVertexBuffer(vertexBuffer);
|
m_vertexArray->addVertexBuffer(vertexBuffer);
|
||||||
|
|
||||||
// Create index buffer
|
ruc::info("RendererFont initialized");
|
||||||
auto indexBuffer = std::make_shared<IndexBuffer>(indices, sizeof(uint32_t) * indexCount);
|
|
||||||
m_vertexArray->setIndexBuffer(indexBuffer);
|
|
||||||
delete[] indices;
|
|
||||||
|
|
||||||
ruc::info("RendererCharacter initialized");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RendererCharacter::~RendererCharacter()
|
void RendererFont::drawSymbol(std::array<SymbolVertex, vertexPerQuad>& symbolQuad, std::shared_ptr<Texture> texture)
|
||||||
{
|
|
||||||
Renderer::destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RendererCharacter::beginScene()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void RendererCharacter::endScene()
|
|
||||||
{
|
|
||||||
nextBatch();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RendererCharacter::drawCharacter(std::array<CharacterVertex, vertexPerQuad>& characterQuad, std::shared_ptr<Texture> texture)
|
|
||||||
{
|
{
|
||||||
// Create a new batch if the quad limit has been reached
|
// Create a new batch if the quad limit has been reached
|
||||||
if (m_quadIndex >= quadCount) {
|
if (m_quadIndex >= maxQuads) {
|
||||||
nextBatch();
|
nextBatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -568,17 +435,17 @@ void RendererCharacter::drawCharacter(std::array<CharacterVertex, vertexPerQuad>
|
|||||||
|
|
||||||
// Add the quads 4 vertices
|
// Add the quads 4 vertices
|
||||||
for (uint32_t i = 0; i < vertexPerQuad; i++) {
|
for (uint32_t i = 0; i < vertexPerQuad; i++) {
|
||||||
m_vertexBufferPtr->quad.position = characterQuad[i].quad.position;
|
m_vertexBufferPtr->quad.position = symbolQuad[i].quad.position;
|
||||||
m_vertexBufferPtr->quad.color = characterQuad[i].quad.color;
|
m_vertexBufferPtr->quad.color = symbolQuad[i].quad.color;
|
||||||
m_vertexBufferPtr->quad.textureCoordinates = characterQuad[i].quad.textureCoordinates;
|
m_vertexBufferPtr->quad.textureCoordinates = symbolQuad[i].quad.textureCoordinates;
|
||||||
m_vertexBufferPtr->quad.textureIndex = (float)textureUnitIndex;
|
m_vertexBufferPtr->quad.textureIndex = (float)textureUnitIndex;
|
||||||
|
|
||||||
m_vertexBufferPtr->width = characterQuad[i].width;
|
m_vertexBufferPtr->width = symbolQuad[i].width;
|
||||||
m_vertexBufferPtr->edge = characterQuad[i].edge;
|
m_vertexBufferPtr->edge = symbolQuad[i].edge;
|
||||||
m_vertexBufferPtr->borderWidth = characterQuad[i].borderWidth;
|
m_vertexBufferPtr->borderWidth = symbolQuad[i].borderWidth;
|
||||||
m_vertexBufferPtr->borderEdge = characterQuad[i].borderEdge;
|
m_vertexBufferPtr->borderEdge = symbolQuad[i].borderEdge;
|
||||||
m_vertexBufferPtr->borderColor = characterQuad[i].borderColor;
|
m_vertexBufferPtr->borderColor = symbolQuad[i].borderColor;
|
||||||
m_vertexBufferPtr->offset = characterQuad[i].offset;
|
m_vertexBufferPtr->offset = symbolQuad[i].offset;
|
||||||
|
|
||||||
m_vertexBufferPtr++;
|
m_vertexBufferPtr++;
|
||||||
}
|
}
|
||||||
@@ -586,45 +453,9 @@ void RendererCharacter::drawCharacter(std::array<CharacterVertex, vertexPerQuad>
|
|||||||
m_quadIndex++;
|
m_quadIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererCharacter::loadShader()
|
void RendererFont::loadShader()
|
||||||
{
|
{
|
||||||
m_shader = ShaderManager::the().load("assets/glsl/batch-font");
|
m_shader = ShaderManager::the().load("assets/glsl/batch-font");
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererCharacter::flush()
|
|
||||||
{
|
|
||||||
if (m_quadIndex == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Upload vertex data to GPU
|
|
||||||
m_vertexArray->getVertexBuffers().at(0)->uploadData(
|
|
||||||
m_vertexBufferBase.get(),
|
|
||||||
m_quadIndex * vertexPerQuad * sizeof(CharacterVertex));
|
|
||||||
|
|
||||||
bind();
|
|
||||||
|
|
||||||
// Render
|
|
||||||
bool depthTest = RenderCommand::depthTest();
|
|
||||||
RenderCommand::setDepthTest(false);
|
|
||||||
RenderCommand::drawIndexed(*m_vertexArray, m_quadIndex * indexPerQuad);
|
|
||||||
RenderCommand::setDepthTest(depthTest);
|
|
||||||
|
|
||||||
unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RendererCharacter::startBatch()
|
|
||||||
{
|
|
||||||
m_quadIndex = 0;
|
|
||||||
m_vertexBufferPtr = m_vertexBufferBase.get();
|
|
||||||
|
|
||||||
m_textureUnitIndex = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RendererCharacter::nextBatch()
|
|
||||||
{
|
|
||||||
flush();
|
|
||||||
startBatch();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Inferno
|
} // namespace Inferno
|
||||||
|
|||||||
@@ -15,28 +15,27 @@
|
|||||||
#include "glm/ext/vector_float4.hpp" // glm::vec4
|
#include "glm/ext/vector_float4.hpp" // glm::vec4
|
||||||
#include "ruc/singleton.h"
|
#include "ruc/singleton.h"
|
||||||
|
|
||||||
#include "inferno/component/transformcomponent.h"
|
|
||||||
|
|
||||||
namespace Inferno {
|
namespace Inferno {
|
||||||
|
|
||||||
class Shader;
|
class Shader;
|
||||||
class Texture;
|
class Texture;
|
||||||
|
class TransformComponent;
|
||||||
class VertexArray;
|
class VertexArray;
|
||||||
|
|
||||||
struct QuadVertex {
|
struct QuadVertex {
|
||||||
glm::vec3 position { 0.0f, 0.0f, 0.0f };
|
glm::vec3 position { 0.0f, 0.0f, 0.0f };
|
||||||
glm::vec4 color { 1.0f, 1.0f, 1.0f, 1.0f };
|
glm::vec4 color { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
glm::vec2 textureCoordinates { 0.0f, 0.0f };
|
glm::vec2 textureCoordinates { 0.0f, 0.0f };
|
||||||
float textureIndex = 0; // TODO: get int to pass to fragment correctly
|
float textureIndex = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CubemapVertex {
|
struct CubemapVertex {
|
||||||
glm::vec3 position { 0.0f, 0.0f, 0.0f };
|
glm::vec3 position { 0.0f, 0.0f, 0.0f };
|
||||||
glm::vec4 color { 1.0f, 1.0f, 1.0f, 1.0f };
|
glm::vec4 color { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
float textureIndex = 0; // TODO: get int to pass to fragment correctly
|
float textureIndex = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CharacterVertex {
|
struct SymbolVertex {
|
||||||
QuadVertex quad;
|
QuadVertex quad;
|
||||||
|
|
||||||
// Font
|
// Font
|
||||||
@@ -52,33 +51,25 @@ struct CharacterVertex {
|
|||||||
|
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
|
|
||||||
class RenderCommand {
|
template<typename T>
|
||||||
public:
|
|
||||||
static void initialize();
|
|
||||||
static void destroy();
|
|
||||||
|
|
||||||
static void clear();
|
|
||||||
static void clearColor(const glm::vec4& color);
|
|
||||||
static void drawIndexed(const VertexArray& vertexArray, uint32_t indexCount = 0);
|
|
||||||
|
|
||||||
static void setViewport(int32_t x, int32_t y, uint32_t width, uint32_t height);
|
|
||||||
static void setDepthTest(bool enabled);
|
|
||||||
|
|
||||||
static bool depthTest();
|
|
||||||
static int32_t textureUnitAmount();
|
|
||||||
};
|
|
||||||
|
|
||||||
// -------------------------------------
|
|
||||||
|
|
||||||
class Renderer {
|
class Renderer {
|
||||||
public:
|
public:
|
||||||
static constexpr const uint32_t vertexPerQuad = 4;
|
static constexpr const uint32_t vertexPerQuad = 4;
|
||||||
static constexpr const uint32_t indexPerQuad = 6;
|
static constexpr const uint32_t indexPerQuad = 6;
|
||||||
static constexpr const uint32_t quadPerCube = 6;
|
static constexpr const uint32_t quadPerCube = 6;
|
||||||
static constexpr const uint32_t textureUnitPerBatch = 32;
|
|
||||||
|
// When to start a new batch
|
||||||
|
static constexpr const uint32_t maxQuads = 20000;
|
||||||
|
static constexpr const uint32_t maxVertices = maxQuads * vertexPerQuad;
|
||||||
|
static constexpr const uint32_t maxIndices = maxQuads * indexPerQuad;
|
||||||
|
static constexpr const uint32_t maxTextureSlots = 32;
|
||||||
|
|
||||||
|
virtual void beginScene(glm::mat4 cameraProjection, glm::mat4 cameraView);
|
||||||
|
virtual void endScene();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Renderer() {}
|
Renderer() {}
|
||||||
|
virtual ~Renderer() { destroy(); };
|
||||||
|
|
||||||
void initialize();
|
void initialize();
|
||||||
void destroy();
|
void destroy();
|
||||||
@@ -87,41 +78,47 @@ protected:
|
|||||||
|
|
||||||
void bind();
|
void bind();
|
||||||
void unbind();
|
void unbind();
|
||||||
virtual void loadShader() = 0;
|
|
||||||
virtual void flush() = 0;
|
|
||||||
virtual void startBatch() = 0;
|
|
||||||
virtual void nextBatch() = 0;
|
|
||||||
|
|
||||||
uint32_t m_quadIndex = 0;
|
virtual void loadShader() = 0;
|
||||||
|
virtual void flush();
|
||||||
|
virtual void startBatch();
|
||||||
|
virtual void nextBatch();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// CPU quad vertices
|
||||||
|
uint32_t m_quadIndex { 0 };
|
||||||
|
T* m_vertexBufferBase { nullptr };
|
||||||
|
T* m_vertexBufferPtr { nullptr };
|
||||||
|
|
||||||
// Texture units
|
// Texture units
|
||||||
static uint32_t m_supportedTextureUnitPerBatch;
|
static uint32_t m_maxSupportedTextureSlots;
|
||||||
uint32_t m_textureUnitIndex = 1;
|
uint32_t m_textureSlotIndex { 1 };
|
||||||
std::array<std::shared_ptr<Texture>, textureUnitPerBatch> m_textureUnits;
|
std::array<std::shared_ptr<Texture>, maxTextureSlots> m_textureSlots;
|
||||||
|
|
||||||
// GPU objects
|
// GPU objects
|
||||||
|
bool m_enableDepthBuffer { true };
|
||||||
std::shared_ptr<Shader> m_shader;
|
std::shared_ptr<Shader> m_shader;
|
||||||
std::shared_ptr<VertexArray> m_vertexArray;
|
std::shared_ptr<VertexArray> m_vertexArray;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TOOD:
|
||||||
|
// - Deduplicate flush()
|
||||||
|
// v Add bool for disabling depth buffer
|
||||||
|
// - Add Size for uploadData (this is prob not needed, we got T already)
|
||||||
|
// - Decide if its worth to remove template<T> from Renderer, just cast vertexBufferPtr before usage
|
||||||
|
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
|
|
||||||
class Renderer2D final
|
class Renderer2D final
|
||||||
: public Renderer
|
: public Renderer<QuadVertex>
|
||||||
, public ruc::Singleton<Renderer2D> {
|
, public ruc::Singleton<Renderer2D> {
|
||||||
public:
|
public:
|
||||||
Renderer2D(s);
|
Renderer2D(s);
|
||||||
virtual ~Renderer2D();
|
virtual ~Renderer2D() {};
|
||||||
|
|
||||||
using Singleton<Renderer2D>::destroy;
|
using Singleton<Renderer2D>::destroy;
|
||||||
|
|
||||||
// When to start a new batch
|
virtual void beginScene(glm::mat4 cameraProjection, glm::mat4 cameraView) override;
|
||||||
static constexpr const uint32_t quadCount = 1000;
|
|
||||||
static constexpr const uint32_t vertexCount = quadCount * vertexPerQuad;
|
|
||||||
static constexpr const uint32_t indexCount = quadCount * indexPerQuad;
|
|
||||||
|
|
||||||
void beginScene(glm::mat4 cameraProjectionView, glm::mat4 cameraView);
|
|
||||||
void endScene();
|
|
||||||
|
|
||||||
void drawQuad(const TransformComponent& transform, glm::vec4 color);
|
void drawQuad(const TransformComponent& transform, glm::vec4 color);
|
||||||
void drawQuad(const TransformComponent& transform, glm::mat4 color);
|
void drawQuad(const TransformComponent& transform, glm::mat4 color);
|
||||||
@@ -130,13 +127,6 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void loadShader() override;
|
void loadShader() override;
|
||||||
void flush() override;
|
|
||||||
void startBatch() override;
|
|
||||||
void nextBatch() override;
|
|
||||||
|
|
||||||
// CPU quad vertices
|
|
||||||
std::unique_ptr<QuadVertex[]> m_vertexBufferBase;
|
|
||||||
QuadVertex* m_vertexBufferPtr { nullptr };
|
|
||||||
|
|
||||||
// Default quad vertex positions
|
// Default quad vertex positions
|
||||||
glm::vec4 m_vertexPositions[vertexPerQuad];
|
glm::vec4 m_vertexPositions[vertexPerQuad];
|
||||||
@@ -144,35 +134,21 @@ private:
|
|||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
|
|
||||||
class RendererCubemap final
|
class RendererCubemap final
|
||||||
: public Renderer
|
: public Renderer<CubemapVertex>
|
||||||
, public ruc::Singleton<RendererCubemap> {
|
, public ruc::Singleton<RendererCubemap> {
|
||||||
public:
|
public:
|
||||||
RendererCubemap(s);
|
RendererCubemap(s);
|
||||||
virtual ~RendererCubemap();
|
virtual ~RendererCubemap() {};
|
||||||
|
|
||||||
using Singleton<RendererCubemap>::destroy;
|
using Singleton<RendererCubemap>::destroy;
|
||||||
|
|
||||||
// When to start a new batch
|
virtual void beginScene(glm::mat4 cameraProjection, glm::mat4 cameraView) override;
|
||||||
static constexpr const uint32_t cubemapCount = 166;
|
|
||||||
static constexpr const uint32_t quadCount = cubemapCount * quadPerCube;
|
|
||||||
static constexpr const uint32_t vertexCount = quadCount * vertexPerQuad;
|
|
||||||
static constexpr const uint32_t indexCount = quadCount * indexPerQuad;
|
|
||||||
|
|
||||||
void beginScene(glm::mat4 cameraProjectionView, glm::mat4 cameraView);
|
|
||||||
void endScene();
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void loadShader() override;
|
void loadShader() override;
|
||||||
void flush() override;
|
|
||||||
void startBatch() override;
|
|
||||||
void nextBatch() override;
|
|
||||||
|
|
||||||
// CPU quad vertices
|
|
||||||
std::unique_ptr<CubemapVertex[]> m_vertexBufferBase;
|
|
||||||
CubemapVertex* m_vertexBufferPtr { nullptr };
|
|
||||||
|
|
||||||
// Default cubemap vertex positions
|
// Default cubemap vertex positions
|
||||||
glm::vec4 m_vertexPositions[vertexPerQuad * quadPerCube];
|
glm::vec4 m_vertexPositions[vertexPerQuad * quadPerCube];
|
||||||
@@ -180,33 +156,19 @@ private:
|
|||||||
|
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
|
|
||||||
class RendererCharacter final
|
class RendererFont final
|
||||||
: public Renderer
|
: public Renderer<SymbolVertex>
|
||||||
, public ruc::Singleton<RendererCharacter> {
|
, public ruc::Singleton<RendererFont> {
|
||||||
public:
|
public:
|
||||||
RendererCharacter(s);
|
RendererFont(s);
|
||||||
virtual ~RendererCharacter();
|
virtual ~RendererFont() {};
|
||||||
|
|
||||||
using Singleton<RendererCharacter>::destroy;
|
using Singleton<RendererFont>::destroy;
|
||||||
|
|
||||||
static const uint32_t quadCount = 1000;
|
void drawSymbol(std::array<SymbolVertex, vertexPerQuad>& symbolQuad, std::shared_ptr<Texture> texture);
|
||||||
static const uint32_t vertexCount = quadCount * vertexPerQuad;
|
|
||||||
static const uint32_t indexCount = quadCount * indexPerQuad;
|
|
||||||
|
|
||||||
void beginScene();
|
|
||||||
void endScene();
|
|
||||||
|
|
||||||
void drawCharacter(std::array<CharacterVertex, vertexPerQuad>& characterQuad, std::shared_ptr<Texture> texture);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void loadShader() override;
|
void loadShader() override;
|
||||||
void flush() override;
|
|
||||||
void startBatch() override;
|
|
||||||
void nextBatch() override;
|
|
||||||
|
|
||||||
// CPU quad vertices
|
|
||||||
std::unique_ptr<CharacterVertex[]> m_vertexBufferBase;
|
|
||||||
CharacterVertex* m_vertexBufferPtr { nullptr };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Inferno
|
} // namespace Inferno
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 Riyyi
|
* Copyright (C) 2022-2024 Riyyi
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "inferno/application.h"
|
#include "inferno/application.h"
|
||||||
#include "inferno/component/textareacomponent.h"
|
#include "inferno/component/textareacomponent.h"
|
||||||
|
#include "inferno/component/transformcomponent.h"
|
||||||
#include "inferno/render/font.h"
|
#include "inferno/render/font.h"
|
||||||
#include "inferno/render/renderer.h"
|
#include "inferno/render/renderer.h"
|
||||||
#include "inferno/render/texture.h"
|
#include "inferno/render/texture.h"
|
||||||
@@ -42,19 +43,19 @@ void TextAreaSystem::render()
|
|||||||
// Loop through textareas content
|
// Loop through textareas content
|
||||||
// Linebreak if width reached
|
// Linebreak if width reached
|
||||||
// Break if lines AND width reached
|
// Break if lines AND width reached
|
||||||
// Calculate character quad
|
// Calculate symbol quad
|
||||||
// Submit character quad for rendering
|
// Submit symbol quad for rendering
|
||||||
|
|
||||||
std::shared_ptr<Font> font = FontManager::the().load(textarea.font);
|
std::shared_ptr<Font> font = FontManager::the().load(textarea.font);
|
||||||
// glm::mat4 translate = transform.translate;
|
// glm::mat4 translate = transform.translate;
|
||||||
|
|
||||||
m_characters.clear();
|
m_symbols.clear();
|
||||||
createLines(font, textarea);
|
createLines(font, textarea);
|
||||||
createQuads(font, textarea);
|
createQuads(font, textarea);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using Characters = std::vector<std::shared_ptr<Character>>;
|
using Symbols = std::vector<std::shared_ptr<Symbol>>;
|
||||||
|
|
||||||
void TextAreaSystem::createLines(std::shared_ptr<Font> font, const TextAreaComponent& textarea)
|
void TextAreaSystem::createLines(std::shared_ptr<Font> font, const TextAreaComponent& textarea)
|
||||||
{
|
{
|
||||||
@@ -73,9 +74,9 @@ void TextAreaSystem::createLines(std::shared_ptr<Font> font, const TextAreaCompo
|
|||||||
size_t spaceIndex = 0;
|
size_t spaceIndex = 0;
|
||||||
float lineWidth = 0.0f;
|
float lineWidth = 0.0f;
|
||||||
float lineWidthSinceLastSpace = 0.0f;
|
float lineWidthSinceLastSpace = 0.0f;
|
||||||
for (char character : textarea.content) {
|
for (char symbol : textarea.content) {
|
||||||
auto c = font->get(character);
|
auto c = font->get(symbol);
|
||||||
m_characters.push_back(c);
|
m_symbols.push_back(c);
|
||||||
|
|
||||||
// Kerning
|
// Kerning
|
||||||
char kerning = 0;
|
char kerning = 0;
|
||||||
@@ -86,18 +87,18 @@ void TextAreaSystem::createLines(std::shared_ptr<Font> font, const TextAreaCompo
|
|||||||
lineWidth += (c->advance + kerning) * fontScale;
|
lineWidth += (c->advance + kerning) * fontScale;
|
||||||
lineWidthSinceLastSpace += (c->advance + kerning) * fontScale;
|
lineWidthSinceLastSpace += (c->advance + kerning) * fontScale;
|
||||||
|
|
||||||
if (character == ' ') {
|
if (symbol == ' ') {
|
||||||
spaceIndex = m_characters.size() - 1;
|
spaceIndex = m_symbols.size() - 1;
|
||||||
lineWidthSinceLastSpace = 0;
|
lineWidthSinceLastSpace = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lineWidth > textureWidth) {
|
if (lineWidth > textureWidth) {
|
||||||
m_characters[spaceIndex] = nullptr;
|
m_symbols[spaceIndex] = nullptr;
|
||||||
lineWidth = 0;
|
lineWidth = 0;
|
||||||
lineWidth = lineWidthSinceLastSpace;
|
lineWidth = lineWidthSinceLastSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
previous = character;
|
previous = symbol;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,26 +109,26 @@ void TextAreaSystem::createQuads(std::shared_ptr<Font> font, const TextAreaCompo
|
|||||||
char previous = 0;
|
char previous = 0;
|
||||||
float advanceX = 0.0f;
|
float advanceX = 0.0f;
|
||||||
float advanceY = 0.0f;
|
float advanceY = 0.0f;
|
||||||
for (const auto& character : m_characters) {
|
for (const auto& symbol : m_symbols) {
|
||||||
// Go to the next line on "\n"
|
// Go to the next line on "\n"
|
||||||
if (character == nullptr) {
|
if (symbol == nullptr) {
|
||||||
advanceX = 0;
|
advanceX = 0;
|
||||||
advanceY -= (font->lineSpacing() * textarea.lineSpacing) * fontScale;
|
advanceY -= (font->lineSpacing() * textarea.lineSpacing) * fontScale;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<CharacterQuad> quad = calculateCharacterQuad(character, previous, font, fontScale, advanceX, advanceY);
|
std::optional<SymbolQuad> quad = calculateSymbolQuad(symbol, previous, font, fontScale, advanceX, advanceY);
|
||||||
if (quad) {
|
if (quad) {
|
||||||
RendererCharacter::the().drawCharacter(quad.value(), font->texture());
|
RendererFont::the().drawSymbol(quad.value(), font->texture());
|
||||||
}
|
}
|
||||||
|
|
||||||
previous = character->id;
|
previous = symbol->id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<CharacterQuad> TextAreaSystem::calculateCharacterQuad(std::shared_ptr<Character> c, char previous, std::shared_ptr<Font> font, float fontScale, float& advanceX, float& advanceY)
|
std::optional<SymbolQuad> TextAreaSystem::calculateSymbolQuad(std::shared_ptr<Symbol> c, char previous, std::shared_ptr<Font> font, float fontScale, float& advanceX, float& advanceY)
|
||||||
{
|
{
|
||||||
CharacterQuad characterQuad;
|
SymbolQuad symbolQuad;
|
||||||
|
|
||||||
// Texture
|
// Texture
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
@@ -136,7 +137,7 @@ std::optional<CharacterQuad> TextAreaSystem::calculateCharacterQuad(std::shared_
|
|||||||
float textureHeight = static_cast<float>(font->texture()->height());
|
float textureHeight = static_cast<float>(font->texture()->height());
|
||||||
VERIFY(textureWidth == textureHeight, "TextAreaSystem read invalid font texture");
|
VERIFY(textureWidth == textureHeight, "TextAreaSystem read invalid font texture");
|
||||||
|
|
||||||
// Skip empty characters (like space)
|
// Skip empty symbols (like space)
|
||||||
if (c->size.x == 0 || c->size.y == 0) {
|
if (c->size.x == 0 || c->size.y == 0) {
|
||||||
// Jump to the next glyph
|
// Jump to the next glyph
|
||||||
advanceX += c->advance * fontScale;
|
advanceX += c->advance * fontScale;
|
||||||
@@ -167,10 +168,10 @@ std::optional<CharacterQuad> TextAreaSystem::calculateCharacterQuad(std::shared_
|
|||||||
(cursorMax.y / textureHeight * 2) + 1,
|
(cursorMax.y / textureHeight * 2) + 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
characterQuad.at(0).quad.position = { cursorScreen.x, cursorScreenMax.y, 0.0f }; // bottom left
|
symbolQuad.at(0).quad.position = { cursorScreen.x, cursorScreenMax.y, 0.0f }; // bottom left
|
||||||
characterQuad.at(1).quad.position = { cursorScreenMax.x, cursorScreenMax.y, 0.0f }; // bottom right
|
symbolQuad.at(1).quad.position = { cursorScreenMax.x, cursorScreenMax.y, 0.0f }; // bottom right
|
||||||
characterQuad.at(2).quad.position = { cursorScreenMax.x, cursorScreen.y, 0.0f }; // top right
|
symbolQuad.at(2).quad.position = { cursorScreenMax.x, cursorScreen.y, 0.0f }; // top right
|
||||||
characterQuad.at(3).quad.position = { cursorScreen.x, cursorScreen.y, 0.0f }; // top left
|
symbolQuad.at(3).quad.position = { cursorScreen.x, cursorScreen.y, 0.0f }; // top left
|
||||||
|
|
||||||
// Jump to the next glyph
|
// Jump to the next glyph
|
||||||
advanceX += (c->advance + kerning) * fontScale;
|
advanceX += (c->advance + kerning) * fontScale;
|
||||||
@@ -187,12 +188,12 @@ std::optional<CharacterQuad> TextAreaSystem::calculateCharacterQuad(std::shared_
|
|||||||
(textureHeight - c->position.y) / textureHeight
|
(textureHeight - c->position.y) / textureHeight
|
||||||
};
|
};
|
||||||
|
|
||||||
characterQuad.at(0).quad.textureCoordinates = { x.x, y.x };
|
symbolQuad.at(0).quad.textureCoordinates = { x.x, y.x };
|
||||||
characterQuad.at(1).quad.textureCoordinates = { x.y, y.x };
|
symbolQuad.at(1).quad.textureCoordinates = { x.y, y.x };
|
||||||
characterQuad.at(2).quad.textureCoordinates = { x.y, y.y };
|
symbolQuad.at(2).quad.textureCoordinates = { x.y, y.y };
|
||||||
characterQuad.at(3).quad.textureCoordinates = { x.x, y.y };
|
symbolQuad.at(3).quad.textureCoordinates = { x.x, y.y };
|
||||||
|
|
||||||
return characterQuad;
|
return symbolQuad;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Inferno
|
} // namespace Inferno
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 Riyyi
|
* Copyright (C) 2022-2024 Riyyi
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
@@ -14,17 +14,16 @@
|
|||||||
#include "glm/ext/vector_float3.hpp" // glm::vec3
|
#include "glm/ext/vector_float3.hpp" // glm::vec3
|
||||||
#include "ruc/singleton.h"
|
#include "ruc/singleton.h"
|
||||||
|
|
||||||
#include "inferno/component/textareacomponent.h"
|
|
||||||
#include "inferno/render/font.h"
|
#include "inferno/render/font.h"
|
||||||
#include "inferno/render/renderer.h"
|
#include "inferno/render/renderer.h"
|
||||||
|
|
||||||
namespace Inferno {
|
namespace Inferno {
|
||||||
|
|
||||||
using Characters = std::vector<std::shared_ptr<Character>>;
|
using Symbols = std::vector<std::shared_ptr<Symbol>>;
|
||||||
using CharacterQuad = std::array<CharacterVertex, Renderer::vertexPerQuad>;
|
using SymbolQuad = std::array<SymbolVertex, Renderer<void>::vertexPerQuad>;
|
||||||
|
|
||||||
class Font;
|
|
||||||
class Scene;
|
class Scene;
|
||||||
|
class TextAreaComponent;
|
||||||
|
|
||||||
class TextAreaSystem final : public ruc::Singleton<TextAreaSystem> {
|
class TextAreaSystem final : public ruc::Singleton<TextAreaSystem> {
|
||||||
public:
|
public:
|
||||||
@@ -39,9 +38,9 @@ private:
|
|||||||
void createLines(std::shared_ptr<Font> font, const TextAreaComponent& textarea);
|
void createLines(std::shared_ptr<Font> font, const TextAreaComponent& textarea);
|
||||||
void createQuads(std::shared_ptr<Font> font, const TextAreaComponent& textarea);
|
void createQuads(std::shared_ptr<Font> font, const TextAreaComponent& textarea);
|
||||||
|
|
||||||
std::optional<CharacterQuad> calculateCharacterQuad(std::shared_ptr<Character> c, char previous, std::shared_ptr<Font> font, float fontSize, float& advanceX, float& advanceY);
|
std::optional<SymbolQuad> calculateSymbolQuad(std::shared_ptr<Symbol> c, char previous, std::shared_ptr<Font> font, float fontSize, float& advanceX, float& advanceY);
|
||||||
|
|
||||||
Characters m_characters;
|
Symbols m_symbols;
|
||||||
Scene* m_scene { nullptr };
|
Scene* m_scene { nullptr };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "inferno/io/input.h"
|
#include "inferno/io/input.h"
|
||||||
#include "inferno/keycodes.h"
|
#include "inferno/keycodes.h"
|
||||||
#include "inferno/render/context.h"
|
#include "inferno/render/context.h"
|
||||||
|
#include "inferno/render/render-command.h"
|
||||||
#include "inferno/render/renderer.h"
|
#include "inferno/render/renderer.h"
|
||||||
#include "inferno/settings.h"
|
#include "inferno/settings.h"
|
||||||
#include "inferno/window.h"
|
#include "inferno/window.h"
|
||||||
|
|||||||
Reference in New Issue
Block a user