Allow using single color channel for font texture

This commit is contained in:
Benau 2017-01-07 16:36:25 +08:00
parent f78d749a0c
commit 314c32865b
4 changed files with 84 additions and 52 deletions

View File

@ -22,6 +22,7 @@
#include "font/font_manager.hpp" #include "font/font_manager.hpp"
#include "font/font_settings.hpp" #include "font/font_settings.hpp"
#include "graphics/2dutils.hpp" #include "graphics/2dutils.hpp"
#include "graphics/central_settings.hpp"
#include "graphics/irr_driver.hpp" #include "graphics/irr_driver.hpp"
#include "graphics/stk_texture.hpp" #include "graphics/stk_texture.hpp"
#include "graphics/stk_tex_manager.hpp" #include "graphics/stk_tex_manager.hpp"
@ -131,13 +132,24 @@ void FontWithFace::loadGlyphInfo(wchar_t c)
*/ */
void FontWithFace::createNewGlyphPage() void FontWithFace::createNewGlyphPage()
{ {
uint8_t* data = new uint8_t[getGlyphPageSize() * getGlyphPageSize() * 4](); #ifndef SERVER_ONLY
uint8_t* data = new uint8_t[getGlyphPageSize() * getGlyphPageSize() *
(CVS->isARBTextureSwizzleUsable() ? 1 : 4)];
#else
uint8_t* data = NULL;
#endif
m_current_height = 0; m_current_height = 0;
m_used_width = 0; m_used_width = 0;
m_used_height = 0; m_used_height = 0;
STKTexture* stkt = new STKTexture(data, typeid(*this).name() + STKTexture* stkt = new STKTexture(data, typeid(*this).name() +
StringUtils::toString(m_spritebank->getTextureCount()), StringUtils::toString(m_spritebank->getTextureCount()),
getGlyphPageSize()); getGlyphPageSize(),
#ifndef SERVER_ONLY
CVS->isARBTextureSwizzleUsable()
#else
false
#endif
);
m_spritebank->addTexture(stkt); m_spritebank->addTexture(stkt);
STKTexManager::getInstance()->addTexture(stkt); STKTexManager::getInstance()->addTexture(stkt);
} // createNewGlyphPage } // createNewGlyphPage
@ -180,6 +192,25 @@ void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi)
createNewGlyphPage(); createNewGlyphPage();
} }
// Determine the linebreak location
if (m_used_width + texture_size.Width > getGlyphPageSize())
{
m_used_width = 0;
m_used_height += m_current_height;
m_current_height = 0;
}
const unsigned int cur_tex = m_spritebank->getTextureCount() -1;
#ifndef SERVER_ONLY
video::ITexture* tex = m_spritebank->getTexture(cur_tex);
glBindTexture(GL_TEXTURE_2D, tex->getOpenGLTextureName());
if (CVS->isARBTextureSwizzleUsable())
{
glTexSubImage2D(GL_TEXTURE_2D, 0, m_used_width, m_used_height,
bits.width, bits.rows, GL_RED, GL_UNSIGNED_BYTE, bits.buffer);
}
else
{
std::vector<uint32_t> image_data; std::vector<uint32_t> image_data;
image_data.resize(texture_size.Width * texture_size.Height, image_data.resize(texture_size.Width * texture_size.Height,
video::SColor(0, 255, 255, 255).color); video::SColor(0, 255, 255, 255).color);
@ -208,33 +239,10 @@ void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi)
default: default:
assert(false); assert(false);
} }
// Done creating a single glyph, now copy to the glyph page...
// Determine the linebreak location
if (m_used_width + texture_size.Width > getGlyphPageSize())
{
m_used_width = 0;
m_used_height += m_current_height;
m_current_height = 0;
}
const unsigned int cur_tex = m_spritebank->getTextureCount() -1;
#ifndef SERVER_ONLY
video::ITexture* tex = m_spritebank->getTexture(cur_tex);
glBindTexture(GL_TEXTURE_2D, tex->getOpenGLTextureName());
unsigned int format = GL_BGRA;
#if defined(USE_GLES2)
if (!CVS->isEXTTextureFormatBGRA8888Usable())
format = GL_RGBA;
#endif
glTexSubImage2D(GL_TEXTURE_2D, 0, m_used_width, m_used_height, glTexSubImage2D(GL_TEXTURE_2D, 0, m_used_width, m_used_height,
texture_size.Width, texture_size.Height, format, GL_UNSIGNED_BYTE, texture_size.Width, texture_size.Height, GL_BGRA, GL_UNSIGNED_BYTE,
image_data.data()); image_data.data());
//glPixelStorei(GL_UNPACK_ALIGNMENT, 1); }
//static GLint swizzle_mask[] = { GL_ONE, GL_ONE, GL_ONE, GL_RED };
//glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle_mask);
//glTexSubImage2D(GL_TEXTURE_2D, 0, m_used_width, m_used_height, bits.width, bits.rows, GL_RED, GL_UNSIGNED_BYTE, bits.buffer);
//glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
if (tex->hasMipMaps()) if (tex->hasMipMaps())
glGenerateMipmap(GL_TEXTURE_2D); glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);

View File

@ -51,6 +51,7 @@ void CentralVideoSettings::init()
hasExplicitAttribLocation = false; hasExplicitAttribLocation = false;
hasGS = false; hasGS = false;
hasTextureFilterAnisotropic = false; hasTextureFilterAnisotropic = false;
hasTextureSwizzle = false;
#if defined(USE_GLES2) #if defined(USE_GLES2)
hasBGRA = false; hasBGRA = false;
@ -182,7 +183,11 @@ void CentralVideoSettings::init()
hasGS = true; hasGS = true;
Log::info("GLDriver", "Geometry Shaders Present"); Log::info("GLDriver", "Geometry Shaders Present");
} }
if (hasGLExtension("GL_ARB_texture_swizzle"))
{
hasTextureSwizzle = true;
Log::info("GLDriver", "ARB Texture Swizzle Present");
}
// Only unset the high def textures if they are set as default. If the // Only unset the high def textures if they are set as default. If the
// user has enabled them (bit 1 set), then leave them enabled. // user has enabled them (bit 1 set), then leave them enabled.
if (GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_HIGHDEFINITION_TEXTURES) && if (GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_HIGHDEFINITION_TEXTURES) &&
@ -228,6 +233,7 @@ void CentralVideoSettings::init()
if (m_glsl == true) if (m_glsl == true)
{ {
hasTextureStorage = true; hasTextureStorage = true;
hasTextureSwizzle = true;
} }
if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_TEXTURE_FORMAT_BGRA8888) && if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_TEXTURE_FORMAT_BGRA8888) &&
@ -447,4 +453,10 @@ bool CentralVideoSettings::supportsHardwareSkinning() const
{ {
return isARBUniformBufferObjectUsable(); return isARBUniformBufferObjectUsable();
} }
bool CentralVideoSettings::isARBTextureSwizzleUsable() const
{
return m_glsl && hasTextureSwizzle;
}
#endif // !SERVER_ONLY #endif // !SERVER_ONLY

View File

@ -43,6 +43,7 @@ private:
bool hasImageLoadStore; bool hasImageLoadStore;
bool hasMultiDrawIndirect; bool hasMultiDrawIndirect;
bool hasTextureFilterAnisotropic; bool hasTextureFilterAnisotropic;
bool hasTextureSwizzle;
#if defined(USE_GLES2) #if defined(USE_GLES2)
bool hasBGRA; bool hasBGRA;
@ -82,6 +83,7 @@ public:
bool isARBMultiDrawIndirectUsable() const; bool isARBMultiDrawIndirectUsable() const;
bool isARBExplicitAttribLocationUsable() const; bool isARBExplicitAttribLocationUsable() const;
bool isEXTTextureFilterAnisotropicUsable() const; bool isEXTTextureFilterAnisotropicUsable() const;
bool isARBTextureSwizzleUsable() const;
#if defined(USE_GLES2) #if defined(USE_GLES2)
bool isEXTTextureFormatBGRA8888Usable() const; bool isEXTTextureFormatBGRA8888Usable() const;

View File

@ -82,6 +82,8 @@ void STKTexture::reload(bool no_upload, uint8_t* preload_data,
if (ProfileWorld::isNoGraphics()) if (ProfileWorld::isNoGraphics())
{ {
m_texture_name = 1; m_texture_name = 1;
if (preload_data)
delete[] preload_data;
return; return;
} }
#ifndef SERVER_ONLY #ifndef SERVER_ONLY
@ -156,8 +158,8 @@ void STKTexture::reload(bool no_upload, uint8_t* preload_data,
const unsigned int w = m_size.Width; const unsigned int w = m_size.Width;
const unsigned int h = m_size.Height; const unsigned int h = m_size.Height;
unsigned int format = GL_BGRA; unsigned int format = single_channel ? GL_RED : GL_BGRA;
unsigned int internal_format = GL_RGBA; unsigned int internal_format = single_channel ? GL_RED : GL_RGBA;
#if !defined(USE_GLES2) #if !defined(USE_GLES2)
if (m_mesh_texture && CVS->isTextureCompressionEnabled()) if (m_mesh_texture && CVS->isTextureCompressionEnabled())
@ -166,14 +168,14 @@ void STKTexture::reload(bool no_upload, uint8_t* preload_data,
GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT : GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT :
GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
} }
else else if (!single_channel)
{ {
internal_format = m_srgb ? GL_SRGB_ALPHA : GL_RGBA; internal_format = m_srgb ? GL_SRGB_ALPHA : GL_RGBA;
} }
#endif #endif
#if defined(USE_GLES2) #if defined(USE_GLES2)
if (!CVS->isEXTTextureFormatBGRA8888Usable()) if (!CVS->isEXTTextureFormatBGRA8888Usable() && !single_channel)
{ {
format = GL_RGBA; format = GL_RGBA;
for (unsigned int i = 0; i < w * h; i++) for (unsigned int i = 0; i < w * h; i++)
@ -206,6 +208,14 @@ void STKTexture::reload(bool no_upload, uint8_t* preload_data,
glBindTexture(GL_TEXTURE_2D, m_texture_name); glBindTexture(GL_TEXTURE_2D, m_texture_name);
if (!reload) if (!reload)
{ {
if (single_channel)
{
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ONE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_ONE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_ONE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED);
}
glTexImage2D(GL_TEXTURE_2D, 0, internal_format, w, h, 0, format, glTexImage2D(GL_TEXTURE_2D, 0, internal_format, w, h, 0, format,
GL_UNSIGNED_BYTE, data); GL_UNSIGNED_BYTE, data);
} }
@ -220,7 +230,7 @@ void STKTexture::reload(bool no_upload, uint8_t* preload_data,
glGenerateMipmap(GL_TEXTURE_2D); glGenerateMipmap(GL_TEXTURE_2D);
} }
m_texture_size = w * h * 4 /*BRGA*/; m_texture_size = w * h * (single_channel ? 1 : 4);
if (no_upload) if (no_upload)
m_texture_image = orig_img; m_texture_image = orig_img;
else if (orig_img) else if (orig_img)
@ -454,10 +464,10 @@ bool STKTexture::hasMipMaps() const
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void* STKTexture::lock(video::E_TEXTURE_LOCK_MODE mode, u32 mipmap_level) void* STKTexture::lock(video::E_TEXTURE_LOCK_MODE mode, u32 mipmap_level)
{ {
#ifndef SERVER_ONLY
if (m_texture_image) if (m_texture_image)
return m_texture_image->lock(); return m_texture_image->lock();
#if !(defined(SERVER_ONLY) || defined(USE_GLES2))
uint8_t* pixels = new uint8_t[m_size.Width * m_size.Height * 4](); uint8_t* pixels = new uint8_t[m_size.Width * m_size.Height * 4]();
GLint tmp_texture; GLint tmp_texture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &tmp_texture); glGetIntegerv(GL_TEXTURE_BINDING_2D, &tmp_texture);