Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1 @@
engines/playground3d/metaengine.cpp

View File

@@ -0,0 +1,3 @@
# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] [components]
add_engine playground3d "Playground 3D: the testing and playground environment for 3d renderers" no "" "" "16bit 3d highres" "tinygl"

View File

@@ -0,0 +1,64 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "engines/advancedDetector.h"
#include "base/plugins.h"
#include "playground3d/playground3d.h"
static const PlainGameDescriptor playground3d_setting[] = {
{ "playground3d", "Playground 3d: the testing and playground environment for 3d renderers" },
{ nullptr, nullptr }
};
static const ADGameDescription playground3dDescriptions[] = {
{
"playground3d",
"",
AD_ENTRY1("PLAYGROUND3D", nullptr),
Common::EN_ANY,
Common::kPlatformDOS,
ADGF_NO_FLAGS,
GUIO1(GUIO_NOLAUNCHLOAD)
},
AD_TABLE_END_MARKER
};
class Playground3dMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
public:
Playground3dMetaEngineDetection() : AdvancedMetaEngineDetection(playground3dDescriptions, playground3d_setting) {
_md5Bytes = 512;
}
const char *getName() const override {
return "playground3d";
}
const char *getEngineName() const override {
return "Playground 3d: the testing and playground environment for 3d renderers";
}
const char *getOriginalCopyright() const override {
return "Copyright (C) ScummVM";
}
};
REGISTER_PLUGIN_STATIC(PLAYGROUND3D_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, Playground3dMetaEngineDetection);

View File

@@ -0,0 +1,160 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "engines/playground3d/gfx.h"
#include "engines/util.h"
#include "common/config-manager.h"
#include "graphics/renderer.h"
#include "graphics/surface.h"
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
#include "graphics/opengl/context.h"
#endif
#include "math/glmath.h"
namespace Playground3d {
const float Renderer::cubeVertices[] = {
// S T X Y Z NX NY NZ R G B
0.0f, 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // blue
1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, // magenta
0.0f, 0.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // cyan
1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, // white
0.0f, 1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, 0.0f, // red
1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, // black
0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, 0.0f, // yellow
1.0f, 0.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // green
0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, // magenta
1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // red
0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // white
1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, // yellow
0.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // black
1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, // blue
0.0f, 0.0f, -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, // green
1.0f, 0.0f, -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, // cyan
0.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // cyan
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, // white
0.0f, 0.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // green
1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, // yellow
0.0f, 1.0f, -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // black
1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, // red
0.0f, 0.0f, -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // blue
1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f // magenta
};
Renderer::Renderer(OSystem *system)
: _system(system) {
}
Renderer::~Renderer() {
}
Common::Rect Renderer::viewport() const {
return _screenViewport;
}
void Renderer::computeScreenViewport() {
int32 screenWidth = _system->getWidth();
int32 screenHeight = _system->getHeight();
// Aspect ratio correction
int32 viewportWidth = MIN<int32>(screenWidth, screenHeight * kOriginalWidth / kOriginalHeight);
int32 viewportHeight = MIN<int32>(screenHeight, screenWidth * kOriginalHeight / kOriginalWidth);
_screenViewport = Common::Rect(viewportWidth, viewportHeight);
// Pillarboxing
_screenViewport.translate((screenWidth - viewportWidth) / 2, (screenHeight - viewportHeight) / 2);
}
Math::Matrix4 Renderer::makeProjectionMatrix(float fov, float nearClip, float farClip) const {
float aspectRatio = kOriginalWidth / (float) kOriginalHeight;
float xmaxValue = nearClip * tanf(fov * M_PI / 360.0f);
float ymaxValue = xmaxValue / aspectRatio;
return Math::makeFrustumMatrix(-xmaxValue, xmaxValue, -ymaxValue, ymaxValue, nearClip, farClip);
}
void Renderer::setupCameraPerspective(float pitch, float heading, float fov) {
_projectionMatrix = makeProjectionMatrix(fov, 1.0f, 10000.0f);
_modelViewMatrix = Math::Matrix4(180.0f - heading, pitch, 0.0f, Math::EO_XYZ);
Math::Matrix4 proj = _projectionMatrix;
Math::Matrix4 model = _modelViewMatrix;
proj.transpose();
model.transpose();
_mvpMatrix = proj * model;
_mvpMatrix.transpose();
}
Renderer *createRenderer(OSystem *system) {
Common::String rendererConfig = ConfMan.get("renderer");
Graphics::RendererType desiredRendererType = Graphics::Renderer::parseTypeCode(rendererConfig);
Graphics::RendererType matchingRendererType = Graphics::Renderer::getBestMatchingAvailableType(desiredRendererType,
#if defined(USE_OPENGL_GAME)
Graphics::kRendererTypeOpenGL |
#endif
#if defined(USE_OPENGL_SHADERS)
Graphics::kRendererTypeOpenGLShaders |
#endif
#if defined(USE_TINYGL)
Graphics::kRendererTypeTinyGL |
#endif
0);
bool isAccelerated = matchingRendererType != Graphics::kRendererTypeTinyGL;
uint width = Renderer::kOriginalWidth;
uint height = Renderer::kOriginalHeight;
if (isAccelerated) {
initGraphics3d(width, height);
} else {
initGraphics(width, height, nullptr);
}
#if defined(USE_OPENGL_SHADERS)
if (matchingRendererType == Graphics::kRendererTypeOpenGLShaders) {
return CreateGfxOpenGLShader(system);
}
#endif
#if defined(USE_OPENGL_GAME)
if (matchingRendererType == Graphics::kRendererTypeOpenGL) {
return CreateGfxOpenGL(system);
}
#endif
#if defined(USE_TINYGL)
if (matchingRendererType == Graphics::kRendererTypeTinyGL) {
return CreateGfxTinyGL(system);
}
#endif
/* We should never end up here, getBestMatchingRendererType would have failed before */
error("Unable to create a renderer");
}
} // End of namespace Playground3d

110
engines/playground3d/gfx.h Normal file
View File

@@ -0,0 +1,110 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef PLAYGROUND3D_GFX_H
#define PLAYGROUND3D_GFX_H
#include "common/rect.h"
#include "common/system.h"
#include "math/frustum.h"
#include "math/matrix4.h"
#include "math/vector3d.h"
#include "graphics/surface.h"
#include "graphics/pixelformat.h"
namespace Playground3d {
struct TextureType {
enum type {
RGBA8888 = 0,
RGB888 = 1,
RGB565 = 2,
RGBA5551 = 3,
RGBA4444 = 4,
MAX = 5
};
};
class Renderer {
public:
Renderer(OSystem *system);
virtual ~Renderer();
virtual void init() = 0;
virtual void deinit() = 0;
virtual void clear(const Math::Vector4d &clearColor) = 0;
/**
* Swap the buffers, making the drawn screen visible
*/
virtual void flipBuffer() { }
Common::Rect viewport() const;
void setupCameraPerspective(float pitch, float heading, float fov);
static const int kOriginalWidth = 640;
static const int kOriginalHeight = 480;
void computeScreenViewport();
virtual void setupViewport(int x, int y, int width, int height) = 0;
virtual void loadTextureRGBA(Graphics::Surface *texture) = 0;
virtual void loadTextureRGB(Graphics::Surface *texture) = 0;
virtual void loadTextureRGB565(Graphics::Surface *texture) = 0;
virtual void loadTextureRGBA5551(Graphics::Surface *texture) = 0;
virtual void loadTextureRGBA4444(Graphics::Surface *texture) = 0;
virtual void drawCube(const Math::Vector3d &pos, const Math::Vector3d &roll) = 0;
virtual void drawPolyOffsetTest(const Math::Vector3d &pos, const Math::Vector3d &roll) = 0;
virtual void dimRegionInOut(float fade) = 0;
virtual void drawInViewport() = 0;
virtual void drawRgbaTexture() = 0;
virtual void enableFog(const Math::Vector4d &fogColor) = 0;
virtual void disableFog() = 0;
virtual void enableScissor(int x, int y, int width, int height) = 0;
virtual void disableScissor() = 0;
protected:
OSystem *_system;
Common::Rect _screenViewport;
Math::Matrix4 _projectionMatrix;
Math::Matrix4 _modelViewMatrix;
Math::Matrix4 _mvpMatrix;
static const float cubeVertices[11 * 6 * 4];
Math::Matrix4 makeProjectionMatrix(float fov, float nearClip, float farClip) const;
};
Renderer *CreateGfxOpenGL(OSystem *system);
Renderer *CreateGfxOpenGLShader(OSystem *system);
Renderer *CreateGfxTinyGL(OSystem *system);
Renderer *createRenderer(OSystem *system);
} // End of namespace Playground3d
#endif // PLAYGROUND3D_GFX_H

View File

@@ -0,0 +1,385 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "common/rect.h"
#include "common/textconsole.h"
#if defined(USE_OPENGL_GAME)
#include "graphics/opengl/context.h"
#include "graphics/opengl/texture.h"
#include "graphics/surface.h"
#include "engines/playground3d/gfx.h"
#include "engines/playground3d/gfx_opengl.h"
namespace Playground3d {
static const GLfloat dimRegionVertices[] = {
// X Y
-0.5f, 0.5f,
0.5f, 0.5f,
-0.5f, -0.5f,
0.5f, -0.5f,
};
static const GLfloat boxVertices[] = {
// X Y
-1.0f, 1.0f,
1.0f, 1.0f,
-1.0f, -1.0f,
1.0f, -1.0f,
};
static const GLfloat bitmapVertices[] = {
// X Y
-0.2f, 0.2f,
0.2f, 0.2f,
-0.2f, -0.2f,
0.2f, -0.2f,
};
Renderer *CreateGfxOpenGL(OSystem *system) {
return new OpenGLRenderer(system);
}
OpenGLRenderer::OpenGLRenderer(OSystem *system) :
Renderer(system), _textures{} {
}
OpenGLRenderer::~OpenGLRenderer() {
}
void OpenGLRenderer::init() {
debug("Initializing OpenGL Renderer");
computeScreenViewport();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
}
void OpenGLRenderer::deinit() {
for(int i = 0; i < ARRAYSIZE(_textures); i++) {
delete _textures[i];
_textures[i] = nullptr;
}
}
void OpenGLRenderer::clear(const Math::Vector4d &clearColor) {
glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void OpenGLRenderer::loadTextureRGBA(Graphics::Surface *texture) {
if (!_textures[TextureType::RGBA8888]) {
_textures[TextureType::RGBA8888] = new OpenGL::Texture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
}
_textures[TextureType::RGBA8888]->setSize(texture->w, texture->h);
_textures[TextureType::RGBA8888]->updateArea(Common::Rect(texture->w, texture->h), *texture);
}
void OpenGLRenderer::loadTextureRGB(Graphics::Surface *texture) {
if (!_textures[TextureType::RGB888]) {
_textures[TextureType::RGB888] = new OpenGL::Texture(GL_RGBA, GL_RGB, GL_UNSIGNED_BYTE);
}
_textures[TextureType::RGB888]->setSize(texture->w, texture->h);
_textures[TextureType::RGB888]->updateArea(Common::Rect(texture->w, texture->h), *texture);
}
void OpenGLRenderer::loadTextureRGB565(Graphics::Surface *texture) {
if (!_textures[TextureType::RGB565]) {
_textures[TextureType::RGB565] = new OpenGL::Texture(GL_RGBA, GL_RGB, GL_UNSIGNED_SHORT_5_6_5);
}
_textures[TextureType::RGB565]->setSize(texture->w, texture->h);
_textures[TextureType::RGB565]->updateArea(Common::Rect(texture->w, texture->h), *texture);
}
void OpenGLRenderer::loadTextureRGBA5551(Graphics::Surface *texture) {
if (!_textures[TextureType::RGBA5551]) {
_textures[TextureType::RGBA5551] = new OpenGL::Texture(GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1);
}
_textures[TextureType::RGBA5551]->setSize(texture->w, texture->h);
_textures[TextureType::RGBA5551]->updateArea(Common::Rect(texture->w, texture->h), *texture);
}
void OpenGLRenderer::loadTextureRGBA4444(Graphics::Surface *texture) {
if (!_textures[TextureType::RGBA4444]) {
_textures[TextureType::RGBA4444] = new OpenGL::Texture(GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4);
}
_textures[TextureType::RGBA4444]->setSize(texture->w, texture->h);
_textures[TextureType::RGBA4444]->updateArea(Common::Rect(texture->w, texture->h), *texture);
}
void OpenGLRenderer::setupViewport(int x, int y, int width, int height) {
glViewport(x, y, width, height);
}
void OpenGLRenderer::enableFog(const Math::Vector4d &fogColor) {
glFogi(GL_FOG_MODE, GL_EXP);
glFogf(GL_FOG_START, 1.0f);
glFogf(GL_FOG_END, 1.0f);
glFogf(GL_FOG_DENSITY, 0.1f);
GLfloat color[4] = { fogColor.x(), fogColor.y(), fogColor.z(), fogColor.w() };
glFogfv(GL_FOG_COLOR, color);
glEnable(GL_FOG);
}
void OpenGLRenderer::disableFog() {
glDisable(GL_FOG);
}
void OpenGLRenderer::enableScissor(int x, int y, int width, int height) {
glScissor(x, y, width, height);
glEnable(GL_SCISSOR_TEST);
}
void OpenGLRenderer::disableScissor() {
glDisable(GL_SCISSOR_TEST);
}
void OpenGLRenderer::drawFace(uint face) {
glBegin(GL_TRIANGLE_STRIP);
for (uint i = 0; i < 4; i++) {
glColor4f(cubeVertices[11 * (4 * face + i) + 8], cubeVertices[11 * (4 * face + i) + 9], cubeVertices[11 * (4 * face + i) + 10], 1.0f);
glVertex3f(cubeVertices[11 * (4 * face + i) + 2], cubeVertices[11 * (4 * face + i) + 3], cubeVertices[11 * (4 * face + i) + 4]);
glNormal3f(cubeVertices[11 * (4 * face + i) + 5], cubeVertices[11 * (4 * face + i) + 6], cubeVertices[11 * (4 * face + i) + 7]);
}
glEnd();
}
void OpenGLRenderer::drawCube(const Math::Vector3d &pos, const Math::Vector3d &roll) {
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(_projectionMatrix.getData());
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(_modelViewMatrix.getData());
glDisable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ZERO);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glDisable(GL_TEXTURE_2D);
glTranslatef(pos.x(), pos.y(), pos.z());
glRotatef(roll.x(), 1.0f, 0.0f, 0.0f);
glRotatef(roll.y(), 0.0f, 1.0f, 0.0f);
glRotatef(roll.z(), 0.0f, 0.0f, 1.0f);
for (uint i = 0; i < 6; i++) {
drawFace(i);
}
}
void OpenGLRenderer::drawPolyOffsetTest(const Math::Vector3d &pos, const Math::Vector3d &roll) {
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(_projectionMatrix.getData());
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(_modelViewMatrix.getData());
glDisable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ZERO);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glDisable(GL_TEXTURE_2D);
glTranslatef(pos.x(), pos.y(), pos.z());
glRotatef(roll.y(), 0.0f, 1.0f, 0.0f);
glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
glBegin(GL_TRIANGLES);
glVertex3f(-1.0f, 1.0, 0.0f);
glVertex3f( 1.0f, 1.0, 0.0f);
glVertex3f( 0.0f, -1.0, 0.0f);
glEnd();
glPolygonOffset(-1.0f, 0.0f);
glEnable(GL_POLYGON_OFFSET_FILL);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glBegin(GL_TRIANGLES);
glVertex3f(-0.5f, 0.5, 0.0f);
glVertex3f( 0.5f, 0.5, 0.0f);
glVertex3f( 0.0f, -0.5, 0.0f);
glEnd();
glDisable(GL_POLYGON_OFFSET_FILL);
}
void OpenGLRenderer::dimRegionInOut(float fade) {
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glColor4f(0.0f, 0.0f, 0.0f, 1.0f - fade);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), dimRegionVertices);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
}
void OpenGLRenderer::drawInViewport() {
static GLfloat box2Vertices[] = {
// X Y
-0.1f, 0.1f,
0.1f, 0.1f,
-0.1f, -0.1f,
0.1f, -0.1f,
};
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), &boxVertices[0]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glPushMatrix();
_pos.x() += 0.01f;
_pos.y() += 0.01f;
if (_pos.x() >= 1.1f) {
_pos.x() = -1.1f;
_pos.y() = -1.1f;
}
glTranslatef(_pos.x(), _pos.y(), 0);
glPolygonOffset(-1.0f, 0.0f);
glEnable(GL_POLYGON_OFFSET_FILL);
glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), &box2Vertices[0]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_POLYGON_OFFSET_FILL);
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
}
void OpenGLRenderer::drawRgbaTexture() {
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glEnable(GL_TEXTURE_2D);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTranslatef(-0.8f, 0.8f, 0);
glVertexPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), bitmapVertices);
glTexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), _textures[TextureType::RGBA8888]->getTexCoords());
if (_textures[TextureType::RGBA8888]->bind()) {
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
glTranslatef(0.5, 0, 0);
glVertexPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), bitmapVertices);
glTexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), _textures[TextureType::RGB888]->getTexCoords());
if (_textures[TextureType::RGB888]->bind()) {
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
glTranslatef(0.5, 0, 0);
glVertexPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), bitmapVertices);
glTexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), _textures[TextureType::RGB565]->getTexCoords());
if (_textures[TextureType::RGB565]->bind()) {
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
glTranslatef(0.5, 0, 0);
glVertexPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), bitmapVertices);
glTexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), _textures[TextureType::RGBA5551]->getTexCoords());
if (_textures[TextureType::RGBA5551]->bind()) {
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
glTranslatef(-1.5, -0.5, 0);
glVertexPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), bitmapVertices);
glTexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), _textures[TextureType::RGBA4444]->getTexCoords());
if (_textures[TextureType::RGBA4444]->bind()) {
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
}
} // End of namespace Playground3d
#endif

View File

@@ -0,0 +1,77 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef PLAYGROUND3D_GFX_OPENGL_H
#define PLAYGROUND3D_GFX_OPENGL_H
#include "common/rect.h"
#include "common/system.h"
#include "math/vector3d.h"
#include "graphics/opengl/system_headers.h"
#include "engines/playground3d/gfx.h"
namespace OpenGL {
class Texture;
}
namespace Playground3d {
class OpenGLRenderer : public Renderer {
public:
OpenGLRenderer(OSystem *_system);
virtual ~OpenGLRenderer();
void init() override;
void deinit() override;
void clear(const Math::Vector4d &clearColor) override;
void loadTextureRGBA(Graphics::Surface *texture) override;
void loadTextureRGB(Graphics::Surface *texture) override;
void loadTextureRGB565(Graphics::Surface *texture) override;
void loadTextureRGBA5551(Graphics::Surface *texture) override;
void loadTextureRGBA4444(Graphics::Surface *texture) override;
void setupViewport(int x, int y, int width, int height) override;
void drawCube(const Math::Vector3d &pos, const Math::Vector3d &roll) override;
void drawPolyOffsetTest(const Math::Vector3d &pos, const Math::Vector3d &roll) override;
void dimRegionInOut(float fade) override;
void drawInViewport() override;
void drawRgbaTexture() override;
void enableFog(const Math::Vector4d &fogColor) override;
void disableFog() override;
void enableScissor(int x, int y, int width, int height) override;
void disableScissor() override;
private:
Math::Vector3d _pos;
OpenGL::Texture *_textures[TextureType::MAX];
void drawFace(uint face);
};
} // End of namespace Playground3d
#endif // PLAYGROUND3D_GFX_OPENGL_H

View File

@@ -0,0 +1,381 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "common/rect.h"
#include "common/textconsole.h"
#if defined(USE_OPENGL_SHADERS)
#include "graphics/surface.h"
#include "math/glmath.h"
#include "math/vector2d.h"
#include "math/rect2d.h"
#include "math/quat.h"
#include "graphics/opengl/shader.h"
#include "graphics/opengl/texture.h"
#include "engines/playground3d/gfx.h"
#include "engines/playground3d/gfx_opengl_shaders.h"
namespace Playground3d {
static const GLfloat offsetVertices[] = {
// X Y
// 1st triangle
-1.0f, 1.0f,
1.0f, 1.0f,
0.0f, -1.0f,
// 2nd triangle
-0.5f, 0.5f,
0.5f, 0.5f,
0.0f, -0.5f,
};
static const GLfloat dimRegionVertices[] = {
// X Y
-0.5f, 0.5f,
0.5f, 0.5f,
-0.5f, -0.5f,
0.5f, -0.5f,
};
static const GLfloat boxVertices[] = {
// X Y
// static green box
-1.0f, 1.0f,
1.0f, 1.0f,
-1.0f, -1.0f,
1.0f, -1.0f,
// moving red box
-0.1f, 0.1f,
0.1f, 0.1f,
-0.1f, -0.1f,
0.1f, -0.1f,
};
static const GLfloat bitmapVertices[] = {
// X Y
-0.2f, 0.2f,
0.2f, 0.2f,
-0.2f, -0.2f,
0.2f, -0.2f,
};
Renderer *CreateGfxOpenGLShader(OSystem *system) {
return new ShaderRenderer(system);
}
ShaderRenderer::ShaderRenderer(OSystem *system) :
Renderer(system),
_currentViewport(kOriginalWidth, kOriginalHeight),
_cubeShader(nullptr),
_offsetShader(nullptr),
_fadeShader(nullptr),
_viewportShader(nullptr),
_bitmapShader(nullptr),
_cubeVBO(0),
_offsetVBO(0),
_fadeVBO(0),
_viewportVBO(0),
_bitmapVBO(0),
_textures{} {
}
ShaderRenderer::~ShaderRenderer() {
OpenGL::Shader::freeBuffer(_cubeVBO);
OpenGL::Shader::freeBuffer(_offsetVBO);
OpenGL::Shader::freeBuffer(_fadeVBO);
OpenGL::Shader::freeBuffer(_viewportVBO);
OpenGL::Shader::freeBuffer(_bitmapVBO);
delete _cubeShader;
delete _offsetShader;
delete _fadeShader;
delete _viewportShader;
delete _bitmapShader;
}
void ShaderRenderer::init() {
debug("Initializing OpenGL Renderer with shaders");
computeScreenViewport();
static const char *cubeAttributes[] = { "position", "normal", "color", "texcoord", nullptr };
_cubeShader = OpenGL::Shader::fromFiles("playground3d_cube", cubeAttributes);
_cubeVBO = OpenGL::Shader::createBuffer(GL_ARRAY_BUFFER, sizeof(cubeVertices), cubeVertices);
_cubeShader->enableVertexAttribute("texcoord", _cubeVBO, 2, GL_FLOAT, GL_FALSE, 11 * sizeof(float), 0);
_cubeShader->enableVertexAttribute("position", _cubeVBO, 3, GL_FLOAT, GL_FALSE, 11 * sizeof(float), 8);
_cubeShader->enableVertexAttribute("normal", _cubeVBO, 3, GL_FLOAT, GL_FALSE, 11 * sizeof(float), 20);
_cubeShader->enableVertexAttribute("color", _cubeVBO, 3, GL_FLOAT, GL_FALSE, 11 * sizeof(float), 32);
static const char *offsetAttributes[] = { "position", nullptr };
_offsetShader = OpenGL::Shader::fromFiles("playground3d_offset", offsetAttributes);
_offsetVBO = OpenGL::Shader::createBuffer(GL_ARRAY_BUFFER, sizeof(offsetVertices), offsetVertices);
_offsetShader->enableVertexAttribute("position", _offsetVBO, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(float), 0);
static const char *fadeAttributes[] = { "position", nullptr };
_fadeShader = OpenGL::Shader::fromFiles("playground3d_fade", fadeAttributes);
_fadeVBO = OpenGL::Shader::createBuffer(GL_ARRAY_BUFFER, sizeof(dimRegionVertices), dimRegionVertices);
_fadeShader->enableVertexAttribute("position", _fadeVBO, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(float), 0);
static const char *viewportAttributes[] = { "position", nullptr };
_viewportShader = OpenGL::Shader::fromFiles("playground3d_viewport", viewportAttributes);
_viewportVBO = OpenGL::Shader::createBuffer(GL_ARRAY_BUFFER, sizeof(boxVertices), boxVertices);
_viewportShader->enableVertexAttribute("position", _viewportVBO, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(float), 0);
static const char *bitmapAttributes[] = { "position", "texcoord", nullptr };
_bitmapShader = OpenGL::Shader::fromFiles("playground3d_bitmap", bitmapAttributes);
_bitmapVBO = OpenGL::Shader::createBuffer(GL_ARRAY_BUFFER, sizeof(bitmapVertices), bitmapVertices);
_bitmapShader->enableVertexAttribute("position", _bitmapVBO, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(float), 0);
_bitmapTexVBO = OpenGL::Shader::createBuffer(GL_ARRAY_BUFFER, 4 * 2 * sizeof(GLfloat), nullptr, GL_DYNAMIC_DRAW);
_bitmapShader->enableVertexAttribute("texcoord", _bitmapTexVBO, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(float), 0);
}
void ShaderRenderer::deinit() {
for(int i = 0; i < ARRAYSIZE(_textures); i++) {
delete _textures[i];
_textures[i] = nullptr;
}
delete _cubeShader;
_cubeShader = nullptr;
delete _offsetShader;
_offsetShader = nullptr;
delete _fadeShader;
_fadeShader = nullptr;
delete _viewportShader;
_viewportShader = nullptr;
delete _bitmapShader;
_bitmapShader = nullptr;
OpenGL::Shader::freeBuffer(_cubeVBO);
OpenGL::Shader::freeBuffer(_offsetVBO);
OpenGL::Shader::freeBuffer(_fadeVBO);
OpenGL::Shader::freeBuffer(_viewportVBO);
OpenGL::Shader::freeBuffer(_bitmapVBO);
OpenGL::Shader::freeBuffer(_bitmapTexVBO);
}
void ShaderRenderer::clear(const Math::Vector4d &clearColor) {
glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void ShaderRenderer::loadTextureRGBA(Graphics::Surface *texture) {
if (!_textures[TextureType::RGBA8888]) {
_textures[TextureType::RGBA8888] = new OpenGL::Texture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
}
_textures[TextureType::RGBA8888]->setSize(texture->w, texture->h);
_textures[TextureType::RGBA8888]->updateArea(Common::Rect(texture->w, texture->h), *texture);
}
void ShaderRenderer::loadTextureRGB(Graphics::Surface *texture) {
if (!_textures[TextureType::RGB888]) {
_textures[TextureType::RGB888] = new OpenGL::Texture(GL_RGB, GL_RGB, GL_UNSIGNED_BYTE);
}
_textures[TextureType::RGB888]->setSize(texture->w, texture->h);
_textures[TextureType::RGB888]->updateArea(Common::Rect(texture->w, texture->h), *texture);
}
void ShaderRenderer::loadTextureRGB565(Graphics::Surface *texture) {
if (!_textures[TextureType::RGB565]) {
_textures[TextureType::RGB565] = new OpenGL::Texture(GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5);
}
_textures[TextureType::RGB565]->setSize(texture->w, texture->h);
_textures[TextureType::RGB565]->updateArea(Common::Rect(texture->w, texture->h), *texture);
}
void ShaderRenderer::loadTextureRGBA5551(Graphics::Surface *texture) {
if (!_textures[TextureType::RGBA5551]) {
_textures[TextureType::RGBA5551] = new OpenGL::Texture(GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1);
}
_textures[TextureType::RGBA5551]->setSize(texture->w, texture->h);
_textures[TextureType::RGBA5551]->updateArea(Common::Rect(texture->w, texture->h), *texture);
}
void ShaderRenderer::loadTextureRGBA4444(Graphics::Surface *texture) {
if (!_textures[TextureType::RGBA4444]) {
_textures[TextureType::RGBA4444] = new OpenGL::Texture(GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4);
}
_textures[TextureType::RGBA4444]->setSize(texture->w, texture->h);
_textures[TextureType::RGBA4444]->updateArea(Common::Rect(texture->w, texture->h), *texture);
}
void ShaderRenderer::setupViewport(int x, int y, int width, int height) {
glViewport(x, y, width, height);
}
void ShaderRenderer::enableFog(const Math::Vector4d &fogColor) {
}
void ShaderRenderer::disableFog() {
}
void ShaderRenderer::enableScissor(int x, int y, int width, int height) {
glScissor(x, y, width, height);
glEnable(GL_SCISSOR_TEST);
}
void ShaderRenderer::disableScissor() {
glDisable(GL_SCISSOR_TEST);
}
void ShaderRenderer::drawCube(const Math::Vector3d &pos, const Math::Vector3d &roll) {
glDisable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ZERO);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
auto rotateMatrix = (Math::Quaternion::fromEuler(roll.x(), roll.y(), roll.z(), Math::EO_XYZ)).inverse().toMatrix();
_cubeShader->use();
_cubeShader->setUniform("textured", false);
_cubeShader->setUniform("mvpMatrix", _mvpMatrix);
_cubeShader->setUniform("rotateMatrix", rotateMatrix);
_cubeShader->setUniform("modelPos", pos);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
glDrawArrays(GL_TRIANGLE_STRIP, 8, 4);
glDrawArrays(GL_TRIANGLE_STRIP, 12, 4);
glDrawArrays(GL_TRIANGLE_STRIP, 16, 4);
glDrawArrays(GL_TRIANGLE_STRIP, 20, 4);
}
void ShaderRenderer::drawPolyOffsetTest(const Math::Vector3d &pos, const Math::Vector3d &roll) {
glDisable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ZERO);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
auto rotateMatrix = (Math::Quaternion::fromEuler(roll.x(), roll.y(), roll.z(), Math::EO_XYZ)).inverse().toMatrix();
_offsetShader->use();
_offsetShader->setUniform("mvpMatrix", _mvpMatrix);
_offsetShader->setUniform("rotateMatrix", rotateMatrix);
_offsetShader->setUniform("modelPos", pos);
_offsetShader->setUniform("triColor", Math::Vector3d(0.0f, 1.0f, 0.0f));
glDrawArrays(GL_TRIANGLES, 0, 3);
glPolygonOffset(-1.0f, 0.0f);
glEnable(GL_POLYGON_OFFSET_FILL);
_offsetShader->setUniform("triColor", Math::Vector3d(1.0f, 1.0f, 1.0f));
glDrawArrays(GL_TRIANGLES, 3, 3);
glDisable(GL_POLYGON_OFFSET_FILL);
}
void ShaderRenderer::dimRegionInOut(float fade) {
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
_fadeShader->use();
_fadeShader->setUniform1f("alphaLevel", 1.0 - fade);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
_fadeShader->unbind();
}
void ShaderRenderer::drawInViewport() {
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
_viewportShader->use();
_viewportShader->setUniform("offset", Math::Vector2d(0.0f, 0.0f));
_viewportShader->setUniform("color", Math::Vector3d(0.0f, 1.0f, 0.0f));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
_pos.setX(_pos.getX() + 0.01f);
_pos.setY(_pos.getY() + 0.01f);
if (_pos.getX() >= 1.1f) {
_pos.setX(-1.1f);
_pos.setY(-1.1f);
}
_viewportShader->setUniform("offset", _pos);
_viewportShader->setUniform("color", Math::Vector3d(1.0f, 0.0f, 0.0f));
glPolygonOffset(-1.0f, 0.0f);
glEnable(GL_POLYGON_OFFSET_FILL);
glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
glDisable(GL_POLYGON_OFFSET_FILL);
_viewportShader->unbind();
}
void ShaderRenderer::drawRgbaTexture() {
Math::Vector2d offset;
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
_bitmapShader->use();
glBindBuffer(GL_ARRAY_BUFFER, _bitmapTexVBO);
offset.setX(-0.8f);
offset.setY(0.8f);
_bitmapShader->setUniform("offsetXY", offset);
glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * 2 * sizeof(GLfloat), _textures[TextureType::RGBA8888]->getTexCoords());
if (_textures[TextureType::RGBA8888]->bind()) {
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
offset.setX(-0.3f);
offset.setY(0.8f);
_bitmapShader->setUniform("offsetXY", offset);
glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * 2 * sizeof(GLfloat), _textures[TextureType::RGB888]->getTexCoords());
if (_textures[TextureType::RGB888]->bind()) {
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
offset.setX(0.2f);
offset.setY(0.8f);
_bitmapShader->setUniform("offsetXY", offset);
glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * 2 * sizeof(GLfloat), _textures[TextureType::RGB565]->getTexCoords());
if (_textures[TextureType::RGB565]->bind()) {
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
offset.setX(0.7f);
offset.setY(0.8f);
_bitmapShader->setUniform("offsetXY", offset);
glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * 2 * sizeof(GLfloat), _textures[TextureType::RGBA5551]->getTexCoords());
if (_textures[TextureType::RGBA5551]->bind()) {
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
offset.setX(-0.8f);
offset.setY(0.2f);
_bitmapShader->setUniform("offsetXY", offset);
glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * 2 * sizeof(GLfloat), _textures[TextureType::RGBA4444]->getTexCoords());
if (_textures[TextureType::RGBA4444]->bind()) {
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
_bitmapShader->unbind();
}
} // End of namespace Playground3d
#endif

View File

@@ -0,0 +1,89 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef PLAYGROUND3D_GFX_OPENGL_SHADERS_H
#define PLAYGROUND3D_GFX_OPENGL_SHADERS_H
#include "common/rect.h"
#include "math/rect2d.h"
#include "graphics/opengl/shader.h"
#include "graphics/opengl/system_headers.h"
#include "engines/playground3d/gfx.h"
namespace OpenGL {
class Texture;
}
namespace Playground3d {
class ShaderRenderer : public Renderer {
public:
ShaderRenderer(OSystem *_system);
virtual ~ShaderRenderer();
void init() override;
void deinit() override;
void clear(const Math::Vector4d &clearColor) override;
void loadTextureRGBA(Graphics::Surface *texture) override;
void loadTextureRGB(Graphics::Surface *texture) override;
void loadTextureRGB565(Graphics::Surface *texture) override;
void loadTextureRGBA5551(Graphics::Surface *texture) override;
void loadTextureRGBA4444(Graphics::Surface *texture) override;
void setupViewport(int x, int y, int width, int height) override;
void drawCube(const Math::Vector3d &pos, const Math::Vector3d &roll) override;
void drawPolyOffsetTest(const Math::Vector3d &pos, const Math::Vector3d &roll) override;
void dimRegionInOut(float fade) override;
void drawInViewport() override;
void drawRgbaTexture() override;
void enableFog(const Math::Vector4d &fogColor) override;
void disableFog() override;
void enableScissor(int x, int y, int width, int height) override;
void disableScissor() override;
private:
OpenGL::Shader *_cubeShader;
OpenGL::Shader *_offsetShader;
OpenGL::Shader *_fadeShader;
OpenGL::Shader *_viewportShader;
OpenGL::Shader *_bitmapShader;
GLuint _cubeVBO;
GLuint _offsetVBO;
GLuint _fadeVBO;
GLuint _viewportVBO;
GLuint _bitmapVBO;
GLuint _bitmapTexVBO;
Common::Rect _currentViewport;
Math::Vector2d _pos;
OpenGL::Texture *_textures[TextureType::MAX];
};
} // End of namespace Playground3d
#endif // PLAYGROUND3D_GFX_OPENGL_SHADERS_H

View File

@@ -0,0 +1,455 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "common/config-manager.h"
#include "common/rect.h"
#include "common/textconsole.h"
#include "graphics/surface.h"
#include "graphics/tinygl/tinygl.h"
#include "math/vector2d.h"
#include "math/glmath.h"
#include "engines/playground3d/gfx.h"
#include "engines/playground3d/gfx_tinygl.h"
namespace Playground3d {
static const TGLfloat dimRegionVertices[] = {
// X Y
-0.5f, 0.5f,
0.5f, 0.5f,
-0.5f, -0.5f,
0.5f, -0.5f,
};
static const TGLuint dimRegionIndices[] = {
0, 1, 2, 3
};
static const TGLfloat boxVertices[] = {
// X Y
-1.0f, 1.0f,
1.0f, 1.0f,
-1.0f, -1.0f,
1.0f, -1.0f,
};
static const TGLfloat bitmapVertices[] = {
// X Y
-0.2f, 0.2f,
0.2f, 0.2f,
-0.2f, -0.2f,
0.2f, -0.2f,
};
static const TGLfloat textCords[] = {
// S T
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
};
Renderer *CreateGfxTinyGL(OSystem *system) {
return new TinyGLRenderer(system);
}
TinyGLRenderer::TinyGLRenderer(OSystem *system) :
Renderer(system),
_context(nullptr),
_blitImageRgba(nullptr),
_blitImageRgb(nullptr),
_blitImageRgb565(nullptr),
_blitImageRgba5551(nullptr),
_blitImageRgba4444(nullptr) {
}
void TinyGLRenderer::init() {
debug("Initializing Software 3D Renderer");
computeScreenViewport();
_context = TinyGL::createContext(kOriginalWidth, kOriginalHeight, g_system->getScreenFormat(), 512, true, ConfMan.getBool("dirtyrects"));
TinyGL::setContext(_context);
tglMatrixMode(TGL_PROJECTION);
tglLoadIdentity();
tglMatrixMode(TGL_MODELVIEW);
tglLoadIdentity();
tglDisable(TGL_LIGHTING);
tglEnable(TGL_DEPTH_TEST);
tglGenTextures(5, _textureRgbaId);
tglGenTextures(5, _textureRgbId);
tglGenTextures(2, _textureRgb565Id);
tglGenTextures(2, _textureRgba5551Id);
tglGenTextures(2, _textureRgba4444Id);
_blitImageRgba = tglGenBlitImage();
_blitImageRgb = tglGenBlitImage();
_blitImageRgb565 = tglGenBlitImage();
_blitImageRgba5551 = tglGenBlitImage();
_blitImageRgba4444 = tglGenBlitImage();
}
void TinyGLRenderer::deinit() {
tglDeleteTextures(5, _textureRgbaId);
tglDeleteTextures(5, _textureRgbId);
tglDeleteTextures(2, _textureRgb565Id);
tglDeleteTextures(2, _textureRgba5551Id);
tglDeleteTextures(2, _textureRgba4444Id);
tglDeleteBlitImage(_blitImageRgba);
tglDeleteBlitImage(_blitImageRgb);
tglDeleteBlitImage(_blitImageRgb565);
tglDeleteBlitImage(_blitImageRgba5551);
tglDeleteBlitImage(_blitImageRgba4444);
TinyGL::destroyContext(_context);
}
void TinyGLRenderer::loadTextureRGBA(Graphics::Surface *texture) {
tglBindTexture(TGL_TEXTURE_2D, _textureRgbaId[0]);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MIN_FILTER, TGL_NEAREST);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MAG_FILTER, TGL_NEAREST);
tglTexImage2D(TGL_TEXTURE_2D, 0, TGL_RGBA, texture->w, texture->h, 0, TGL_RGBA, TGL_UNSIGNED_BYTE, texture->getPixels());
tglUploadBlitImage(_blitImageRgba, *texture, 0, false);
}
void TinyGLRenderer::loadTextureRGB(Graphics::Surface *texture) {
tglBindTexture(TGL_TEXTURE_2D, _textureRgbId[0]);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MIN_FILTER, TGL_NEAREST);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MAG_FILTER, TGL_NEAREST);
tglTexImage2D(TGL_TEXTURE_2D, 0, TGL_RGBA, texture->w, texture->h, 0, TGL_RGB, TGL_UNSIGNED_BYTE, texture->getPixels());
tglUploadBlitImage(_blitImageRgb, *texture, 0, false);
}
void TinyGLRenderer::loadTextureRGB565(Graphics::Surface *texture) {
tglBindTexture(TGL_TEXTURE_2D, _textureRgb565Id[0]);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MIN_FILTER, TGL_NEAREST);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MAG_FILTER, TGL_NEAREST);
tglTexImage2D(TGL_TEXTURE_2D, 0, TGL_RGBA, texture->w, texture->h, 0, TGL_RGB, TGL_UNSIGNED_SHORT_5_6_5, texture->getPixels());
tglUploadBlitImage(_blitImageRgb565, *texture, 0, false);
}
void TinyGLRenderer::loadTextureRGBA5551(Graphics::Surface *texture) {
tglBindTexture(TGL_TEXTURE_2D, _textureRgba5551Id[0]);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MIN_FILTER, TGL_NEAREST);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MAG_FILTER, TGL_NEAREST);
tglTexImage2D(TGL_TEXTURE_2D, 0, TGL_RGBA, texture->w, texture->h, 0, TGL_RGBA, TGL_UNSIGNED_SHORT_5_5_5_1, texture->getPixels());
tglUploadBlitImage(_blitImageRgba5551, *texture, 0, false);
}
void TinyGLRenderer::loadTextureRGBA4444(Graphics::Surface *texture) {
tglBindTexture(TGL_TEXTURE_2D, _textureRgba4444Id[0]);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MIN_FILTER, TGL_NEAREST);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MAG_FILTER, TGL_NEAREST);
tglTexImage2D(TGL_TEXTURE_2D, 0, TGL_RGBA, texture->w, texture->h, 0, TGL_RGBA, TGL_UNSIGNED_SHORT_4_4_4_4, texture->getPixels());
tglUploadBlitImage(_blitImageRgba4444, *texture, 0, false);
}
void TinyGLRenderer::clear(const Math::Vector4d &clearColor) {
tglClearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
tglClear(TGL_COLOR_BUFFER_BIT | TGL_DEPTH_BUFFER_BIT);
}
void TinyGLRenderer::setupViewport(int x, int y, int width, int height) {
tglViewport(x, y, width, height);
}
void TinyGLRenderer::enableFog(const Math::Vector4d &fogColor) {
tglFogi(TGL_FOG_MODE, TGL_EXP);
tglFogf(TGL_FOG_START, 1.0f);
tglFogf(TGL_FOG_END, 1.0f);
tglFogf(TGL_FOG_DENSITY, 0.1f);
TGLfloat color[4] = { fogColor.x(), fogColor.y(), fogColor.z(), fogColor.w() };
tglFogfv(TGL_FOG_COLOR, color);
tglEnable(TGL_FOG);
}
void TinyGLRenderer::disableFog() {
tglDisable(TGL_FOG);
}
void TinyGLRenderer::enableScissor(int x, int y, int width, int height) {
tglScissor(x, y, width, height);
tglEnable(TGL_SCISSOR_TEST);
}
void TinyGLRenderer::disableScissor() {
tglDisable(TGL_SCISSOR_TEST);
}
void TinyGLRenderer::drawFace(uint face) {
tglBegin(TGL_TRIANGLE_STRIP);
for (uint i = 0; i < 4; i++) {
tglColor4f(cubeVertices[11 * (4 * face + i) + 8], cubeVertices[11 * (4 * face + i) + 9], cubeVertices[11 * (4 * face + i) + 10], 1.0f);
tglVertex3f(cubeVertices[11 * (4 * face + i) + 2], cubeVertices[11 * (4 * face + i) + 3], cubeVertices[11 * (4 * face + i) + 4]);
tglNormal3f(cubeVertices[11 * (4 * face + i) + 5], cubeVertices[11 * (4 * face + i) + 6], cubeVertices[11 * (4 * face + i) + 7]);
}
tglEnd();
}
void TinyGLRenderer::drawCube(const Math::Vector3d &pos, const Math::Vector3d &roll) {
tglMatrixMode(TGL_PROJECTION);
tglLoadMatrixf(_projectionMatrix.getData());
tglMatrixMode(TGL_MODELVIEW);
tglLoadMatrixf(_modelViewMatrix.getData());
tglDisable(TGL_BLEND);
tglBlendFunc(TGL_ONE, TGL_ZERO);
tglEnable(TGL_DEPTH_TEST);
tglDepthMask(TGL_TRUE);
tglDisable(TGL_TEXTURE_2D);
tglTranslatef(pos.x(), pos.y(), pos.z());
tglRotatef(roll.x(), 1.0f, 0.0f, 0.0f);
tglRotatef(roll.y(), 0.0f, 1.0f, 0.0f);
tglRotatef(roll.z(), 0.0f, 0.0f, 1.0f);
for (uint i = 0; i < 6; i++) {
drawFace(i);
}
}
void TinyGLRenderer::drawPolyOffsetTest(const Math::Vector3d &pos, const Math::Vector3d &roll) {
tglMatrixMode(TGL_PROJECTION);
tglLoadMatrixf(_projectionMatrix.getData());
tglMatrixMode(TGL_MODELVIEW);
tglLoadMatrixf(_modelViewMatrix.getData());
tglDisable(TGL_BLEND);
tglBlendFunc(TGL_ONE, TGL_ZERO);
tglEnable(TGL_DEPTH_TEST);
tglDepthMask(TGL_TRUE);
tglDisable(TGL_TEXTURE_2D);
tglTranslatef(pos.x(), pos.y(), pos.z());
tglRotatef(roll.y(), 0.0f, 1.0f, 0.0f);
tglColor4f(0.0f, 1.0f, 0.0f, 1.0f);
tglBegin(TGL_TRIANGLES);
tglVertex3f(-1.0f, 1.0, 0.0f);
tglVertex3f( 1.0f, 1.0, 0.0f);
tglVertex3f( 0.0f, -1.0, 0.0f);
tglEnd();
tglPolygonOffset(-1.0f, 0.0f);
tglEnable(TGL_POLYGON_OFFSET_FILL);
tglColor4f(1.0f, 1.0f, 1.0f, 1.0f);
tglBegin(TGL_TRIANGLES);
tglVertex3f(-0.5f, 0.5, 0.0f);
tglVertex3f( 0.5f, 0.5, 0.0f);
tglVertex3f( 0.0f, -0.5, 0.0f);
tglEnd();
tglDisable(TGL_POLYGON_OFFSET_FILL);
}
void TinyGLRenderer::flipBuffer() {
Common::List<Common::Rect> dirtyAreas;
TinyGL::presentBuffer(dirtyAreas);
Graphics::Surface glBuffer;
TinyGL::getSurfaceRef(glBuffer);
if (!dirtyAreas.empty()) {
for (Common::List<Common::Rect>::iterator itRect = dirtyAreas.begin(); itRect != dirtyAreas.end(); ++itRect) {
g_system->copyRectToScreen(glBuffer.getBasePtr((*itRect).left, (*itRect).top), glBuffer.pitch,
(*itRect).left, (*itRect).top, (*itRect).width(), (*itRect).height());
}
}
}
void TinyGLRenderer::dimRegionInOut(float fade) {
tglMatrixMode(TGL_PROJECTION);
tglPushMatrix();
tglLoadIdentity();
tglMatrixMode(TGL_MODELVIEW);
tglPushMatrix();
tglLoadIdentity();
tglEnable(TGL_BLEND);
tglBlendFunc(TGL_ONE, TGL_ONE_MINUS_SRC_ALPHA);
tglDisable(TGL_DEPTH_TEST);
tglDepthMask(TGL_FALSE);
tglColor4f(0.0f, 0.0f, 0.0f, 1.0f - fade);
tglEnableClientState(TGL_VERTEX_ARRAY);
tglVertexPointer(2, TGL_FLOAT, 0, dimRegionVertices);
tglDrawElements(TGL_TRIANGLE_STRIP, 4, TGL_UNSIGNED_INT, dimRegionIndices);
//tglDrawArrays(TGL_TRIANGLE_STRIP, 0, 4);
tglDisableClientState(TGL_VERTEX_ARRAY);
tglMatrixMode(TGL_MODELVIEW);
tglPopMatrix();
tglMatrixMode(TGL_PROJECTION);
tglPopMatrix();
}
void TinyGLRenderer::drawInViewport() {
static TGLfloat box2Vertices[] = {
// X Y
-0.1f, 0.1f,
0.1f, 0.1f,
-0.1f, -0.1f,
0.1f, -0.1f,
};
tglMatrixMode(TGL_PROJECTION);
tglPushMatrix();
tglLoadIdentity();
tglMatrixMode(TGL_MODELVIEW);
tglPushMatrix();
tglLoadIdentity();
tglEnable(TGL_BLEND);
tglBlendFunc(TGL_ONE, TGL_ONE_MINUS_SRC_ALPHA);
tglDisable(TGL_DEPTH_TEST);
tglDepthMask(TGL_FALSE);
tglColor4f(0.0f, 1.0f, 0.0f, 1.0f);
tglEnableClientState(TGL_VERTEX_ARRAY);
tglVertexPointer(2, TGL_FLOAT, 2 * sizeof(TGLfloat), &boxVertices[0]);
tglDrawArrays(TGL_TRIANGLE_STRIP, 0, 4);
tglDisableClientState(TGL_VERTEX_ARRAY);
tglPushMatrix();
_pos.x() += 0.01f;
_pos.y() += 0.01f;
if (_pos.x() >= 1.1f) {
_pos.x() = -1.1f;
_pos.y() = -1.1f;
}
tglTranslatef(_pos.x(), _pos.y(), 0);
tglPolygonOffset(-1.0f, 0.0f);
tglEnable(TGL_POLYGON_OFFSET_FILL);
tglColor4f(1.0f, 0.0f, 0.0f, 1.0f);
tglEnableClientState(TGL_VERTEX_ARRAY);
tglVertexPointer(2, TGL_FLOAT, 2 * sizeof(TGLfloat), &box2Vertices[0]);
tglDrawArrays(TGL_TRIANGLE_STRIP, 0, 4);
tglDisableClientState(TGL_VERTEX_ARRAY);
tglDisable(TGL_POLYGON_OFFSET_FILL);
tglMatrixMode(TGL_MODELVIEW);
tglPopMatrix();
tglPopMatrix();
tglMatrixMode(TGL_PROJECTION);
tglPopMatrix();
}
void TinyGLRenderer::drawRgbaTexture() {
tglMatrixMode(TGL_PROJECTION);
tglPushMatrix();
tglLoadIdentity();
tglMatrixMode(TGL_MODELVIEW);
tglPushMatrix();
tglLoadIdentity();
tglEnable(TGL_BLEND);
tglBlendFunc(TGL_ONE, TGL_ONE_MINUS_SRC_ALPHA);
tglDisable(TGL_DEPTH_TEST);
tglDepthMask(TGL_FALSE);
tglEnable(TGL_TEXTURE_2D);
tglColor4f(1.0f, 1.0f, 1.0f, 1.0f);
tglEnableClientState(TGL_VERTEX_ARRAY);
tglEnableClientState(TGL_TEXTURE_COORD_ARRAY);
tglTranslatef(-0.799f, 0.8f, 0);
//tglTranslatef(-0.8, 0.8, 0); // some gfx issue
tglVertexPointer(2, TGL_FLOAT, 2 * sizeof(TGLfloat), bitmapVertices);
tglTexCoordPointer(2, TGL_FLOAT, 2 * sizeof(TGLfloat), textCords);
tglBindTexture(TGL_TEXTURE_2D, _textureRgbaId[0]);
tglDrawArrays(TGL_TRIANGLE_STRIP, 0, 4);
tglTranslatef(0.5, 0, 0);
tglVertexPointer(2, TGL_FLOAT, 2 * sizeof(TGLfloat), bitmapVertices);
tglTexCoordPointer(2, TGL_FLOAT, 2 * sizeof(TGLfloat), textCords);
tglBindTexture(TGL_TEXTURE_2D, _textureRgbId[0]);
tglDrawArrays(TGL_TRIANGLE_STRIP, 0, 4);
tglTranslatef(0.501f, 0, 0);
//tglTranslatef(0.5, 0, 0); // some gfx issue
tglVertexPointer(2, TGL_FLOAT, 2 * sizeof(TGLfloat), bitmapVertices);
tglTexCoordPointer(2, TGL_FLOAT, 2 * sizeof(TGLfloat), textCords);
tglBindTexture(TGL_TEXTURE_2D, _textureRgb565Id[0]);
tglDrawArrays(TGL_TRIANGLE_STRIP, 0, 4);
tglTranslatef(0.5, 0, 0);
tglVertexPointer(2, TGL_FLOAT, 2 * sizeof(TGLfloat), bitmapVertices);
tglTexCoordPointer(2, TGL_FLOAT, 2 * sizeof(TGLfloat), textCords);
tglBindTexture(TGL_TEXTURE_2D, _textureRgba5551Id[0]);
tglDrawArrays(TGL_TRIANGLE_STRIP, 0, 4);
tglTranslatef(-1.5, -0.5, 0);
tglVertexPointer(2, TGL_FLOAT, 2 * sizeof(TGLfloat), bitmapVertices);
tglTexCoordPointer(2, TGL_FLOAT, 2 * sizeof(TGLfloat), textCords);
tglBindTexture(TGL_TEXTURE_2D, _textureRgba4444Id[0]);
tglDrawArrays(TGL_TRIANGLE_STRIP, 0, 4);
tglDisableClientState(TGL_VERTEX_ARRAY);
tglDisableClientState(TGL_TEXTURE_COORD_ARRAY);
int blitTextureWidth, blitTextureHeight;
tglGetBlitImageSize(_blitImageRgba, blitTextureWidth, blitTextureHeight);
TinyGL::BlitTransform transform(0, 250);
transform.sourceRectangle(0, 0, blitTextureWidth, blitTextureHeight);
tglBlit(_blitImageRgba, transform);
transform = TinyGL::BlitTransform(130, 250);
transform.sourceRectangle(0, 0, blitTextureWidth, blitTextureHeight);
tglBlit(_blitImageRgb, transform);
transform = TinyGL::BlitTransform(260, 250);
transform.sourceRectangle(0, 0, blitTextureWidth, blitTextureHeight);
tglBlit(_blitImageRgb565, transform);
transform = TinyGL::BlitTransform(390, 250);
transform.sourceRectangle(0, 0, blitTextureWidth, blitTextureHeight);
tglBlit(_blitImageRgba5551, transform);
transform = TinyGL::BlitTransform(520, 250);
transform.sourceRectangle(0, 0, blitTextureWidth, blitTextureHeight);
tglBlit(_blitImageRgba4444, transform);
tglMatrixMode(TGL_MODELVIEW);
tglPopMatrix();
tglMatrixMode(TGL_PROJECTION);
tglPopMatrix();
}
} // End of namespace Playground3d

View File

@@ -0,0 +1,84 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef PLAYGROUND3D_GFX_TINYGL_H
#define PLAYGROUND3D_GFX_TINYGL_H
#include "common/rect.h"
#include "common/system.h"
#include "math/vector3d.h"
#include "graphics/tinygl/tinygl.h"
#include "engines/playground3d/gfx.h"
namespace Playground3d {
class TinyGLRenderer : public Renderer {
public:
TinyGLRenderer(OSystem *_system);
void init() override;
void deinit() override;
void clear(const Math::Vector4d &clearColor) override;
void loadTextureRGB(Graphics::Surface *texture) override;
void loadTextureRGBA(Graphics::Surface *texture) override;
void loadTextureRGB565(Graphics::Surface *texture) override;
void loadTextureRGBA5551(Graphics::Surface *texture) override;
void loadTextureRGBA4444(Graphics::Surface *texture) override;
void setupViewport(int x, int y, int width, int height) override;
void drawCube(const Math::Vector3d &pos, const Math::Vector3d &roll) override;
void drawPolyOffsetTest(const Math::Vector3d &pos, const Math::Vector3d &roll) override;
void dimRegionInOut(float fade) override;
void drawInViewport() override;
void drawRgbaTexture() override;
void enableFog(const Math::Vector4d &fogColor) override;
void disableFog() override;
void enableScissor(int x, int y, int width, int height) override;
void disableScissor() override;
void flipBuffer() override;
private:
TinyGL::ContextHandle *_context;
Math::Vector3d _pos;
TGLuint _textureRgbaId[5];
TGLuint _textureRgbId[5];
TGLuint _textureRgb565Id[2];
TGLuint _textureRgba5551Id[2];
TGLuint _textureRgba4444Id[2];
TinyGL::BlitImage *_blitImageRgba;
TinyGL::BlitImage *_blitImageRgb;
TinyGL::BlitImage *_blitImageRgb565;
TinyGL::BlitImage *_blitImageRgba5551;
TinyGL::BlitImage *_blitImageRgba4444;
void drawFace(uint face);
};
} // End of namespace Playground3d
#endif // PLAYGROUND3D_GFX_TINYGL_H

View File

@@ -0,0 +1,82 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "base/plugins.h"
#include "common/system.h"
#include "common/translation.h"
#include "backends/keymapper/action.h"
#include "backends/keymapper/keymapper.h"
#include "backends/keymapper/standard-actions.h"
#include "engines/advancedDetector.h"
#include "playground3d/playground3d.h"
class Playground3dMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
public:
const char *getName() const override {
return "playground3d";
}
Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription * /* desc */) const override {
*engine = new Playground3d::Playground3dEngine(syst);
return Common::kNoError;
}
bool hasFeature(MetaEngineFeature f) const override {
return false;
}
Common::KeymapArray initKeymaps(const char *target) const override {
Common::Keymap *keymap = new Common::Keymap(Common::Keymap::kKeymapTypeGame, "playground3d", _("Default keymappings"));
Common::Action *act;
act = new Common::Action(Common::kStandardActionLeftClick, _("Switch test"));
act->setCustomEngineActionEvent(Playground3d::kActionSwitchTest);
act->addDefaultInputMapping("MOUSE_LEFT");
act->addDefaultInputMapping("JOY_A");
keymap->addAction(act);
act = new Common::Action("FOG", _("Enable/Disable fog"));
act->setCustomEngineActionEvent(Playground3d::kActionEnableFog);
act->addDefaultInputMapping("f");
act->addDefaultInputMapping("JOY_X");
keymap->addAction(act);
act = new Common::Action("SCISSOR", _("Enable/Disable scissor"));
act->setCustomEngineActionEvent(Playground3d::kActionEnableScissor);
act->addDefaultInputMapping("s");
act->addDefaultInputMapping("JOY_Y");
keymap->addAction(act);
Common::KeymapArray keymaps = { keymap };
return keymaps;
}
};
#if PLUGIN_ENABLED_DYNAMIC(PLAYGROUND3D)
REGISTER_PLUGIN_DYNAMIC(PLAYGROUND3D, PLUGIN_TYPE_ENGINE, Playground3dMetaEngine);
#else
REGISTER_PLUGIN_STATIC(PLAYGROUND3D, PLUGIN_TYPE_ENGINE, Playground3dMetaEngine);
#endif

View File

@@ -0,0 +1,27 @@
MODULE := engines/playground3d
MODULE_OBJS := \
metaengine.o \
gfx.o \
gfx_opengl.o \
gfx_opengl_shaders.o \
playground3d.o
ifdef USE_TINYGL
MODULE_OBJS += \
gfx_tinygl.o
endif
MODULE_DIRS += \
engines/playground3d
# This module can be built as a plugin
ifeq ($(ENABLE_PLAYGROUND3D), DYNAMIC_PLUGIN)
PLUGIN := 1
endif
# Include common rules
include $(srcdir)/rules.mk
# Detection objects
DETECT_OBJS += $(MODULE)/detection.o

View File

@@ -0,0 +1,331 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "common/scummsys.h"
#include "common/config-manager.h"
#include "common/error.h"
#include "common/events.h"
#include "graphics/cursorman.h"
#include "graphics/renderer.h"
#include "engines/util.h"
#include "playground3d/playground3d.h"
namespace Playground3d {
bool Playground3dEngine::hasFeature(EngineFeature f) const {
// The TinyGL renderer does not support arbitrary resolutions for now
Common::String rendererConfig = ConfMan.get("renderer");
Graphics::RendererType desiredRendererType = Graphics::Renderer::parseTypeCode(rendererConfig);
Graphics::RendererType matchingRendererType = Graphics::Renderer::getBestMatchingAvailableType(desiredRendererType,
#if defined(USE_OPENGL_GAME)
Graphics::kRendererTypeOpenGL |
#endif
#if defined(USE_OPENGL_SHADERS)
Graphics::kRendererTypeOpenGLShaders |
#endif
#if defined(USE_TINYGL)
Graphics::kRendererTypeTinyGL |
#endif
0);
bool softRenderer = matchingRendererType == Graphics::kRendererTypeTinyGL;
return
(f == kSupportsReturnToLauncher) ||
(f == kSupportsArbitraryResolutions && !softRenderer);
}
void Playground3dEngine::genTextures() {
Graphics::PixelFormat pixelFormatRGBA = Graphics::PixelFormat::createFormatRGBA32();
Graphics::PixelFormat pixelFormatRGB = Graphics::PixelFormat::createFormatRGB24();
Graphics::PixelFormat pixelFormatRGB565(2, 5, 6, 5, 0, 11, 5, 0, 0);
Graphics::PixelFormat pixelFormatRGB5551(2, 5, 5, 5, 1, 11, 6, 1, 0);
Graphics::PixelFormat pixelFormatRGB4444(2, 4, 4, 4, 4, 12, 8, 4, 0);
_rgbaTexture = generateRgbaTexture(120, 120, pixelFormatRGBA);
_rgbTexture = _rgbaTexture->convertTo(pixelFormatRGB);
_rgb565Texture = generateRgbaTexture(120, 120, pixelFormatRGB565);
_rgba5551Texture = generateRgbaTexture(120, 120, pixelFormatRGB5551);
_rgba4444Texture = generateRgbaTexture(120, 120, pixelFormatRGB4444);
}
Playground3dEngine::Playground3dEngine(OSystem *syst)
: Engine(syst), _system(syst), _gfx(nullptr), _frameLimiter(nullptr),
_rotateAngleX(0), _rotateAngleY(0), _rotateAngleZ(0), _fogEnable(false),
_clearColor(0.0f, 0.0f, 0.0f, 1.0f), _fogColor(0.0f, 0.0f, 0.0f, 1.0f),
_testId(0), _fade(1.0f), _fadeIn(false), _scissorEnable(false),
_rgbaTexture(nullptr), _rgbTexture(nullptr), _rgb565Texture(nullptr),
_rgba5551Texture(nullptr), _rgba4444Texture(nullptr) {
}
Playground3dEngine::~Playground3dEngine() {
delete _frameLimiter;
delete _gfx;
if (_rgbaTexture) {
_rgbaTexture->free();
delete _rgbaTexture;
_rgbTexture->free();
delete _rgbTexture;
_rgb565Texture->free();
delete _rgb565Texture;
_rgba5551Texture->free();
delete _rgba5551Texture;
_rgba4444Texture->free();
delete _rgba4444Texture;
}
}
Common::Error Playground3dEngine::run() {
_gfx = createRenderer(_system);
_gfx->init();
_frameLimiter = new Graphics::FrameLimiter(_system, ConfMan.getInt("engine_speed"));
CursorMan.setDefaultArrowCursor();
CursorMan.showMouse(true);
// 1 - rotated colorfull cube
// 2 - rotated two triangles with depth offset
// 3 - fade in/out
// 4 - moving filled rectangle in viewport
// 5 - drawing RGBA pattern texture to check endian correctness
_testId = 1;
_fogEnable = false;
_scissorEnable = false;
if (_fogEnable) {
_fogColor = Math::Vector4d(1.0f, 1.0f, 1.0f, 1.0f);
}
switch (_testId) {
case 1:
_clearColor = Math::Vector4d(0.5f, 0.5f, 0.5f, 1.0f);
_rotateAngleX = 45, _rotateAngleY = 45, _rotateAngleZ = 10;
break;
case 2:
_clearColor = Math::Vector4d(0.5f, 0.5f, 0.5f, 1.0f);
break;
case 3:
_clearColor = Math::Vector4d(1.0f, 0.0f, 0.0f, 1.0f);
break;
case 4:
_clearColor = Math::Vector4d(0.5f, 0.5f, 0.5f, 1.0f);
break;
case 5: {
_clearColor = Math::Vector4d(0.5f, 0.5f, 0.5f, 1.0f);
if (!_rgbaTexture) {
genTextures();
}
break;
}
default:
assert(false);
}
while (!shouldQuit()) {
processInput();
drawFrame();
}
_gfx->deinit();
CursorMan.showMouse(false);
return Common::kNoError;
}
void Playground3dEngine::processInput() {
Common::Event event;
while (getEventManager()->pollEvent(event)) {
if (event.type == Common::EVENT_SCREEN_CHANGED) {
_gfx->computeScreenViewport();
}
if (event.type != Common::EVENT_CUSTOM_ENGINE_ACTION_START) {
continue;
}
switch (event.customType) {
case kActionSwitchTest:
_testId++;
if (_testId > 5)
_testId = 1;
switch (_testId) {
case 1:
_clearColor = Math::Vector4d(0.5f, 0.5f, 0.5f, 1.0f);
_rotateAngleX = 45, _rotateAngleY = 45, _rotateAngleZ = 10;
break;
case 2:
_clearColor = Math::Vector4d(0.5f, 0.5f, 0.5f, 1.0f);
break;
case 3:
_clearColor = Math::Vector4d(1.0f, 0.0f, 0.0f, 1.0f);
break;
case 4:
_clearColor = Math::Vector4d(0.5f, 0.5f, 0.5f, 1.0f);
break;
case 5: {
_clearColor = Math::Vector4d(0.5f, 0.5f, 0.5f, 1.0f);
if (!_rgbaTexture) {
genTextures();
}
break;
}
default:
assert(false);
}
break;
case kActionEnableFog:
_fogEnable = !_fogEnable;
break;
case kActionEnableScissor:
_scissorEnable = !_scissorEnable;
break;
}
}
}
Graphics::Surface *Playground3dEngine::generateRgbaTexture(int width, int height, Graphics::PixelFormat format) {
Graphics::Surface *surface = new Graphics::Surface;
surface->create(width, height, format);
const int barW = width / 4;
Common::Rect r(0, 0, barW, height);
uint32 pixel = format.ARGBToColor(255, 255, 0, 0);
surface->fillRect(r, pixel);
r.left += barW;
r.right += barW;
pixel = format.ARGBToColor(255, 0, 255, 0);
surface->fillRect(r, pixel);
r.left += barW;
r.right += barW;
pixel = format.ARGBToColor(255, 0, 0, 255);
surface->fillRect(r, pixel);
r.left += barW;
r.right += barW;
pixel = format.ARGBToColor(128, 0, 0, 0);
surface->fillRect(r, pixel);
return surface;
}
void Playground3dEngine::drawAndRotateCube() {
Math::Vector3d pos = Math::Vector3d(0.0f, 0.0f, 6.0f);
_gfx->drawCube(pos, Math::Vector3d(_rotateAngleX, _rotateAngleY, _rotateAngleZ));
_rotateAngleX += 0.25f;
_rotateAngleY += 0.50f;
_rotateAngleZ += 0.10f;
if (_rotateAngleX >= 360)
_rotateAngleX = 0;
if (_rotateAngleY >= 360)
_rotateAngleY = 0;
if (_rotateAngleZ >= 360)
_rotateAngleZ = 0;
}
void Playground3dEngine::drawPolyOffsetTest() {
Math::Vector3d pos = Math::Vector3d(0.0f, 0.0f, 6.0f);
_gfx->drawPolyOffsetTest(pos, Math::Vector3d(0, _rotateAngleY, 0));
_rotateAngleY += 0.10f;
if (_rotateAngleY >= 360)
_rotateAngleY = 0;
}
void Playground3dEngine::dimRegionInOut() {
_gfx->dimRegionInOut(_fade);
if (_fadeIn)
_fade += 0.01f;
else
_fade -= 0.01f;
if (_fade > 1.0f) {
_fade = 1;
_fadeIn = false;
} else if (_fade < 0.0f) {
_fade = 0;
_fadeIn = true;
}
}
void Playground3dEngine::drawInViewport() {
_gfx->drawInViewport();
}
void Playground3dEngine::drawRgbaTexture() {
_gfx->drawRgbaTexture();
}
void Playground3dEngine::drawFrame() {
_gfx->clear(_clearColor);
float pitch = 0.0f;
float heading = 0.0f;
float fov = 45.0f;
_gfx->setupCameraPerspective(pitch, heading, fov);
Common::Rect vp = _gfx->viewport();
_gfx->setupViewport(vp.left, _system->getHeight() - vp.top - vp.height(), vp.width(), vp.height());
if (_scissorEnable) {
_gfx->enableScissor(vp.left + vp.width() / 4, _system->getHeight() - vp.top - (vp.height() * 3) / 4, vp.width() / 2, vp.height() / 2);
}
_gfx->disableFog();
switch (_testId) {
case 1:
if (_fogEnable) {
_gfx->enableFog(_fogColor);
}
drawAndRotateCube();
break;
case 2:
drawPolyOffsetTest();
break;
case 3:
dimRegionInOut();
break;
case 4:
_gfx->setupViewport(vp.left + 40, _system->getHeight() - vp.top - vp.height() + 40, vp.width() - 80, vp.height() - 80);
drawInViewport();
break;
case 5:
_gfx->loadTextureRGBA(_rgbaTexture);
_gfx->loadTextureRGB(_rgbTexture);
_gfx->loadTextureRGB565(_rgb565Texture);
_gfx->loadTextureRGBA5551(_rgba5551Texture);
_gfx->loadTextureRGBA4444(_rgba4444Texture);
drawRgbaTexture();
break;
default:
assert(false);
}
if (_scissorEnable) {
_gfx->disableScissor();
}
_gfx->flipBuffer();
_frameLimiter->delayBeforeSwap();
_system->updateScreen();
_frameLimiter->startFrame();
}
} // End of namespace Playground3d

View File

@@ -0,0 +1,85 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef PLAYGROUND3D_H
#define PLAYGROUND3D_H
#include "common/array.h"
#include "graphics/framelimiter.h"
#include "engines/engine.h"
#include "engines/playground3d/gfx.h"
namespace Playground3d {
enum Actions {
kActionSwitchTest,
kActionEnableFog,
kActionEnableScissor
};
class Playground3dEngine : public Engine {
public:
Playground3dEngine(OSystem *syst);
~Playground3dEngine() override;
Common::Error run() override;
bool hasFeature(EngineFeature f) const override;
void genTextures();
void processInput();
void drawFrame();
private:
OSystem *_system;
Renderer *_gfx;
Graphics::FrameLimiter *_frameLimiter;
Math::Vector4d _clearColor;
Math::Vector4d _fogColor;
int _testId;
float _fade;
bool _fadeIn;
bool _fogEnable;
bool _scissorEnable;
Graphics::Surface *_rgbaTexture;
Graphics::Surface *_rgbTexture;
Graphics::Surface *_rgb565Texture;
Graphics::Surface *_rgba5551Texture;
Graphics::Surface *_rgba4444Texture;
float _rotateAngleX, _rotateAngleY, _rotateAngleZ;
Graphics::Surface *generateRgbaTexture(int width, int height, Graphics::PixelFormat format);
void drawAndRotateCube();
void drawPolyOffsetTest();
void dimRegionInOut();
void drawInViewport();
void drawRgbaTexture();
};
} // End of namespace Playground3d
#endif // PLAYGROUND3D_H

View File

@@ -0,0 +1,9 @@
in vec2 Texcoord;
OUTPUT
uniform sampler2D tex;
void main() {
outColor = texture(tex, Texcoord);
}

View File

@@ -0,0 +1,11 @@
in vec2 position;
in vec2 texcoord;
out vec2 Texcoord;
uniform vec2 offsetXY;
void main() {
Texcoord = texcoord;
gl_Position = vec4(position + offsetXY, 0.0, 1.0);
}

View File

@@ -0,0 +1,14 @@
in vec2 Texcoord;
in vec3 Color;
OUTPUT
uniform UBOOL textured;
uniform sampler2D tex;
void main() {
outColor = vec4(Color, 1.0);
if (UBOOL_TEST(textured)) {
outColor *= texture(tex, Texcoord);
}
}

View File

@@ -0,0 +1,27 @@
in vec3 position;
in vec3 color;
in vec3 normal;
in vec2 texcoord;
uniform mat4 mvpMatrix;
uniform mat4 projMatrix;
uniform mat4 modelMatrix;
uniform mat4 rotateMatrix;
uniform UBOOL textured;
uniform vec3 modelPos;
out vec2 Texcoord;
out vec3 Color;
void main() {
Texcoord = texcoord;
vec4 pos = rotateMatrix * vec4(position, 1.0);
gl_Position = mvpMatrix * (pos + vec4(modelPos, 1.0));
if (UBOOL_TEST(textured)) {
Color = vec3(1.0);
} else {
Color = color;
}
}

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

@@ -0,0 +1,8 @@
OUTPUT
uniform vec3 triColor;
void main() {
outColor = vec4(triColor, 1.0);
}

View File

@@ -0,0 +1,12 @@
in vec2 position;
uniform mat4 mvpMatrix;
uniform mat4 projMatrix;
uniform mat4 modelMatrix;
uniform mat4 rotateMatrix;
uniform vec3 modelPos;
void main() {
vec4 pos = rotateMatrix * vec4(position, 0.0, 1.0);
gl_Position = mvpMatrix * (pos + vec4(modelPos, 1.0));
}

View File

@@ -0,0 +1,8 @@
OUTPUT
uniform vec3 color;
void main() {
outColor = vec4(color, 1.0);
}

View File

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