mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-14 16:07:39 +00:00
Merge branch 'master' into tinygl-dirty-rects
Conflicts: graphics/tinygl/zbuffer.cpp graphics/tinygl/zbuffer.h
This commit is contained in:
commit
8abb5b008c
@ -97,9 +97,9 @@ Actor::Actor() :
|
||||
_mustPlaceText(false),
|
||||
_puckOrient(false), _talking(false),
|
||||
_inOverworld(false), _drawnToClean(false), _backgroundTalk(false),
|
||||
_sortOrder(0), _haveSectorSortOrder(false), _sectorSortOrder(0),
|
||||
_cleanBuffer(0), _lightMode(LightFastDyn), _hasFollowedBoxes(false),
|
||||
_lookAtActor(0) {
|
||||
_sortOrder(0), _haveSectorSortOrder(false), _useParentSortOrder(false),
|
||||
_sectorSortOrder(0), _cleanBuffer(0), _lightMode(LightFastDyn),
|
||||
_hasFollowedBoxes(false), _lookAtActor(0) {
|
||||
|
||||
// Some actors don't set walk and turn rates, so we default the
|
||||
// _turnRate so Doug at the cat races can turn and we set the
|
||||
@ -247,6 +247,7 @@ void Actor::saveState(SaveGame *savedState) const {
|
||||
|
||||
savedState->writeBool(_inOverworld);
|
||||
savedState->writeLESint32(_sortOrder);
|
||||
savedState->writeBool(_useParentSortOrder);
|
||||
|
||||
savedState->writeLESint32(_attachedActor);
|
||||
savedState->writeString(_attachedJoint);
|
||||
@ -422,6 +423,9 @@ bool Actor::restoreState(SaveGame *savedState) {
|
||||
|
||||
_inOverworld = savedState->readBool();
|
||||
_sortOrder = savedState->readLESint32();
|
||||
if (savedState->saveMinorVersion() >= 22)
|
||||
_useParentSortOrder = savedState->readBool();
|
||||
|
||||
if (savedState->saveMinorVersion() < 18)
|
||||
savedState->readBool(); // Used to be _shadowActive.
|
||||
|
||||
@ -1436,7 +1440,7 @@ void Actor::update(uint frameTime) {
|
||||
set->findClosestSector(_pos, nullptr, &_pos);
|
||||
}
|
||||
|
||||
if (g_grim->getGameType() == GType_MONKEY4) {
|
||||
if (_followBoxes && g_grim->getGameType() == GType_MONKEY4) {
|
||||
// Check for sort order information in the current sector
|
||||
int oldSortOrder = getEffectiveSortOrder();
|
||||
|
||||
@ -2266,16 +2270,22 @@ Math::Vector3d Actor::getHeadPos() const {
|
||||
return getWorldPos();
|
||||
}
|
||||
|
||||
void Actor::setSortOrder(const int order) {
|
||||
_sortOrder = order;
|
||||
|
||||
// If this actor is attached to another actor, we'll use the
|
||||
// explicitly specified sort order instead of the parent actor's
|
||||
// sort order from now on.
|
||||
if (_useParentSortOrder)
|
||||
_useParentSortOrder = false;
|
||||
}
|
||||
|
||||
int Actor::getSortOrder() const {
|
||||
if (_attachedActor != 0) {
|
||||
Actor *attachedActor = Actor::getPool().getObject(_attachedActor);
|
||||
return attachedActor->getSortOrder();
|
||||
}
|
||||
return _sortOrder;
|
||||
}
|
||||
|
||||
int Actor::getEffectiveSortOrder() const {
|
||||
if (_attachedActor != 0) {
|
||||
if (_useParentSortOrder && _attachedActor != 0) {
|
||||
Actor *attachedActor = Actor::getPool().getObject(_attachedActor);
|
||||
return attachedActor->getEffectiveSortOrder();
|
||||
}
|
||||
@ -2377,12 +2387,24 @@ void Actor::attachToActor(Actor *other, const char *joint) {
|
||||
// Save the attachement info
|
||||
_attachedActor = other->getId();
|
||||
_attachedJoint = jointStr;
|
||||
|
||||
// Use the parent actor's sort order.
|
||||
_useParentSortOrder = true;
|
||||
}
|
||||
|
||||
void Actor::detach() {
|
||||
if (!isAttached())
|
||||
return;
|
||||
|
||||
// Replace our sort order with the parent actor's sort order. Note
|
||||
// that we do this even if a sort order was explicitly specified for
|
||||
// the actor during the time it was attached (in which case the actor
|
||||
// doesn't respect the parent actor's sort order). This seems weird,
|
||||
// but matches the behavior of the original engine.
|
||||
Actor *attachedActor = Actor::getPool().getObject(_attachedActor);
|
||||
_sortOrder = attachedActor->getEffectiveSortOrder();
|
||||
_useParentSortOrder = false;
|
||||
|
||||
// FIXME: Use last known position of attached joint
|
||||
Math::Vector3d oldPos = getWorldPos();
|
||||
_attachedActor = 0;
|
||||
|
@ -540,7 +540,7 @@ public:
|
||||
void setAlphaMode(AlphaMode mode) { _alphaMode = mode; }
|
||||
|
||||
int getSortOrder() const;
|
||||
void setSortOrder(const int order) { _sortOrder = order; }
|
||||
void setSortOrder(const int order);
|
||||
int getEffectiveSortOrder() const;
|
||||
|
||||
void activateShadow(bool active, const char *shadowName);
|
||||
@ -708,6 +708,7 @@ private:
|
||||
int _sortOrder;
|
||||
bool _haveSectorSortOrder;
|
||||
int _sectorSortOrder;
|
||||
bool _useParentSortOrder;
|
||||
|
||||
int _cleanBuffer;
|
||||
bool _drawnToClean;
|
||||
|
@ -46,6 +46,7 @@ void Debug::registerDebugChannels() {
|
||||
DebugMan.addDebugChannel(TextObjects, "textobjects", "");
|
||||
DebugMan.addDebugChannel(Patchr, "patchr", "");
|
||||
DebugMan.addDebugChannel(Lipsync, "lipsync", "");
|
||||
DebugMan.addDebugChannel(Sprites, "sprites", "");
|
||||
}
|
||||
|
||||
bool Debug::isChannelEnabled(DebugChannel chan) {
|
||||
|
@ -50,7 +50,8 @@ public:
|
||||
Sets = 2 << 15,
|
||||
TextObjects = 2 << 16,
|
||||
Patchr = 2 << 17,
|
||||
Lipsync = 2 << 18
|
||||
Lipsync = 2 << 18,
|
||||
Sprites = 2 << 19
|
||||
};
|
||||
|
||||
static void registerDebugChannels();
|
||||
|
@ -100,7 +100,7 @@ Bone::~Bone() {
|
||||
|
||||
AnimationStateEmi::AnimationStateEmi(const Common::String &anim) :
|
||||
_skel(nullptr), _looping(false), _active(false),
|
||||
_fadeMode(Animation::None), _fade(1.0f), _fadeLength(0), _time(0.0f), _startFade(1.0f),
|
||||
_fadeMode(Animation::None), _fade(1.0f), _fadeLength(0), _time(0), _startFade(1.0f),
|
||||
_boneJoints(nullptr) {
|
||||
_anim = g_resourceloader->getAnimationEmi(anim);
|
||||
if (_anim)
|
||||
@ -138,9 +138,10 @@ void AnimationStateEmi::update(uint time) {
|
||||
}
|
||||
|
||||
if (!_paused) {
|
||||
if (_time > _anim->_duration) {
|
||||
uint durationMs = (uint)_anim->_duration;
|
||||
if (_time >= durationMs) {
|
||||
if (_looping) {
|
||||
_time = 0.0f;
|
||||
_time = _time % durationMs;
|
||||
} else {
|
||||
if (_fadeMode != Animation::FadeOut)
|
||||
deactivate();
|
||||
@ -284,7 +285,7 @@ void AnimationStateEmi::animate() {
|
||||
|
||||
void AnimationStateEmi::play() {
|
||||
if (!_active) {
|
||||
_time = 0.f;
|
||||
_time = 0;
|
||||
if (_fadeMode == Animation::FadeOut)
|
||||
_fadeMode = Animation::None;
|
||||
if (_fadeMode == Animation::FadeIn || _fade > 0.f)
|
||||
@ -295,7 +296,7 @@ void AnimationStateEmi::play() {
|
||||
|
||||
void AnimationStateEmi::stop() {
|
||||
_fadeMode = Animation::None;
|
||||
_time = 0.f;
|
||||
_time = 0;
|
||||
deactivate();
|
||||
}
|
||||
|
||||
@ -342,7 +343,7 @@ void AnimationStateEmi::saveState(SaveGame *state) {
|
||||
state->writeBool(_looping);
|
||||
state->writeBool(_active);
|
||||
state->writeBool(_paused);
|
||||
state->writeFloat(_time);
|
||||
state->writeLEUint32(_time);
|
||||
state->writeFloat(_fade);
|
||||
state->writeFloat(_startFade);
|
||||
state->writeLESint32((int)_fadeMode);
|
||||
@ -354,7 +355,11 @@ void AnimationStateEmi::restoreState(SaveGame *state) {
|
||||
_looping = state->readBool();
|
||||
bool active = state->readBool();
|
||||
_paused = state->readBool();
|
||||
_time = state->readFloat();
|
||||
if (state->saveMinorVersion() < 22) {
|
||||
_time = (uint)state->readFloat();
|
||||
} else {
|
||||
_time = state->readLEUint32();
|
||||
}
|
||||
_fade = state->readFloat();
|
||||
_startFade = state->readFloat();
|
||||
_fadeMode = (Animation::FadeMode)state->readLESint32();
|
||||
|
@ -99,7 +99,7 @@ private:
|
||||
bool _looping;
|
||||
bool _active;
|
||||
bool _paused;
|
||||
float _time;
|
||||
uint _time;
|
||||
float _fade;
|
||||
float _startFade;
|
||||
Animation::FadeMode _fadeMode;
|
||||
|
@ -48,9 +48,6 @@ void EMISpriteComponent::reset() {
|
||||
}
|
||||
|
||||
void EMISpriteComponent::draw() {
|
||||
// HACK: don't draw _masks for now.
|
||||
if (_name.contains("_mask"))
|
||||
return;
|
||||
if (_sprite) {
|
||||
_sprite->draw();
|
||||
}
|
||||
|
@ -271,7 +271,13 @@ void EMIEngine::sortTextObjects() {
|
||||
|
||||
bool EMIEngine::compareActor(const Actor *x, const Actor *y) {
|
||||
if (x->getEffectiveSortOrder() == y->getEffectiveSortOrder()) {
|
||||
return x->getId() < y->getId();
|
||||
float xDist = (g_grim->getCurrSet()->getCurrSetup()->_pos - x->getWorldPos()).getSquareMagnitude();
|
||||
float yDist = (g_grim->getCurrSet()->getCurrSetup()->_pos - y->getWorldPos()).getSquareMagnitude();
|
||||
if (fabs(xDist - yDist) < 0.001f) {
|
||||
return x->getId() < y->getId();
|
||||
} else {
|
||||
return xDist > yDist;
|
||||
}
|
||||
}
|
||||
return x->getEffectiveSortOrder() > y->getEffectiveSortOrder();
|
||||
}
|
||||
|
@ -130,6 +130,8 @@ protected:
|
||||
DECLARE_LUA_OPCODE(ImStateHasEnded);
|
||||
DECLARE_LUA_OPCODE(ImPushState);
|
||||
DECLARE_LUA_OPCODE(ImPopState);
|
||||
DECLARE_LUA_OPCODE(ImPause);
|
||||
DECLARE_LUA_OPCODE(ImResume);
|
||||
DECLARE_LUA_OPCODE(GetSectorName);
|
||||
DECLARE_LUA_OPCODE(GetCameraPosition);
|
||||
DECLARE_LUA_OPCODE(GetCameraYaw);
|
||||
|
@ -421,7 +421,7 @@ void Lua_V2::GetActorSortOrder() {
|
||||
return;
|
||||
|
||||
Actor *actor = getactor(actorObj);
|
||||
lua_pushnumber(actor->getSortOrder());
|
||||
lua_pushnumber(actor->getEffectiveSortOrder());
|
||||
}
|
||||
|
||||
void Lua_V2::ActorActivateShadow() {
|
||||
|
@ -573,4 +573,14 @@ void Lua_V2::ImPopState() {
|
||||
Debug::debug(Debug::Sound | Debug::Scripts, "Lua_V2::ImPopState: currently guesswork");
|
||||
}
|
||||
|
||||
// Used in the demo only.
|
||||
void Lua_V2::ImPause() {
|
||||
g_emiSound->pause(true);
|
||||
}
|
||||
|
||||
// Used in the demo only.
|
||||
void Lua_V2::ImResume() {
|
||||
g_emiSound->pause(false);
|
||||
}
|
||||
|
||||
} // end of namespace Grim
|
||||
|
@ -92,8 +92,10 @@ EMIMeshFace::~EMIMeshFace() {
|
||||
}
|
||||
|
||||
void EMIModel::setTex(uint32 index) {
|
||||
if (index < _numTextures && _mats[index])
|
||||
if (index < _numTextures && _mats[index]) {
|
||||
_mats[index]->select();
|
||||
g_driver->setBlendMode(_texFlags[index] & BlendAdditive);
|
||||
}
|
||||
}
|
||||
|
||||
void EMIModel::loadMesh(Common::SeekableReadStream *data) {
|
||||
@ -114,12 +116,14 @@ void EMIModel::loadMesh(Common::SeekableReadStream *data) {
|
||||
_numTextures = data->readUint32LE();
|
||||
|
||||
_texNames = new Common::String[_numTextures];
|
||||
_texFlags = new uint32[_numTextures];
|
||||
|
||||
for (uint32 i = 0; i < _numTextures; i++) {
|
||||
_texNames[i] = readLAString(data);
|
||||
// Every texname seems to be followed by 4 0-bytes (Ref mk1.mesh,
|
||||
// this is intentional)
|
||||
data->skip(4);
|
||||
_texFlags[i] = data->readUint32LE();
|
||||
if (_texFlags[i] & ~(BlendAdditive)) {
|
||||
Debug::debug(Debug::Models, "Model %s has unknown flags (%d) for texture %s", nameString.c_str(), _texFlags[i], _texNames[i].c_str());
|
||||
}
|
||||
}
|
||||
|
||||
prepareTextures();
|
||||
@ -292,14 +296,21 @@ void EMIModel::draw() {
|
||||
_lightingDirty = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (actor->getLightMode() == Actor::LightNone) {
|
||||
g_driver->disableLights();
|
||||
}
|
||||
}
|
||||
|
||||
// We will need to add a call to the skeleton, to get the modified vertices, but for now,
|
||||
// I'll be happy with just static drawing
|
||||
for (uint32 i = 0; i < _numFaces; i++) {
|
||||
setTex(_faces[i]._texID);
|
||||
g_driver->drawEMIModelFace(this, &_faces[i]);
|
||||
}
|
||||
|
||||
if (g_driver->supportsShaders() && actor->getLightMode() == Actor::LightNone) {
|
||||
g_driver->enableLights();
|
||||
}
|
||||
}
|
||||
|
||||
void EMIModel::updateLighting(const Math::Matrix4 &modelToWorld) {
|
||||
@ -438,6 +449,7 @@ EMIModel::EMIModel(const Common::String &filename, Common::SeekableReadStream *d
|
||||
_boneNames = nullptr;
|
||||
_lighting = nullptr;
|
||||
_lightingDirty = true;
|
||||
_texFlags = nullptr;
|
||||
|
||||
loadMesh(data);
|
||||
g_driver->createEMIModel(this);
|
||||
@ -457,6 +469,7 @@ EMIModel::~EMIModel() {
|
||||
delete[] _vertexBoneInfo;
|
||||
delete[] _boneNames;
|
||||
delete[] _lighting;
|
||||
delete[] _texFlags;
|
||||
delete _center;
|
||||
delete _boxData;
|
||||
delete _boxData2;
|
||||
|
@ -62,6 +62,10 @@ public:
|
||||
uint32 _flags;
|
||||
EMIModel *_parent;
|
||||
|
||||
enum MeshFaceFlags {
|
||||
kAlphaBlend = 0x10000
|
||||
};
|
||||
|
||||
EMIMeshFace() : _faceLength(0), _numFaces(0), _hasTexture(0), _texID(0), _flags(0), _indexes(NULL), _parent(NULL), _indicesEBO(0) { }
|
||||
~EMIMeshFace();
|
||||
void loadFace(Common::SeekableReadStream *data);
|
||||
@ -74,6 +78,11 @@ public:
|
||||
*/
|
||||
class EMIModel : public Object {
|
||||
public:
|
||||
enum TextureFlags {
|
||||
BlendAdditive = 0x400
|
||||
// There are more flags, but their purpose is currently unknown.
|
||||
};
|
||||
|
||||
int _numVertices;
|
||||
Math::Vector3d *_vertices;
|
||||
Math::Vector3d *_drawVertices;
|
||||
@ -87,6 +96,7 @@ public:
|
||||
EMIMeshFace *_faces;
|
||||
uint32 _numTextures;
|
||||
Common::String *_texNames;
|
||||
uint32 *_texFlags;
|
||||
Material **_mats;
|
||||
|
||||
Skeleton *_skeleton;
|
||||
|
@ -184,6 +184,7 @@ void EMISound::timerHandler(void *refCon) {
|
||||
|
||||
EMISound::EMISound(int fps) {
|
||||
_curMusicState = -1;
|
||||
_numMusicStates = 0;
|
||||
_musicTrack = nullptr;
|
||||
_curTrackId = 0;
|
||||
_callbackFps = fps;
|
||||
@ -396,7 +397,7 @@ SoundTrack *EMISound::initTrack(const Common::String &soundName, Audio::Mixer::S
|
||||
soundNameLower.toLowercase();
|
||||
if (soundNameLower.hasSuffix(".scx")) {
|
||||
track = new SCXTrack(soundType);
|
||||
} else if (soundNameLower.hasSuffix(".m4b")) {
|
||||
} else if (soundNameLower.hasSuffix(".m4b") || soundNameLower.hasSuffix(".lab")) {
|
||||
track = new MP3Track(soundType);
|
||||
} else if (soundNameLower.hasSuffix(".aif")) {
|
||||
track = new AIFFTrack(soundType);
|
||||
@ -439,6 +440,10 @@ bool EMISound::stateHasEnded(int stateId) {
|
||||
|
||||
void EMISound::setMusicState(int stateId) {
|
||||
Common::StackLock lock(_mutex);
|
||||
// The demo calls ImSetState with state id 1000, which exceeds the number of states in the
|
||||
// music table.
|
||||
if (stateId >= _numMusicStates)
|
||||
stateId = 0;
|
||||
if (stateId == _curMusicState)
|
||||
return;
|
||||
|
||||
@ -519,13 +524,14 @@ uint32 EMISound::getMsPos(int stateId) {
|
||||
return _musicTrack->getPos().msecs();
|
||||
}
|
||||
|
||||
MusicEntry *initMusicTableDemo(const Common::String &filename) {
|
||||
MusicEntry *EMISound::initMusicTableDemo(const Common::String &filename) {
|
||||
Common::SeekableReadStream *data = g_resourceloader->openNewStreamFile(filename);
|
||||
|
||||
if (!data)
|
||||
error("Couldn't open %s", filename.c_str());
|
||||
// FIXME, for now we use a fixed-size table, as I haven't looked at the retail-data yet.
|
||||
MusicEntry *musicTable = new MusicEntry[15];
|
||||
_numMusicStates = 15;
|
||||
MusicEntry *musicTable = new MusicEntry[_numMusicStates];
|
||||
for (int i = 0; i < 15; ++i) {
|
||||
musicTable->_x = 0;
|
||||
musicTable->_y = 0;
|
||||
@ -559,7 +565,7 @@ MusicEntry *initMusicTableDemo(const Common::String &filename) {
|
||||
return musicTable;
|
||||
}
|
||||
|
||||
MusicEntry *initMusicTableRetail(MusicEntry *table, const Common::String &filename) {
|
||||
MusicEntry *EMISound::initMusicTableRetail(MusicEntry *table, const Common::String &filename) {
|
||||
Common::SeekableReadStream *data = g_resourceloader->openNewStreamFile(filename);
|
||||
|
||||
// Remember to check, in case we forgot to copy over those files from the CDs.
|
||||
@ -571,14 +577,15 @@ MusicEntry *initMusicTableRetail(MusicEntry *table, const Common::String &filena
|
||||
|
||||
MusicEntry *musicTable = table;
|
||||
if (!table) {
|
||||
musicTable = new MusicEntry[126];
|
||||
}
|
||||
for (int i = 0; i < 126; ++i) {
|
||||
musicTable->_x = 0;
|
||||
musicTable->_y = 0;
|
||||
musicTable->_sync = 0;
|
||||
musicTable->_trim = 0;
|
||||
musicTable->_id = i;
|
||||
_numMusicStates = 126;
|
||||
musicTable = new MusicEntry[_numMusicStates];
|
||||
for (int i = 0; i < 126; ++i) {
|
||||
musicTable->_x = 0;
|
||||
musicTable->_y = 0;
|
||||
musicTable->_sync = 0;
|
||||
musicTable->_trim = 0;
|
||||
musicTable->_id = i;
|
||||
}
|
||||
}
|
||||
|
||||
TextSplitter *ts = new TextSplitter(filename, data);
|
||||
@ -629,6 +636,7 @@ void EMISound::initMusicTable() {
|
||||
_musicPrefix = "Music/";
|
||||
} else if (g_grim->getGamePlatform() == Common::kPlatformPS2) {
|
||||
_musicTable = emiPS2MusicTable;
|
||||
_numMusicStates = ARRAYSIZE(emiPS2MusicTable);
|
||||
_musicPrefix = "";
|
||||
} else {
|
||||
_musicTable = nullptr;
|
||||
|
@ -107,6 +107,7 @@ private:
|
||||
TrackMap _preloadedTrackMap;
|
||||
|
||||
int _curMusicState;
|
||||
int _numMusicStates;
|
||||
int _callbackFps;
|
||||
int _curTrackId;
|
||||
|
||||
@ -125,6 +126,8 @@ private:
|
||||
bool startSound(const Common::String &soundName, Audio::Mixer::SoundType soundType, int volume, int pan);
|
||||
void saveTrack(SoundTrack *track, SaveGame *savedState);
|
||||
SoundTrack *restoreTrack(SaveGame *savedState);
|
||||
MusicEntry *initMusicTableDemo(const Common::String &filename);
|
||||
MusicEntry *initMusicTableRetail(MusicEntry *table, const Common::String &filename);
|
||||
};
|
||||
|
||||
extern EMISound *g_emiSound;
|
||||
|
@ -34,6 +34,7 @@ namespace Grim {
|
||||
SCXTrack::SCXTrack(Audio::Mixer::SoundType soundType) {
|
||||
_disposeAfterPlaying = DisposeAfterUse::NO;
|
||||
_soundType = soundType;
|
||||
_looping = false;
|
||||
}
|
||||
|
||||
SCXTrack::~SCXTrack() {
|
||||
|
@ -279,6 +279,8 @@ public:
|
||||
static Math::Matrix4 makeProjMatrix(float fov, float nclip, float fclip);
|
||||
Texture *getSpecialtyTexturePtr(uint id) { if (id >= _numSpecialtyTextures) return nullptr; return &_specialtyTextures[id]; };
|
||||
Texture *getSpecialtyTexturePtr(Common::String name);
|
||||
|
||||
virtual void setBlendMode(bool additive) = 0;
|
||||
protected:
|
||||
Bitmap *createScreenshotBitmap(const Graphics::PixelBuffer src, int w, int h, bool flipOrientation);
|
||||
static const unsigned int _numSpecialtyTextures = 22;
|
||||
|
@ -634,11 +634,6 @@ void GfxOpenGL::startActorDraw(const Actor *actor) {
|
||||
glScalef(scale, scale, scale);
|
||||
glMultMatrixf(quat.toMatrix().getData());
|
||||
}
|
||||
|
||||
if (!_currentShadowArray && actor->getSortOrder() >= 100) {
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||
glDepthMask(GL_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void GfxOpenGL::finishActorDraw() {
|
||||
@ -760,6 +755,8 @@ void GfxOpenGL::drawEMIModelFace(const EMIModel *model, const EMIMeshFace *face)
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
else
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
if (face->_flags & EMIMeshFace::kAlphaBlend)
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
float dim = 1.0f - _dimLevel;
|
||||
@ -835,7 +832,7 @@ void GfxOpenGL::drawSprite(const Sprite *sprite) {
|
||||
act(3, 1) = modelview[13];
|
||||
act(3, 2) = modelview[14];
|
||||
glLoadMatrixf(act.getData());
|
||||
glTranslatef(sprite->_pos.x(), sprite->_pos.y(), sprite->_pos.z());
|
||||
glTranslatef(sprite->_pos.x(), sprite->_pos.y(), -sprite->_pos.z());
|
||||
} else {
|
||||
glTranslatef(sprite->_pos.x(), sprite->_pos.y(), sprite->_pos.z());
|
||||
GLdouble modelview[16];
|
||||
@ -854,7 +851,7 @@ void GfxOpenGL::drawSprite(const Sprite *sprite) {
|
||||
glLoadMatrixd(modelview);
|
||||
}
|
||||
|
||||
if (sprite->_blendMode == Sprite::BlendAdditive) {
|
||||
if (sprite->_flags1 & Sprite::BlendAdditive) {
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
} else {
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
@ -862,35 +859,27 @@ void GfxOpenGL::drawSprite(const Sprite *sprite) {
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
if (sprite->_alphaTest) {
|
||||
if (sprite->_flags2 & Sprite::AlphaTest) {
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glAlphaFunc(GL_GEQUAL, g_grim->getGameType() == GType_MONKEY4 ? 0.1f : 0.5f);
|
||||
} else {
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
}
|
||||
|
||||
if (sprite->_writeDepth) {
|
||||
if (sprite->_flags2 & Sprite::DepthTest) {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
} else {
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
if (g_grim->getGameType() == GType_MONKEY4) {
|
||||
if (_currentActor->isInOverworld()) {
|
||||
// The Overworld actors don't have a proper sort order
|
||||
// so we rely on the z coordinates
|
||||
glDepthMask(GL_TRUE);
|
||||
} else {
|
||||
glDepthMask(GL_FALSE);
|
||||
}
|
||||
glDepthMask(GL_TRUE);
|
||||
|
||||
float halfWidth = sprite->_width / 2;
|
||||
float halfHeight = sprite->_height / 2;
|
||||
float dim = 1.0f - _dimLevel;
|
||||
float texCoordsX[] = { 0.0f, 0.0f, 1.0f, 1.0f };
|
||||
float texCoordsY[] = { 1.0f, 0.0f, 0.0f, 1.0f };
|
||||
float vertexX[] = { -1.0f, -1.0f, 1.0f, 1.0f };
|
||||
float vertexY[] = { -1.0f, 1.0f, 1.0f, -1.0f };
|
||||
float vertexX[] = { -1.0f, 1.0f, 1.0f, -1.0f };
|
||||
float vertexY[] = { 1.0f, 1.0f, -1.0f, -1.0f };
|
||||
|
||||
glBegin(GL_POLYGON);
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
@ -900,7 +889,7 @@ void GfxOpenGL::drawSprite(const Sprite *sprite) {
|
||||
float a = sprite->_alpha[i] * dim * _alpha / 255.0f;
|
||||
|
||||
glColor4f(r, g, b, a);
|
||||
glTexCoord2f(texCoordsX[i], texCoordsY[i]);
|
||||
glTexCoord2f(sprite->_texCoordX[i], sprite->_texCoordY[i]);
|
||||
glVertex3f(vertexX[i] * halfWidth, vertexY[i] * halfHeight, 0.0f);
|
||||
}
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
@ -1151,6 +1140,7 @@ void GfxOpenGL::drawBitmap(const Bitmap *bitmap, int dx, int dy, uint32 layer) {
|
||||
glDisable(GL_LIGHTING);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
@ -2048,6 +2038,14 @@ void GfxOpenGL::createSpecialtyTextureFromScreen(uint id, uint8 *data, int x, in
|
||||
createSpecialtyTexture(id, data, width, height);
|
||||
}
|
||||
|
||||
void GfxOpenGL::setBlendMode(bool additive) {
|
||||
if (additive) {
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
} else {
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
}
|
||||
|
||||
} // end of namespace Grim
|
||||
|
||||
#endif
|
||||
|
@ -125,6 +125,8 @@ public:
|
||||
void drawMovieFrame(int offsetX, int offsetY) override;
|
||||
void releaseMovieFrame() override;
|
||||
|
||||
void setBlendMode(bool additive) override;
|
||||
|
||||
protected:
|
||||
void createSpecialtyTextureFromScreen(uint id, uint8 *data, int x, int y, int width, int height) override;
|
||||
void drawDepthBitmap(int x, int y, int w, int h, char *data);
|
||||
|
@ -907,6 +907,8 @@ void GfxOpenGLS::updateEMIModel(const EMIModel* model) {
|
||||
}
|
||||
|
||||
void GfxOpenGLS::drawEMIModelFace(const EMIModel* model, const EMIMeshFace* face) {
|
||||
if (face->_flags & EMIMeshFace::kAlphaBlend)
|
||||
glEnable(GL_BLEND);
|
||||
const EMIModelUserData *mud = (const EMIModelUserData *)model->_userData;
|
||||
mud->_shader->use();
|
||||
bool textured = face->_hasTexture && !_currentShadowArray;
|
||||
@ -962,9 +964,13 @@ void GfxOpenGLS::drawModelFace(const Mesh *mesh, const MeshFace *face) {
|
||||
}
|
||||
|
||||
void GfxOpenGLS::drawSprite(const Sprite *sprite) {
|
||||
glDepthMask(GL_FALSE);
|
||||
if (g_grim->getGameType() == GType_MONKEY4) {
|
||||
glDepthMask(GL_TRUE);
|
||||
} else {
|
||||
glDepthMask(GL_FALSE);
|
||||
}
|
||||
|
||||
if (sprite->_blendMode == Sprite::BlendAdditive) {
|
||||
if (sprite->_flags1 & Sprite::BlendAdditive) {
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
} else {
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
@ -972,7 +978,7 @@ void GfxOpenGLS::drawSprite(const Sprite *sprite) {
|
||||
|
||||
// FIXME: depth test does not work yet because final z coordinates
|
||||
// for Sprites and actor textures are inconsistently calculated
|
||||
if (sprite->_writeDepth || _currentActor->isInOverworld()) {
|
||||
if (sprite->_flags2 & Sprite::DepthTest || _currentActor->isInOverworld()) {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
} else {
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
@ -988,16 +994,16 @@ void GfxOpenGLS::drawSprite(const Sprite *sprite) {
|
||||
extraMatrix(0, 0) = sprite->_width;
|
||||
extraMatrix(1, 1) = sprite->_height;
|
||||
|
||||
extraMatrix = extraMatrix * rotateMatrix;
|
||||
extraMatrix = rotateMatrix * extraMatrix;
|
||||
extraMatrix.transpose();
|
||||
_spriteProgram->setUniform("extraMatrix", extraMatrix);
|
||||
_spriteProgram->setUniform("textured", GL_TRUE);
|
||||
_spriteProgram->setUniform("isBillboard", GL_TRUE);
|
||||
_spriteProgram->setUniform("lightsEnabled", false);
|
||||
if (sprite->_alphaTest) {
|
||||
_spriteProgram->setUniform("alphaRef", g_grim->getGameType() == GType_MONKEY4 ? 0.1f : 0.5f);
|
||||
if (sprite->_flags2 & Sprite::AlphaTest) {
|
||||
_spriteProgram->setUniform1f("alphaRef", g_grim->getGameType() == GType_MONKEY4 ? 0.1f : 0.5f);
|
||||
} else {
|
||||
_spriteProgram->setUniform("alphaRef", 0.0f);
|
||||
_spriteProgram->setUniform1f("alphaRef", 0.0f);
|
||||
}
|
||||
|
||||
// FIXME: Currently vertex-specific colors are not supported for sprites.
|
||||
@ -2020,6 +2026,14 @@ void GfxOpenGLS::createSpecialtyTextureFromScreen(uint id, uint8 *data, int x, i
|
||||
createSpecialtyTexture(id, data, width, height);
|
||||
}
|
||||
|
||||
void GfxOpenGLS::setBlendMode(bool additive) {
|
||||
if (additive) {
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
} else {
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -205,6 +205,8 @@ public:
|
||||
virtual void createEMIModel(EMIModel *model) override;
|
||||
virtual void updateEMIModel(const EMIModel* model) override;
|
||||
|
||||
virtual void setBlendMode(bool additive) override;
|
||||
|
||||
protected:
|
||||
void setupShaders();
|
||||
GLuint compileShader(const char *vertex, const char *fragment);
|
||||
|
@ -568,11 +568,6 @@ void GfxTinyGL::startActorDraw(const Actor *actor) {
|
||||
tglScalef(scale, scale, scale);
|
||||
tglMultMatrixf(quat.toMatrix().getData());
|
||||
}
|
||||
|
||||
if (!_currentShadowArray && actor->getSortOrder() >= 100) {
|
||||
tglColorMask(TGL_FALSE, TGL_FALSE, TGL_FALSE, TGL_FALSE);
|
||||
tglDepthMask(TGL_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void GfxTinyGL::finishActorDraw() {
|
||||
@ -681,6 +676,8 @@ void GfxTinyGL::drawEMIModelFace(const EMIModel *model, const EMIMeshFace *face)
|
||||
tglEnable(TGL_TEXTURE_2D);
|
||||
else
|
||||
tglDisable(TGL_TEXTURE_2D);
|
||||
if (face->_flags & EMIMeshFace::kAlphaBlend)
|
||||
tglEnable(TGL_BLEND);
|
||||
|
||||
tglBegin(TGL_TRIANGLES);
|
||||
float dim = 1.0f - _dimLevel;
|
||||
@ -751,7 +748,7 @@ void GfxTinyGL::drawSprite(const Sprite *sprite) {
|
||||
act(3, 1) = modelview[13];
|
||||
act(3, 2) = modelview[14];
|
||||
tglLoadMatrixf(act.getData());
|
||||
tglTranslatef(sprite->_pos.x(), sprite->_pos.y(), sprite->_pos.z());
|
||||
tglTranslatef(sprite->_pos.x(), sprite->_pos.y(), -sprite->_pos.z());
|
||||
} else {
|
||||
tglTranslatef(sprite->_pos.x(), sprite->_pos.y(), sprite->_pos.z());
|
||||
TGLfloat modelview[16];
|
||||
@ -770,7 +767,7 @@ void GfxTinyGL::drawSprite(const Sprite *sprite) {
|
||||
tglLoadMatrixf(modelview);
|
||||
}
|
||||
|
||||
if (sprite->_blendMode == Sprite::BlendAdditive) {
|
||||
if (sprite->_flags1 & Sprite::BlendAdditive) {
|
||||
tglBlendFunc(TGL_SRC_ALPHA, TGL_ONE);
|
||||
} else {
|
||||
tglBlendFunc(TGL_SRC_ALPHA, TGL_ONE_MINUS_SRC_ALPHA);
|
||||
@ -778,35 +775,27 @@ void GfxTinyGL::drawSprite(const Sprite *sprite) {
|
||||
|
||||
tglDisable(TGL_LIGHTING);
|
||||
|
||||
if (sprite->_alphaTest) {
|
||||
if (sprite->_flags2 & Sprite::AlphaTest) {
|
||||
tglEnable(TGL_ALPHA_TEST);
|
||||
tglAlphaFunc(TGL_GEQUAL, g_grim->getGameType() == GType_MONKEY4 ? 0.1f : 0.5f);
|
||||
} else {
|
||||
tglDisable(TGL_ALPHA_TEST);
|
||||
}
|
||||
|
||||
if (sprite->_writeDepth) {
|
||||
if (sprite->_flags2 & Sprite::DepthTest) {
|
||||
tglEnable(TGL_DEPTH_TEST);
|
||||
} else {
|
||||
tglDisable(TGL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
if (g_grim->getGameType() == GType_MONKEY4) {
|
||||
if (_currentActor->isInOverworld()) {
|
||||
// The Overworld actors don't have a proper sort order
|
||||
// so we rely on the z coordinates
|
||||
tglDepthMask(TGL_TRUE);
|
||||
} else {
|
||||
tglDepthMask(TGL_FALSE);
|
||||
}
|
||||
tglDepthMask(TGL_TRUE);
|
||||
|
||||
float halfWidth = sprite->_width / 2;
|
||||
float halfHeight = sprite->_height / 2;
|
||||
float dim = 1.0f - _dimLevel;
|
||||
float texCoordsX[] = { 0.0f, 0.0f, 1.0f, 1.0f };
|
||||
float texCoordsY[] = { 1.0f, 0.0f, 0.0f, 1.0f };
|
||||
float vertexX[] = { -1.0f, -1.0f, 1.0f, 1.0f };
|
||||
float vertexY[] = { -1.0f, 1.0f, 1.0f, -1.0f };
|
||||
float vertexX[] = { -1.0f, 1.0f, 1.0f, -1.0f };
|
||||
float vertexY[] = { 1.0f, 1.0f, -1.0f, -1.0f };
|
||||
|
||||
tglBegin(TGL_POLYGON);
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
@ -816,11 +805,11 @@ void GfxTinyGL::drawSprite(const Sprite *sprite) {
|
||||
float a = sprite->_alpha[i] * dim * _alpha / 255.0f;
|
||||
|
||||
tglColor4f(r, g, b, a);
|
||||
tglTexCoord2f(texCoordsX[i], texCoordsY[i]);
|
||||
tglTexCoord2f(sprite->_texCoordX[i], sprite->_texCoordY[i]);
|
||||
tglVertex3f(vertexX[i] * halfWidth, vertexY[i] * halfHeight, 0.0f);
|
||||
}
|
||||
tglColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
tglEnd();
|
||||
tglColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
} else {
|
||||
// In Grim, the bottom edge of the sprite is at y=0 and
|
||||
// the texture is flipped along the X-axis.
|
||||
@ -1454,4 +1443,12 @@ void GfxTinyGL::readPixels(int x, int y, int width, int height, uint8 *buffer) {
|
||||
}
|
||||
}
|
||||
|
||||
void GfxTinyGL::setBlendMode(bool additive) {
|
||||
if (additive) {
|
||||
tglBlendFunc(TGL_SRC_ALPHA, TGL_ONE);
|
||||
} else {
|
||||
tglBlendFunc(TGL_SRC_ALPHA, TGL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
}
|
||||
|
||||
} // end of namespace Grim
|
||||
|
@ -131,6 +131,8 @@ public:
|
||||
void drawBuffers() override;
|
||||
void refreshBuffers() override;
|
||||
|
||||
void setBlendMode(bool additive) override;
|
||||
|
||||
protected:
|
||||
void createSpecialtyTextureFromScreen(uint id, uint8 *data, int x, int y, int width, int height);
|
||||
|
||||
|
@ -1278,7 +1278,8 @@ void GrimEngine::openMainMenuDialog() {
|
||||
void GrimEngine::pauseEngineIntern(bool pause) {
|
||||
if (g_imuse)
|
||||
g_imuse->pause(pause);
|
||||
g_movie->pause(pause);
|
||||
if (g_movie)
|
||||
g_movie->pause(pause);
|
||||
|
||||
if (pause) {
|
||||
_pauseStartTime = _system->getMillis();
|
||||
|
@ -35,7 +35,7 @@ namespace Grim {
|
||||
#define SAVEGAME_FOOTERTAG 'ESAV'
|
||||
|
||||
uint SaveGame::SAVEGAME_MAJOR_VERSION = 22;
|
||||
uint SaveGame::SAVEGAME_MINOR_VERSION = 21;
|
||||
uint SaveGame::SAVEGAME_MINOR_VERSION = 22;
|
||||
|
||||
SaveGame *SaveGame::openForLoading(const Common::String &filename) {
|
||||
Common::InSaveFile *inSaveFile = g_system->getSavefileManager()->openForLoading(filename);
|
||||
|
@ -206,7 +206,7 @@ void Set::loadBinary(Common::SeekableReadStream *data) {
|
||||
_shadows = new SetShadow[_numShadows];
|
||||
|
||||
for (int i = 0; i < _numShadows; ++i) {
|
||||
_shadows[i].loadBinary(data);
|
||||
_shadows[i].loadBinary(data, this);
|
||||
}
|
||||
|
||||
// Enable lights by default
|
||||
@ -593,23 +593,29 @@ bool Light::restoreState(SaveGame *savedState) {
|
||||
SetShadow::SetShadow() : _numSectors(0) {
|
||||
}
|
||||
|
||||
void SetShadow::loadBinary(Common::SeekableReadStream *data) {
|
||||
void SetShadow::loadBinary(Common::SeekableReadStream *data, Set *set) {
|
||||
uint32 nameLen = data->readUint32LE();
|
||||
char *name = new char[nameLen];
|
||||
data->read(name, nameLen);
|
||||
_name = Common::String(name);
|
||||
|
||||
int numUnknownBytes = data->readSint32LE();
|
||||
// The following bytes seem to be always 0. Perhaps padding of some sort?
|
||||
for (int i = 0; i < numUnknownBytes; ++i) {
|
||||
byte value = data->readByte();
|
||||
assert(value == 0);
|
||||
}
|
||||
int lightNameLen = data->readSint32LE();
|
||||
char *lightName = new char[lightNameLen];
|
||||
data->read(lightName, lightNameLen);
|
||||
|
||||
char v[sizeof(float) * 3];
|
||||
data->read(v, sizeof(float) * 3);
|
||||
_shadowPoint = Math::Vector3d::getVector3d(v);
|
||||
|
||||
if (lightNameLen > 0) {
|
||||
for (Common::List<Light *>::const_iterator it = set->getLights().begin(); it != set->getLights().end(); ++it) {
|
||||
if ((*it)->_name.equals(lightName)) {
|
||||
_shadowPoint = (*it)->_pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int numSectors = data->readSint32LE();
|
||||
for (int i = 0; i < numSectors; ++i) {
|
||||
uint32 sectorNameLen = data->readUint32LE();
|
||||
|
@ -195,7 +195,7 @@ struct Light {
|
||||
*/
|
||||
struct SetShadow {
|
||||
SetShadow();
|
||||
void loadBinary(Common::SeekableReadStream *data);
|
||||
void loadBinary(Common::SeekableReadStream *data, Set *set);
|
||||
void saveState(SaveGame *savedState) const;
|
||||
void restoreState(SaveGame *savedState);
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "common/endian.h"
|
||||
|
||||
#include "engines/grim/debug.h"
|
||||
#include "engines/grim/sprite.h"
|
||||
#include "engines/grim/resource.h"
|
||||
#include "engines/grim/gfx_base.h"
|
||||
@ -31,8 +32,8 @@
|
||||
namespace Grim {
|
||||
|
||||
Sprite::Sprite() :
|
||||
_width(0), _height(0), _visible(false), _material(nullptr), _next(nullptr), _blendMode(BlendNormal),
|
||||
_writeDepth(true), _alphaTest(true) {
|
||||
_width(0), _height(0), _visible(false), _material(nullptr), _next(nullptr),
|
||||
_flags1(0), _flags2(0) {
|
||||
}
|
||||
|
||||
|
||||
@ -65,41 +66,36 @@ void Sprite::loadBinary(Common::SeekableReadStream *stream, EMICostume *costume)
|
||||
uint32 texnamelength = stream->readUint32LE();
|
||||
char *texname = new char[texnamelength];
|
||||
stream->read(texname, texnamelength);
|
||||
stream->readByte(); // Unknown
|
||||
byte blendMode = stream->readByte();
|
||||
if (blendMode == 4)
|
||||
_blendMode = BlendAdditive;
|
||||
else if (blendMode != 0)
|
||||
warning("Unknown blend mode value %d for sprite %s", blendMode, name);
|
||||
stream->skip(2); // Unknown
|
||||
float width, height;
|
||||
float offX, offY;
|
||||
char data[16];
|
||||
_flags1 = stream->readUint32LE();
|
||||
if (_flags1 & ~(BlendAdditive)) {
|
||||
Debug::debug(Debug::Sprites, "Sprite %s has unknown flags (%d) in first flag field", name, _flags1);
|
||||
}
|
||||
char data[20];
|
||||
stream->read(data, sizeof(data));
|
||||
width = get_float(data);
|
||||
height = get_float(data + 4);
|
||||
offX = get_float(data + 8);
|
||||
offY = get_float(data + 12);
|
||||
stream->skip(4);//Unknown
|
||||
_width = get_float(data);
|
||||
_height = get_float(data + 4);
|
||||
_pos = Math::Vector3d::getVector3d(data + 8);
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
_alpha[i] = stream->readSint32LE();
|
||||
_red[i] = stream->readSint32LE();
|
||||
_green[i] = stream->readSint32LE();
|
||||
_blue[i] = stream->readSint32LE();
|
||||
}
|
||||
stream->skip(8 * 4); // 8 floats (texcoords?)
|
||||
stream->readByte(); // Unknown (seems to always be 4)
|
||||
if (stream->readByte() == 2)
|
||||
_writeDepth = false;
|
||||
if (stream->readByte() < 2)
|
||||
_alphaTest = false;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
char f[4];
|
||||
stream->read(f, 4);
|
||||
_texCoordX[i] = get_float(f);
|
||||
stream->read(f, 4);
|
||||
_texCoordY[i] = get_float(f);
|
||||
}
|
||||
_flags2 = stream->readUint32LE();
|
||||
if (_flags2 & ~(DepthTest | AlphaTest)) {
|
||||
Debug::debug(Debug::Sprites, "Sprite %s has unknown flags (%d) in second flag field", name, _flags1);
|
||||
}
|
||||
|
||||
_material = costume->loadMaterial(texname, true);
|
||||
_width = width;
|
||||
_height = height;
|
||||
_next = nullptr;
|
||||
_visible = true;
|
||||
_pos.set(offX, offY, 0);
|
||||
|
||||
delete[] name;
|
||||
delete[] texname;
|
||||
|
@ -38,9 +38,12 @@ class EMICostume;
|
||||
|
||||
class Sprite {
|
||||
public:
|
||||
enum BlendMode {
|
||||
BlendNormal = 0,
|
||||
BlendAdditive = 1
|
||||
enum SpriteFlags1 {
|
||||
BlendAdditive = 0x400
|
||||
};
|
||||
enum SpriteFlags2 {
|
||||
DepthTest = 0x100,
|
||||
AlphaTest = 0x20000
|
||||
};
|
||||
|
||||
Sprite();
|
||||
@ -54,13 +57,14 @@ public:
|
||||
bool _visible;
|
||||
Material *_material;
|
||||
Sprite *_next;
|
||||
BlendMode _blendMode;
|
||||
uint32 _flags1;
|
||||
int _red[4];
|
||||
int _green[4];
|
||||
int _blue[4];
|
||||
int _alpha[4];
|
||||
bool _writeDepth;
|
||||
bool _alphaTest;
|
||||
float _texCoordX[4];
|
||||
float _texCoordY[4];
|
||||
uint32 _flags2;
|
||||
};
|
||||
|
||||
} // end of namespace Grim
|
||||
|
@ -63,7 +63,7 @@ TinyGLTexture::TinyGLTexture(const Graphics::Surface *surface, bool nonPoTSuppor
|
||||
|
||||
tglGenTextures(1, &id);
|
||||
tglBindTexture(TGL_TEXTURE_2D, id);
|
||||
tglTexImage2D(TGL_TEXTURE_2D, 0, internalFormat, internalWidth, internalHeight, 0, internalFormat, sourceFormat, 0);
|
||||
tglTexImage2D(TGL_TEXTURE_2D, 0, 3, internalWidth, internalHeight, 0, internalFormat, sourceFormat, 0);
|
||||
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MIN_FILTER, TGL_LINEAR);
|
||||
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MAG_FILTER, TGL_LINEAR);
|
||||
|
||||
@ -82,7 +82,7 @@ TinyGLTexture::~TinyGLTexture() {
|
||||
|
||||
void TinyGLTexture::update(const Graphics::Surface *surface) {
|
||||
tglBindTexture(TGL_TEXTURE_2D, id);
|
||||
tglTexImage2D(TGL_TEXTURE_2D, 0, internalFormat, internalWidth, internalHeight, 0,
|
||||
tglTexImage2D(TGL_TEXTURE_2D, 0, 3, internalWidth, internalHeight, 0,
|
||||
internalFormat, sourceFormat, const_cast<void *>(surface->getPixels())); // TESTME: Not sure if it works.
|
||||
Graphics::tglUploadBlitImage(_blitImage, *surface, 0, false);
|
||||
}
|
||||
|
@ -60,6 +60,7 @@ void glopEnableDisable(GLContext *c, GLParam *p) {
|
||||
break;
|
||||
case TGL_DEPTH_TEST:
|
||||
c->depth_test = v;
|
||||
c->fb->enableDepthTest(v);
|
||||
break;
|
||||
case TGL_ALPHA_TEST:
|
||||
c->fb->enableAlphaTest(v);
|
||||
|
@ -89,6 +89,7 @@ FrameBuffer::FrameBuffer(int width, int height, const Graphics::PixelBuffer &fra
|
||||
this->buffer.zbuf = this->_zbuf;
|
||||
_blendingEnabled = false;
|
||||
_alphaTestEnabled = false;
|
||||
_depthTestEnabled = false;
|
||||
_depthFunc = TGL_LESS;
|
||||
}
|
||||
|
||||
@ -180,4 +181,34 @@ void FrameBuffer::setTexture(const Graphics::PixelBuffer &texture) {
|
||||
current_texture = texture;
|
||||
}
|
||||
|
||||
void FrameBuffer::setBlendingFactors(int sFactor, int dFactor) {
|
||||
_sourceBlendingFactor = sFactor;
|
||||
_destinationBlendingFactor = dFactor;
|
||||
}
|
||||
|
||||
void FrameBuffer::enableBlending(bool enable) {
|
||||
_blendingEnabled = enable;
|
||||
}
|
||||
|
||||
void FrameBuffer::setAlphaTestFunc(int func, float ref) {
|
||||
_alphaTestFunc = func;
|
||||
_alphaTestRefVal = (int)(ref * 255);
|
||||
}
|
||||
|
||||
void FrameBuffer::enableAlphaTest(bool enable) {
|
||||
_alphaTestEnabled = enable;
|
||||
}
|
||||
|
||||
void FrameBuffer::setDepthFunc(int func) {
|
||||
_depthFunc = func;
|
||||
}
|
||||
|
||||
void FrameBuffer::enableDepthTest(bool enable) {
|
||||
_depthTestEnabled = enable;
|
||||
}
|
||||
|
||||
void FrameBuffer::enableAlphaTest(bool enable) {
|
||||
_alphaTestEnabled = enable;
|
||||
}
|
||||
|
||||
} // end of namespace TinyGL
|
||||
|
@ -85,6 +85,9 @@ struct FrameBuffer {
|
||||
}
|
||||
|
||||
FORCEINLINE bool compareDepth(unsigned int &zSrc, unsigned int &zDst) {
|
||||
if (!_depthTestEnabled)
|
||||
return true;
|
||||
|
||||
switch (_depthFunc) {
|
||||
case TGL_NEVER:
|
||||
break;
|
||||
@ -306,6 +309,13 @@ struct FrameBuffer {
|
||||
_blendingEnabled = enable;
|
||||
}
|
||||
|
||||
void enableBlending(bool enable);
|
||||
void setBlendingFactors(int sfactor, int dfactor);
|
||||
void enableAlphaTest(bool enable);
|
||||
void enableDepthTest(bool enable);
|
||||
void setAlphaTestFunc(int func, float ref);
|
||||
void setDepthFunc(int func);
|
||||
|
||||
void setBlendingFactors(int sFactor, int dFactor) {
|
||||
_sourceBlendingFactor = sFactor;
|
||||
_destinationBlendingFactor = dFactor;
|
||||
@ -413,6 +423,7 @@ private:
|
||||
int _sourceBlendingFactor;
|
||||
int _destinationBlendingFactor;
|
||||
bool _alphaTestEnabled;
|
||||
bool _depthTestEnabled;
|
||||
int _alphaTestFunc;
|
||||
int _alphaTestRefVal;
|
||||
int _depthFunc;
|
||||
|
Loading…
x
Reference in New Issue
Block a user