1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-25 11:52:40 +01: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 <audio/MADStream.hpp>
#include <render/TextureData.hpp>
#include <memory>
@ -24,26 +25,6 @@ class GameWorld;
class TextureAtlas;
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
* information, weather etc.
@ -195,6 +176,11 @@ public:
*/
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
*/
@ -252,9 +238,9 @@ public:
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.

View File

@ -11,6 +11,7 @@
#include <loaders/rwbinarystream.h>
#include "DrawBuffer.hpp"
#include "GeometryBuffer.hpp"
#include "TextureData.hpp"
/**
* ModelFrame stores the hierarchy of a model's geometry as well as default
@ -80,6 +81,7 @@ public:
struct Texture {
std::string name;
std::string alphaName;
TextureData::Handle texture;
};
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
// - gunflash
auto tracerTex = _character->engine->gameData.textures[{"shad_exp",""}].texName;
auto flashTex = _character->engine->gameData.textures[{"gunflash2",""}].texName;
auto flashTex1 = _character->engine->gameData.textures[{"gunflash1",""}].texName;
auto tracerTex = _character->engine->gameData.findTexture("shad_exp")->getName();
auto flashTex = _character->engine->gameData.findTexture("gunflash2")->getName();
auto flashTex1 = _character->engine->gameData.findTexture("gunflash1")->getName();
float tracertime = 0.1f;
auto distance = glm::distance(fireOrigin, farTarget);

View File

@ -1,6 +1,7 @@
#include <loaders/TextureLoader.hpp>
#include <engine/GameData.hpp>
#include <render/TextureAtlas.hpp>
#include <render/TextureData.hpp>
#include <fstream>
#include <iostream>
@ -29,9 +30,10 @@ GLuint gTextureRed[] = {0xFF0000FF};
GLuint gTextureGreen[] = {0xFF00FF00};
GLuint gTextureBlue[] = {0xFFFF0000};
GLuint getErrorTexture()
TextureData::Handle getErrorTexture()
{
static GLuint errTexName = 0;
static TextureData::Handle tex;
if(errTexName == 0)
{
glGenTextures(1, &errTexName);
@ -42,8 +44,10 @@ GLuint getErrorTexture()
GL_RGBA, GL_UNSIGNED_BYTE, gErrorTextureData
);
glGenerateMipmap(GL_TEXTURE_2D);
tex = TextureData::create(errTexName, {2, 2}, false);
}
return errTexName;
return tex;
}
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.
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_888;
// 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)) {
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);
return textureName;
return TextureData::create( textureName, { texNative.width, texNative.height }, transparent );
}
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(alpha.begin(), alpha.end(), alpha.begin(), ::tolower );
bool transparent = false;
GLuint id = createTexture(texNative, rootSection, &transparent);
auto texture = createTexture(texNative, rootSection);
gameData->textures[{name, alpha}] = {id, transparent};
gameData->textures[{name, alpha}] = texture;
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({
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.
engine->renderer.addParticle({
@ -80,7 +80,7 @@ void ProjectileObject::explode()
0.f,
GameRenderer::FXParticle::Camera,
engine->gameTime, 0.5f,
engine->gameData.textures[explodeTexName].texName,
tex,
{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) );
Renderer::DrawParameters dp;
dp.texture = arrowTex.texName;
dp.texture = arrowTex->getName();
dp.ambient = 1.f;
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;
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);
glBindTexture(GL_TEXTURE_2D, waterTex.texName);
auto camposFlat = glm::vec2(camera.position);
Renderer::DrawParameters wdp;
wdp.start = 0;
wdp.count = waterHQVerts.size();
wdp.texture = waterTex.texName;
wdp.texture = waterTex->getName();
renderer->useProgram(waterProg);
renderer->setSceneParameters(sceneParams);
@ -500,10 +499,10 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha)
GLuint splashTexName = 0;
auto fc = engine->state.fadeColour;
if((fc.r + fc.g + fc.b) == 0 && engine->state.currentSplash.size() > 0) {
std::pair<std::string, std::string> splashName(engine->state.currentSplash, "");
auto splshfnd = engine->gameData.textures.find(splashName);
if( splshfnd != engine->gameData.textures.end() ) {
splashTexName = splshfnd->second.texName;
auto splash = engine->gameData.findTexture(engine->state.currentSplash);
if ( splash )
{
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];
if(mat.textures.size() > 0 ) {
auto& tC = mat.textures[0].name;
auto& tA = mat.textures[0].alphaName;
auto t = engine->gameData.textures.find({tC, tA});
if(t != engine->gameData.textures.end()) {
TextureInfo& tex = t->second;
if(tex.transparent) {
auto tex = mat.textures[0].texture;
if( ! tex )
{
auto& tC = mat.textures[0].name;
auto& tA = mat.textures[0].alphaName;
tex = engine->gameData.findTexture(tC, tA);
mat.textures[0].texture = tex;
}
if( tex )
{
if( tex->isTransparent() ) {
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 {
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);
Renderer::DrawParameters dp;
dp.texture = engine->gameData.textures[{"cloud1",""}].texName;
dp.texture = engine->gameData.findTexture("cloud1")->getName();
dp.ambient = 1.f;
dp.colour = glm::u8vec4(50, 100, 255, 1);
dp.start = 0;

View File

@ -123,7 +123,7 @@ void MapRenderer::draw(const MapInfo& mi)
std::string name = "radar" + num + std::to_string(m);
auto texture = world->gameData.textures[{name,""}];
glBindTexture(GL_TEXTURE_2D, texture.texName);
glBindTexture(GL_TEXTURE_2D, texture->getName());
int mX = initX + (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;
if ( !texture.empty() )
{
auto sprite= world->gameData.textures[{texture,""}];
tex = sprite.texName;
auto sprite= world->gameData.findTexture(texture);
tex = sprite->getName();
renderer->setUniform(rectProg, "colour", glm::vec4(0.f));
}
else

View File

@ -140,7 +140,8 @@ void TextRenderer::renderText(const TextRenderer::TextInfo& ti)
Renderer::DrawParameters dp;
dp.start = 0;
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 );
/// @todo smarter alignment

View File

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

View File

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