First version of new texture format

Todo: IBL, texture compression, GLES, premul alpha ....
This commit is contained in:
Benau 2017-01-02 16:14:59 +08:00
parent 6a16f23132
commit 2dbf4675a5
25 changed files with 1818 additions and 1346 deletions

View File

@ -64,7 +64,6 @@ endif()
set(IRRLICHT_SOURCES
source/Irrlicht/CAnimatedMeshSceneNode.cpp
source/Irrlicht/CAttributes.cpp
source/Irrlicht/CB3DMeshFileLoader.cpp
source/Irrlicht/CBillboardSceneNode.cpp
source/Irrlicht/CBoneSceneNode.cpp
source/Irrlicht/CCameraSceneNode.cpp
@ -196,7 +195,6 @@ source/Irrlicht/BuiltInFont.h
source/Irrlicht/CAnimatedMeshSceneNode.h
source/Irrlicht/CAttributeImpl.h
source/Irrlicht/CAttributes.h
source/Irrlicht/CB3DMeshFileLoader.h
source/Irrlicht/CBillboardSceneNode.h
source/Irrlicht/CBlit.h
source/Irrlicht/CBoneSceneNode.h

View File

@ -190,6 +190,9 @@ public:
//! Get name of texture (in most cases this is the filename)
const io::SNamedPath& getName() const { return NamedPath; }
//! return open gl texture name
virtual u32 getOpenGLTextureName() const = 0;
protected:
//! Helper function, helps to get the desired texture creation format from the flags.

File diff suppressed because it is too large Load Diff

View File

@ -1,140 +0,0 @@
// Copyright (C) 2006-2012 Luke Hoschke
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
// B3D Mesh loader
// File format designed by Mark Sibly for the Blitz3D engine and has been
// declared public domain
#include "IrrCompileConfig.h"
#ifndef __C_B3D_MESH_LOADER_H_INCLUDED__
#define __C_B3D_MESH_LOADER_H_INCLUDED__
#include "IMeshLoader.h"
#include "ISceneManager.h"
#include "CSkinnedMesh.h"
#include "IReadFile.h"
namespace irr
{
namespace scene
{
//! Meshloader for B3D format
class CB3DMeshFileLoader : public IMeshLoader
{
public:
//! Constructor
CB3DMeshFileLoader(scene::ISceneManager* smgr);
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".bsp")
virtual bool isALoadableFileExtension(const io::path& filename) const;
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IReferenceCounted::drop() for more information.
virtual IAnimatedMesh* createMesh(io::IReadFile* file);
private:
struct SB3dChunkHeader
{
c8 name[4];
s32 size;
};
struct SB3dChunk
{
SB3dChunk(const SB3dChunkHeader& header, long sp)
: length(header.size+8), startposition(sp)
{
name[0]=header.name[0];
name[1]=header.name[1];
name[2]=header.name[2];
name[3]=header.name[3];
}
c8 name[4];
s32 length;
long startposition;
};
struct SB3dTexture
{
core::stringc TextureName;
s32 Flags;
s32 Blend;
f32 Xpos;
f32 Ypos;
f32 Xscale;
f32 Yscale;
f32 Angle;
};
struct SB3dMaterial
{
SB3dMaterial() : red(1.0f), green(1.0f),
blue(1.0f), alpha(1.0f), shininess(0.0f), blend(1),
fx(0)
{
for (u32 i=0; i<video::MATERIAL_MAX_TEXTURES; ++i)
Textures[i]=0;
}
video::SMaterial Material;
f32 red, green, blue, alpha;
f32 shininess;
s32 blend,fx;
SB3dTexture *Textures[video::MATERIAL_MAX_TEXTURES];
};
bool load();
bool readChunkNODE(CSkinnedMesh::SJoint* InJoint);
bool readChunkMESH(CSkinnedMesh::SJoint* InJoint);
bool readChunkVRTS(CSkinnedMesh::SJoint* InJoint);
bool readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 MeshBufferID, s32 Vertices_Start);
bool readChunkBONE(CSkinnedMesh::SJoint* InJoint);
bool readChunkKEYS(CSkinnedMesh::SJoint* InJoint);
bool readChunkANIM();
bool readChunkTEXS();
bool readChunkBRUS();
void loadTextures(SB3dMaterial& material) const;
void readString(core::stringc& newstring);
void readFloats(f32* vec, u32 count);
core::array<SB3dChunk> B3dStack;
core::array<SB3dMaterial> Materials;
core::array<SB3dTexture> Textures;
core::array<s32> AnimatedVertices_VertexID;
core::array<s32> AnimatedVertices_BufferID;
core::array<video::S3DVertex2TCoords> BaseVertices;
ISceneManager* SceneManager;
CSkinnedMesh* AnimatedMesh;
io::IReadFile* B3DFile;
//B3Ds have Vertex ID's local within the mesh I don't want this
// Variable needs to be class member due to recursion in calls
u32 VerticesStart;
bool NormalsInFile;
bool HasVertexColors;
bool ShowWarning;
};
} // end namespace scene
} // end namespace irr
#endif // __C_B3D_MESH_LOADER_H_INCLUDED__

View File

@ -744,6 +744,7 @@ namespace video
virtual E_DRIVER_TYPE getDriverType() const { return video::EDT_NULL; }
virtual ECOLOR_FORMAT getColorFormat() const { return video::ECF_A1R5G5B5; };
virtual u32 getPitch() const { return 0; }
virtual u32 getOpenGLTextureName() const { return 0; }
virtual void regenerateMipMapLevels(void* mipmapData=0) {};
core::dimension2d<u32> size;
};

View File

@ -81,7 +81,7 @@ public:
virtual u32 getPitch() const;
//! return open gl texture name
GLuint getOpenGLTextureName() const;
virtual u32 getOpenGLTextureName() const;
//! return whether this texture has mipmaps
virtual bool hasMipMaps() const;

View File

@ -78,7 +78,7 @@ public:
virtual u32 getPitch() const;
//! return open gl texture name
GLuint getOpenGLTextureName() const;
virtual u32 getOpenGLTextureName() const;
//! return whether this texture has mipmaps
virtual bool hasMipMaps() const;

View File

@ -24,10 +24,6 @@
#include "CSkinnedMesh.h"
#endif
#ifdef _IRR_COMPILE_WITH_B3D_LOADER_
#include "CB3DMeshFileLoader.h"
#endif
#include "CCubeSceneNode.h"
#include "CSphereSceneNode.h"
#include "CAnimatedMeshSceneNode.h"
@ -121,13 +117,6 @@ CSceneManager::CSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs,
// create geometry creator
GeometryCreator = new CGeometryCreator();
// add file format loaders. add the least commonly used ones first,
// as these are checked last
#ifdef _IRR_COMPILE_WITH_B3D_LOADER_
MeshLoaderList.push_back(new CB3DMeshFileLoader(this));
#endif
// factories
ISceneNodeFactory* factory = new CDefaultSceneNodeFactory(this);
registerSceneNodeFactory(factory);
@ -1427,11 +1416,6 @@ void CSceneManager::drawAll(u32 flags)
void CSceneManager::setLightManager(ILightManager* lightManager)
{
if (lightManager)
lightManager->grab();
if (LightManager)
LightManager->drop();
LightManager = lightManager;
}

View File

@ -1,5 +1,5 @@
# Modify this file to change the last-modified date when you add/remove a file.
# This will then trigger a new cmake run automatically.
# This will then trigger a new cmake run automatically.
file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp")
file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp")
file(GLOB_RECURSE STK_SHADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "data/shaders/*")

View File

@ -28,14 +28,6 @@
#include "graphics/texture_shader.hpp"
#include "utils/cpp2011.hpp"
#if defined(USE_GLES2)
# define _IRR_COMPILE_WITH_OGLES2_
# include "../../lib/irrlicht/source/Irrlicht/COGLES2Texture.h"
#else
# include "../../lib/irrlicht/source/Irrlicht/COpenGLTexture.h"
#endif
// ============================================================================
class Primitive2DList : public TextureShader<Primitive2DList, 1, float>
{
@ -186,16 +178,8 @@ static void drawTexColoredQuad(const video::ITexture *texture,
ColoredTextureRectShader::getInstance()->use();
glBindVertexArray(ColoredTextureRectShader::getInstance()->m_vao);
#if !defined(USE_GLES2)
const irr::video::COpenGLTexture *t =
static_cast<const irr::video::COpenGLTexture*>(texture);
#else
const irr::video::COGLES2Texture *t =
static_cast<const irr::video::COGLES2Texture*>(texture);
#endif
ColoredTextureRectShader::getInstance()
->setTextureUnits(t->getOpenGLTextureName());
->setTextureUnits(texture->getOpenGLTextureName());
ColoredTextureRectShader::getInstance()
->setUniforms(core::vector2df(center_pos_x, center_pos_y),
core::vector2df(width, height),
@ -367,16 +351,8 @@ void draw2DImage(const video::ITexture* texture,
UniformColoredTextureRectShader::getInstance()->use();
glBindVertexArray(SharedGPUObjects::getUI_VAO());
#if !defined(USE_GLES2)
const video::COpenGLTexture *c_texture =
static_cast<const video::COpenGLTexture*>(texture);
#else
const video::COGLES2Texture *c_texture =
static_cast<const video::COGLES2Texture*>(texture);
#endif
UniformColoredTextureRectShader::getInstance()
->setTextureUnits(c_texture->getOpenGLTextureName());
->setTextureUnits(texture->getOpenGLTextureName());
UniformColoredTextureRectShader::getInstance()
->setUniforms(core::vector2df(center_pos_x, center_pos_y),
@ -450,16 +426,8 @@ void draw2DImage(const video::ITexture* texture,
UniformColoredTextureRectShader::getInstance()->use();
glBindVertexArray(SharedGPUObjects::getUI_VAO());
#if !defined(USE_GLES2)
const video::COpenGLTexture *c_texture =
static_cast<const video::COpenGLTexture*>(texture);
#else
const video::COGLES2Texture *c_texture =
static_cast<const video::COGLES2Texture*>(texture);
#endif
UniformColoredTextureRectShader::getInstance()
->setTextureUnits(c_texture->getOpenGLTextureName());
->setTextureUnits(texture->getOpenGLTextureName());
UniformColoredTextureRectShader::getInstance()
->setUniforms(core::vector2df(center_pos_x, center_pos_y),
@ -574,14 +542,7 @@ void draw2DImage(const video::ITexture* texture,
}
else
{
#if !defined(USE_GLES2)
const video::COpenGLTexture *c_texture =
static_cast<const video::COpenGLTexture*>(texture);
#else
const video::COGLES2Texture *c_texture =
static_cast<const video::COGLES2Texture*>(texture);
#endif
drawTexQuad(c_texture->getOpenGLTextureName(), width, height,
drawTexQuad(texture->getOpenGLTextureName(), width, height,
center_pos_x, center_pos_y, tex_center_pos_x,
tex_center_pos_y, tex_width, tex_height);
}
@ -657,14 +618,7 @@ void draw2DImage(const video::ITexture* texture,
}
else
{
#if !defined(USE_GLES2)
const video::COpenGLTexture *c_texture =
static_cast<const video::COpenGLTexture*>(texture);
#else
const video::COGLES2Texture *c_texture =
static_cast<const video::COGLES2Texture*>(texture);
#endif
drawTexQuad(c_texture->getOpenGLTextureName(), width, height,
drawTexQuad(texture->getOpenGLTextureName(), width, height,
center_pos_x, center_pos_y, tex_center_pos_x,
tex_center_pos_y, tex_width, tex_height);
}

View File

@ -36,7 +36,10 @@
#include "graphics/shaders.hpp"
#include "graphics/stk_animated_mesh.hpp"
#include "graphics/stk_billboard.hpp"
#include "graphics/stk_mesh_loader.hpp"
#include "graphics/stk_mesh_scene_node.hpp"
#include "graphics/stk_tex_manager.hpp"
#include "graphics/stk_texture.hpp"
#include "graphics/sun.hpp"
#include "graphics/texture_manager.hpp"
#include "guiengine/engine.hpp"
@ -600,6 +603,9 @@ void IrrDriver::initDevice()
m_scene_manager = m_device->getSceneManager();
m_gui_env = m_device->getGUIEnvironment();
m_video_driver = m_device->getVideoDriver();
STKMeshLoader* sml = new STKMeshLoader(m_scene_manager);
m_scene_manager->addExternalMeshLoader(sml);
sml->drop();
m_actual_screen_size = m_video_driver->getCurrentRenderTargetSize();
#ifndef SERVER_ONLY
@ -1671,6 +1677,11 @@ video::ITexture *IrrDriver::getTexture(const std::string &filename,
bool is_prediv,
bool complain_if_not_found)
{
if (CVS->isGLSL())
{
return STKTexManager::getInstance()->getTexture(filename);
}
video::ITexture* out;
if(!is_premul && !is_prediv)
{

View File

@ -399,12 +399,11 @@ Material::Material(const XMLNode *node, bool deprecated)
m_high_tire_adhesion = true;
} // Material
//-----------------------------------------------------------------------------
video::ITexture* Material::getTexture()
video::ITexture* Material::getTexture(bool srgb, bool premul_alpha)
{
if (!m_installed)
{
install();
install(srgb, premul_alpha);
}
return m_texture;
} // getTexture
@ -489,7 +488,7 @@ void Material::init()
} // init
//-----------------------------------------------------------------------------
void Material::install()
void Material::install(bool srgb, bool premul_alpha)
{
// Don't load a texture that are not supposed to be loaded automatically
if (m_installed) return;
@ -515,7 +514,7 @@ void Material::install()
// now set the name to the basename, so that all tests work as expected
m_texname = StringUtils::getBasename(m_texname);
if (m_mask.size() > 0)
if (!CVS->isGLSL() && m_mask.size() > 0)
{
irr_driver->applyMask(m_texture, m_mask);
}

View File

@ -267,7 +267,7 @@ private:
bool m_installed;
void init ();
void install ();
void install (bool srgb = false, bool premul_alpha = false);
void initCustomSFX(const XMLNode *sfx);
void initParticlesEffect(const XMLNode *node);
@ -290,7 +290,7 @@ public:
void isInitiallyHidden(scene::IMeshBuffer* who);
/** Returns the ITexture associated with this material. */
video::ITexture *getTexture();
video::ITexture *getTexture(bool srgb = false, bool premul_alpha = false);
// ------------------------------------------------------------------------
bool isIgnore () const { return m_ignore; }
// ------------------------------------------------------------------------
@ -419,7 +419,8 @@ public:
/** True if this texture should have the U coordinates mirrored. */
char getMirrorAxisInReverse() const { return m_mirror_axis_when_reverse; }
// ------------------------------------------------------------------------
} ;
const std::string getAlphaMask() const { return m_mask; }
};
#endif

View File

@ -78,13 +78,8 @@ Material* MaterialManager::getMaterialFor(video::ITexture* t,
}
//-----------------------------------------------------------------------------
Material* MaterialManager::getMaterialFor(video::ITexture* t,
video::E_MATERIAL_TYPE material_type)
Material* MaterialManager::getMaterialFor(video::ITexture* t)
{
if (t == NULL)
return getDefaultMaterial(material_type);
core::stringc img_path = core::stringc(t->getName());
img_path.make_lower();
@ -116,6 +111,19 @@ Material* MaterialManager::getMaterialFor(video::ITexture* t,
}
} // for i
}
return NULL;
}
//-----------------------------------------------------------------------------
Material* MaterialManager::getMaterialFor(video::ITexture* t,
video::E_MATERIAL_TYPE material_type)
{
if (t == NULL)
return getDefaultMaterial(material_type);
Material* m = getMaterialFor(t);
if (m != NULL)
return m;
return getDefaultMaterial(material_type);
}

View File

@ -61,6 +61,7 @@ public:
scene::IMeshBuffer *mb);
Material* getMaterialFor(video::ITexture* t,
video::E_MATERIAL_TYPE material_type);
Material* getMaterialFor(video::ITexture* t);
void setAllMaterialFlags(video::ITexture* t,
scene::IMeshBuffer *mb);
void adjustForFog(video::ITexture* t,

View File

@ -333,6 +333,7 @@ Out of legacy the sequence of textures maps to:
*/
Skybox::Skybox(const std::vector<video::ITexture *> &skybox_textures)
{
return;
m_skybox_textures = skybox_textures;
#if !defined(USE_GLES2)

View File

@ -385,6 +385,7 @@ SphericalHarmonics::~SphericalHarmonics()
/** Compute spherical harmonics coefficients from 6 textures */
void SphericalHarmonics::setTextures(const std::vector<video::ITexture *> &spherical_harmonics_textures)
{
return;
assert(spherical_harmonics_textures.size() == 6);
m_spherical_harmonics_textures = spherical_harmonics_textures;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,139 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2017 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 HEADER_STK_MESH_LOADER_HPP
#define HEADER_STK_MESH_LOADER_HPP
#include "../lib/irrlicht/source/Irrlicht/CSkinnedMesh.h"
#include <IMeshLoader.h>
#include <ISceneManager.h>
#include <IReadFile.h>
using namespace irr;
class STKMeshLoader : public scene::IMeshLoader
{
public:
//! Constructor
STKMeshLoader(scene::ISceneManager* smgr);
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".bsp")
virtual bool isALoadableFileExtension(const io::path& filename) const;
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IReferenceCounted::drop() for more information.
virtual scene::IAnimatedMesh* createMesh(io::IReadFile* file);
private:
struct SB3dChunkHeader
{
c8 name[4];
s32 size;
};
struct SB3dChunk
{
SB3dChunk(const SB3dChunkHeader& header, long sp)
: length(header.size+8), startposition(sp)
{
name[0]=header.name[0];
name[1]=header.name[1];
name[2]=header.name[2];
name[3]=header.name[3];
}
c8 name[4];
s32 length;
long startposition;
};
struct SB3dTexture
{
core::stringc TextureName;
s32 Flags;
s32 Blend;
f32 Xpos;
f32 Ypos;
f32 Xscale;
f32 Yscale;
f32 Angle;
};
struct SB3dMaterial
{
SB3dMaterial() : red(1.0f), green(1.0f),
blue(1.0f), alpha(1.0f), shininess(0.0f), blend(1),
fx(0)
{
for (u32 i=0; i<video::MATERIAL_MAX_TEXTURES; ++i)
Textures[i]=0;
}
video::SMaterial Material;
f32 red, green, blue, alpha;
f32 shininess;
s32 blend,fx;
SB3dTexture *Textures[video::MATERIAL_MAX_TEXTURES];
};
bool load();
bool readChunkNODE(scene::CSkinnedMesh::SJoint* InJoint);
bool readChunkMESH(scene::CSkinnedMesh::SJoint* InJoint);
bool readChunkVRTS(scene::CSkinnedMesh::SJoint* InJoint);
bool readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 MeshBufferID, s32 Vertices_Start);
bool readChunkBONE(scene::CSkinnedMesh::SJoint* InJoint);
bool readChunkKEYS(scene::CSkinnedMesh::SJoint* InJoint);
bool readChunkANIM();
bool readChunkTEXS();
bool readChunkBRUS();
void loadTextures(SB3dMaterial& material) const;
void readString(core::stringc& newstring);
void readFloats(f32* vec, u32 count);
core::array<SB3dChunk> B3dStack;
core::array<SB3dMaterial> Materials;
core::array<SB3dTexture> Textures;
core::array<s32> AnimatedVertices_VertexID;
core::array<s32> AnimatedVertices_BufferID;
core::array<video::S3DVertex2TCoords> BaseVertices;
scene::ISceneManager* SceneManager;
scene::CSkinnedMesh* AnimatedMesh;
io::IReadFile* B3DFile;
//B3Ds have Vertex ID's local within the mesh I don't want this
// Variable needs to be class member due to recursion in calls
u32 VerticesStart;
bool NormalsInFile;
bool HasVertexColors;
bool ShowWarning;
};
#endif

View File

@ -0,0 +1,126 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2017 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.
#include "graphics/stk_tex_manager.hpp"
#include "graphics/central_settings.hpp"
#include "graphics/stk_texture.hpp"
#include "io/file_manager.hpp"
#include "utils/string_utils.hpp"
#include "utils/log.hpp"
#include <fstream>
#include <sstream>
// ----------------------------------------------------------------------------
STKTexManager::~STKTexManager()
{
} // ~STKTexManager
// ----------------------------------------------------------------------------
STKTexture* STKTexManager::findTextureInFileSystem(const std::string& filename,
std::string* full_path)
{
*full_path = file_manager->searchTexture(filename);
if (*full_path == "")
{
Log::warn("STKTexManager", "Failed to load %s.", filename.c_str());
return NULL;
}
for (auto p : m_all_textures)
{
if (p.second == NULL)
continue;
if (*full_path == p.second->getName().getPtr())
return p.second;
}
return NULL;
} // findTextureInFileSystem
// ----------------------------------------------------------------------------
STKTexture* STKTexManager::findTexturePathless(const std::string& filename)
{
for (auto p : m_all_textures)
{
if (p.second == NULL)
continue;
std::string lc_name = StringUtils::toLowerCase(filename);
std::string lc_path =
StringUtils::toLowerCase(p.second->getName().getPtr());
std::string tex_name = StringUtils::getBasename(lc_path);
if (lc_name == tex_name || lc_name == lc_path)
return p.second;
}
return NULL;
} // findTexturePathless
// ----------------------------------------------------------------------------
STKTexture* STKTexManager::getTexture(const std::string& path, bool srgb,
bool premul_alpha, bool set_material)
{
auto ret = m_all_textures.find(path);
if (ret != m_all_textures.end())
return ret->second;
STKTexture* new_texture = NULL;
std::string full_path;
if (path.find('/') == std::string::npos)
{
new_texture = findTextureInFileSystem(path, &full_path);
if (full_path == "")
return NULL;
if (new_texture)
return new_texture;
}
new_texture = new STKTexture(full_path == "" ? path : full_path, srgb,
premul_alpha, set_material);
new_texture->reload();
if (new_texture->getOpenGLTextureName() == 0)
{
m_all_textures[new_texture->getName().getPtr()] = NULL;
delete new_texture;
return NULL;
}
m_all_textures[new_texture->getName().getPtr()] = new_texture;
return new_texture;
} // getTexture
// ----------------------------------------------------------------------------
void STKTexManager::dumpAllTexture()
{
for (auto p : m_all_textures)
{
Log::info("STKTexManager", "%s loc: %p", p.first.c_str(), p.second);
}
} // dumpAllTexture
// ----------------------------------------------------------------------------
int STKTexManager::dumpTextureUsage()
{
int size = 0;
for (auto p : m_all_textures)
{
if (p.second == NULL)
continue;
size += p.second->getTextureSize() / 1024 / 1024;
}
Log::info("STKTexManager", "Total %dMB", size);
return size;
} // dumpAllTexture

View File

@ -0,0 +1,61 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2016 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 HEADER_STK_TEX_MANAGER_HPP
#define HEADER_STK_TEX_MANAGER_HPP
#include "graphics/gl_headers.hpp"
#include "utils/no_copy.hpp"
#include "utils/singleton.hpp"
#include <algorithm>
#include <string>
#include <unordered_map>
class STKTexture;
class STKTexManager : public Singleton<STKTexManager>, NoCopy
{
private:
std::unordered_map<std::string, STKTexture*> m_all_textures;
public:
// ------------------------------------------------------------------------
STKTexManager() {}
// ------------------------------------------------------------------------
~STKTexManager();
// ------------------------------------------------------------------------
STKTexture* findTexturePathless(const std::string& filename);
// ------------------------------------------------------------------------
STKTexture* findTextureInFileSystem(const std::string& filename,
std::string* full_path);
// ------------------------------------------------------------------------
STKTexture* getTexture(const std::string& path, bool srgb = false,
bool premul_alpha = false,
bool set_material = false);
// ------------------------------------------------------------------------
void removeTexture(STKTexture* t);
// ------------------------------------------------------------------------
void dumpAllTexture();
// ------------------------------------------------------------------------
int dumpTextureUsage();
// ------------------------------------------------------------------------
void clean();
}; // STKTexManager
#endif

View File

@ -0,0 +1,214 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2017 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.
#include "graphics/stk_texture.hpp"
#include "graphics/central_settings.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material.hpp"
#include "graphics/material_manager.hpp"
#include "io/file_manager.hpp"
#include "utils/string_utils.hpp"
#include "utils/log.hpp"
#include <fstream>
#include <sstream>
// ----------------------------------------------------------------------------
STKTexture::STKTexture(const std::string& path, bool srgb, bool premul_alpha,
bool set_material)
: video::ITexture(path.c_str()), m_texture_handle(0), m_srgb(srgb),
m_premul_alpha(premul_alpha), m_mesh_texture(set_material),
m_material(NULL), m_texture_name(0), m_texture_size(0),
m_texture_image(NULL)
{
if (set_material)
{
m_material = material_manager->getMaterialFor(this);
}
} // STKTexture
// ----------------------------------------------------------------------------
STKTexture::STKTexture(video::IImage* image)
: video::ITexture(""), m_texture_handle(0), m_srgb(false),
m_premul_alpha(false),
m_mesh_texture(false), m_texture_name(0), m_texture_size(0),
m_texture_image(image)
{
m_size = m_texture_image->getDimension();
m_orig_size = m_texture_image->getDimension();
} // STKTexture
// ----------------------------------------------------------------------------
STKTexture::~STKTexture()
{
if (m_texture_name != 0)
{
glDeleteTextures(1, &m_texture_name);
}
if (m_texture_image != NULL)
m_texture_image->drop();
} // ~STKTexture
// ----------------------------------------------------------------------------
void STKTexture::reload()
{
#ifndef SERVER_ONLY
irr_driver->getDevice()->getLogger()->setLogLevel(ELL_NONE);
video::IImage* orig_img =
irr_driver->getVideoDriver()->createImageFromFile(NamedPath);
if (orig_img == NULL)
{
Log::warn("STKTexture", "No image %s.", NamedPath.getPtr());
return;
}
if (orig_img->getDimension().Width == 0 ||
orig_img->getDimension().Height == 0)
{
Log::warn("STKTexture", "image %s has 0 size.", NamedPath.getPtr());
return;
}
video::IImage* new_texture = convertImage(&orig_img);
applyMask(new_texture);
const bool reload = m_texture_name != 0;
if (!reload)
glGenTextures(1, &m_texture_name);
glBindTexture(GL_TEXTURE_2D, m_texture_name);
if (!reload)
{
glTexImage2D(GL_TEXTURE_2D, 0, m_srgb ? GL_SRGB_ALPHA : GL_RGBA,
new_texture->getDimension().Width,
new_texture->getDimension().Height, 0, GL_BGRA, GL_UNSIGNED_BYTE,
new_texture->lock());
}
else
{
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
new_texture->getDimension().Width,
new_texture->getDimension().Height, GL_BGRA, GL_UNSIGNED_BYTE,
new_texture->lock());
}
new_texture->unlock();
m_size = new_texture->getDimension();
m_orig_size = orig_img->getDimension();
m_texture_size = m_size.Width * m_size.Height * 4 /*BRGA*/;
new_texture->drop();
orig_img->drop();
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
irr_driver->getDevice()->getLogger()->setLogLevel(ELL_WARNING);
#endif // !SERVER_ONLY
} // reload
// ----------------------------------------------------------------------------
video::IImage* STKTexture::convertImage(video::IImage** orig_img)
{
#ifndef SERVER_ONLY
video::IImage* image = *orig_img;
core::dimension2du size = image->getDimension();
bool scale_image = false;
const float ratio = float(size.Width) / float(size.Height);
const unsigned int drv_max_size =
irr_driver->getVideoDriver()->getMaxTextureSize().Width;
if ((size.Width > drv_max_size) && (ratio >= 1.0f))
{
size.Width = drv_max_size;
size.Height = (unsigned)(drv_max_size / ratio);
scale_image = true;
}
else if (size.Height > drv_max_size)
{
size.Height = drv_max_size;
size.Width = (unsigned)(drv_max_size * ratio);
scale_image = true;
}
if (scale_image)
{
video::IImage* new_img = irr_driver->getVideoDriver()
->createImage(video::ECF_A8R8G8B8, size);
image->copyToScaling(new_img);
image->drop();
image = new_img;
*orig_img = new_img;
}
bool scale_texture = false;
size = size.getOptimalSize
(!irr_driver->getVideoDriver()->queryFeature(video::EVDF_TEXTURE_NPOT));
const core::dimension2du& max_size = irr_driver->getVideoDriver()
->getDriverAttributes().getAttributeAsDimension2d("MAX_TEXTURE_SIZE");
if (max_size.Width > 0 && size.Width > max_size.Width)
{
size.Width = max_size.Width;
scale_texture = true;
}
if (max_size.Height > 0 && size.Height > max_size.Height)
{
size.Height = max_size.Height;
scale_texture = true;
}
video::IImage* new_texture =
irr_driver->getVideoDriver()->createImage(video::ECF_A8R8G8B8, size);
if (scale_texture)
image->copyToScaling(new_texture);
else
image->copyTo(new_texture);
return new_texture;
#endif // !SERVER_ONLY
} // convertImage
// ----------------------------------------------------------------------------
void STKTexture::applyMask(video::IImage* orig_img)
{
#ifndef SERVER_ONLY
if (m_material && !m_material->getAlphaMask().empty())
{
video::IImage* tmp_mask = irr_driver->getVideoDriver()
->createImageFromFile(m_material->getAlphaMask().c_str());
if (tmp_mask == NULL)
{
Log::warn("STKTexture", "Applying mask failed for '%s'!",
m_material->getAlphaMask().c_str());
return;
}
video::IImage* converted_mask = convertImage(&tmp_mask);
tmp_mask->drop();
if (converted_mask->lock())
{
core::dimension2d<u32> dim = orig_img->getDimension();
for (unsigned int x = 0; x < dim.Width; x++)
{
for (unsigned int y = 0; y < dim.Height; y++)
{
video::SColor col = orig_img->getPixel(x, y);
video::SColor alpha = converted_mask->getPixel(x, y);
col.setAlpha(alpha.getRed());
orig_img->setPixel(x, y, col, false);
} // for y
} // for x
}
}
#endif // !SERVER_ONLY
} // applyMask

View File

@ -0,0 +1,115 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2017 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 HEADER_STK_TEXTURE_HPP
#define HEADER_STK_TEXTURE_HPP
#include "graphics/gl_headers.hpp"
#include "utils/no_copy.hpp"
#include <string>
#include <ITexture.h>
using namespace irr;
class Material;
class STKTexture : public video::ITexture, NoCopy
{
private:
core::dimension2d<u32> m_size, m_orig_size;
uint64_t m_texture_handle;
bool m_srgb, m_premul_alpha, m_mesh_texture;
Material* m_material;
GLuint m_texture_name;
unsigned int m_texture_size;
video::IImage* m_texture_image;
// ------------------------------------------------------------------------
video::IImage* convertImage(video::IImage** orig_img);
// ------------------------------------------------------------------------
void applyMask(video::IImage* orig_img);
public:
// ------------------------------------------------------------------------
STKTexture(const std::string& path, bool srgb = false,
bool premul_alpha = false, bool mesh_texture = false);
// ------------------------------------------------------------------------
STKTexture(video::IImage* image);
// ------------------------------------------------------------------------
~STKTexture();
// ------------------------------------------------------------------------
virtual void* lock(video::E_TEXTURE_LOCK_MODE mode =
video::ETLM_READ_WRITE, u32 mipmap_level = 0)
{
if (m_texture_image)
return m_texture_image->lock();
return NULL;
}
// ------------------------------------------------------------------------
virtual void unlock()
{
if (m_texture_image)
m_texture_image->unlock();
}
// ------------------------------------------------------------------------
virtual const core::dimension2d<u32>& getOriginalSize() const
{ return m_orig_size; }
// ------------------------------------------------------------------------
virtual const core::dimension2d<u32>& getSize() const { return m_size; }
// ------------------------------------------------------------------------
virtual video::E_DRIVER_TYPE getDriverType() const
{
#if defined(USE_GLES2)
return video::EDT_OGLES2;
#else
return video::EDT_OPENGL;
#endif
}
// ------------------------------------------------------------------------
virtual video::ECOLOR_FORMAT getColorFormat() const
{ return video::ECF_A8R8G8B8; }
// ------------------------------------------------------------------------
virtual u32 getPitch() const { return 0; }
// ------------------------------------------------------------------------
virtual void regenerateMipMapLevels(void* mipmap_data = NULL) {}
// ------------------------------------------------------------------------
virtual u32 getOpenGLTextureName() const { return m_texture_name; }
// ------------------------------------------------------------------------
uint64_t getTextureHandle() const { return m_texture_handle; }
// ------------------------------------------------------------------------
bool isSrgb() const { return m_srgb; }
// ------------------------------------------------------------------------
bool isPremulAlpha() const { return m_premul_alpha; }
// ------------------------------------------------------------------------
bool isMeshTexture() const { return m_mesh_texture; }
// ------------------------------------------------------------------------
void setMeshTexture(bool val) { m_mesh_texture = val; }
// ------------------------------------------------------------------------
unsigned int getTextureSize() const { return m_texture_size; }
// ------------------------------------------------------------------------
void reload();
}; // STKTexture
#endif

View File

@ -22,6 +22,7 @@
#include "graphics/central_settings.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/materials.hpp"
#include "graphics/stk_texture.hpp"
#include "utils/string_utils.hpp"
#if defined(USE_GLES2)
@ -40,22 +41,9 @@ GLuint getTextureGLuint(irr::video::ITexture *tex)
{
if (tex == NULL)
return 0;
#if defined(USE_GLES2)
return static_cast<irr::video::COGLES2Texture*>(tex)->getOpenGLTextureName();
#else
return static_cast<irr::video::COpenGLTexture*>(tex)->getOpenGLTextureName();
#endif
return tex->getOpenGLTextureName();
}
GLuint getDepthTexture(irr::video::ITexture *tex)
{
assert(tex->isRenderTarget());
#if defined(USE_GLES2)
return static_cast<irr::video::COGLES2FBOTexture*>(tex)->DepthBufferTexture;
#else
return static_cast<irr::video::COpenGLFBOTexture*>(tex)->DepthBufferTexture;
#endif
}
static std::set<irr::video::ITexture *> AlreadyTransformedTexture;
static std::map<int, video::ITexture*> unicolor_cache;
@ -94,6 +82,9 @@ void cleanUnicolorTextures()
void compressTexture(irr::video::ITexture *tex, bool srgb, bool premul_alpha)
{
STKTexture* stk_tex = dynamic_cast<STKTexture*>(tex);
if (stk_tex) return;
if (AlreadyTransformedTexture.find(tex) != AlreadyTransformedTexture.end())
return;
AlreadyTransformedTexture.insert(tex);

View File

@ -26,7 +26,7 @@
#include <string>
GLuint getTextureGLuint(irr::video::ITexture *tex);
GLuint getDepthTexture(irr::video::ITexture *tex);
void resetTextureTable();
void cleanUnicolorTextures();
void compressTexture(irr::video::ITexture *tex, bool srgb, bool premul_alpha = false);