Merge pull request #1326 from firesock/stark-opfade

STARK: Implement opFadeScene
This commit is contained in:
Bastien Bouclet 2017-04-08 17:17:16 +02:00 committed by GitHub
commit ce9637dee2
21 changed files with 301 additions and 10 deletions

View File

@ -59,6 +59,8 @@ shaders/stark_prop.fragment FILE "engines/stark/shaders/stark_prop.fragm
shaders/stark_prop.vertex FILE "engines/stark/shaders/stark_prop.vertex"
shaders/stark_surface.fragment FILE "engines/stark/shaders/stark_surface.fragment"
shaders/stark_surface.vertex FILE "engines/stark/shaders/stark_surface.vertex"
shaders/stark_fade.fragment FILE "engines/stark/shaders/stark_fade.fragment"
shaders/stark_fade.vertex FILE "engines/stark/shaders/stark_fade.vertex"
#endif
#endif

View File

@ -59,6 +59,8 @@ shaders/stark_prop.fragment FILE "engines/stark/shaders/stark_prop.fragm
shaders/stark_prop.vertex FILE "engines/stark/shaders/stark_prop.vertex"
shaders/stark_surface.fragment FILE "engines/stark/shaders/stark_surface.fragment"
shaders/stark_surface.vertex FILE "engines/stark/shaders/stark_surface.vertex"
shaders/stark_fade.fragment FILE "engines/stark/shaders/stark_fade.fragment"
shaders/stark_fade.vertex FILE "engines/stark/shaders/stark_fade.vertex"
#endif
#endif

View File

@ -38,6 +38,7 @@ class VisualProp;
namespace Gfx {
class SurfaceRenderer;
class FadeRenderer;
class Texture;
class Driver {
@ -89,6 +90,13 @@ public:
*/
virtual SurfaceRenderer *createSurfaceRenderer() = 0;
/**
* Create a new fade renderer
*
* The caller is responsible for freeing it.
*/
virtual FadeRenderer *createFadeRenderer() = 0;
/** Bound a screen coordinate coord within the actual game area */
Common::Point getScreenPosBounded(const Common::Point &point) const;

View File

@ -0,0 +1,46 @@
/* ResidualVM - A 3D game interpreter
*
* ResidualVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef STARK_GFX_FADE_RENDERER_H
#define STARK_GFX_FADE_RENDERER_H
namespace Stark {
namespace Gfx {
/**
* A renderer to draw fade screen to the current viewport
*/
class FadeRenderer {
public:
virtual ~FadeRenderer() { }
/**
* Draw the fade screen at the provided fade level
*/
virtual void render(float fadeLevel) = 0;
};
} // End of namespace Gfx
} // End of namespace Stark
#endif // STARK_GFX_FADE_RENDERER_H

View File

@ -31,6 +31,7 @@
#include "engines/stark/gfx/openglsactor.h"
#include "engines/stark/gfx/openglsprop.h"
#include "engines/stark/gfx/openglssurface.h"
#include "engines/stark/gfx/openglsfade.h"
#include "engines/stark/gfx/opengltexture.h"
#include "graphics/pixelbuffer.h"
@ -47,16 +48,28 @@ static const GLfloat surfaceVertices[] = {
1.0, 1.0,
};
static const GLfloat fadeVertices[] = {
// XS YT
-1.0, 1.0,
1.0, 1.0,
-1.0, -1.0,
1.0, -1.0,
};
OpenGLSDriver::OpenGLSDriver() :
_surfaceShader(nullptr),
_actorShader(nullptr),
_surfaceVBO(0) {
_fadeShader(nullptr),
_surfaceVBO(0),
_fadeVBO(0) {
}
OpenGLSDriver::~OpenGLSDriver() {
OpenGL::Shader::freeBuffer(_surfaceVBO);
OpenGL::Shader::freeBuffer(_fadeVBO);
delete _surfaceShader;
delete _actorShader;
delete _fadeShader;
}
void OpenGLSDriver::init() {
@ -70,6 +83,11 @@ void OpenGLSDriver::init() {
static const char* actorAttributes[] = { "position1", "position2", "bone1", "bone2", "boneWeight", "normal", "texcoord", nullptr };
_actorShader = OpenGL::Shader::fromFiles("stark_actor", actorAttributes);
static const char* fadeAttributes[] = { "position", nullptr };
_fadeShader = OpenGL::Shader::fromFiles("stark_fade", fadeAttributes);
_fadeVBO = OpenGL::Shader::createBuffer(GL_ARRAY_BUFFER, sizeof(fadeVertices), fadeVertices);
_fadeShader->enableVertexAttribute("position", _fadeVBO, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(float), 0);
}
void OpenGLSDriver::setScreenViewport(bool noScaling) {
@ -135,6 +153,10 @@ SurfaceRenderer *OpenGLSDriver::createSurfaceRenderer() {
return new OpenGLSSurfaceRenderer(this);
}
FadeRenderer *OpenGLSDriver::createFadeRenderer() {
return new OpenGLSFadeRenderer(this);
}
void OpenGLSDriver::start2DMode() {
// Enable alpha blending
glEnable(GL_BLEND);
@ -174,6 +196,10 @@ OpenGL::Shader *OpenGLSDriver::createSurfaceShaderInstance() {
return _surfaceShader->clone();
}
OpenGL::Shader *OpenGLSDriver::createFadeShaderInstance() {
return _fadeShader->clone();
}
} // End of namespace Gfx
} // End of namespace Stark

View File

@ -53,9 +53,11 @@ public:
VisualActor *createActorRenderer() override;
VisualProp *createPropRenderer() override;
SurfaceRenderer *createSurfaceRenderer() override;
FadeRenderer *createFadeRenderer() override;
OpenGL::Shader *createActorShaderInstance();
OpenGL::Shader *createSurfaceShaderInstance();
OpenGL::Shader *createFadeShaderInstance();
void start2DMode();
void end2DMode();
@ -70,7 +72,9 @@ private:
OpenGL::Shader *_surfaceShader;
OpenGL::Shader *_actorShader;
OpenGL::Shader *_fadeShader;
uint32 _surfaceVBO;
uint32 _fadeVBO;
};
} // End of namespace Gfx

View File

@ -0,0 +1,54 @@
/* ResidualVM - A 3D game interpreter
*
* ResidualVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "engines/stark/gfx/openglsfade.h"
#include "engines/stark/gfx/opengls.h"
#include "graphics/opengl/shader.h"
namespace Stark {
namespace Gfx {
OpenGLSFadeRenderer::OpenGLSFadeRenderer(OpenGLSDriver *gfx) :
FadeRenderer(),
_gfx(gfx) {
_shader = _gfx->createFadeShaderInstance();
}
OpenGLSFadeRenderer::~OpenGLSFadeRenderer() {
delete _shader;
}
void OpenGLSFadeRenderer::render(float fadeLevel) {
_gfx->start2DMode();
_shader->use();
_shader->setUniform1f("alphaLevel", 1.0 - fadeLevel);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
_shader->unbind();
_gfx->end2DMode();
}
} // End of namespace Gfx
} // End of namespace Stark

View File

@ -0,0 +1,56 @@
/* ResidualVM - A 3D game interpreter
*
* ResidualVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef STARK_GFX_OPENGL_S_FADE_H
#define STARK_GFX_OPENGL_S_FADE_H
#include "engines/stark/gfx/faderenderer.h"
namespace OpenGL {
class Shader;
}
namespace Stark {
namespace Gfx {
class OpenGLSDriver;
/**
* An programmable pipeline OpenGL fade screen renderer
*/
class OpenGLSFadeRenderer : public FadeRenderer {
public:
OpenGLSFadeRenderer(OpenGLSDriver *gfx);
~OpenGLSFadeRenderer();
// FadeRenderer API
void render(float fadeLevel);
private:
OpenGLSDriver *_gfx;
OpenGL::Shader *_shader;
};
} // End of namespace Gfx
} // End of namespace Stark
#endif // STARK_GFX_OPENGL_S_FADE_H

View File

@ -61,6 +61,7 @@ void OpenGLSSurfaceRenderer::render(const Texture *texture, const Common::Point
texture->bind();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
_shader->unbind();
_gfx->end2DMode();
}

View File

@ -6,6 +6,7 @@ MODULE_OBJS := \
gfx/driver.o \
gfx/opengls.o \
gfx/openglsactor.o \
gfx/openglsfade.o \
gfx/openglsprop.o \
gfx/openglssurface.o \
gfx/opengltexture.o \

View File

@ -103,7 +103,7 @@ Command *Command::execute(uint32 callMode, Script *script) {
case kRumbleScene:
return opRumbleScene(script, _arguments[1].intValue, _arguments[2].intValue);
case kFadeScene:
return opFadeScene(_arguments[1].intValue, _arguments[2].intValue, _arguments[3].intValue);
return opFadeScene(script, _arguments[1].intValue, _arguments[2].intValue, _arguments[3].intValue);
case kGameEnd:
return opGameEnd();
case kInventoryOpen:
@ -376,10 +376,24 @@ Command *Command::opRumbleScene(Script *script, int32 rumbleDuration, int32 paus
}
}
Command *Command::opFadeScene(int32 unknown1, int32 unknown2, int32 unknown3) {
warning("(TODO: Implement) opFadeScene(%d, %d, %d) : %s", unknown1, unknown2, unknown3, getName().c_str());
Command *Command::opFadeScene(Script *script, bool fadeOut, int32 fadeDuration, bool pause) {
uint gameloopDuration = StarkGlobal->getMillisecondsPerGameloop();
int32 fadeFrames = fadeDuration / gameloopDuration;
return nextCommand();
Current *current = StarkGlobal->getCurrent();
Location *location = current->getLocation();
if (fadeOut) {
location->fadeOutInit(fadeFrames);
} else {
location->fadeInInit(fadeFrames);
}
if (pause) {
script->pause(fadeDuration);
return this; // Stay on this command while the script is suspended
} else {
return nextCommand();
}
}
Math::Vector3d Command::getObjectPosition(const ResourceReference &targetRef, int32 *floorFace) {

View File

@ -209,7 +209,7 @@ protected:
Command *opExit2DLocation();
Command *opGoto2DLocation(const Common::String &level, const Common::String &location);
Command *opRumbleScene(Script *script, int32 rumbleDuration, int32 pause);
Command *opFadeScene(int32 unknown1, int32 unknown2, int32 unknown3);
Command *opFadeScene(Script *script, bool fadeOut, int32 fadeDuration, bool pause);
Command *opGameEnd();
Command *opInventoryOpen(bool open);
Command *opDoNothing();

View File

@ -52,7 +52,9 @@ Location::Location(Object *parent, byte subType, uint16 index, const Common::Str
_currentLayer(nullptr),
_hasActiveScroll(false),
_scrollFollowCharacter(false),
_rumbleFramesRemaining(0) {
_rumbleFramesRemaining(0),
_fadeFramesRemaining(0),
_fadeLevelIncrement(0.0) {
_type = TYPE;
}
@ -65,6 +67,13 @@ void Location::onAllLoaded() {
void Location::onGameLoop() {
Object::onGameLoop();
if (_fadeFramesRemaining > 0) {
_fadeFramesRemaining--;
float newFadeLevel = CLIP<float>(StarkScene->getFadeLevel() + _fadeLevelIncrement, 0.0, 1.0);
StarkScene->setFadeLevel(newFadeLevel);
}
if (_hasActiveScroll) {
// Script triggered scrolling has precedence over following the character
_scrollFollowCharacter = false;
@ -396,5 +405,23 @@ void Location::setRumbleFramesRemaining(int32 rumbleFramesRemaining) {
_rumbleFramesRemaining = rumbleFramesRemaining;
}
void Location::fadeInInit(int32 fadeFrames) {
_fadeFramesRemaining = fadeFrames;
if (fadeFrames > 0) {
StarkScene->setFadeLevel(0.0);
_fadeLevelIncrement = 1.0 / fadeFrames;
}
}
void Location::fadeOutInit(int32 fadeFrames) {
_fadeFramesRemaining = fadeFrames;
if (fadeFrames > 0) {
StarkScene->setFadeLevel(1.0);
_fadeLevelIncrement = -1.0 / fadeFrames;
}
}
} // End of namespace Resources
} // End of namespace Stark

View File

@ -122,6 +122,10 @@ public:
/** Set remaining frames to rumble on this lcation */
void setRumbleFramesRemaining(int32 rumbleFramesRemaining);
/** Setup fading for this location */
void fadeInInit(int32 fadeFrames);
void fadeOutInit(int32 fadeFrames);
protected:
void printData() override;
@ -147,6 +151,9 @@ private:
int32 _rumbleFramesRemaining;
int32 _fadeFramesRemaining;
float _fadeLevelIncrement;
uint getScrollStep();
};

View File

@ -35,7 +35,8 @@ Scene::Scene(Gfx::Driver *gfx) :
_gfx(gfx),
_fov(45.0),
_nearClipPlane(100.0),
_farClipPlane(64000.0) {
_farClipPlane(64000.0),
_fadeLevel(0.0) {
}
Scene::~Scene() {
@ -53,6 +54,8 @@ void Scene::initCamera(const Math::Vector3d &position, const Math::Vector3d &loo
_viewMatrix = Math::makeLookAtMatrix(_cameraPosition, _cameraPosition + _cameraLookDirection, Math::Vector3d(0.0, 0.0, 1.0));
_viewMatrix.transpose(); // Math::makeLookAtMatrix outputs transposed matrices ...
_viewMatrix.translate(-_cameraPosition);
setFadeLevel(1.0);
}
void Scene::scrollCamera(const Common::Rect &viewport) {
@ -132,4 +135,12 @@ Common::Point Scene::convertPosition3DToGameScreenOriginal(const Math::Vector3d
return point;
}
void Scene::setFadeLevel(float fadeLevel) {
_fadeLevel = fadeLevel;
}
float Scene::getFadeLevel() const {
return _fadeLevel;
}
} // End of namespace Stark

View File

@ -72,6 +72,10 @@ public:
*/
Common::Point convertPosition3DToGameScreenOriginal(const Math::Vector3d &obj) const;
/** Get and set scene fade level */
void setFadeLevel(float fadeLevel);
float getFadeLevel() const;
private:
void computeClippingRect(float *xmin, float *xmax, float *ymin, float *ymax);
@ -88,6 +92,7 @@ private:
Math::Matrix4 _projectionMatrix;
Math::Matrix4 _viewMatrix;
float _fadeLevel;
};
} // End of namespace Stark

View File

@ -30,7 +30,7 @@
namespace Stark {
Global::Global() :
_millisecondsPerGameloop(0),
_millisecondsPerGameloop(10),
_april(nullptr),
_root(nullptr),
_level(nullptr),

View File

@ -0,0 +1,8 @@
OUTPUT
uniform float alphaLevel;
void main() {
outColor = vec4(0.0, 0.0, 0.0, alphaLevel);
}

View File

@ -0,0 +1,5 @@
in vec2 position;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
}

View File

@ -51,6 +51,12 @@ GameWindow::GameWindow(Gfx::Driver *gfx, Cursor *cursor, ActionMenu *actionMenu,
_position = Common::Rect(Gfx::Driver::kGameViewportWidth, Gfx::Driver::kGameViewportHeight);
_position.translate(0, Gfx::Driver::kTopBorderHeight);
_visible = true;
_fadeRenderer = _gfx->createFadeRenderer();
}
GameWindow::~GameWindow() {
delete _fadeRenderer;
}
void GameWindow::onRender() {
@ -68,6 +74,11 @@ void GameWindow::onRender() {
// Go for the next one
element++;
}
float fadeLevel = StarkScene->getFadeLevel();
if ((1.0f - fadeLevel) > 0.00001f) {
_fadeRenderer->render(fadeLevel);
}
}
void GameWindow::onMouseMove(const Common::Point &pos) {

View File

@ -23,6 +23,7 @@
#ifndef STARK_UI_GAME_WINDOW_H
#define STARK_UI_GAME_WINDOW_H
#include "engines/stark/gfx/faderenderer.h"
#include "engines/stark/gfx/renderentry.h"
#include "engines/stark/ui/window.h"
@ -39,7 +40,7 @@ class InventoryWindow;
class GameWindow : public Window {
public:
GameWindow(Gfx::Driver *gfx, Cursor *cursor, ActionMenu *actionMenu, InventoryWindow *inventory);
virtual ~GameWindow() {}
virtual ~GameWindow();
/** Clear the location dependent state */
void reset();
@ -59,6 +60,8 @@ protected:
Gfx::RenderEntryArray _renderEntries;
Resources::ItemVisual *_objectUnderCursor;
Common::Point _objectRelativePosition;
Gfx::FadeRenderer *_fadeRenderer;
};
} // End of namespace Stark