Port billboard text
This commit is contained in:
parent
ec59e3f573
commit
cce8abe6f3
15
data/shaders/sp_text_billboard.frag
Normal file
15
data/shaders/sp_text_billboard.frag
Normal file
@ -0,0 +1,15 @@
|
||||
in vec2 uv;
|
||||
in vec4 color;
|
||||
out vec4 o_diffuse_color;
|
||||
|
||||
uniform sampler2D font_texture;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 col = texture(font_texture, uv);
|
||||
if (col.a < 0.5)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
o_diffuse_color = vec4(col.xyz * color.xyz, 1.0);
|
||||
}
|
@ -25,6 +25,8 @@
|
||||
#include "graphics/lod_node.hpp"
|
||||
#include "graphics/shaders.hpp"
|
||||
#include "graphics/stk_particle.hpp"
|
||||
#include "graphics/stk_text_billboard.hpp"
|
||||
#include "graphics/text_billboard_drawer.hpp"
|
||||
#include "graphics/sp/sp_base.hpp"
|
||||
#include "graphics/sp/sp_mesh_node.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
@ -155,7 +157,7 @@ void DrawCalls::parseSceneManager(core::list<scene::ISceneNode*> &List,
|
||||
if (!(*I)->isVisible())
|
||||
continue;
|
||||
|
||||
if (STKParticle *node = dynamic_cast<STKParticle *>(*I))
|
||||
if (STKParticle *node = dynamic_cast<STKParticle*>(*I))
|
||||
{
|
||||
if (!isCulledPrecise(cam, *I, irr_driver->getBoundingBoxesViz()) ||
|
||||
SP::sp_first_frame)
|
||||
@ -164,13 +166,22 @@ void DrawCalls::parseSceneManager(core::list<scene::ISceneNode*> &List,
|
||||
}
|
||||
|
||||
if (scene::IBillboardSceneNode *node =
|
||||
dynamic_cast<scene::IBillboardSceneNode *>(*I))
|
||||
dynamic_cast<scene::IBillboardSceneNode*>(*I))
|
||||
{
|
||||
if (!isCulledPrecise(cam, *I) || SP::sp_first_frame)
|
||||
CPUParticleManager::getInstance()->addBillboardNode(node);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (STKTextBillboard *tb =
|
||||
dynamic_cast<STKTextBillboard*>(*I))
|
||||
{
|
||||
if (!isCulledPrecise(cam, *I, irr_driver->getBoundingBoxesViz()) ||
|
||||
SP::sp_first_frame)
|
||||
TextBillboardDrawer::addTextBillboard(tb);
|
||||
continue;
|
||||
}
|
||||
|
||||
SP::SPMeshNode* node = dynamic_cast<SP::SPMeshNode*>(*I);
|
||||
if (node)
|
||||
{
|
||||
@ -199,6 +210,7 @@ DrawCalls::~DrawCalls()
|
||||
void DrawCalls::prepareDrawCalls(scene::ICameraSceneNode *camnode)
|
||||
{
|
||||
CPUParticleManager::getInstance()->reset();
|
||||
TextBillboardDrawer::reset();
|
||||
PROFILER_PUSH_CPU_MARKER("- culling", 0xFF, 0xFF, 0x0);
|
||||
SP::prepareDrawCalls();
|
||||
parseSceneManager(
|
||||
@ -246,8 +258,10 @@ void DrawCalls::prepareDrawCalls(scene::ICameraSceneNode *camnode)
|
||||
break;
|
||||
}*/
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("- cpu particle upload", 0x3F, 0x03, 0x61);
|
||||
PROFILER_PUSH_CPU_MARKER("- particle and text billboard upload", 0x3F,
|
||||
0x03, 0x61);
|
||||
CPUParticleManager::getInstance()->uploadAll();
|
||||
TextBillboardDrawer::updateAll();
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("- SP::upload instance and skinning matrices",
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "graphics/spherical_harmonics.hpp"
|
||||
#include "graphics/sp/sp_base.hpp"
|
||||
#include "graphics/sp/sp_shader.hpp"
|
||||
#include "graphics/text_billboard_drawer.hpp"
|
||||
#include "items/item_manager.hpp"
|
||||
#include "items/powerup_manager.hpp"
|
||||
#include "modes/world.hpp"
|
||||
@ -392,11 +393,13 @@ void ShaderBasedRenderer::renderSceneDeferred(scene::ICameraSceneNode * const ca
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
|
||||
// Render particles
|
||||
// Render particles and text billboard
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- Particles", 0xFF, 0xFF, 0x00);
|
||||
PROFILER_PUSH_CPU_MARKER("- Particles and text billboard", 0xFF, 0xFF,
|
||||
0x00);
|
||||
ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_PARTICLES));
|
||||
CPUParticleManager::getInstance()->drawAll();
|
||||
TextBillboardDrawer::drawAll();
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
|
||||
@ -494,20 +497,6 @@ void ShaderBasedRenderer::renderScene(scene::ICameraSceneNode * const camnode,
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
|
||||
const Track * const track = Track::getCurrentTrack();
|
||||
// Render discrete lights scattering
|
||||
if (CVS->isDefferedEnabled() && track && track->isFogEnabled())
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- PointLight Scatter", 0xFF, 0x00, 0x00);
|
||||
ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_FOG));
|
||||
m_lighting_passes.renderLightsScatter(m_rtts->getDepthStencilTexture(),
|
||||
m_rtts->getFBO(FBO_HALF1),
|
||||
m_rtts->getFBO(FBO_HALF2),
|
||||
m_rtts->getFBO(FBO_COLORS),
|
||||
m_post_processing);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
|
||||
// Render transparent
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- Transparent Pass", 0xFF, 0x00, 0x00);
|
||||
@ -517,11 +506,13 @@ void ShaderBasedRenderer::renderScene(scene::ICameraSceneNode * const camnode,
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
|
||||
// Render particles
|
||||
// Render particles and text billboard
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- Particles", 0xFF, 0xFF, 0x00);
|
||||
PROFILER_PUSH_CPU_MARKER("- Particles and text billboard", 0xFF, 0xFF,
|
||||
0x00);
|
||||
ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_PARTICLES));
|
||||
CPUParticleManager::getInstance()->drawAll();
|
||||
TextBillboardDrawer::drawAll();
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
|
||||
|
@ -77,6 +77,8 @@ public:
|
||||
short hue_packed = short(core::clamp(int(hue * 100.0f), 0, 100));
|
||||
memcpy(m_data + 30, &hue_packed, 2);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
const void* getData() const { return m_data; }
|
||||
|
||||
};
|
||||
|
||||
|
@ -203,8 +203,7 @@ void SPMeshBuffer::uploadGLMesh()
|
||||
offset += 4;
|
||||
|
||||
video::SColor vc = m_vertices[i].m_color;
|
||||
if (CVS->isDefferedEnabled() ||
|
||||
CVS->isARBSRGBFramebufferUsable())
|
||||
if (CVS->isDefferedEnabled())
|
||||
{
|
||||
video::SColorf tmp(vc);
|
||||
vc.setRed(srgbToLinear(tmp.r));
|
||||
|
@ -18,35 +18,41 @@
|
||||
#ifndef SERVER_ONLY
|
||||
|
||||
#include "graphics/stk_text_billboard.hpp"
|
||||
#include "graphics/shaders.hpp"
|
||||
#include "graphics/sp/sp_base.hpp"
|
||||
#include "graphics/central_settings.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/stk_mesh_scene_node.hpp"
|
||||
#include "graphics/stk_tex_manager.hpp"
|
||||
#include <SMesh.h>
|
||||
#include <SMeshBuffer.h>
|
||||
#include <ISceneManager.h>
|
||||
#include <ICameraSceneNode.h>
|
||||
#include "graphics/graphics_restrictions.hpp"
|
||||
|
||||
using namespace irr;
|
||||
|
||||
STKTextBillboard::STKTextBillboard(core::stringw text, FontWithFace* font,
|
||||
const video::SColor& color_top, const video::SColor& color_bottom,
|
||||
irr::scene::ISceneNode* parent,
|
||||
irr::scene::ISceneManager* mgr, irr::s32 id,
|
||||
const irr::core::vector3df& position, const irr::core::vector3df& size) :
|
||||
STKMeshSceneNode(new scene::SMesh(),
|
||||
parent, irr_driver->getSceneManager(), -1, "text_billboard",
|
||||
position, core::vector3df(0.0f, 0.0f, 0.0f), size, false)
|
||||
// ----------------------------------------------------------------------------
|
||||
STKTextBillboard::STKTextBillboard(const video::SColor& color_top,
|
||||
const video::SColor& color_bottom,
|
||||
ISceneNode* parent, ISceneManager* mgr,
|
||||
s32 id,
|
||||
const core::vector3df& position,
|
||||
const core::vector3df& size)
|
||||
: ISceneNode(parent, mgr, id, position,
|
||||
core::vector3df(0.0f, 0.0f, 0.0f), size)
|
||||
{
|
||||
m_color_top = color_top;
|
||||
if (CVS->isDefferedEnabled())
|
||||
{
|
||||
video::SColorf tmp(m_color_top);
|
||||
m_color_top.setRed(SP::srgbToLinear(tmp.r));
|
||||
m_color_top.setGreen(SP::srgbToLinear(tmp.g));
|
||||
m_color_top.setBlue(SP::srgbToLinear(tmp.b));
|
||||
}
|
||||
m_color_bottom = color_bottom;
|
||||
getTextMesh(text, font);
|
||||
createGLMeshes();
|
||||
Mesh->drop();
|
||||
//setAutomaticCulling(0);
|
||||
updateAbsolutePosition();
|
||||
}
|
||||
if (CVS->isDefferedEnabled())
|
||||
{
|
||||
video::SColorf tmp(m_color_bottom);
|
||||
m_color_bottom.setRed(SP::srgbToLinear(tmp.r));
|
||||
m_color_bottom.setGreen(SP::srgbToLinear(tmp.g));
|
||||
m_color_bottom.setBlue(SP::srgbToLinear(tmp.b));
|
||||
}
|
||||
static_assert(sizeof(GLTB) == 20, "Wrong compiler padding");
|
||||
} // STKTextBillboard
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void STKTextBillboard::updateAbsolutePosition()
|
||||
{
|
||||
// Make billboard always face the camera
|
||||
@ -71,126 +77,193 @@ void STKTextBillboard::updateAbsolutePosition()
|
||||
core::matrix4 m;
|
||||
m.setScale(RelativeScale);
|
||||
AbsoluteTransformation *= m;
|
||||
}
|
||||
m_instanced_data = SP::SPInstancedData(AbsoluteTransformation, 0, 0, 0, 0);
|
||||
|
||||
scene::IMesh* STKTextBillboard::getTextMesh(core::stringw text, FontWithFace* font)
|
||||
} // updateAbsolutePosition
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void STKTextBillboard::init(core::stringw text, FontWithFace* face)
|
||||
{
|
||||
core::dimension2du size = font->getDimension(text.c_str());
|
||||
font->render(text, core::rect<s32>(0, 0, size.Width, size.Height), video::SColor(255,255,255,255),
|
||||
false, false, NULL, NULL, this);
|
||||
m_chars = new std::vector<STKTextBillboardChar>();
|
||||
core::dimension2du size = face->getDimension(text.c_str());
|
||||
face->render(text, core::rect<s32>(0, 0, size.Width, size.Height),
|
||||
video::SColor(255,255,255,255), false, false, NULL, NULL, this);
|
||||
|
||||
const float scale = 0.02f;
|
||||
|
||||
//scene::SMesh* mesh = new scene::SMesh();
|
||||
std::map<video::ITexture*, scene::SMeshBuffer*> buffers;
|
||||
|
||||
float max_x = 0;
|
||||
float min_y = 0;
|
||||
float max_y = 0;
|
||||
for (unsigned int i = 0; i < m_chars.size(); i++)
|
||||
for (unsigned int i = 0; i < m_chars->size(); i++)
|
||||
{
|
||||
float char_x = m_chars[i].m_destRect.LowerRightCorner.X;
|
||||
float char_x = (*m_chars)[i].m_dest_rect.LowerRightCorner.X;
|
||||
if (char_x > max_x)
|
||||
{
|
||||
max_x = char_x;
|
||||
}
|
||||
|
||||
float char_min_y = m_chars[i].m_destRect.UpperLeftCorner.Y;
|
||||
float char_max_y = m_chars[i].m_destRect.LowerRightCorner.Y;
|
||||
float char_min_y = (*m_chars)[i].m_dest_rect.UpperLeftCorner.Y;
|
||||
float char_max_y = (*m_chars)[i].m_dest_rect.LowerRightCorner.Y;
|
||||
if (char_min_y < min_y)
|
||||
{
|
||||
min_y = char_min_y;
|
||||
}
|
||||
if (char_max_y > min_y)
|
||||
{
|
||||
max_y = char_max_y;
|
||||
}
|
||||
}
|
||||
float scaled_center_x = (max_x / 2.0f) * scale;
|
||||
float scaled_y = (max_y / 2.0f) * scale; // -max_y * scale;
|
||||
float scaled_y = (max_y / 2.0f) * scale;
|
||||
|
||||
for (unsigned int i = 0; i < m_chars.size(); i++)
|
||||
for (unsigned int i = 0; i < m_chars->size(); i++)
|
||||
{
|
||||
core::vector3df char_pos(m_chars[i].m_destRect.UpperLeftCorner.X,
|
||||
m_chars[i].m_destRect.UpperLeftCorner.Y, 0);
|
||||
core::vector3df char_pos((*m_chars)[i].m_dest_rect.UpperLeftCorner.X,
|
||||
(*m_chars)[i].m_dest_rect.UpperLeftCorner.Y, 0);
|
||||
char_pos *= scale;
|
||||
|
||||
core::vector3df char_pos2(m_chars[i].m_destRect.LowerRightCorner.X,
|
||||
m_chars[i].m_destRect.LowerRightCorner.Y, 0);
|
||||
core::vector3df char_pos2((*m_chars)[i].m_dest_rect.LowerRightCorner.X,
|
||||
(*m_chars)[i].m_dest_rect.LowerRightCorner.Y, 0);
|
||||
char_pos2 *= scale;
|
||||
|
||||
//core::dimension2di char_size_i = m_chars[i].m_destRect.getSize();
|
||||
//core::dimension2df char_size(char_size_i.Width*scale, char_size_i.Height*scale);
|
||||
|
||||
std::map<video::ITexture*, scene::SMeshBuffer*>::iterator map_itr = buffers.find(m_chars[i].m_texture);
|
||||
scene::SMeshBuffer* buffer;
|
||||
if (map_itr == buffers.end())
|
||||
{
|
||||
buffer = new scene::SMeshBuffer();
|
||||
buffer->getMaterial().setTexture(0, m_chars[i].m_texture);
|
||||
buffer->getMaterial().setTexture(1, STKTexManager::getInstance()->getUnicolorTexture(video::SColor(0, 0, 0, 0)));
|
||||
buffer->getMaterial().setTexture(2, STKTexManager::getInstance()->getUnicolorTexture(video::SColor(0, 0, 0, 0)));
|
||||
buffer->getMaterial().MaterialType = Shaders::getShader(ES_OBJECT_UNLIT);
|
||||
buffers[m_chars[i].m_texture] = buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = map_itr->second;
|
||||
}
|
||||
|
||||
float tex_width = (float) m_chars[i].m_texture->getSize().Width;
|
||||
float tex_height = (float)m_chars[i].m_texture->getSize().Height;
|
||||
|
||||
|
||||
video::S3DVertex vertices[] =
|
||||
{
|
||||
video::S3DVertex(char_pos.X - scaled_center_x, char_pos.Y - scaled_y, 0.0f,
|
||||
0.0f, 0.0f, 1.0f,
|
||||
float tex_width = (float)(*m_chars)[i].m_texture->getSize().Width;
|
||||
float tex_height = (float)(*m_chars)[i].m_texture->getSize().Height;
|
||||
using namespace MiniGLM;
|
||||
std::array<GLTB, 4> triangle_strip =
|
||||
{{
|
||||
{
|
||||
core::vector3df
|
||||
(char_pos.X - scaled_center_x, char_pos.Y - scaled_y, 0),
|
||||
m_color_bottom,
|
||||
m_chars[i].m_sourceRect.UpperLeftCorner.X / tex_width,
|
||||
m_chars[i].m_sourceRect.LowerRightCorner.Y / tex_height),
|
||||
{
|
||||
toFloat16((*m_chars)
|
||||
[i].m_source_rect.UpperLeftCorner.X / tex_width),
|
||||
toFloat16((*m_chars)
|
||||
[i].m_source_rect.LowerRightCorner.Y / tex_height)
|
||||
}
|
||||
},
|
||||
|
||||
video::S3DVertex(char_pos2.X - scaled_center_x, char_pos.Y - scaled_y, 0.0f,
|
||||
0.0f, 0.0f, 1.0f,
|
||||
{
|
||||
core::vector3df
|
||||
(char_pos.X - scaled_center_x, char_pos2.Y - scaled_y, 0),
|
||||
m_color_top,
|
||||
{
|
||||
toFloat16((*m_chars)
|
||||
[i].m_source_rect.UpperLeftCorner.X / tex_width),
|
||||
toFloat16((*m_chars)
|
||||
[i].m_source_rect.UpperLeftCorner.Y / tex_height)
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
core::vector3df
|
||||
(char_pos2.X - scaled_center_x, char_pos.Y - scaled_y, 0),
|
||||
m_color_bottom,
|
||||
m_chars[i].m_sourceRect.LowerRightCorner.X / tex_width,
|
||||
m_chars[i].m_sourceRect.LowerRightCorner.Y / tex_height),
|
||||
{
|
||||
toFloat16((*m_chars)
|
||||
[i].m_source_rect.LowerRightCorner.X / tex_width),
|
||||
toFloat16((*m_chars)
|
||||
[i].m_source_rect.LowerRightCorner.Y / tex_height)
|
||||
}
|
||||
},
|
||||
|
||||
video::S3DVertex(char_pos2.X - scaled_center_x, char_pos2.Y - scaled_y, 0.0f,
|
||||
0.0f, 0.0f, 1.0f,
|
||||
{
|
||||
core::vector3df
|
||||
(char_pos2.X - scaled_center_x, char_pos2.Y - scaled_y, 0),
|
||||
m_color_top,
|
||||
m_chars[i].m_sourceRect.LowerRightCorner.X / tex_width,
|
||||
m_chars[i].m_sourceRect.UpperLeftCorner.Y / tex_height),
|
||||
|
||||
video::S3DVertex(char_pos.X - scaled_center_x, char_pos2.Y - scaled_y, 0.0f,
|
||||
0.0f, 0.0f, 1.0f,
|
||||
m_color_top,
|
||||
m_chars[i].m_sourceRect.UpperLeftCorner.X / tex_width,
|
||||
m_chars[i].m_sourceRect.UpperLeftCorner.Y / tex_height)
|
||||
};
|
||||
|
||||
irr::u16 indices[] = { 2, 1, 0, 3, 2, 0 };
|
||||
|
||||
buffer->append(vertices, 4, indices, 6);
|
||||
{
|
||||
toFloat16((*m_chars)
|
||||
[i].m_source_rect.LowerRightCorner.X / tex_width),
|
||||
toFloat16((*m_chars)
|
||||
[i].m_source_rect.UpperLeftCorner.Y / tex_height)
|
||||
}
|
||||
}
|
||||
}};
|
||||
m_gl_tbs[(*m_chars)[i].m_texture].push_back(triangle_strip);
|
||||
}
|
||||
|
||||
for (std::map<video::ITexture*, scene::SMeshBuffer*>::iterator map_itr = buffers.begin();
|
||||
map_itr != buffers.end(); map_itr++)
|
||||
glGenBuffers(1, &m_instanced_array);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_instanced_array);
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
12 /*position*/ + 4/*quaternion*/ + 8 /*scale*/, NULL,
|
||||
GL_DYNAMIC_DRAW);
|
||||
for (auto& p : m_gl_tbs)
|
||||
{
|
||||
((scene::SMesh*)Mesh)->addMeshBuffer(map_itr->second);
|
||||
glGenVertexArrays(1, &m_vao_vbos[p.first].first);
|
||||
glGenBuffers(1, &m_vao_vbos[p.first].second);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vao_vbos.at(p.first).second);
|
||||
glBufferData(GL_ARRAY_BUFFER, m_gl_tbs.at(p.first).size() * 4 * 20,
|
||||
m_gl_tbs.at(p.first).data(), GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(m_vao_vbos.at(p.first).first);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vao_vbos.at(p.first).second);
|
||||
|
||||
map_itr->second->recalculateBoundingBox();
|
||||
Mesh->setBoundingBox(map_itr->second->getBoundingBox()); // TODO: wrong if several buffers
|
||||
// Position
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 20, (void*)0);
|
||||
|
||||
map_itr->second->drop();
|
||||
// Vertex color
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, 20,
|
||||
(void*)12);
|
||||
|
||||
// 1st texture coordinates
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_HALF_FLOAT, GL_FALSE, 20, (void*)16);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_instanced_array);
|
||||
// Origin
|
||||
glEnableVertexAttribArray(8);
|
||||
glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, 24, (void*)0);
|
||||
glVertexAttribDivisorARB(8, 1);
|
||||
|
||||
// Rotation (quaternion .xyz)
|
||||
glEnableVertexAttribArray(9);
|
||||
glVertexAttribPointer(9, 4, GL_INT_2_10_10_10_REV,
|
||||
GraphicsRestrictions::isDisabled
|
||||
(GraphicsRestrictions::GR_10BIT_VECTOR) ? GL_FALSE : GL_TRUE, 24,
|
||||
(void*)12);
|
||||
glVertexAttribDivisorARB(9, 1);
|
||||
|
||||
// Scale (3 half floats and .w for quaternion .w)
|
||||
glEnableVertexAttribArray(10);
|
||||
glVertexAttribPointer(10, 4, GL_HALF_FLOAT, GL_FALSE, 24, (void*)16);
|
||||
glVertexAttribDivisorARB(10, 1);
|
||||
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
getMaterial(0).MaterialType = Shaders::getShader(ES_OBJECT_UNLIT);
|
||||
Vec3 min = Vec3( 999999.9f);
|
||||
Vec3 max = Vec3(-999999.9f);
|
||||
for (auto& p : m_gl_tbs)
|
||||
{
|
||||
for (auto& q : p.second)
|
||||
{
|
||||
for (auto& r : q)
|
||||
{
|
||||
Vec3 c(r.m_position.X, r.m_position.Y, r.m_position.Z);
|
||||
min.min(c);
|
||||
max.max(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_bbox.MinEdge = min.toIrrVector();
|
||||
m_bbox.MaxEdge = max.toIrrVector();
|
||||
|
||||
return Mesh;
|
||||
}
|
||||
delete m_chars;
|
||||
updateAbsolutePosition();
|
||||
} // init
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void STKTextBillboard::collectChar(video::ITexture* texture,
|
||||
const core::rect<float>& destRect,
|
||||
const core::rect<s32>& sourceRect,
|
||||
const video::SColor* const colors)
|
||||
const core::rect<float>& dest_rect,
|
||||
const core::rect<s32>& source_rect,
|
||||
const video::SColor* const colors)
|
||||
{
|
||||
m_chars.push_back(STKTextBillboardChar(texture, destRect, sourceRect, colors));
|
||||
}
|
||||
assert(m_chars != NULL);
|
||||
m_chars->push_back(STKTextBillboardChar(texture, dest_rect, source_rect,
|
||||
colors));
|
||||
} // collectChar
|
||||
|
||||
#endif // !SERVER_ONLY
|
||||
|
||||
|
@ -18,73 +18,134 @@
|
||||
#ifndef STK_TEXT_BILLBOARD_HPP
|
||||
#define STK_TEXT_BILLBOARD_HPP
|
||||
|
||||
#include "graphics/stk_mesh_scene_node.hpp"
|
||||
#include "font/font_with_face.hpp"
|
||||
#include "utils/cpp2011.hpp"
|
||||
#include "graphics/gl_headers.hpp"
|
||||
#include "graphics/sp/sp_instanced_data.hpp"
|
||||
#include "utils/no_copy.hpp"
|
||||
|
||||
#include "../lib/irrlicht/source/Irrlicht/CBillboardSceneNode.h"
|
||||
#include <IBillboardSceneNode.h>
|
||||
#include <irrTypes.h>
|
||||
#include <IMesh.h>
|
||||
#include <ISceneNode.h>
|
||||
#include <array>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
class STKTextBillboardChar
|
||||
using namespace irr;
|
||||
using namespace scene;
|
||||
|
||||
class STKTextBillboard : public ISceneNode, public NoCopy,
|
||||
FontWithFace::FontCharCollector
|
||||
{
|
||||
public:
|
||||
irr::video::ITexture* m_texture;
|
||||
irr::core::rect<float> m_destRect;
|
||||
irr::core::rect<irr::s32> m_sourceRect;
|
||||
//irr::video::SColor m_colors[4];
|
||||
|
||||
STKTextBillboardChar(irr::video::ITexture* texture,
|
||||
const irr::core::rect<float>& destRect,
|
||||
const irr::core::rect<irr::s32>& sourceRect,
|
||||
const irr::video::SColor* const colors)
|
||||
private:
|
||||
struct STKTextBillboardChar
|
||||
{
|
||||
m_texture = texture;
|
||||
m_destRect = destRect;
|
||||
m_sourceRect = sourceRect;
|
||||
//if (colors == NULL)
|
||||
//{
|
||||
// m_colors[0] = m_colors[1] = m_colors[2] = m_colors[3] = NULL;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// m_colors[0] = colors[0];
|
||||
// m_colors[1] = colors[1];
|
||||
// m_colors[2] = colors[2];
|
||||
// m_colors[3] = colors[3];
|
||||
//}
|
||||
}
|
||||
};
|
||||
video::ITexture* m_texture;
|
||||
|
||||
class STKTextBillboard : public STKMeshSceneNode, FontWithFace::FontCharCollector
|
||||
{
|
||||
std::vector<STKTextBillboardChar> m_chars;
|
||||
irr::video::SColor m_color_top;
|
||||
irr::video::SColor m_color_bottom;
|
||||
core::rect<float> m_dest_rect;
|
||||
|
||||
irr::scene::IMesh* getTextMesh(irr::core::stringw text, FontWithFace* font);
|
||||
core::rect<s32> m_source_rect;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
STKTextBillboardChar(video::ITexture* texture,
|
||||
const core::rect<float>& dest_rect,
|
||||
const core::rect<irr::s32>& source_rect,
|
||||
const video::SColor* const colors)
|
||||
{
|
||||
m_texture = texture;
|
||||
m_dest_rect = dest_rect;
|
||||
m_source_rect = source_rect;
|
||||
}
|
||||
};
|
||||
|
||||
struct GLTB
|
||||
{
|
||||
core::vector3df m_position;
|
||||
video::SColor m_color;
|
||||
short m_uv[2];
|
||||
};
|
||||
|
||||
SP::SPInstancedData m_instanced_data;
|
||||
|
||||
GLuint m_instanced_array = 0;
|
||||
|
||||
std::vector<STKTextBillboardChar>* m_chars = NULL;
|
||||
|
||||
video::SColor m_color_top;
|
||||
|
||||
video::SColor m_color_bottom;
|
||||
|
||||
std::unordered_map<video::ITexture*, std::vector<std::array<GLTB, 4> > >
|
||||
m_gl_tbs;
|
||||
|
||||
std::unordered_map<video::ITexture*, std::pair<GLuint, GLuint> >
|
||||
m_vao_vbos;
|
||||
|
||||
core::aabbox3df m_bbox;
|
||||
|
||||
public:
|
||||
STKTextBillboard(irr::core::stringw text, FontWithFace* font,
|
||||
const irr::video::SColor& color_top,
|
||||
const irr::video::SColor& color_bottom,
|
||||
irr::scene::ISceneNode* parent,
|
||||
irr::scene::ISceneManager* mgr, irr::s32 id,
|
||||
const irr::core::vector3df& position,
|
||||
const irr::core::vector3df& size);
|
||||
|
||||
virtual scene::ESCENE_NODE_TYPE getType() const OVERRIDE
|
||||
// ------------------------------------------------------------------------
|
||||
STKTextBillboard(const video::SColor& color_top,
|
||||
const video::SColor& color_bottom, ISceneNode* parent,
|
||||
ISceneManager* mgr, s32 id,
|
||||
const core::vector3df& position,
|
||||
const core::vector3df& size);
|
||||
// ------------------------------------------------------------------------
|
||||
~STKTextBillboard()
|
||||
{
|
||||
return scene::ESNT_TEXT;
|
||||
#ifndef SERVER_ONLY
|
||||
if (m_instanced_array != 0)
|
||||
{
|
||||
glDeleteBuffers(1, &m_instanced_array);
|
||||
}
|
||||
for (auto& p : m_vao_vbos)
|
||||
{
|
||||
glDeleteVertexArrays(1, &p.second.first);
|
||||
glDeleteBuffers(1, &p.second.second);
|
||||
}
|
||||
m_vao_vbos.clear();
|
||||
#endif
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void collectChar(video::ITexture* texture,
|
||||
const core::rect<float>& dest_rect,
|
||||
const core::rect<irr::s32>& source_rect,
|
||||
const video::SColor* const colors);
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void updateAbsolutePosition();
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void render() {}
|
||||
// ------------------------------------------------------------------------
|
||||
virtual const core::aabbox3df& getBoundingBox() const { return m_bbox; }
|
||||
// ------------------------------------------------------------------------
|
||||
void init(core::stringw text, FontWithFace* face);
|
||||
// ------------------------------------------------------------------------
|
||||
void draw(video::ITexture* tex) const
|
||||
{
|
||||
#ifndef SERVER_ONLY
|
||||
glBindVertexArray(m_vao_vbos.at(tex).first);
|
||||
for (unsigned i = 0; i < m_gl_tbs.at(tex).size(); i++)
|
||||
{
|
||||
glDrawArraysInstanced(GL_TRIANGLE_STRIP, i * 4, 4, 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
std::vector<video::ITexture*> getAllTBTextures() const
|
||||
{
|
||||
std::vector<video::ITexture*> ret;
|
||||
for (auto& p : m_vao_vbos)
|
||||
{
|
||||
ret.push_back(p.first);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
void updateGLInstanceData() const
|
||||
{
|
||||
#ifndef SERVER_ONLY
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_instanced_array);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, 24, m_instanced_data.getData());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual void collectChar(irr::video::ITexture* texture,
|
||||
const irr::core::rect<float>& destRect,
|
||||
const irr::core::rect<irr::s32>& sourceRect,
|
||||
const irr::video::SColor* const colors) OVERRIDE;
|
||||
|
||||
virtual void updateAbsolutePosition() OVERRIDE;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
96
src/graphics/text_billboard_drawer.cpp
Normal file
96
src/graphics/text_billboard_drawer.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2018 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef SERVER_ONLY
|
||||
|
||||
#include "graphics/stk_text_billboard.hpp"
|
||||
#include "graphics/texture_shader.hpp"
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
namespace TextBillboardDrawer
|
||||
{
|
||||
// ----------------------------------------------------------------------------
|
||||
std::unordered_map<video::ITexture*, std::vector<STKTextBillboard*> > g_tbs;
|
||||
// ----------------------------------------------------------------------------
|
||||
std::unordered_set<STKTextBillboard*> g_tbs_update;
|
||||
// ============================================================================
|
||||
/** A Shader to render text billboard.
|
||||
*/
|
||||
class TBRenderer : public TextureShader<TBRenderer, 1>
|
||||
{
|
||||
public:
|
||||
TBRenderer()
|
||||
{
|
||||
loadProgram(PARTICLES_RENDERING,
|
||||
GL_VERTEX_SHADER, "sp_pass.vert",
|
||||
GL_FRAGMENT_SHADER, "sp_text_billboard.frag");
|
||||
assignUniforms();
|
||||
assignSamplerNames(0, "font_texture",
|
||||
ST_TRILINEAR_ANISOTROPIC_FILTERED);
|
||||
} // TBRenderer
|
||||
}; // TBRenderer
|
||||
|
||||
// ============================================================================
|
||||
void addTextBillboard(STKTextBillboard* tb)
|
||||
{
|
||||
g_tbs_update.insert(tb);
|
||||
const auto& tex = tb->getAllTBTextures();
|
||||
for (video::ITexture* t : tex)
|
||||
{
|
||||
g_tbs[t].push_back(tb);
|
||||
}
|
||||
} // addTextBillboard
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void drawAll()
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glDisable(GL_BLEND);
|
||||
TBRenderer::getInstance()->use();
|
||||
for (auto& p : g_tbs)
|
||||
{
|
||||
TBRenderer::getInstance()
|
||||
->setTextureUnits(p.first->getOpenGLTextureName());
|
||||
for (auto* q : p.second)
|
||||
{
|
||||
q->draw(p.first);
|
||||
}
|
||||
}
|
||||
} // drawAll
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void reset()
|
||||
{
|
||||
g_tbs.clear();
|
||||
g_tbs_update.clear();
|
||||
} // reset
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void updateAll()
|
||||
{
|
||||
for (STKTextBillboard* tb : g_tbs_update)
|
||||
{
|
||||
tb->updateGLInstanceData();
|
||||
}
|
||||
} // updateAll
|
||||
|
||||
}
|
||||
|
||||
#endif
|
31
src/graphics/text_billboard_drawer.hpp
Normal file
31
src/graphics/text_billboard_drawer.hpp
Normal file
@ -0,0 +1,31 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2018 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef TEXT_BILLBOARD_DRAWER_HPP
|
||||
#define TEXT_BILLBOARD_DRAWER_HPP
|
||||
|
||||
class STKTextBillboard;
|
||||
|
||||
namespace TextBillboardDrawer
|
||||
{
|
||||
void addTextBillboard(STKTextBillboard* tb);
|
||||
void drawAll();
|
||||
void reset();
|
||||
void updateAll();
|
||||
}
|
||||
|
||||
#endif
|
@ -31,6 +31,7 @@
|
||||
#include "graphics/central_settings.hpp"
|
||||
#include "graphics/explosion.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/material.hpp"
|
||||
#include "graphics/material_manager.hpp"
|
||||
#include "graphics/particle_emitter.hpp"
|
||||
#include "graphics/particle_kind_manager.hpp"
|
||||
@ -2971,13 +2972,14 @@ void Kart::setOnScreenText(const wchar_t *text)
|
||||
|
||||
if (CVS->isGLSL())
|
||||
{
|
||||
scene::ISceneNode* tb =
|
||||
new STKTextBillboard(text, bold_face,
|
||||
STKTextBillboard* tb =
|
||||
new STKTextBillboard(
|
||||
GUIEngine::getSkin()->getColor("font::bottom"),
|
||||
GUIEngine::getSkin()->getColor("font::top"),
|
||||
getNode(), irr_driver->getSceneManager(), -1,
|
||||
core::vector3df(0.0f, 1.5f, 0.0f),
|
||||
core::vector3df(1.0f, 1.0f, 1.0f));
|
||||
tb->init(text, bold_face);
|
||||
tb->drop();
|
||||
}
|
||||
else
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "font/digit_face.hpp"
|
||||
#include "font/font_manager.hpp"
|
||||
#include "graphics/central_settings.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/stk_text_billboard.hpp"
|
||||
#include "guiengine/scalable_font.hpp"
|
||||
#include "input/device_manager.hpp"
|
||||
@ -98,12 +99,13 @@ namespace Scripting
|
||||
#ifndef SERVER_ONLY
|
||||
if (CVS->isGLSL())
|
||||
{
|
||||
STKTextBillboard* tb = new STKTextBillboard(wtext.c_str(), digit_face,
|
||||
STKTextBillboard* tb = new STKTextBillboard(
|
||||
GUIEngine::getSkin()->getColor("font::bottom"),
|
||||
GUIEngine::getSkin()->getColor("font::top"),
|
||||
irr_driver->getSceneManager()->getRootSceneNode(),
|
||||
irr_driver->getSceneManager(), -1, xyz,
|
||||
core::vector3df(1.5f, 1.5f, 1.5f));
|
||||
tb->init(wtext.c_str(), digit_face);
|
||||
|
||||
::Track::getCurrentTrack()->addNode(tb);
|
||||
tb->drop();
|
||||
|
Loading…
x
Reference in New Issue
Block a user