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:
parent
9eb4c62a04
commit
be023b5093
@ -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.
|
||||
|
@ -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 {
|
||||
|
34
rwengine/include/render/TextureData.hpp
Normal file
34
rwengine/include/render/TextureData.hpp
Normal 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;
|
||||
};
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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}
|
||||
});
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
1
rwengine/src/render/TextureData.cpp
Normal file
1
rwengine/src/render/TextureData.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include <render/TextureData.hpp>
|
@ -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);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user