1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-09-18 16:32:32 +02:00

Overhaul texture handling, add TextureData handles.

+ Use shared ptrs to track loaded texture handles
+ Cache textures on models to avoid lookups
This commit is contained in:
Daniel Evans 2015-02-16 00:36:11 +00:00
parent 9eb4c62a04
commit be023b5093
12 changed files with 92 additions and 57 deletions

View File

@ -15,6 +15,7 @@
#include <data/ZoneData.hpp> #include <data/ZoneData.hpp>
#include <audio/MADStream.hpp> #include <audio/MADStream.hpp>
#include <render/TextureData.hpp>
#include <memory> #include <memory>
@ -24,26 +25,6 @@ class GameWorld;
class TextureAtlas; class TextureAtlas;
class SCMFile; class SCMFile;
/**
* @brief Stores simple data about Textures such as transparency flags.
*
* @todo Covert usage to TextureHandles or something for streaming.
* @todo Move out of GameData.hpp and into TextureInfo.hpp
*/
struct TextureInfo
{
/// Texture Name
GLuint texName;
/// Transparent flag.
bool transparent;
TextureInfo(GLuint tex, bool t)
: texName(tex), transparent(t) {}
TextureInfo()
: texName(0), transparent(false) {}
};
/** /**
* @brief Loads and stores all "static" data such as loaded models, handling * @brief Loads and stores all "static" data such as loaded models, handling
* information, weather etc. * information, weather etc.
@ -195,6 +176,11 @@ public:
*/ */
TextureAtlas* getAtlas(size_t i); TextureAtlas* getAtlas(size_t i);
TextureData::Handle findTexture( const std::string& name, const std::string& alpha = "" )
{
return textures[{name, alpha}];
}
/** /**
* Files that have been loaded previously * Files that have been loaded previously
*/ */
@ -252,9 +238,9 @@ public:
std::map<std::string, ModelHandle*> models; std::map<std::string, ModelHandle*> models;
/** /**
* Loaded Textures and their atlas entries. * Loaded textures (Textures are ID by name and alpha pairs)
*/ */
std::map<std::pair<std::string, std::string>, TextureInfo> textures; std::map<std::pair<std::string, std::string>, TextureData::Handle> textures;
/** /**
* Texture atlases. * Texture atlases.

View File

@ -11,6 +11,7 @@
#include <loaders/rwbinarystream.h> #include <loaders/rwbinarystream.h>
#include "DrawBuffer.hpp" #include "DrawBuffer.hpp"
#include "GeometryBuffer.hpp" #include "GeometryBuffer.hpp"
#include "TextureData.hpp"
/** /**
* ModelFrame stores the hierarchy of a model's geometry as well as default * ModelFrame stores the hierarchy of a model's geometry as well as default
@ -80,6 +81,7 @@ public:
struct Texture { struct Texture {
std::string name; std::string name;
std::string alphaName; std::string alphaName;
TextureData::Handle texture;
}; };
enum { enum {

View File

@ -0,0 +1,34 @@
#pragma once
#include <GL/gl.h>
#include <glm/glm.hpp>
#include <memory>
/**
* Stores a handle and metadata about a loaded texture.
*/
class TextureData
{
public:
TextureData(GLuint name, const glm::ivec2& dims, bool alpha)
: texName( name ), size( dims ), hasAlpha(alpha) { }
GLuint getName() const { return texName; }
const glm::ivec2& getSize() const { return size; }
bool isTransparent() const { return hasAlpha; }
typedef std::shared_ptr<TextureData> Handle;
static Handle create(GLuint name, const glm::ivec2& size, bool transparent)
{
return Handle( new TextureData( name, size, transparent ) );
}
private:
GLuint texName;
glm::ivec2 size;
bool hasAlpha;
};

View File

@ -34,9 +34,9 @@ void WeaponItem::fireHitscan()
// - smoke emited at hit point // - smoke emited at hit point
// - gunflash // - gunflash
auto tracerTex = _character->engine->gameData.textures[{"shad_exp",""}].texName; auto tracerTex = _character->engine->gameData.findTexture("shad_exp")->getName();
auto flashTex = _character->engine->gameData.textures[{"gunflash2",""}].texName; auto flashTex = _character->engine->gameData.findTexture("gunflash2")->getName();
auto flashTex1 = _character->engine->gameData.textures[{"gunflash1",""}].texName; auto flashTex1 = _character->engine->gameData.findTexture("gunflash1")->getName();
float tracertime = 0.1f; float tracertime = 0.1f;
auto distance = glm::distance(fireOrigin, farTarget); auto distance = glm::distance(fireOrigin, farTarget);

View File

@ -1,6 +1,7 @@
#include <loaders/TextureLoader.hpp> #include <loaders/TextureLoader.hpp>
#include <engine/GameData.hpp> #include <engine/GameData.hpp>
#include <render/TextureAtlas.hpp> #include <render/TextureAtlas.hpp>
#include <render/TextureData.hpp>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
@ -29,9 +30,10 @@ GLuint gTextureRed[] = {0xFF0000FF};
GLuint gTextureGreen[] = {0xFF00FF00}; GLuint gTextureGreen[] = {0xFF00FF00};
GLuint gTextureBlue[] = {0xFFFF0000}; GLuint gTextureBlue[] = {0xFFFF0000};
GLuint getErrorTexture() TextureData::Handle getErrorTexture()
{ {
static GLuint errTexName = 0; static GLuint errTexName = 0;
static TextureData::Handle tex;
if(errTexName == 0) if(errTexName == 0)
{ {
glGenTextures(1, &errTexName); glGenTextures(1, &errTexName);
@ -42,8 +44,10 @@ GLuint getErrorTexture()
GL_RGBA, GL_UNSIGNED_BYTE, gErrorTextureData GL_RGBA, GL_UNSIGNED_BYTE, gErrorTextureData
); );
glGenerateMipmap(GL_TEXTURE_2D); glGenerateMipmap(GL_TEXTURE_2D);
tex = TextureData::create(errTexName, {2, 2}, false);
} }
return errTexName; return tex;
} }
const size_t paletteSize = 1024; const size_t paletteSize = 1024;
@ -62,7 +66,7 @@ void processPalette(uint32_t* fullColor, RW::BSTextureNative& texNative, RW::Bin
} }
GLuint createTexture(RW::BSTextureNative& texNative, RW::BinaryStreamSection& rootSection, bool* transparent) TextureData::Handle createTexture(RW::BSTextureNative& texNative, RW::BinaryStreamSection& rootSection)
{ {
// TODO: Exception handling. // TODO: Exception handling.
if(texNative.platform != 8) { if(texNative.platform != 8) {
@ -75,7 +79,7 @@ GLuint createTexture(RW::BSTextureNative& texNative, RW::BinaryStreamSection& ro
texNative.rasterformat == RW::BSTextureNative::FORMAT_8888 || texNative.rasterformat == RW::BSTextureNative::FORMAT_8888 ||
texNative.rasterformat == RW::BSTextureNative::FORMAT_888; texNative.rasterformat == RW::BSTextureNative::FORMAT_888;
// Export this value // Export this value
*transparent = !((texNative.rasterformat&RW::BSTextureNative::FORMAT_888) == RW::BSTextureNative::FORMAT_888); bool transparent = !((texNative.rasterformat&RW::BSTextureNative::FORMAT_888) == RW::BSTextureNative::FORMAT_888);
if(! (isPal8 || isFulc)) { if(! (isPal8 || isFulc)) {
std::cerr << "Unsuported raster format " << std::dec << texNative.rasterformat << std::endl; std::cerr << "Unsuported raster format " << std::dec << texNative.rasterformat << std::endl;
@ -194,7 +198,7 @@ GLuint createTexture(RW::BSTextureNative& texNative, RW::BinaryStreamSection& ro
glGenerateMipmap(GL_TEXTURE_2D); glGenerateMipmap(GL_TEXTURE_2D);
return textureName; return TextureData::create( textureName, { texNative.width, texNative.height }, transparent );
} }
bool TextureLoader::loadFromMemory(char *data, GameData *gameData) bool TextureLoader::loadFromMemory(char *data, GameData *gameData)
@ -215,13 +219,12 @@ bool TextureLoader::loadFromMemory(char *data, GameData *gameData)
std::transform(name.begin(), name.end(), name.begin(), ::tolower ); std::transform(name.begin(), name.end(), name.begin(), ::tolower );
std::transform(alpha.begin(), alpha.end(), alpha.begin(), ::tolower ); std::transform(alpha.begin(), alpha.end(), alpha.begin(), ::tolower );
bool transparent = false; auto texture = createTexture(texNative, rootSection);
GLuint id = createTexture(texNative, rootSection, &transparent);
gameData->textures[{name, alpha}] = {id, transparent}; gameData->textures[{name, alpha}] = texture;
if( !alpha.empty() ) { if( !alpha.empty() ) {
gameData->textures[{name, ""}] = {id, transparent}; gameData->textures[{name, ""}] = texture;
} }
} }

View File

@ -65,7 +65,7 @@ void PickupObject::tick(float dt)
} }
} }
auto tex = engine->gameData.textures[{"coronacircle",""}].texName; auto tex = engine->gameData.findTexture("coronacircle")->getName();
engine->renderer.addParticle({ engine->renderer.addParticle({
position, position,

View File

@ -71,7 +71,7 @@ void ProjectileObject::explode()
}); });
} }
std::pair<std::string, std::string> explodeTexName { "explo02", "" }; auto tex = engine->gameData.findTexture("explo02")->getName();
/// @todo add support for image sets and opacity to the particle system. /// @todo add support for image sets and opacity to the particle system.
engine->renderer.addParticle({ engine->renderer.addParticle({
@ -80,7 +80,7 @@ void ProjectileObject::explode()
0.f, 0.f,
GameRenderer::FXParticle::Camera, GameRenderer::FXParticle::Camera,
engine->gameTime, 0.5f, engine->gameTime, 0.5f,
engine->gameData.textures[explodeTexName].texName, tex,
{exp_size, exp_size} {exp_size, exp_size}
}); });

View File

@ -382,7 +382,7 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha)
model = glm::scale( model, glm::vec3(1.5f, 1.5f, 1.5f) ); model = glm::scale( model, glm::vec3(1.5f, 1.5f, 1.5f) );
Renderer::DrawParameters dp; Renderer::DrawParameters dp;
dp.texture = arrowTex.texName; dp.texture = arrowTex->getName();
dp.ambient = 1.f; dp.ambient = 1.f;
dp.colour = glm::u8vec4(255, 255, 255, 255); dp.colour = glm::u8vec4(255, 255, 255, 255);
@ -414,16 +414,15 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha)
float blockHQSize = WATER_WORLD_SIZE/WATER_HQ_DATA_SIZE; float blockHQSize = WATER_WORLD_SIZE/WATER_HQ_DATA_SIZE;
glm::vec2 waterOffset { -WATER_WORLD_SIZE/2.f, -WATER_WORLD_SIZE/2.f }; glm::vec2 waterOffset { -WATER_WORLD_SIZE/2.f, -WATER_WORLD_SIZE/2.f };
auto waterTex = engine->gameData.textures[{"water_old",""}]; auto waterTex = engine->gameData.findTexture("water_old");
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, waterTex.texName);
auto camposFlat = glm::vec2(camera.position); auto camposFlat = glm::vec2(camera.position);
Renderer::DrawParameters wdp; Renderer::DrawParameters wdp;
wdp.start = 0; wdp.start = 0;
wdp.count = waterHQVerts.size(); wdp.count = waterHQVerts.size();
wdp.texture = waterTex.texName; wdp.texture = waterTex->getName();
renderer->useProgram(waterProg); renderer->useProgram(waterProg);
renderer->setSceneParameters(sceneParams); renderer->setSceneParameters(sceneParams);
@ -500,10 +499,10 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha)
GLuint splashTexName = 0; GLuint splashTexName = 0;
auto fc = engine->state.fadeColour; auto fc = engine->state.fadeColour;
if((fc.r + fc.g + fc.b) == 0 && engine->state.currentSplash.size() > 0) { if((fc.r + fc.g + fc.b) == 0 && engine->state.currentSplash.size() > 0) {
std::pair<std::string, std::string> splashName(engine->state.currentSplash, ""); auto splash = engine->gameData.findTexture(engine->state.currentSplash);
auto splshfnd = engine->gameData.textures.find(splashName); if ( splash )
if( splshfnd != engine->gameData.textures.end() ) { {
splashTexName = splshfnd->second.texName; splashTexName = splash->getName();
} }
} }
@ -920,15 +919,20 @@ void GameRenderer::renderGeometry(Model* model, size_t g, const glm::mat4& model
Model::Material& mat = model->geometries[g]->materials[subgeom.material]; Model::Material& mat = model->geometries[g]->materials[subgeom.material];
if(mat.textures.size() > 0 ) { if(mat.textures.size() > 0 ) {
auto& tC = mat.textures[0].name; auto tex = mat.textures[0].texture;
auto& tA = mat.textures[0].alphaName; if( ! tex )
auto t = engine->gameData.textures.find({tC, tA}); {
if(t != engine->gameData.textures.end()) { auto& tC = mat.textures[0].name;
TextureInfo& tex = t->second; auto& tA = mat.textures[0].alphaName;
if(tex.transparent) { tex = engine->gameData.findTexture(tC, tA);
mat.textures[0].texture = tex;
}
if( tex )
{
if( tex->isTransparent() ) {
abortTransparent = true; abortTransparent = true;
} }
dp.texture = tex.texName; dp.texture = tex->getName();
} }
} }
@ -964,6 +968,7 @@ void GameRenderer::renderGeometry(Model* model, size_t g, const glm::mat4& model
); );
} }
else { else {
renderer->draw(modelMatrix, &model->geometries[g]->dbuff, dp); renderer->draw(modelMatrix, &model->geometries[g]->dbuff, dp);
} }
} }
@ -977,7 +982,7 @@ void GameRenderer::renderAreaIndicator(const AreaIndicatorInfo* info)
glm::vec3 scale = info->radius + 0.15f * glm::sin(engine->gameTime * 5.f); glm::vec3 scale = info->radius + 0.15f * glm::sin(engine->gameTime * 5.f);
Renderer::DrawParameters dp; Renderer::DrawParameters dp;
dp.texture = engine->gameData.textures[{"cloud1",""}].texName; dp.texture = engine->gameData.findTexture("cloud1")->getName();
dp.ambient = 1.f; dp.ambient = 1.f;
dp.colour = glm::u8vec4(50, 100, 255, 1); dp.colour = glm::u8vec4(50, 100, 255, 1);
dp.start = 0; dp.start = 0;

View File

@ -123,7 +123,7 @@ void MapRenderer::draw(const MapInfo& mi)
std::string name = "radar" + num + std::to_string(m); std::string name = "radar" + num + std::to_string(m);
auto texture = world->gameData.textures[{name,""}]; auto texture = world->gameData.textures[{name,""}];
glBindTexture(GL_TEXTURE_2D, texture.texName); glBindTexture(GL_TEXTURE_2D, texture->getName());
int mX = initX + (m % mapBlockLine); int mX = initX + (m % mapBlockLine);
int mY = initY + (m / mapBlockLine); int mY = initY + (m / mapBlockLine);
@ -195,8 +195,8 @@ void MapRenderer::drawBlip(const glm::vec2& coord, const glm::mat4& model, const
GLuint tex = 0; GLuint tex = 0;
if ( !texture.empty() ) if ( !texture.empty() )
{ {
auto sprite= world->gameData.textures[{texture,""}]; auto sprite= world->gameData.findTexture(texture);
tex = sprite.texName; tex = sprite->getName();
renderer->setUniform(rectProg, "colour", glm::vec4(0.f)); renderer->setUniform(rectProg, "colour", glm::vec4(0.f));
} }
else else

View File

@ -140,7 +140,8 @@ void TextRenderer::renderText(const TextRenderer::TextInfo& ti)
Renderer::DrawParameters dp; Renderer::DrawParameters dp;
dp.start = 0; dp.start = 0;
dp.count = gb.getCount(); dp.count = gb.getCount();
dp.texture = engine->gameData.textures[{fonts[ti.font], ""}].texName; auto ftexture = engine->gameData.findTexture(fonts[ti.font]);
dp.texture = ftexture->getName();
glm::vec2 ss( ti.size ); glm::vec2 ss( ti.size );
/// @todo smarter alignment /// @todo smarter alignment

View File

@ -0,0 +1 @@
#include <render/TextureData.hpp>

View File

@ -12,6 +12,7 @@ class RWGame
sf::Clock clock; sf::Clock clock;
bool inFocus; bool inFocus;
ViewCamera lastCam, nextCam; ViewCamera lastCam, nextCam;
bool showDebugStats;
float accum; float accum;
float timescale; float timescale;
@ -65,6 +66,8 @@ public:
private: private:
void tick(float dt); void tick(float dt);
void render(float alpha); void render(float alpha);
void renderDebugStats();
void globalKeyEvent(const sf::Event& event); void globalKeyEvent(const sf::Event& event);
}; };