ab aeterno
This commit is contained in:
parent
e13ae421a7
commit
8abb30da00
4 changed files with 129 additions and 31 deletions
|
@ -107,15 +107,31 @@ static bool saveAsDDS(const char* path, const u8* image_data, int image_width, i
|
|||
|
||||
|
||||
|
||||
struct FontPlugin final : public AssetBrowser::IPlugin
|
||||
struct FontPlugin final : public AssetBrowser::IPlugin, AssetCompiler::IPlugin
|
||||
{
|
||||
FontPlugin(StudioApp& app) { app.getAssetCompiler().registerExtension("ttf", FontResource::TYPE); }
|
||||
FontPlugin(StudioApp& app) : app(app)
|
||||
{
|
||||
app.getAssetCompiler().registerExtension("ttf", FontResource::TYPE);
|
||||
}
|
||||
|
||||
bool compile(const Path& src) override
|
||||
{
|
||||
const char* dst_dir = app.getAssetCompiler().getCompiledDir();
|
||||
const u32 hash = crc32(src.c_str());
|
||||
|
||||
const StaticString<MAX_PATH_LENGTH> dst(dst_dir, hash, ".res");
|
||||
|
||||
copyFile(src.c_str(), dst);
|
||||
return true;
|
||||
}
|
||||
|
||||
void onGUI(Resource* resource) override {}
|
||||
void onResourceUnloaded(Resource* resource) override {}
|
||||
const char* getName() const override { return "Font"; }
|
||||
|
||||
ResourceType getResourceType() const override { return FontResource::TYPE; }
|
||||
|
||||
StudioApp& app;
|
||||
};
|
||||
|
||||
|
||||
|
@ -2870,6 +2886,9 @@ struct StudioAppPlugin : StudioApp::IPlugin
|
|||
asset_compiler.addPlugin(*m_model_plugin, model_exts);
|
||||
|
||||
m_font_plugin = LUMIX_NEW(allocator, FontPlugin)(m_app);
|
||||
const char* fonts_exts[] = {"ttf", nullptr};
|
||||
asset_compiler.addPlugin(*m_font_plugin, fonts_exts);
|
||||
|
||||
AssetBrowser& asset_browser = m_app.getAssetBrowser();
|
||||
asset_browser.addPlugin(*m_model_plugin);
|
||||
asset_browser.addPlugin(*m_particle_emitter_plugin);
|
||||
|
@ -2913,6 +2932,7 @@ struct StudioAppPlugin : StudioApp::IPlugin
|
|||
asset_browser.removePlugin(*m_shader_plugin);
|
||||
|
||||
AssetCompiler& asset_compiler = m_app.getAssetCompiler();
|
||||
asset_compiler.removePlugin(*m_font_plugin);
|
||||
asset_compiler.removePlugin(*m_shader_plugin);
|
||||
asset_compiler.removePlugin(*m_texture_plugin);
|
||||
asset_compiler.removePlugin(*m_model_plugin);
|
||||
|
|
|
@ -204,6 +204,7 @@ struct PipelineImpl final : Pipeline
|
|||
ResourceManagerHub& rm = renderer.getEngine().getResourceManager();
|
||||
m_draw2d_shader = rm.load<Shader>(Path("pipelines/draw2d.shd"));
|
||||
m_debug_shape_shader = rm.load<Shader>(Path("pipelines/debug_shape.shd"));
|
||||
m_text_mesh_shader = rm.load<Shader>(Path("pipelines/text_mesh.shd"));
|
||||
TextureManager& texture_manager = renderer.getTextureManager();
|
||||
m_default_cubemap = rm.load<Texture>(Path("textures/common/default_probe.dds"));
|
||||
|
||||
|
@ -270,6 +271,7 @@ struct PipelineImpl final : Pipeline
|
|||
|
||||
m_draw2d_shader->getResourceManager().unload(*m_draw2d_shader);
|
||||
m_debug_shape_shader->getResourceManager().unload(*m_debug_shape_shader);
|
||||
m_text_mesh_shader->getResourceManager().unload(*m_text_mesh_shader);
|
||||
m_default_cubemap->getResourceManager().unload(*m_default_cubemap);
|
||||
|
||||
for(ShaderRef& shader : m_shaders) {
|
||||
|
@ -1508,6 +1510,88 @@ struct PipelineImpl final : Pipeline
|
|||
}
|
||||
|
||||
|
||||
void renderTextMeshes()
|
||||
{
|
||||
if (!m_text_mesh_shader->isReady()) return;
|
||||
if (m_text_mesh_shader->m_texture_slot_count < 1) return;
|
||||
|
||||
struct RenderJob : Renderer::RenderJob
|
||||
{
|
||||
RenderJob(IAllocator& allocator) : m_vertices(allocator) {}
|
||||
|
||||
|
||||
void setup() override
|
||||
{
|
||||
const Quat& rot = m_pipeline->m_viewport.rot;
|
||||
const DVec3& pos = m_pipeline->m_viewport.pos;
|
||||
m_pipeline->m_scene->getTextMeshesVertices(m_vertices, pos, rot);
|
||||
Renderer& renderer = m_pipeline->m_renderer;
|
||||
Texture* atlas = renderer.getFontManager().getAtlasTexture();
|
||||
m_atlas = atlas ? atlas->handle : ffr::INVALID_TEXTURE;
|
||||
}
|
||||
|
||||
|
||||
void execute() override
|
||||
{
|
||||
const Shader::Program& p = Shader::getProgram(m_shader, 0);
|
||||
if(!p.handle.isValid()) return;
|
||||
|
||||
Renderer& renderer = m_pipeline->m_renderer;
|
||||
const Renderer::TransientSlice transient = renderer.allocTransient(m_vertices.byte_size());
|
||||
ffr::update(transient.buffer, m_vertices.begin(), transient.offset, transient.size);
|
||||
ffr::setUniform1i(m_texture_uniform, 0);
|
||||
ffr::useProgram(p.handle);
|
||||
ffr::VertexDecl decl;
|
||||
ffr::blending(1);
|
||||
ffr::setState((u64)ffr::StateFlags::DEPTH_WRITE | (u64)ffr::StateFlags::DEPTH_TEST);
|
||||
ffr::bindTexture(0, m_atlas);
|
||||
decl.addAttribute(3, ffr::AttributeType::FLOAT, false, false);
|
||||
decl.addAttribute(4, ffr::AttributeType::U8, true, false);
|
||||
decl.addAttribute(2, ffr::AttributeType::FLOAT, false, false);
|
||||
ffr::setVertexBuffer(&decl, transient.buffer, transient.offset, nullptr);
|
||||
ffr::drawArrays(0, m_vertices.size(), ffr::PrimitiveType::TRIANGLES);
|
||||
}
|
||||
|
||||
|
||||
ffr::TextureHandle m_atlas;
|
||||
ShaderRenderData* m_shader;
|
||||
PipelineImpl* m_pipeline;
|
||||
ffr::UniformHandle m_texture_uniform;
|
||||
Array<TextMeshVertex> m_vertices;
|
||||
};
|
||||
|
||||
|
||||
IAllocator& allocator = m_renderer.getAllocator();
|
||||
RenderJob* job = LUMIX_NEW(allocator, RenderJob)(allocator);
|
||||
job->m_pipeline = this;
|
||||
job->m_shader = m_text_mesh_shader->m_render_data;
|
||||
job->m_texture_uniform = m_text_mesh_shader->m_texture_slots[0].uniform_handle;
|
||||
m_renderer.push(job);
|
||||
|
||||
/* if (!m_text_mesh_shader->isReady()) return;
|
||||
|
||||
IAllocator& allocator = m_renderer.getEngine().getLIFOAllocator();
|
||||
Array<TextMeshVertex> vertices(allocator);
|
||||
vertices.reserve(1024);
|
||||
m_scene->getTextMeshesVertices(vertices, m_applied_camera);
|
||||
|
||||
const bgfx::VertexDecl& decl = m_renderer.getBasicVertexDecl();
|
||||
bgfx::TransientVertexBuffer vertex_buffer;
|
||||
if (vertices.empty()) return;
|
||||
if (bgfx::getAvailTransientVertexBuffer(vertices.size(), decl) < (u32)vertices.size()) return;
|
||||
|
||||
bgfx::allocTransientVertexBuffer(&vertex_buffer, vertices.size(), decl);
|
||||
copyMemory(vertex_buffer.data, &vertices[0], vertices.size() * sizeof(vertices[0]));
|
||||
|
||||
Texture* atlas_texture = m_renderer.getFontManager().getAtlasTexture();
|
||||
bgfx::UniformHandle texture_uniform = m_text_mesh_shader->m_texture_slots[0].uniform_handle;
|
||||
setTexture(0, atlas_texture->handle, texture_uniform);
|
||||
ShaderInstance& shader_instance = m_text_mesh_shader->getInstance(0);
|
||||
u64 state = m_text_mesh_shader->m_render_states & ~BGFX_STATE_CULL_MASK;
|
||||
render(vertex_buffer, vertices.size(), state, shader_instance);*/
|
||||
}
|
||||
|
||||
|
||||
void renderBucket(const char* define, CommandSet* cmd_set)
|
||||
{
|
||||
struct RenderJob : Renderer::RenderJob
|
||||
|
@ -2662,6 +2746,7 @@ struct PipelineImpl final : Pipeline
|
|||
REGISTER_FUNCTION(render2D);
|
||||
REGISTER_FUNCTION(renderBucket);
|
||||
REGISTER_FUNCTION(renderDebugShapes);
|
||||
REGISTER_FUNCTION(renderTextMeshes);
|
||||
REGISTER_FUNCTION(setOutput);
|
||||
REGISTER_FUNCTION(setStencil);
|
||||
REGISTER_FUNCTION(viewport);
|
||||
|
@ -2742,6 +2827,7 @@ struct PipelineImpl final : Pipeline
|
|||
Viewport m_viewport;
|
||||
int m_output;
|
||||
Shader* m_debug_shape_shader;
|
||||
Shader* m_text_mesh_shader;
|
||||
Texture* m_default_cubemap;
|
||||
Array<CommandSet*> m_command_sets;
|
||||
Array<CustomCommandHandler> m_custom_commands_handlers;
|
||||
|
|
|
@ -918,44 +918,37 @@ public:
|
|||
}
|
||||
|
||||
|
||||
void getTextMeshesVertices(Array<TextMeshVertex>& vertices, EntityRef camera) override
|
||||
void getTextMeshesVertices(Array<TextMeshVertex>& vertices, const DVec3& cam_pos, const Quat& cam_rot) override
|
||||
{
|
||||
// TODO
|
||||
ASSERT(false);
|
||||
/*
|
||||
Matrix camera_mtx = m_universe.getMatrix(camera);
|
||||
Vec3 cam_right = camera_mtx.getXVector();
|
||||
Vec3 cam_up = -camera_mtx.getYVector();
|
||||
for (int j = 0, nj = m_text_meshes.size(); j < nj; ++j)
|
||||
{
|
||||
TextMesh& text = *m_text_meshes.at(j);
|
||||
Font* font = text.getFont();
|
||||
const Vec3 cam_right = cam_rot * Vec3(1, 0, 0);
|
||||
const Vec3 cam_up = cam_rot * Vec3(0, -1, 0);
|
||||
for (int j = 0, nj = m_text_meshes.size(); j < nj; ++j) {
|
||||
const TextMesh& text = *m_text_meshes.at(j);
|
||||
const Font* font = text.getFont();
|
||||
if (!font) font = m_renderer.getFontManager().getDefaultFont();
|
||||
EntityRef entity = m_text_meshes.getKey(j);
|
||||
const EntityRef entity = m_text_meshes.getKey(j);
|
||||
const char* str = text.text.c_str();
|
||||
Vec3 base = m_universe.getPosition(entity);
|
||||
Quat rot = m_universe.getRotation(entity);
|
||||
float scale = m_universe.getScale(entity);
|
||||
Vec3 right = rot.rotate({ 1, 0, 0 }) * scale;
|
||||
Vec3 up = rot.rotate({ 0, -1, 0 }) * scale;
|
||||
if (text.m_flags.isSet(TextMesh::CAMERA_ORIENTED))
|
||||
{
|
||||
Vec3 base = (m_universe.getPosition(entity) - cam_pos).toFloat();
|
||||
const Quat rot = m_universe.getRotation(entity);
|
||||
const float scale = m_universe.getScale(entity);
|
||||
Vec3 right = rot.rotate(Vec3(1, 0, 0)) * scale;
|
||||
Vec3 up = rot.rotate(Vec3(0, -1, 0)) * scale;
|
||||
if (text.m_flags.isSet(TextMesh::CAMERA_ORIENTED)) {
|
||||
right = cam_right * scale;
|
||||
up = cam_up * scale;
|
||||
}
|
||||
u32 color = text.color;
|
||||
Vec2 text_size = font->CalcTextSizeA((float)text.getFontSize(), FLT_MAX, 0, str);
|
||||
const Vec2 text_size = font->CalcTextSizeA((float)text.getFontSize(), FLT_MAX, 0, str);
|
||||
base += right * text_size.x * -0.5f;
|
||||
base += up * text_size.y * -0.5f;
|
||||
for (int i = 0, n = text.text.length(); i < n; ++i)
|
||||
{
|
||||
for (int i = 0, n = text.text.length(); i < n; ++i) {
|
||||
const Font::Glyph* glyph = font->FindGlyph(str[i]);
|
||||
if (!glyph) continue;
|
||||
|
||||
Vec3 x0y0 = base + right * glyph->X0 + up * glyph->Y0;
|
||||
Vec3 x1y0 = base + right * glyph->X1 + up * glyph->Y0;
|
||||
Vec3 x1y1 = base + right * glyph->X1 + up * glyph->Y1;
|
||||
Vec3 x0y1 = base + right * glyph->X0 + up * glyph->Y1;
|
||||
const Vec3 x0y0 = base + right * glyph->X0 + up * glyph->Y0;
|
||||
const Vec3 x1y0 = base + right * glyph->X1 + up * glyph->Y0;
|
||||
const Vec3 x1y1 = base + right * glyph->X1 + up * glyph->Y1;
|
||||
const Vec3 x0y1 = base + right * glyph->X0 + up * glyph->Y1;
|
||||
|
||||
vertices.push({ x0y0, color, { glyph->U0, glyph->V0 } });
|
||||
vertices.push({ x1y0, color, { glyph->U1, glyph->V0 } });
|
||||
|
@ -967,8 +960,7 @@ public:
|
|||
|
||||
base += right * glyph->XAdvance;
|
||||
}
|
||||
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -384,7 +384,7 @@ public:
|
|||
virtual void setTextMeshFontPath(EntityRef entity, const Path& path) = 0;
|
||||
virtual bool isTextMeshCameraOriented(EntityRef entity) = 0;
|
||||
virtual void setTextMeshCameraOriented(EntityRef entity, bool is_oriented) = 0;
|
||||
virtual void getTextMeshesVertices(Array<TextMeshVertex>& vertices, EntityRef camera) = 0;
|
||||
virtual void getTextMeshesVertices(Array<TextMeshVertex>& vertices, const DVec3& cam_pos, const Quat& rot) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~RenderScene() {}
|
||||
|
|
Loading…
Reference in a new issue