mirror of
https://github.com/rwengine/openrw.git
synced 2024-09-19 08:52:33 +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:
parent
9eb4c62a04
commit
be023b5093
@ -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.
|
||||||
|
@ -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 {
|
||||||
|
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
|
// - 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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -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 tex = mat.textures[0].texture;
|
||||||
|
if( ! tex )
|
||||||
|
{
|
||||||
auto& tC = mat.textures[0].name;
|
auto& tC = mat.textures[0].name;
|
||||||
auto& tA = mat.textures[0].alphaName;
|
auto& tA = mat.textures[0].alphaName;
|
||||||
auto t = engine->gameData.textures.find({tC, tA});
|
tex = engine->gameData.findTexture(tC, tA);
|
||||||
if(t != engine->gameData.textures.end()) {
|
mat.textures[0].texture = tex;
|
||||||
TextureInfo& tex = t->second;
|
}
|
||||||
if(tex.transparent) {
|
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;
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
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;
|
sf::Clock clock;
|
||||||
bool inFocus;
|
bool inFocus;
|
||||||
ViewCamera lastCam, nextCam;
|
ViewCamera lastCam, nextCam;
|
||||||
|
bool showDebugStats;
|
||||||
|
|
||||||
float accum;
|
float accum;
|
||||||
float timescale;
|
float timescale;
|
||||||
@ -66,6 +67,8 @@ 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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user