2012-01-06 23:29:45 +01:00
|
|
|
/* ResidualVM - A 3D game interpreter
|
2009-05-05 11:34:43 +00:00
|
|
|
*
|
2012-01-06 23:29:45 +01:00
|
|
|
* ResidualVM is the legal property of its developers, whose names
|
2011-04-16 14:12:44 +02:00
|
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
2009-05-05 11:34:43 +00:00
|
|
|
* file distributed with this source distribution.
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
* This library 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
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2010-01-24 08:23:20 +00:00
|
|
|
#if defined(WIN32) && !defined(__SYMBIAN32__)
|
|
|
|
#include <windows.h>
|
|
|
|
// winnt.h defines ARRAYSIZE, but we want our own one...
|
|
|
|
#undef ARRAYSIZE
|
|
|
|
#endif
|
|
|
|
|
2009-05-05 11:34:43 +00:00
|
|
|
#include "common/endian.h"
|
2009-05-07 19:06:31 +00:00
|
|
|
#include "common/system.h"
|
2009-05-05 11:34:43 +00:00
|
|
|
|
2011-10-01 22:40:31 +02:00
|
|
|
#include "graphics/surface.h"
|
2012-01-16 17:12:14 +01:00
|
|
|
#include "graphics/pixelbuffer.h"
|
2011-10-01 22:40:31 +02:00
|
|
|
|
2009-05-24 19:13:58 +00:00
|
|
|
#include "engines/grim/actor.h"
|
|
|
|
#include "engines/grim/colormap.h"
|
|
|
|
#include "engines/grim/font.h"
|
|
|
|
#include "engines/grim/material.h"
|
|
|
|
#include "engines/grim/gfx_opengl.h"
|
2009-06-26 16:13:11 +00:00
|
|
|
#include "engines/grim/grim.h"
|
2011-05-13 17:55:14 -07:00
|
|
|
#include "engines/grim/bitmap.h"
|
|
|
|
#include "engines/grim/primitives.h"
|
2011-07-23 12:14:33 +02:00
|
|
|
#include "engines/grim/model.h"
|
2011-09-19 16:53:08 +02:00
|
|
|
#include "engines/grim/set.h"
|
2012-01-29 16:14:36 +01:00
|
|
|
#include "engines/grim/emi/modelemi.h"
|
2009-05-05 11:34:43 +00:00
|
|
|
|
2011-05-20 03:12:48 +08:00
|
|
|
#ifdef USE_OPENGL
|
|
|
|
|
2011-05-21 18:08:12 +02:00
|
|
|
#if defined (SDL_BACKEND) && defined(GL_ARB_fragment_program)
|
2011-05-19 20:19:28 +08:00
|
|
|
|
2011-05-20 03:12:48 +08:00
|
|
|
// We need SDL.h for SDL_GL_GetProcAddress.
|
|
|
|
#include "backends/platform/sdl/sdl-sys.h"
|
|
|
|
|
2011-05-19 20:19:28 +08:00
|
|
|
// Extension functions needed for fragment programs.
|
|
|
|
PFNGLGENPROGRAMSARBPROC glGenProgramsARB;
|
|
|
|
PFNGLBINDPROGRAMARBPROC glBindProgramARB;
|
|
|
|
PFNGLPROGRAMSTRINGARBPROC glProgramStringARB;
|
|
|
|
PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB;
|
2012-03-07 16:12:14 +01:00
|
|
|
PFNGLPROGRAMLOCALPARAMETER4FARBPROC glProgramLocalParameter4fARB;
|
2011-05-19 20:19:28 +08:00
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2009-05-25 06:49:57 +00:00
|
|
|
namespace Grim {
|
|
|
|
|
2011-05-21 18:18:27 +02:00
|
|
|
GfxBase *CreateGfxOpenGL() {
|
|
|
|
return new GfxOpenGL();
|
|
|
|
}
|
|
|
|
|
2011-05-19 20:19:28 +08:00
|
|
|
// Simple ARB fragment program that writes the value from a texture to the Z-buffer.
|
|
|
|
static char fragSrc[] =
|
|
|
|
"!!ARBfp1.0\n\
|
2011-11-01 05:18:31 +08:00
|
|
|
TEMP d;\n\
|
|
|
|
TEX d, fragment.texcoord[0], texture[0], 2D;\n\
|
|
|
|
MOV result.depth, d.r;\n\
|
2011-05-19 20:19:28 +08:00
|
|
|
END\n";
|
|
|
|
|
2012-03-07 16:12:14 +01:00
|
|
|
static char dimFragSrc[] =
|
|
|
|
"!!ARBfp1.0\n\
|
|
|
|
PARAM level = program.local[0];\n\
|
|
|
|
TEMP color;\n\
|
|
|
|
TEMP d;\n\
|
|
|
|
TEX d, fragment.texcoord[0], texture[0], 2D;\n\
|
|
|
|
TEMP sum;\n\
|
|
|
|
MOV sum, d.r;\n\
|
|
|
|
ADD sum, sum, d.g;\n\
|
|
|
|
ADD sum, sum, d.b;\n\
|
|
|
|
MUL sum, sum, 0.33;\n\
|
|
|
|
MUL sum, sum, level.x;\n\
|
|
|
|
MOV result.color.r, sum;\n\
|
|
|
|
MOV result.color.g, sum;\n\
|
|
|
|
MOV result.color.b, sum;\n\
|
|
|
|
END\n";
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
GfxOpenGL::GfxOpenGL() {
|
2011-05-21 18:18:27 +02:00
|
|
|
g_driver = this;
|
2009-05-05 11:34:43 +00:00
|
|
|
_storedDisplay = NULL;
|
2009-05-17 09:29:36 +00:00
|
|
|
_emergFont = 0;
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
GfxOpenGL::~GfxOpenGL() {
|
2009-05-05 11:34:43 +00:00
|
|
|
delete[] _storedDisplay;
|
2012-01-27 17:44:33 +01:00
|
|
|
|
2009-05-05 11:34:43 +00:00
|
|
|
if (_emergFont && glIsList(_emergFont))
|
|
|
|
glDeleteLists(_emergFont, 128);
|
2011-05-19 20:19:28 +08:00
|
|
|
|
|
|
|
#ifdef GL_ARB_fragment_program
|
|
|
|
if (_useDepthShader)
|
|
|
|
glDeleteProgramsARB(1, &_fragmentProgram);
|
2012-03-07 16:12:14 +01:00
|
|
|
|
|
|
|
if (_useDimShader)
|
|
|
|
glDeleteProgramsARB(1, &_dimFragProgram);
|
2011-05-19 20:19:28 +08:00
|
|
|
#endif
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
|
|
|
|
2009-05-31 08:55:57 +00:00
|
|
|
byte *GfxOpenGL::setupScreen(int screenW, int screenH, bool fullscreen) {
|
2012-01-24 18:20:33 +01:00
|
|
|
_pixelFormat = g_system->setupScreen(screenW, screenH, fullscreen, true).getFormat();
|
2009-05-05 11:34:43 +00:00
|
|
|
|
|
|
|
_screenWidth = screenW;
|
|
|
|
_screenHeight = screenH;
|
2012-01-25 23:02:24 +01:00
|
|
|
_scaleW = _screenWidth / (float)_gameWidth;
|
|
|
|
_scaleH = _screenHeight / (float)_gameHeight;
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
_isFullscreen = g_system->getFeatureState(OSystem::kFeatureFullscreenMode);
|
2011-05-19 20:19:28 +08:00
|
|
|
_useDepthShader = false;
|
2012-03-07 16:12:14 +01:00
|
|
|
_useDimShader = false;
|
2009-05-05 11:34:43 +00:00
|
|
|
|
2011-06-02 12:16:04 +02:00
|
|
|
g_system->showMouse(!fullscreen);
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
char GLDriver[1024];
|
2012-01-06 11:37:57 +01:00
|
|
|
sprintf(GLDriver, "ResidualVM: %s/%s", glGetString(GL_VENDOR), glGetString(GL_RENDERER));
|
2009-05-07 19:06:31 +00:00
|
|
|
g_system->setWindowCaption(GLDriver);
|
2009-05-05 11:34:43 +00:00
|
|
|
|
|
|
|
// Load emergency built-in font
|
|
|
|
loadEmergFont();
|
|
|
|
|
2012-01-16 17:12:14 +01:00
|
|
|
_screenSize = _screenWidth * _screenHeight * 4;
|
|
|
|
_storedDisplay = new byte[_screenSize];
|
|
|
|
memset(_storedDisplay, 0, _screenSize);
|
2009-05-05 11:34:43 +00:00
|
|
|
_smushNumTex = 0;
|
|
|
|
|
|
|
|
_currentShadowArray = NULL;
|
|
|
|
|
2011-05-20 00:12:43 +02:00
|
|
|
GLfloat ambientSource[] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
2009-05-05 11:34:43 +00:00
|
|
|
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientSource);
|
|
|
|
|
|
|
|
glPolygonOffset(-6.0, -6.0);
|
2009-05-07 19:06:31 +00:00
|
|
|
|
2011-05-19 20:19:28 +08:00
|
|
|
initExtensions();
|
2012-02-24 17:41:52 +01:00
|
|
|
glGetIntegerv(GL_MAX_LIGHTS, &_maxLights);
|
2011-05-19 20:19:28 +08:00
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
return NULL;
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
|
|
|
|
2011-05-19 20:19:28 +08:00
|
|
|
void GfxOpenGL::initExtensions()
|
|
|
|
{
|
2011-05-20 02:33:52 +08:00
|
|
|
#if defined (SDL_BACKEND) && defined(GL_ARB_fragment_program)
|
2011-05-20 01:20:47 +08:00
|
|
|
union {
|
|
|
|
void* obj_ptr;
|
|
|
|
void (APIENTRY *func_ptr)();
|
|
|
|
} u;
|
2011-05-20 03:12:48 +08:00
|
|
|
// We're casting from an object pointer to a function pointer, the
|
|
|
|
// sizes need to be the same for this to work.
|
|
|
|
assert(sizeof(u.obj_ptr) == sizeof(u.func_ptr));
|
2011-05-20 01:20:47 +08:00
|
|
|
u.obj_ptr = SDL_GL_GetProcAddress("glGenProgramsARB");
|
|
|
|
glGenProgramsARB = (PFNGLGENPROGRAMSARBPROC)u.func_ptr;
|
|
|
|
u.obj_ptr = SDL_GL_GetProcAddress("glBindProgramARB");
|
|
|
|
glBindProgramARB = (PFNGLBINDPROGRAMARBPROC)u.func_ptr;
|
|
|
|
u.obj_ptr = SDL_GL_GetProcAddress("glProgramStringARB");
|
|
|
|
glProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC)u.func_ptr;
|
|
|
|
u.obj_ptr = SDL_GL_GetProcAddress("glDeleteProgramsARB");
|
|
|
|
glDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC)u.func_ptr;
|
2012-03-07 16:12:14 +01:00
|
|
|
u.obj_ptr = SDL_GL_GetProcAddress("glProgramLocalParameter4fARB");
|
|
|
|
glProgramLocalParameter4fARB = (PFNGLPROGRAMLOCALPARAMETER4FARBPROC)u.func_ptr;
|
2011-05-19 20:19:28 +08:00
|
|
|
|
|
|
|
const char* extensions = (const char*)glGetString(GL_EXTENSIONS);
|
|
|
|
if (strstr(extensions, "ARB_fragment_program")) {
|
|
|
|
_useDepthShader = true;
|
2012-03-07 16:12:14 +01:00
|
|
|
_useDimShader = true;
|
2011-05-19 20:19:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (_useDepthShader) {
|
|
|
|
glGenProgramsARB(1, &_fragmentProgram);
|
|
|
|
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, _fragmentProgram);
|
|
|
|
|
|
|
|
GLint errorPos;
|
|
|
|
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(fragSrc), fragSrc);
|
|
|
|
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
|
|
|
|
if (errorPos != -1) {
|
2012-03-07 16:12:14 +01:00
|
|
|
warning("Error compiling depth fragment program:\n%s", glGetString(GL_PROGRAM_ERROR_STRING_ARB));
|
2011-11-01 03:55:08 +08:00
|
|
|
_useDepthShader = false;
|
2011-05-19 20:19:28 +08:00
|
|
|
}
|
2012-03-07 16:12:14 +01:00
|
|
|
|
|
|
|
|
|
|
|
glGenProgramsARB(1, &_dimFragProgram);
|
|
|
|
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, _dimFragProgram);
|
|
|
|
|
|
|
|
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(dimFragSrc), dimFragSrc);
|
|
|
|
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
|
|
|
|
if (errorPos != -1) {
|
|
|
|
warning("Error compiling dim fragment program:\n%s", glGetString(GL_PROGRAM_ERROR_STRING_ARB));
|
|
|
|
_useDimShader = false;
|
|
|
|
}
|
2011-05-19 20:19:28 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
const char *GfxOpenGL::getVideoDeviceName() {
|
|
|
|
return "OpenGL Renderer";
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
void GfxOpenGL::setupCamera(float fov, float nclip, float fclip, float roll) {
|
2009-05-05 11:34:43 +00:00
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
|
|
|
|
2009-05-10 14:15:07 +00:00
|
|
|
float right = nclip * tan(fov / 2 * (LOCAL_PI / 180));
|
2009-05-05 11:34:43 +00:00
|
|
|
glFrustum(-right, right, -right * 0.75, right * 0.75, nclip, fclip);
|
|
|
|
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
|
|
|
|
glRotatef(roll, 0, 0, -1);
|
|
|
|
}
|
|
|
|
|
2012-02-04 18:07:24 -08:00
|
|
|
void GfxOpenGL::positionCamera(const Math::Vector3d &pos, const Math::Vector3d &interest) {
|
2011-09-10 17:46:07 +02:00
|
|
|
Math::Vector3d up_vec(0, 0, 1);
|
2009-05-05 11:34:43 +00:00
|
|
|
|
2012-01-29 22:04:45 +01:00
|
|
|
// EMI only: transform XYZ to YXZ
|
|
|
|
if (g_grim->getGameType() == GType_MONKEY4) {
|
|
|
|
static const float EMI_MATRIX[] = {
|
|
|
|
0,1,0,0,
|
|
|
|
1,0,0,0,
|
|
|
|
0,0,1,0,
|
|
|
|
0,0,0,1
|
|
|
|
};
|
|
|
|
|
|
|
|
glMultMatrixf(EMI_MATRIX);
|
|
|
|
}
|
|
|
|
|
2009-05-05 11:34:43 +00:00
|
|
|
if (pos.x() == interest.x() && pos.y() == interest.y())
|
2011-09-10 17:46:07 +02:00
|
|
|
up_vec = Math::Vector3d(0, 1, 0);
|
2009-05-05 11:34:43 +00:00
|
|
|
|
|
|
|
gluLookAt(pos.x(), pos.y(), pos.z(), interest.x(), interest.y(), interest.z(), up_vec.x(), up_vec.y(), up_vec.z());
|
|
|
|
}
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
void GfxOpenGL::clearScreen() {
|
2009-05-05 11:34:43 +00:00
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
}
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
void GfxOpenGL::flipBuffer() {
|
|
|
|
g_system->updateScreen();
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
bool GfxOpenGL::isHardwareAccelerated() {
|
2009-05-05 11:34:43 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-02-04 18:07:24 -08:00
|
|
|
static void glShadowProjection(const Math::Vector3d &light, const Math::Vector3d &plane, const Math::Vector3d &normal, bool dontNegate) {
|
2009-05-05 11:34:43 +00:00
|
|
|
// Based on GPL shadow projection example by
|
|
|
|
// (c) 2002-2003 Phaetos <phaetos@gaffga.de>
|
|
|
|
float d, c;
|
|
|
|
float mat[16];
|
|
|
|
float nx, ny, nz, lx, ly, lz, px, py, pz;
|
|
|
|
|
2011-05-01 06:15:37 +08:00
|
|
|
nx = normal.x();
|
|
|
|
ny = normal.y();
|
|
|
|
nz = normal.z();
|
2009-05-05 11:34:43 +00:00
|
|
|
// for some unknown for me reason normal need negation
|
2011-05-01 06:15:37 +08:00
|
|
|
if (!dontNegate) {
|
2009-05-05 11:34:43 +00:00
|
|
|
nx = -nx;
|
|
|
|
ny = -ny;
|
|
|
|
nz = -nz;
|
|
|
|
}
|
|
|
|
lx = light.x();
|
|
|
|
ly = light.y();
|
|
|
|
lz = light.z();
|
|
|
|
px = plane.x();
|
|
|
|
py = plane.y();
|
|
|
|
pz = plane.z();
|
|
|
|
|
|
|
|
d = nx * lx + ny * ly + nz * lz;
|
|
|
|
c = px * nx + py * ny + pz * nz - d;
|
|
|
|
|
|
|
|
mat[0] = lx * nx + c;
|
|
|
|
mat[4] = ny * lx;
|
|
|
|
mat[8] = nz * lx;
|
|
|
|
mat[12] = -lx * c - lx * d;
|
|
|
|
|
|
|
|
mat[1] = nx * ly;
|
|
|
|
mat[5] = ly * ny + c;
|
|
|
|
mat[9] = nz * ly;
|
|
|
|
mat[13] = -ly * c - ly * d;
|
|
|
|
|
|
|
|
mat[2] = nx * lz;
|
|
|
|
mat[6] = ny * lz;
|
|
|
|
mat[10] = lz * nz + c;
|
|
|
|
mat[14] = -lz * c - lz * d;
|
|
|
|
|
|
|
|
mat[3] = nx;
|
|
|
|
mat[7] = ny;
|
|
|
|
mat[11] = nz;
|
|
|
|
mat[15] = -d;
|
|
|
|
|
|
|
|
glMultMatrixf((GLfloat *)mat);
|
|
|
|
}
|
|
|
|
|
2011-07-22 22:09:49 +02:00
|
|
|
void GfxOpenGL::getBoundingBoxPos(const Mesh *model, int *x1, int *y1, int *x2, int *y2) {
|
2009-05-05 11:34:43 +00:00
|
|
|
if (_currentShadowArray) {
|
|
|
|
*x1 = -1;
|
|
|
|
*y1 = -1;
|
|
|
|
*x2 = -1;
|
|
|
|
*y2 = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-04-06 05:55:07 +08:00
|
|
|
GLdouble top = 1000;
|
|
|
|
GLdouble right = -1000;
|
|
|
|
GLdouble left = 1000;
|
|
|
|
GLdouble bottom = -1000;
|
2009-05-05 11:34:43 +00:00
|
|
|
GLdouble winX, winY, winZ;
|
|
|
|
|
|
|
|
for (int i = 0; i < model->_numFaces; i++) {
|
2011-09-10 17:46:07 +02:00
|
|
|
Math::Vector3d v;
|
2009-05-05 11:34:43 +00:00
|
|
|
float* pVertices;
|
|
|
|
|
|
|
|
for (int j = 0; j < model->_faces[i]._numVertices; j++) {
|
|
|
|
GLdouble modelView[16], projection[16];
|
|
|
|
GLint viewPort[4];
|
|
|
|
|
|
|
|
glGetDoublev(GL_MODELVIEW_MATRIX, modelView);
|
|
|
|
glGetDoublev(GL_PROJECTION_MATRIX, projection);
|
|
|
|
glGetIntegerv(GL_VIEWPORT, viewPort);
|
|
|
|
|
|
|
|
pVertices = model->_vertices + 3 * model->_faces[i]._vertices[j];
|
|
|
|
|
|
|
|
v.set(*(pVertices), *(pVertices + 1), *(pVertices + 2));
|
|
|
|
|
|
|
|
gluProject(v.x(), v.y(), v.z(), modelView, projection, viewPort, &winX, &winY, &winZ);
|
|
|
|
|
|
|
|
if (winX > right)
|
|
|
|
right = winX;
|
|
|
|
if (winX < left)
|
|
|
|
left = winX;
|
|
|
|
if (winY < top)
|
|
|
|
top = winY;
|
|
|
|
if (winY > bottom)
|
|
|
|
bottom = winY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-06 05:55:07 +08:00
|
|
|
double t = bottom;
|
2012-01-27 19:59:34 +01:00
|
|
|
bottom = _gameHeight - top;
|
|
|
|
top = _gameHeight - t;
|
2009-05-05 11:34:43 +00:00
|
|
|
|
|
|
|
if (left < 0)
|
|
|
|
left = 0;
|
2012-01-27 19:59:34 +01:00
|
|
|
if (right >= _gameWidth)
|
|
|
|
right = _gameWidth - 1;
|
2009-05-05 11:34:43 +00:00
|
|
|
if (top < 0)
|
|
|
|
top = 0;
|
2012-01-27 19:59:34 +01:00
|
|
|
if (bottom >= _gameHeight)
|
|
|
|
bottom = _gameHeight - 1;
|
2009-05-05 11:34:43 +00:00
|
|
|
|
2012-01-27 19:59:34 +01:00
|
|
|
if (top >= _gameHeight || left >= _gameWidth || bottom < 0 || right < 0) {
|
2009-05-05 11:34:43 +00:00
|
|
|
*x1 = -1;
|
|
|
|
*y1 = -1;
|
|
|
|
*x2 = -1;
|
|
|
|
*y2 = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
*x1 = (int)left;
|
|
|
|
*y1 = (int)top;
|
|
|
|
*x2 = (int)right;
|
|
|
|
*y2 = (int)bottom;
|
|
|
|
}
|
|
|
|
|
2012-02-04 18:07:24 -08:00
|
|
|
void GfxOpenGL::startActorDraw(const Math::Vector3d &pos, float scale, const Math::Angle &yaw,
|
2012-01-27 19:58:17 +01:00
|
|
|
const Math::Angle &pitch, const Math::Angle &roll) {
|
2009-05-05 11:34:43 +00:00
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glPushMatrix();
|
2009-06-18 21:07:51 +00:00
|
|
|
if (_currentShadowArray) {
|
2009-06-18 20:23:46 +00:00
|
|
|
// TODO find out why shadowMask at device in woods is null
|
2009-06-18 21:35:29 +00:00
|
|
|
if (!_currentShadowArray->shadowMask) {
|
|
|
|
_currentShadowArray->shadowMask = new byte[_screenWidth * _screenHeight];
|
2011-03-21 05:16:27 +08:00
|
|
|
_currentShadowArray->shadowMaskSize = _screenWidth * _screenHeight;
|
2009-06-18 21:07:51 +00:00
|
|
|
}
|
2011-06-07 22:58:42 +02:00
|
|
|
Sector *shadowSector = _currentShadowArray->planeList.front().sector;
|
2009-06-18 21:35:29 +00:00
|
|
|
glEnable(GL_POLYGON_OFFSET_FILL);
|
|
|
|
glDisable(GL_LIGHTING);
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
2011-12-12 12:26:49 +01:00
|
|
|
// glColor3f(0.0f, 1.0f, 0.0f);
|
2011-04-06 05:55:07 +08:00
|
|
|
glColor3f(_shadowColorR / 255.0f, _shadowColorG / 255.0f, _shadowColorB / 255.0f);
|
2009-06-18 21:35:29 +00:00
|
|
|
glShadowProjection(_currentShadowArray->pos, shadowSector->getVertices()[0], shadowSector->getNormal(), _currentShadowArray->dontNegate);
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
|
|
|
glTranslatef(pos.x(), pos.y(), pos.z());
|
2011-04-28 22:07:36 +02:00
|
|
|
glScalef(scale, scale, scale);
|
2012-01-29 22:04:45 +01:00
|
|
|
// EMI uses Y axis as down-up, so we need to rotate differently.
|
|
|
|
if (g_grim->getGameType() == GType_MONKEY4) {
|
|
|
|
glRotatef(yaw.getDegrees(), 0, -1, 0);
|
|
|
|
glRotatef(pitch.getDegrees(), 1, 0, 0);
|
|
|
|
glRotatef(roll.getDegrees(), 0, 0, 1);
|
|
|
|
} else {
|
|
|
|
glRotatef(yaw.getDegrees(), 0, 0, 1);
|
|
|
|
glRotatef(pitch.getDegrees(), 1, 0, 0);
|
|
|
|
glRotatef(roll.getDegrees(), 0, 1, 0);
|
|
|
|
}
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
void GfxOpenGL::finishActorDraw() {
|
2009-05-05 11:34:43 +00:00
|
|
|
glPopMatrix();
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
if (_currentShadowArray) {
|
|
|
|
glEnable(GL_LIGHTING);
|
2011-04-06 05:55:07 +08:00
|
|
|
glColor3f(1.0f, 1.0f, 1.0f);
|
2009-05-05 11:34:43 +00:00
|
|
|
glDisable(GL_POLYGON_OFFSET_FILL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
void GfxOpenGL::setShadow(Shadow *shadow) {
|
2009-05-05 11:34:43 +00:00
|
|
|
_currentShadowArray = shadow;
|
|
|
|
}
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
void GfxOpenGL::drawShadowPlanes() {
|
2009-05-05 11:34:43 +00:00
|
|
|
/* glColor3f(1.0f, 1.0f, 1.0f);
|
|
|
|
_currentShadowArray->planeList.begin();
|
|
|
|
for (SectorListType::iterator i = _currentShadowArray->planeList.begin(); i != _currentShadowArray->planeList.end(); i++) {
|
2011-12-12 12:26:49 +01:00
|
|
|
Sector *shadowSector = i->sector;
|
2009-05-05 11:34:43 +00:00
|
|
|
glBegin(GL_POLYGON);
|
|
|
|
for (int k = 0; k < shadowSector->getNumVertices(); k++) {
|
|
|
|
glVertex3f(shadowSector->getVertices()[k].x(), shadowSector->getVertices()[k].y(), shadowSector->getVertices()[k].z());
|
|
|
|
}
|
|
|
|
glEnd();
|
|
|
|
}
|
|
|
|
*/
|
2011-12-12 12:26:49 +01:00
|
|
|
|
2009-05-05 11:34:43 +00:00
|
|
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
2011-07-15 05:26:53 +08:00
|
|
|
glDepthMask(GL_FALSE);
|
2009-05-05 11:34:43 +00:00
|
|
|
glClearStencil(~0);
|
|
|
|
glClear(GL_STENCIL_BUFFER_BIT);
|
|
|
|
|
|
|
|
glEnable(GL_STENCIL_TEST);
|
|
|
|
glStencilFunc(GL_ALWAYS, 1, (GLuint)~0);
|
|
|
|
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
|
|
|
|
glDisable(GL_LIGHTING);
|
2011-07-19 09:08:46 +02:00
|
|
|
glDisable(GL_TEXTURE_2D);
|
2010-02-04 19:43:50 +00:00
|
|
|
for (SectorListType::iterator i = _currentShadowArray->planeList.begin(); i != _currentShadowArray->planeList.end(); ++i) {
|
2011-06-07 22:58:42 +02:00
|
|
|
Sector *shadowSector = i->sector;
|
2009-05-05 11:34:43 +00:00
|
|
|
glBegin(GL_POLYGON);
|
|
|
|
for (int k = 0; k < shadowSector->getNumVertices(); k++) {
|
|
|
|
glVertex3f(shadowSector->getVertices()[k].x(), shadowSector->getVertices()[k].y(), shadowSector->getVertices()[k].z());
|
|
|
|
}
|
|
|
|
glEnd();
|
|
|
|
}
|
|
|
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
|
|
|
|
|
|
|
glStencilFunc(GL_EQUAL, 1, (GLuint)~0);
|
|
|
|
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
|
|
|
}
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
void GfxOpenGL::setShadowMode() {
|
2011-12-12 18:57:17 +01:00
|
|
|
GfxBase::setShadowMode();
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
void GfxOpenGL::clearShadowMode() {
|
2011-12-12 18:57:17 +01:00
|
|
|
GfxBase::clearShadowMode();
|
|
|
|
|
2009-05-05 11:34:43 +00:00
|
|
|
glDisable(GL_STENCIL_TEST);
|
2011-12-12 12:26:49 +01:00
|
|
|
glDepthMask(GL_TRUE);
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
void GfxOpenGL::setShadowColor(byte r, byte g, byte b) {
|
2009-05-05 11:34:43 +00:00
|
|
|
_shadowColorR = r;
|
|
|
|
_shadowColorG = g;
|
|
|
|
_shadowColorB = b;
|
|
|
|
}
|
|
|
|
|
2011-04-24 15:41:40 +02:00
|
|
|
void GfxOpenGL::getShadowColor(byte *r, byte *g, byte *b) {
|
|
|
|
*r = _shadowColorR;
|
|
|
|
*g = _shadowColorG;
|
|
|
|
*b = _shadowColorB;
|
|
|
|
}
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
void GfxOpenGL::set3DMode() {
|
2009-05-05 11:34:43 +00:00
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
2009-06-27 10:24:51 +00:00
|
|
|
glDepthFunc(GL_LESS);
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
|
|
|
|
2011-12-30 12:53:49 +01:00
|
|
|
void GfxOpenGL::drawEMIModelFace(const EMIModel* model, const EMIMeshFace* face) {
|
|
|
|
int *indices = (int*)face->_indexes;
|
2012-01-27 17:44:33 +01:00
|
|
|
|
2012-01-07 03:16:55 +01:00
|
|
|
glEnable(GL_DEPTH_TEST);
|
2011-12-30 12:53:49 +01:00
|
|
|
glDisable(GL_ALPHA_TEST);
|
2012-01-02 14:00:05 +01:00
|
|
|
glDisable(GL_LIGHTING);
|
2012-01-07 03:16:55 +01:00
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
|
2011-12-30 12:53:49 +01:00
|
|
|
glBegin(GL_TRIANGLES);
|
2012-01-27 13:48:36 +01:00
|
|
|
for (uint j = 0; j < face->_faceLength * 3; j++) {
|
2011-12-30 12:53:49 +01:00
|
|
|
int index = indices[j];
|
|
|
|
if (face->_hasTexture) {
|
|
|
|
glTexCoord2f(model->_texVerts[index].getX(), model->_texVerts[index].getY());
|
|
|
|
}
|
|
|
|
glColor4ub(model->_colorMap[index].r,model->_colorMap[index].g,model->_colorMap[index].b,model->_colorMap[index].a);
|
2012-01-16 17:12:14 +01:00
|
|
|
|
2011-12-30 12:53:49 +01:00
|
|
|
Math::Vector3d normal = model->_normals[index];
|
2012-01-31 00:14:26 +01:00
|
|
|
Math::Vector3d vertex = model->_drawVertices[index];
|
2012-01-16 17:12:14 +01:00
|
|
|
|
2011-12-30 12:53:49 +01:00
|
|
|
glNormal3fv(normal.getData());
|
|
|
|
glVertex3fv(vertex.getData());
|
|
|
|
}
|
|
|
|
glEnd();
|
2012-01-02 14:00:05 +01:00
|
|
|
glEnable(GL_TEXTURE_2D);
|
2011-12-30 12:53:49 +01:00
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glEnable(GL_ALPHA_TEST);
|
2012-01-02 14:00:05 +01:00
|
|
|
glEnable(GL_LIGHTING);
|
2011-12-30 12:53:49 +01:00
|
|
|
glColor3f(1.0f,1.0f,1.0f);
|
|
|
|
}
|
2012-01-16 17:12:14 +01:00
|
|
|
|
2011-07-22 22:09:49 +02:00
|
|
|
void GfxOpenGL::drawModelFace(const MeshFace *face, float *vertices, float *vertNormals, float *textureVerts) {
|
2009-05-05 11:34:43 +00:00
|
|
|
// Support transparency in actor objects, such as the message tube
|
|
|
|
// in Manny's Office
|
|
|
|
glAlphaFunc(GL_GREATER, 0.5);
|
|
|
|
glEnable(GL_ALPHA_TEST);
|
2011-09-14 22:48:24 +02:00
|
|
|
glNormal3fv(face->_normal.getData());
|
2009-05-05 11:34:43 +00:00
|
|
|
glBegin(GL_POLYGON);
|
|
|
|
for (int i = 0; i < face->_numVertices; i++) {
|
|
|
|
glNormal3fv(vertNormals + 3 * face->_vertices[i]);
|
|
|
|
|
|
|
|
if (face->_texVertices)
|
|
|
|
glTexCoord2fv(textureVerts + 2 * face->_texVertices[i]);
|
|
|
|
|
|
|
|
glVertex3fv(vertices + 3 * face->_vertices[i]);
|
|
|
|
}
|
|
|
|
glEnd();
|
|
|
|
// Done with transparency-capable objects
|
|
|
|
glDisable(GL_ALPHA_TEST);
|
|
|
|
}
|
|
|
|
|
2011-05-15 16:47:09 +03:00
|
|
|
void GfxOpenGL::drawSprite(const Sprite *sprite) {
|
|
|
|
glMatrixMode(GL_TEXTURE);
|
|
|
|
glLoadIdentity();
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glPushMatrix();
|
|
|
|
glTranslatef(sprite->_pos.x(), sprite->_pos.y(), sprite->_pos.z());
|
|
|
|
|
|
|
|
GLdouble modelview[16];
|
|
|
|
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
|
|
|
|
|
|
|
|
// We want screen-aligned sprites so reset the rotation part of the matrix.
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
for (int j = 0; j < 3; j++) {
|
|
|
|
if (i == j) {
|
2012-01-27 20:00:30 +01:00
|
|
|
modelview[i * 4 + j] = 1.0f;
|
2011-05-15 16:47:09 +03:00
|
|
|
} else {
|
2012-01-27 20:00:30 +01:00
|
|
|
modelview[i * 4 + j] = 0.0f;
|
2011-05-15 16:47:09 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
glLoadMatrixd(modelview);
|
|
|
|
|
|
|
|
glAlphaFunc(GL_GREATER, 0.5);
|
|
|
|
glEnable(GL_ALPHA_TEST);
|
|
|
|
glDisable(GL_LIGHTING);
|
|
|
|
|
|
|
|
glBegin(GL_POLYGON);
|
|
|
|
glTexCoord2f(0.0f, 0.0f);
|
2012-01-25 23:02:24 +01:00
|
|
|
glVertex3f((sprite->_width / 2) *_scaleW, sprite->_height * _scaleH, 0.0f);
|
2011-05-15 16:47:09 +03:00
|
|
|
glTexCoord2f(0.0f, 1.0f);
|
2012-01-25 23:02:24 +01:00
|
|
|
glVertex3f((sprite->_width / 2) * _scaleW, 0.0f, 0.0f);
|
2011-05-15 16:47:09 +03:00
|
|
|
glTexCoord2f(1.0f, 1.0f);
|
2012-01-25 23:02:24 +01:00
|
|
|
glVertex3f((-sprite->_width / 2) * _scaleW, 0.0f, 0.0f);
|
2011-05-15 16:47:09 +03:00
|
|
|
glTexCoord2f(1.0f, 0.0f);
|
2012-01-25 23:02:24 +01:00
|
|
|
glVertex3f((-sprite->_width / 2) * _scaleW, sprite->_height * _scaleH, 0.0f);
|
2011-05-15 16:47:09 +03:00
|
|
|
glEnd();
|
|
|
|
|
|
|
|
glEnable(GL_LIGHTING);
|
|
|
|
glDisable(GL_ALPHA_TEST);
|
|
|
|
|
|
|
|
glPopMatrix();
|
|
|
|
}
|
|
|
|
|
2011-12-12 18:57:17 +01:00
|
|
|
void GfxOpenGL::translateViewpointStart() {
|
2009-05-05 11:34:43 +00:00
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glPushMatrix();
|
|
|
|
}
|
|
|
|
|
2011-12-12 18:57:17 +01:00
|
|
|
void GfxOpenGL::translateViewpoint(const Math::Vector3d &vec) {
|
|
|
|
glTranslatef(vec.x(), vec.y(), vec.z());
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
|
|
|
|
2011-12-12 18:57:17 +01:00
|
|
|
void GfxOpenGL::rotateViewpoint(const Math::Angle &angle, const Math::Vector3d &axis) {
|
|
|
|
glRotatef(angle.getDegrees(), axis.x(), axis.y(), axis.z());
|
|
|
|
}
|
2009-05-05 11:34:43 +00:00
|
|
|
|
2011-12-12 18:57:17 +01:00
|
|
|
void GfxOpenGL::translateViewpointFinish() {
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glPopMatrix();
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
|
|
|
|
2011-07-13 14:09:32 +03:00
|
|
|
void GfxOpenGL::enableLights() {
|
|
|
|
glEnable(GL_LIGHTING);
|
|
|
|
}
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
void GfxOpenGL::disableLights() {
|
2009-05-05 11:34:43 +00:00
|
|
|
glDisable(GL_LIGHTING);
|
|
|
|
}
|
|
|
|
|
2011-07-23 12:14:33 +02:00
|
|
|
void GfxOpenGL::setupLight(Light *light, int lightId) {
|
2012-02-24 17:41:52 +01:00
|
|
|
if (lightId >= _maxLights) {
|
2012-02-10 14:55:04 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-05-05 11:34:43 +00:00
|
|
|
glEnable(GL_LIGHTING);
|
|
|
|
float lightColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
|
|
|
float lightPos[] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
2011-05-20 22:25:20 +02:00
|
|
|
float lightDir[] = { 0.0f, 0.0f, -1.0f };
|
2011-05-21 04:28:48 +08:00
|
|
|
float cutoff = 180.0f;
|
2009-05-05 11:34:43 +00:00
|
|
|
|
|
|
|
float intensity = light->_intensity / 1.3f;
|
2011-05-05 10:58:29 +02:00
|
|
|
lightColor[0] = ((float)light->_color.getRed() / 15.0f) * intensity;
|
2011-05-20 00:16:08 +02:00
|
|
|
lightColor[1] = ((float)light->_color.getGreen() / 15.0f) * intensity;
|
|
|
|
lightColor[2] = ((float)light->_color.getBlue() / 15.0f) * intensity;
|
2009-05-05 11:34:43 +00:00
|
|
|
|
2011-05-20 08:54:46 +02:00
|
|
|
if (light->_type == "omni") {
|
2009-05-05 11:34:43 +00:00
|
|
|
lightPos[0] = light->_pos.x();
|
|
|
|
lightPos[1] = light->_pos.y();
|
|
|
|
lightPos[2] = light->_pos.z();
|
2011-05-20 08:54:46 +02:00
|
|
|
} else if (light->_type == "direct") {
|
2011-05-20 22:44:12 +02:00
|
|
|
lightPos[0] = -light->_dir.x();
|
|
|
|
lightPos[1] = -light->_dir.y();
|
|
|
|
lightPos[2] = -light->_dir.z();
|
2011-04-30 22:47:02 +08:00
|
|
|
lightPos[3] = 0;
|
2011-05-20 08:54:46 +02:00
|
|
|
} else if (light->_type == "spot") {
|
2009-05-05 11:34:43 +00:00
|
|
|
lightPos[0] = light->_pos.x();
|
|
|
|
lightPos[1] = light->_pos.y();
|
|
|
|
lightPos[2] = light->_pos.z();
|
|
|
|
lightDir[0] = light->_dir.x();
|
|
|
|
lightDir[1] = light->_dir.y();
|
|
|
|
lightDir[2] = light->_dir.z();
|
2011-05-21 04:28:48 +08:00
|
|
|
cutoff = light->_penumbraangle;
|
2009-05-05 11:34:43 +00:00
|
|
|
} else {
|
2011-09-19 16:53:08 +02:00
|
|
|
error("Set::setupLights() Unknown type of light: %s", light->_type.c_str());
|
2011-05-21 04:28:48 +08:00
|
|
|
return;
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
2011-05-21 04:28:48 +08:00
|
|
|
glDisable(GL_LIGHT0 + lightId);
|
|
|
|
glLightfv(GL_LIGHT0 + lightId, GL_DIFFUSE, lightColor);
|
|
|
|
glLightfv(GL_LIGHT0 + lightId, GL_POSITION, lightPos);
|
|
|
|
glLightfv(GL_LIGHT0 + lightId, GL_SPOT_DIRECTION, lightDir);
|
|
|
|
glLightf(GL_LIGHT0 + lightId, GL_SPOT_CUTOFF, cutoff);
|
|
|
|
glEnable(GL_LIGHT0 + lightId);
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
|
|
|
|
2011-10-18 18:01:52 +02:00
|
|
|
void GfxOpenGL::turnOffLight(int lightId) {
|
|
|
|
glDisable(GL_LIGHT0 + lightId);
|
|
|
|
}
|
|
|
|
|
2009-05-05 11:34:43 +00:00
|
|
|
#define BITMAP_TEXTURE_SIZE 256
|
|
|
|
|
2011-05-09 19:20:47 +02:00
|
|
|
void GfxOpenGL::createBitmap(BitmapData *bitmap) {
|
2009-05-05 11:34:43 +00:00
|
|
|
GLuint *textures;
|
2011-05-19 20:19:28 +08:00
|
|
|
|
|
|
|
if (bitmap->_format != 1) {
|
|
|
|
for (int pic = 0; pic < bitmap->_numImages; pic++) {
|
2012-01-24 19:02:50 +01:00
|
|
|
uint16 *zbufPtr = reinterpret_cast<uint16 *>(bitmap->getImageData(pic).getRawBuffer());
|
2011-05-19 20:19:28 +08:00
|
|
|
for (int i = 0; i < (bitmap->_width * bitmap->_height); i++) {
|
2012-01-27 17:28:56 +01:00
|
|
|
uint16 val = READ_LE_UINT16(zbufPtr + i);
|
2012-01-17 16:21:30 -08:00
|
|
|
// fix the value if it is incorrectly set to the bitmap transparency color
|
|
|
|
if (val == 0xf81f) {
|
|
|
|
val = 0;
|
|
|
|
}
|
2012-01-27 19:58:17 +01:00
|
|
|
zbufPtr[i] = 0xffff - ((uint32)val) * 0x10000 / 100 / (0x10000 - val);
|
2011-05-19 20:19:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Flip the zbuffer image to match what GL expects
|
|
|
|
if (!_useDepthShader) {
|
|
|
|
for (int y = 0; y < bitmap->_height / 2; y++) {
|
|
|
|
uint16 *ptr1 = zbufPtr + y * bitmap->_width;
|
|
|
|
uint16 *ptr2 = zbufPtr + (bitmap->_height - 1 - y) * bitmap->_width;
|
|
|
|
for (int x = 0; x < bitmap->_width; x++, ptr1++, ptr2++) {
|
|
|
|
uint16 tmp = *ptr1;
|
|
|
|
*ptr1 = *ptr2;
|
|
|
|
*ptr2 = tmp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (bitmap->_format == 1 || _useDepthShader) {
|
2009-05-05 11:34:43 +00:00
|
|
|
bitmap->_hasTransparency = false;
|
|
|
|
bitmap->_numTex = ((bitmap->_width + (BITMAP_TEXTURE_SIZE - 1)) / BITMAP_TEXTURE_SIZE) *
|
|
|
|
((bitmap->_height + (BITMAP_TEXTURE_SIZE - 1)) / BITMAP_TEXTURE_SIZE);
|
|
|
|
bitmap->_texIds = new GLuint[bitmap->_numTex * bitmap->_numImages];
|
|
|
|
textures = (GLuint *)bitmap->_texIds;
|
|
|
|
glGenTextures(bitmap->_numTex * bitmap->_numImages, textures);
|
|
|
|
|
2011-05-01 03:50:18 +08:00
|
|
|
byte *texData = 0;
|
|
|
|
byte *texOut = 0;
|
2009-05-05 11:34:43 +00:00
|
|
|
|
2011-05-19 20:19:28 +08:00
|
|
|
GLint format = GL_RGBA;
|
|
|
|
GLint type = GL_UNSIGNED_BYTE;
|
|
|
|
int bytes = 4;
|
|
|
|
if (bitmap->_format != 1) {
|
|
|
|
format = GL_DEPTH_COMPONENT;
|
|
|
|
type = GL_UNSIGNED_SHORT;
|
|
|
|
bytes = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
glPixelStorei(GL_UNPACK_ALIGNMENT, bytes);
|
2011-05-13 14:11:04 -07:00
|
|
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, bitmap->_width);
|
|
|
|
|
2009-05-05 11:34:43 +00:00
|
|
|
for (int pic = 0; pic < bitmap->_numImages; pic++) {
|
2011-05-19 20:19:28 +08:00
|
|
|
if (bitmap->_format == 1 && bitmap->_bpp == 16 && bitmap->_colorFormat != BM_RGB1555) {
|
2011-05-01 03:50:18 +08:00
|
|
|
if (texData == 0)
|
|
|
|
texData = new byte[4 * bitmap->_width * bitmap->_height];
|
|
|
|
// Convert data to 32-bit RGBA format
|
|
|
|
byte *texDataPtr = texData;
|
2012-01-24 19:02:50 +01:00
|
|
|
uint16 *bitmapData = reinterpret_cast<uint16 *>(bitmap->getImageData(pic).getRawBuffer());
|
2011-05-01 03:50:18 +08:00
|
|
|
for (int i = 0; i < bitmap->_width * bitmap->_height; i++, texDataPtr += 4, bitmapData++) {
|
|
|
|
uint16 pixel = *bitmapData;
|
|
|
|
int r = pixel >> 11;
|
|
|
|
texDataPtr[0] = (r << 3) | (r >> 2);
|
|
|
|
int g = (pixel >> 5) & 0x3f;
|
|
|
|
texDataPtr[1] = (g << 2) | (g >> 4);
|
|
|
|
int b = pixel & 0x1f;
|
|
|
|
texDataPtr[2] = (b << 3) | (b >> 2);
|
|
|
|
if (pixel == 0xf81f) { // transparent
|
|
|
|
texDataPtr[3] = 0;
|
|
|
|
bitmap->_hasTransparency = true;
|
|
|
|
} else {
|
|
|
|
texDataPtr[3] = 255;
|
|
|
|
}
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
2011-05-01 03:50:18 +08:00
|
|
|
texOut = texData;
|
2011-05-19 20:19:28 +08:00
|
|
|
} else if (bitmap->_format == 1 && bitmap->_colorFormat == BM_RGB1555) {
|
2012-01-24 19:02:50 +01:00
|
|
|
bitmap->convertToColorFormat(pic, Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24));
|
|
|
|
texOut = (byte *)bitmap->getImageData(pic).getRawBuffer();
|
2011-05-01 03:50:18 +08:00
|
|
|
} else {
|
2012-01-24 19:02:50 +01:00
|
|
|
texOut = (byte *)bitmap->getImageData(pic).getRawBuffer();
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < bitmap->_numTex; i++) {
|
|
|
|
glBindTexture(GL_TEXTURE_2D, textures[bitmap->_numTex * pic + i]);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
2011-05-19 20:19:28 +08:00
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, format, BITMAP_TEXTURE_SIZE, BITMAP_TEXTURE_SIZE, 0, format, type, NULL);
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int cur_tex_idx = bitmap->_numTex * pic;
|
|
|
|
|
|
|
|
for (int y = 0; y < bitmap->_height; y += BITMAP_TEXTURE_SIZE) {
|
|
|
|
for (int x = 0; x < bitmap->_width; x += BITMAP_TEXTURE_SIZE) {
|
2012-01-27 17:44:33 +01:00
|
|
|
int width = (x + BITMAP_TEXTURE_SIZE >= bitmap->_width) ? (bitmap->_width - x) : BITMAP_TEXTURE_SIZE;
|
2009-05-05 11:34:43 +00:00
|
|
|
int height = (y + BITMAP_TEXTURE_SIZE >= bitmap->_height) ? (bitmap->_height - y) : BITMAP_TEXTURE_SIZE;
|
|
|
|
glBindTexture(GL_TEXTURE_2D, textures[cur_tex_idx]);
|
2011-05-19 20:19:28 +08:00
|
|
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type,
|
|
|
|
texOut + (y * bytes * bitmap->_width) + (bytes * x));
|
2009-05-05 11:34:43 +00:00
|
|
|
cur_tex_idx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
2011-05-13 14:11:04 -07:00
|
|
|
|
2009-05-05 11:34:43 +00:00
|
|
|
delete[] texData;
|
2012-02-02 09:34:53 -08:00
|
|
|
bitmap->freeData();
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-02 09:34:53 -08:00
|
|
|
void GfxOpenGL::drawBitmap(const Bitmap *bitmap, int dx, int dy) {
|
2011-07-29 23:02:52 +02:00
|
|
|
int format = bitmap->getFormat();
|
|
|
|
if ((format == 1 && !_renderBitmaps) || (format == 5 && !_renderZBitmaps)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-05-05 11:34:43 +00:00
|
|
|
GLuint *textures;
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
|
|
|
glOrtho(0, _screenWidth, _screenHeight, 0, 0, 1);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
glMatrixMode(GL_TEXTURE);
|
|
|
|
glLoadIdentity();
|
|
|
|
// A lot more may need to be put there : disabling Alpha test, blending, ...
|
|
|
|
// For now, just keep this here :-)
|
2011-05-09 19:20:47 +02:00
|
|
|
if (bitmap->getFormat() == 1 && bitmap->getHasTransparency()) {
|
2009-05-05 11:34:43 +00:00
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
2012-01-27 17:44:33 +01:00
|
|
|
} else {
|
2009-05-05 11:34:43 +00:00
|
|
|
glDisable(GL_BLEND);
|
2012-01-27 17:44:33 +01:00
|
|
|
}
|
2009-05-05 11:34:43 +00:00
|
|
|
glDisable(GL_LIGHTING);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
|
2011-05-19 20:19:28 +08:00
|
|
|
// If drawing a Z-buffer image, but no shaders are available, fall back to the glDrawPixels method.
|
|
|
|
if (bitmap->getFormat() == 5 && !_useDepthShader) {
|
2009-05-05 11:34:43 +00:00
|
|
|
// Only draw the manual zbuffer when enabled
|
2011-09-18 18:46:20 +02:00
|
|
|
if (bitmap->getActiveImage() - 1 < bitmap->getNumImages()) {
|
2012-02-02 09:34:53 -08:00
|
|
|
drawDepthBitmap(dx, dy, bitmap->getWidth(), bitmap->getHeight(), (char *)bitmap->getData(bitmap->getActiveImage() - 1).getRawBuffer());
|
2009-05-05 11:34:43 +00:00
|
|
|
} else {
|
2011-09-18 18:46:20 +02:00
|
|
|
warning("zbuffer image has index out of bounds! %d/%d", bitmap->getActiveImage(), bitmap->getNumImages());
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
2011-05-19 20:19:28 +08:00
|
|
|
glEnable(GL_LIGHTING);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bitmap->getFormat() == 1) { // Normal image
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
glDepthMask(GL_FALSE);
|
|
|
|
} else { // ZBuffer image
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glDepthFunc(GL_ALWAYS);
|
|
|
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
|
|
|
glDepthMask(GL_TRUE);
|
|
|
|
#ifdef GL_ARB_fragment_program
|
2012-03-07 16:12:14 +01:00
|
|
|
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, _fragmentProgram);
|
2011-05-19 20:19:28 +08:00
|
|
|
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
glEnable(GL_SCISSOR_TEST);
|
2012-02-02 09:34:53 -08:00
|
|
|
glScissor((int)(dx * _scaleW), _screenHeight - (int)(((dy + bitmap->getHeight())) * _scaleH), (int)(bitmap->getWidth() * _scaleW), (int)(bitmap->getHeight() * _scaleH));
|
2011-09-18 18:46:20 +02:00
|
|
|
int cur_tex_idx = bitmap->getNumTex() * (bitmap->getActiveImage() - 1);
|
2012-02-02 09:34:53 -08:00
|
|
|
for (int y = dy; y < (dy + bitmap->getHeight()); y += BITMAP_TEXTURE_SIZE) {
|
|
|
|
for (int x = dx; x < (dx + bitmap->getWidth()); x += BITMAP_TEXTURE_SIZE) {
|
2011-05-19 20:19:28 +08:00
|
|
|
textures = (GLuint *)bitmap->getTexIds();
|
|
|
|
glBindTexture(GL_TEXTURE_2D, textures[cur_tex_idx]);
|
|
|
|
glBegin(GL_QUADS);
|
|
|
|
glTexCoord2f(0.0f, 0.0f);
|
2012-01-25 23:02:24 +01:00
|
|
|
glVertex2f(x * _scaleW, y * _scaleH);
|
2011-05-19 20:19:28 +08:00
|
|
|
glTexCoord2f(1.0f, 0.0f);
|
2012-01-25 23:02:24 +01:00
|
|
|
glVertex2f((x + BITMAP_TEXTURE_SIZE) * _scaleW, y * _scaleH);
|
2011-05-19 20:19:28 +08:00
|
|
|
glTexCoord2f(1.0f, 1.0f);
|
2012-01-25 23:02:24 +01:00
|
|
|
glVertex2f((x + BITMAP_TEXTURE_SIZE) * _scaleW, (y + BITMAP_TEXTURE_SIZE) * _scaleH);
|
2011-05-19 20:19:28 +08:00
|
|
|
glTexCoord2f(0.0f, 1.0f);
|
2012-01-25 23:02:24 +01:00
|
|
|
glVertex2f(x * _scaleW, (y + BITMAP_TEXTURE_SIZE) * _scaleH);
|
2011-05-19 20:19:28 +08:00
|
|
|
glEnd();
|
|
|
|
cur_tex_idx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
glDisable(GL_SCISSOR_TEST);
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
if (bitmap->getFormat() == 1) {
|
|
|
|
glDepthMask(GL_TRUE);
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
} else {
|
|
|
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
|
|
|
glDepthFunc(GL_LESS);
|
|
|
|
#ifdef GL_ARB_fragment_program
|
|
|
|
glDisable(GL_FRAGMENT_PROGRAM_ARB);
|
|
|
|
#endif
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
|
|
|
glEnable(GL_LIGHTING);
|
|
|
|
}
|
|
|
|
|
2011-05-09 19:20:47 +02:00
|
|
|
void GfxOpenGL::destroyBitmap(BitmapData *bitmap) {
|
2011-05-13 14:11:04 -07:00
|
|
|
GLuint *textures = (GLuint *)bitmap->_texIds;
|
2009-05-05 11:34:43 +00:00
|
|
|
if (textures) {
|
|
|
|
glDeleteTextures(bitmap->_numTex * bitmap->_numImages, textures);
|
|
|
|
delete[] textures;
|
2011-11-01 04:21:19 +08:00
|
|
|
bitmap->_texIds = 0;
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-27 17:44:33 +01:00
|
|
|
struct FontUserData {
|
2011-05-23 19:06:08 -07:00
|
|
|
int size;
|
|
|
|
GLuint texture;
|
|
|
|
};
|
|
|
|
|
2011-05-22 20:43:28 -07:00
|
|
|
void GfxOpenGL::createFont(Font *font) {
|
2011-05-23 19:06:08 -07:00
|
|
|
const byte *bitmapData = font->getFontData();
|
|
|
|
uint dataSize = font->getDataSize();
|
2011-05-22 20:43:28 -07:00
|
|
|
|
2011-05-23 19:55:20 -07:00
|
|
|
uint8 bpp = 4;
|
|
|
|
uint8 charsWide = 16;
|
|
|
|
uint8 charsHigh = 16;
|
|
|
|
|
|
|
|
byte *texDataPtr = new byte[dataSize * bpp];
|
2011-05-22 20:43:28 -07:00
|
|
|
byte *data = texDataPtr;
|
|
|
|
|
2011-05-23 19:55:20 -07:00
|
|
|
for (uint i = 0; i < dataSize; i++, texDataPtr += bpp, bitmapData++) {
|
2011-05-22 20:43:28 -07:00
|
|
|
byte pixel = *bitmapData;
|
|
|
|
if (pixel == 0x00) {
|
2012-01-27 17:44:33 +01:00
|
|
|
texDataPtr[0] = texDataPtr[1] = texDataPtr[2] = texDataPtr[3] = 0;
|
2011-05-22 20:43:28 -07:00
|
|
|
} else if (pixel == 0x80) {
|
2012-01-27 17:44:33 +01:00
|
|
|
texDataPtr[0] = texDataPtr[1] = texDataPtr[2] = 0;
|
2011-05-23 19:55:20 -07:00
|
|
|
texDataPtr[3] = 255;
|
2011-05-22 20:43:28 -07:00
|
|
|
} else if (pixel == 0xFF) {
|
2012-01-27 17:44:33 +01:00
|
|
|
texDataPtr[0] = texDataPtr[1] = texDataPtr[2] = texDataPtr[3] = 255;
|
2011-05-22 20:43:28 -07:00
|
|
|
}
|
|
|
|
}
|
2011-05-23 12:47:43 -07:00
|
|
|
int size = 0;
|
|
|
|
for (int i = 0; i < 256; ++i) {
|
|
|
|
int width = font->getCharDataWidth(i), height = font->getCharDataHeight(i);
|
2011-05-23 20:03:46 -07:00
|
|
|
int m = MAX(width, height);
|
2011-05-23 14:26:44 -07:00
|
|
|
if (m > size)
|
2011-05-23 13:40:57 -07:00
|
|
|
size = m;
|
2011-05-23 12:47:43 -07:00
|
|
|
}
|
|
|
|
assert(size < 64);
|
|
|
|
if (size < 8)
|
|
|
|
size = 8;
|
|
|
|
if (size < 16)
|
|
|
|
size = 16;
|
|
|
|
else if (size < 32)
|
|
|
|
size = 32;
|
|
|
|
else if (size < 64)
|
|
|
|
size = 64;
|
|
|
|
|
2011-05-23 19:55:20 -07:00
|
|
|
uint arraySize = size * size * bpp * charsWide * charsHigh;
|
2011-05-23 14:26:44 -07:00
|
|
|
byte *temp = new byte[arraySize];
|
|
|
|
if (!temp)
|
|
|
|
error("Could not allocate %d bytes", arraySize);
|
2011-05-23 12:47:43 -07:00
|
|
|
|
2011-05-23 14:26:44 -07:00
|
|
|
memset(temp, 0, arraySize);
|
2011-05-22 20:43:28 -07:00
|
|
|
|
2011-05-23 19:06:08 -07:00
|
|
|
FontUserData *userData = new FontUserData;
|
|
|
|
font->setUserData(userData);
|
|
|
|
userData->texture = 0;
|
|
|
|
userData->size = size;
|
|
|
|
|
|
|
|
GLuint *texture = &(userData->texture);
|
|
|
|
glGenTextures(1, texture);
|
2011-05-22 20:43:28 -07:00
|
|
|
|
2011-05-23 12:47:43 -07:00
|
|
|
for (int i = 0, row = 0; i < 256; ++i) {
|
2011-05-22 20:43:28 -07:00
|
|
|
int width = font->getCharDataWidth(i), height = font->getCharDataHeight(i);
|
2011-05-26 10:37:30 -07:00
|
|
|
int32 d = font->getCharOffset(i);
|
2011-05-22 20:43:28 -07:00
|
|
|
for (int x = 0; x < height; ++x) {
|
2011-06-06 13:48:44 -07:00
|
|
|
// a is the offset to get to the correct row.
|
|
|
|
// b is the offset to get to the correct line in the character.
|
|
|
|
// c is the offset of the character from the start of the row.
|
2011-05-23 19:55:20 -07:00
|
|
|
uint a = row * size * size * bpp * charsHigh;
|
|
|
|
uint b = x * size * charsWide * bpp;
|
|
|
|
uint c = 0;
|
|
|
|
if (i != 0)
|
|
|
|
c = ((i - 1) % 16) * size * bpp;
|
|
|
|
|
2011-05-23 19:41:46 -07:00
|
|
|
uint pos = a + b + c;
|
2011-05-23 19:55:20 -07:00
|
|
|
uint pos2 = d * bpp + x * width * bpp;
|
|
|
|
assert(pos + width * bpp <= arraySize);
|
|
|
|
assert(pos2 + width * bpp <= dataSize * bpp);
|
|
|
|
memcpy(temp + pos, data + pos2, width * bpp);
|
2011-05-22 20:43:28 -07:00
|
|
|
}
|
2011-05-23 19:55:20 -07:00
|
|
|
if (i != 0 && i % charsWide == 0)
|
2011-05-23 12:47:43 -07:00
|
|
|
++row;
|
|
|
|
|
2011-05-22 20:43:28 -07:00
|
|
|
}
|
2011-05-23 19:06:08 -07:00
|
|
|
glBindTexture(GL_TEXTURE_2D, texture[0]);
|
2011-05-23 12:47:43 -07:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
2011-05-23 19:55:20 -07:00
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size * charsWide, size * charsHigh, 0, GL_RGBA, GL_UNSIGNED_BYTE, temp);
|
2011-05-23 12:47:43 -07:00
|
|
|
|
|
|
|
delete[] data;
|
|
|
|
delete[] temp;
|
2011-05-22 20:43:28 -07:00
|
|
|
}
|
|
|
|
|
2011-05-23 14:26:44 -07:00
|
|
|
void GfxOpenGL::destroyFont(Font *font) {
|
2011-05-23 19:06:08 -07:00
|
|
|
FontUserData *data = (FontUserData *)font->getUserData();
|
|
|
|
if (data) {
|
|
|
|
glDeleteTextures(1, &(data->texture));
|
|
|
|
delete data;
|
2011-05-23 14:26:44 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-23 22:00:53 -07:00
|
|
|
void GfxOpenGL::createTextObject(TextObject *text) {
|
|
|
|
}
|
|
|
|
|
2011-05-23 16:19:47 -07:00
|
|
|
void GfxOpenGL::drawTextObject(TextObject *text) {
|
|
|
|
if (!text)
|
2011-05-22 20:43:28 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
|
|
|
glOrtho(0, _screenWidth, _screenHeight, 0, 0, 1);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
glMatrixMode(GL_TEXTURE);
|
|
|
|
glLoadIdentity();
|
|
|
|
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
|
|
|
|
glDisable(GL_LIGHTING);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glDepthMask(GL_FALSE);
|
|
|
|
|
2012-01-27 11:47:28 -08:00
|
|
|
const Color &color = text->getFGColor();
|
2011-05-23 19:06:08 -07:00
|
|
|
Font *font = text->getFont();
|
2011-05-23 16:19:47 -07:00
|
|
|
|
2012-01-27 11:47:28 -08:00
|
|
|
glColor3f(color.getRed() / 255.f, color.getGreen() / 255.f, color.getBlue() / 255.f);
|
2011-05-23 19:06:08 -07:00
|
|
|
FontUserData *userData = (FontUserData *)font->getUserData();
|
|
|
|
if (!userData)
|
|
|
|
error("Could not get font userdata");
|
2012-01-25 23:02:24 +01:00
|
|
|
float size = userData->size * _scaleW;
|
2011-05-23 19:06:08 -07:00
|
|
|
GLuint texture = userData->texture;
|
2011-05-23 16:19:47 -07:00
|
|
|
const Common::String *lines = text->getLines();
|
|
|
|
int numLines = text->getNumLines();
|
|
|
|
for (int j = 0; j < numLines; ++j) {
|
|
|
|
const Common::String &line = lines[j];
|
2012-01-27 18:01:44 +01:00
|
|
|
int x = text->getLineX(j);
|
|
|
|
int y = text->getLineY(j);
|
2011-05-23 16:19:47 -07:00
|
|
|
for (uint i = 0; i < line.size(); ++i) {
|
|
|
|
uint8 character = line[i];
|
2012-01-25 23:02:24 +01:00
|
|
|
float w = y + font->getCharStartingLine(character) + font->getBaseOffsetY();
|
|
|
|
float z = x + font->getCharStartingCol(character);
|
|
|
|
z *= _scaleW;
|
|
|
|
w *= _scaleH;
|
2011-05-23 16:19:47 -07:00
|
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
2011-06-06 13:48:44 -07:00
|
|
|
float width = 1 / 16.f;
|
2012-01-27 18:01:44 +01:00
|
|
|
float cx = ((character - 1) % 16) / 16.0f;
|
|
|
|
float cy = ((character - 1) / 16) / 16.0f;
|
2011-05-23 16:19:47 -07:00
|
|
|
glBegin(GL_QUADS);
|
|
|
|
glTexCoord2f(cx, cy);
|
2012-01-25 23:02:24 +01:00
|
|
|
glVertex2f(z, w);
|
2011-06-06 13:48:44 -07:00
|
|
|
glTexCoord2f(cx + width, cy);
|
2012-01-25 23:02:24 +01:00
|
|
|
glVertex2f(z + size, w);
|
2011-06-06 13:48:44 -07:00
|
|
|
glTexCoord2f(cx + width, cy + width);
|
2012-01-25 23:02:24 +01:00
|
|
|
glVertex2f(z + size, w + size);
|
2011-06-06 13:48:44 -07:00
|
|
|
glTexCoord2f(cx, cy + width);
|
2012-01-25 23:02:24 +01:00
|
|
|
glVertex2f(z, w + size);
|
2011-05-23 16:19:47 -07:00
|
|
|
glEnd();
|
|
|
|
x += font->getCharWidth(character);
|
|
|
|
}
|
2011-05-22 20:43:28 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
glColor3f(1, 1, 1);
|
|
|
|
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glEnable(GL_LIGHTING);
|
2011-06-07 16:52:38 +02:00
|
|
|
glDepthMask(GL_TRUE);
|
2011-05-22 20:43:28 -07:00
|
|
|
}
|
|
|
|
|
2011-05-23 22:00:53 -07:00
|
|
|
void GfxOpenGL::destroyTextObject(TextObject *text) {
|
|
|
|
}
|
|
|
|
|
2011-07-28 22:21:16 +02:00
|
|
|
void GfxOpenGL::createMaterial(Texture *material, const char *data, const CMap *cmap) {
|
|
|
|
material->_texture = new GLuint[1];
|
|
|
|
glGenTextures(1, (GLuint *)material->_texture);
|
2009-05-05 11:34:43 +00:00
|
|
|
char *texdata = new char[material->_width * material->_height * 4];
|
2011-07-28 22:21:16 +02:00
|
|
|
char *texdatapos = texdata;
|
2012-01-16 17:12:14 +01:00
|
|
|
|
2012-01-02 14:00:05 +01:00
|
|
|
if (cmap != NULL) { // EMI doesn't have colour-maps
|
|
|
|
for (int y = 0; y < material->_height; y++) {
|
|
|
|
for (int x = 0; x < material->_width; x++) {
|
2012-04-03 16:58:04 -07:00
|
|
|
uint8 col = *(const uint8 *)(data);
|
2012-01-02 14:00:05 +01:00
|
|
|
if (col == 0) {
|
|
|
|
memset(texdatapos, 0, 4); // transparent
|
|
|
|
if (!material->_hasAlpha) {
|
|
|
|
texdatapos[3] = '\xff'; // fully opaque
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
memcpy(texdatapos, cmap->_colors + 3 * (col), 3);
|
2009-05-05 11:34:43 +00:00
|
|
|
texdatapos[3] = '\xff'; // fully opaque
|
|
|
|
}
|
2012-01-02 14:00:05 +01:00
|
|
|
texdatapos += 4;
|
|
|
|
data++;
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
|
|
|
}
|
2012-01-02 14:00:05 +01:00
|
|
|
} else {
|
|
|
|
memcpy(texdata, data, material->_width * material->_height * material->_bpp);
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
2012-01-16 17:12:14 +01:00
|
|
|
|
2012-01-02 14:00:05 +01:00
|
|
|
GLuint format = 0;
|
2012-01-10 06:39:04 +01:00
|
|
|
GLuint internalFormat = 0;
|
2012-01-02 14:00:05 +01:00
|
|
|
if (material->_colorFormat == BM_RGBA) {
|
|
|
|
format = GL_RGBA;
|
2012-01-10 06:39:04 +01:00
|
|
|
internalFormat = GL_RGBA;
|
|
|
|
} else { // The only other colorFormat we load right now is BGR
|
|
|
|
format = GL_BGR;
|
|
|
|
internalFormat = GL_RGB;
|
2012-01-02 14:00:05 +01:00
|
|
|
}
|
2012-01-16 17:12:14 +01:00
|
|
|
|
2011-07-28 22:21:16 +02:00
|
|
|
GLuint *textures = (GLuint *)material->_texture;
|
|
|
|
glBindTexture(GL_TEXTURE_2D, textures[0]);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
2012-01-10 06:39:04 +01:00
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, material->_width, material->_height, 0, format, GL_UNSIGNED_BYTE, texdata);
|
2009-05-05 11:34:43 +00:00
|
|
|
delete[] texdata;
|
|
|
|
}
|
|
|
|
|
2011-07-28 22:21:16 +02:00
|
|
|
void GfxOpenGL::selectMaterial(const Texture *material) {
|
|
|
|
GLuint *textures = (GLuint *)material->_texture;
|
|
|
|
glBindTexture(GL_TEXTURE_2D, textures[0]);
|
2012-01-16 17:12:14 +01:00
|
|
|
|
2012-01-07 03:16:55 +01:00
|
|
|
// Grim has inverted tex-coords, EMI doesn't
|
|
|
|
if (g_grim->getGameType() != GType_MONKEY4) {
|
|
|
|
glMatrixMode(GL_TEXTURE);
|
|
|
|
glLoadIdentity();
|
|
|
|
glScalef(1.0f / material->_width, 1.0f / material->_height, 1);
|
|
|
|
}
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
|
|
|
|
2011-07-28 22:21:16 +02:00
|
|
|
void GfxOpenGL::destroyMaterial(Texture *material) {
|
|
|
|
GLuint *textures = (GLuint *)material->_texture;
|
2011-05-13 14:11:04 -07:00
|
|
|
if (textures) {
|
2011-07-28 22:21:16 +02:00
|
|
|
glDeleteTextures(1, textures);
|
2011-05-13 14:11:04 -07:00
|
|
|
delete[] textures;
|
|
|
|
}
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
void GfxOpenGL::drawDepthBitmap(int x, int y, int w, int h, char *data) {
|
2012-01-27 18:01:44 +01:00
|
|
|
//if (num != 0) {
|
|
|
|
// warning("Animation not handled yet in GL texture path");
|
|
|
|
//}
|
2009-06-23 06:46:05 +00:00
|
|
|
|
2009-06-27 11:53:55 +00:00
|
|
|
if (y + h == 480) {
|
2009-05-05 11:34:43 +00:00
|
|
|
glRasterPos2i(x, _screenHeight - 1);
|
2009-06-27 12:12:16 +00:00
|
|
|
glBitmap(0, 0, 0, 0, 0, -1, NULL);
|
2009-06-27 11:53:55 +00:00
|
|
|
} else
|
2009-05-05 11:34:43 +00:00
|
|
|
glRasterPos2i(x, y + h);
|
|
|
|
|
2009-06-27 11:53:55 +00:00
|
|
|
glDisable(GL_TEXTURE_2D);
|
2009-06-27 12:24:13 +00:00
|
|
|
glEnable(GL_DEPTH_TEST);
|
2009-05-05 11:34:43 +00:00
|
|
|
glDepthFunc(GL_ALWAYS);
|
|
|
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
2009-06-27 12:24:13 +00:00
|
|
|
glDepthMask(GL_TRUE);
|
2009-05-05 11:34:43 +00:00
|
|
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
|
2009-06-23 06:46:05 +00:00
|
|
|
|
2009-05-05 11:34:43 +00:00
|
|
|
glDrawPixels(w, h, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, data);
|
|
|
|
|
2009-06-23 06:46:05 +00:00
|
|
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
2009-05-05 11:34:43 +00:00
|
|
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
2009-06-27 10:06:11 +00:00
|
|
|
glDepthFunc(GL_LESS);
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
|
|
|
|
2011-10-01 02:51:55 +02:00
|
|
|
void GfxOpenGL::prepareMovieFrame(Graphics::Surface* frame) {
|
|
|
|
int height = frame->h;
|
|
|
|
int width = frame->w;
|
|
|
|
byte *bitmap = (byte *)frame->pixels;
|
|
|
|
|
2009-05-05 11:34:43 +00:00
|
|
|
// remove if already exist
|
|
|
|
if (_smushNumTex > 0) {
|
|
|
|
glDeleteTextures(_smushNumTex, _smushTexIds);
|
|
|
|
delete[] _smushTexIds;
|
|
|
|
_smushNumTex = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// create texture
|
|
|
|
_smushNumTex = ((width + (BITMAP_TEXTURE_SIZE - 1)) / BITMAP_TEXTURE_SIZE) *
|
|
|
|
((height + (BITMAP_TEXTURE_SIZE - 1)) / BITMAP_TEXTURE_SIZE);
|
|
|
|
_smushTexIds = new GLuint[_smushNumTex];
|
|
|
|
glGenTextures(_smushNumTex, _smushTexIds);
|
|
|
|
for (int i = 0; i < _smushNumTex; i++) {
|
|
|
|
glBindTexture(GL_TEXTURE_2D, _smushTexIds[i]);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, BITMAP_TEXTURE_SIZE, BITMAP_TEXTURE_SIZE, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
|
|
|
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
|
|
|
|
|
|
|
|
int curTexIdx = 0;
|
|
|
|
for (int y = 0; y < height; y += BITMAP_TEXTURE_SIZE) {
|
|
|
|
for (int x = 0; x < width; x += BITMAP_TEXTURE_SIZE) {
|
|
|
|
int t_width = (x + BITMAP_TEXTURE_SIZE >= width) ? (width - x) : BITMAP_TEXTURE_SIZE;
|
|
|
|
int t_height = (y + BITMAP_TEXTURE_SIZE >= height) ? (height - y) : BITMAP_TEXTURE_SIZE;
|
|
|
|
glBindTexture(GL_TEXTURE_2D, _smushTexIds[curTexIdx]);
|
|
|
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, t_width, t_height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, bitmap + (y * 2 * width) + (2 * x));
|
|
|
|
curTexIdx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
|
|
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
2012-01-25 23:02:24 +01:00
|
|
|
_smushWidth = (int)(width * _scaleW);
|
|
|
|
_smushHeight = (int)(height * _scaleH);
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
|
|
|
|
2011-08-14 18:35:49 +02:00
|
|
|
void GfxOpenGL::drawMovieFrame(int offsetX, int offsetY) {
|
2009-05-05 11:34:43 +00:00
|
|
|
// prepare view
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
|
|
|
glOrtho(0, _screenWidth, _screenHeight, 0, 0, 1);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
glMatrixMode(GL_TEXTURE);
|
|
|
|
glLoadIdentity();
|
|
|
|
// A lot more may need to be put there : disabling Alpha test, blending, ...
|
|
|
|
// For now, just keep this here :-)
|
|
|
|
|
|
|
|
glDisable(GL_LIGHTING);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
// draw
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
glDepthMask(GL_FALSE);
|
|
|
|
glEnable(GL_SCISSOR_TEST);
|
|
|
|
|
2012-01-27 13:48:36 +01:00
|
|
|
offsetX = (int)(offsetX * _scaleW);
|
|
|
|
offsetY = (int)(offsetY * _scaleH);
|
2012-01-25 23:02:24 +01:00
|
|
|
|
2009-05-05 11:34:43 +00:00
|
|
|
glScissor(offsetX, _screenHeight - (offsetY + _smushHeight), _smushWidth, _smushHeight);
|
|
|
|
|
|
|
|
int curTexIdx = 0;
|
2012-01-25 23:02:24 +01:00
|
|
|
for (int y = 0; y < _smushHeight; y += (int)(BITMAP_TEXTURE_SIZE * _scaleH)) {
|
|
|
|
for (int x = 0; x < _smushWidth; x += (int)(BITMAP_TEXTURE_SIZE * _scaleW)) {
|
2009-05-05 11:34:43 +00:00
|
|
|
glBindTexture(GL_TEXTURE_2D, _smushTexIds[curTexIdx]);
|
|
|
|
glBegin(GL_QUADS);
|
|
|
|
glTexCoord2f(0, 0);
|
2012-01-25 23:02:24 +01:00
|
|
|
glVertex2f(x + offsetX, y + offsetY);
|
2011-04-06 05:55:07 +08:00
|
|
|
glTexCoord2f(1.0f, 0.0f);
|
2012-01-25 23:02:24 +01:00
|
|
|
glVertex2f(x + offsetX + BITMAP_TEXTURE_SIZE * _scaleW, y + offsetY);
|
2011-04-06 05:55:07 +08:00
|
|
|
glTexCoord2f(1.0f, 1.0f);
|
2012-01-25 23:02:24 +01:00
|
|
|
glVertex2f(x + offsetX + BITMAP_TEXTURE_SIZE * _scaleW, y + offsetY + BITMAP_TEXTURE_SIZE * _scaleH);
|
2011-04-06 05:55:07 +08:00
|
|
|
glTexCoord2f(0.0f, 1.0f);
|
2012-01-25 23:02:24 +01:00
|
|
|
glVertex2f(x + offsetX, y + offsetY + BITMAP_TEXTURE_SIZE * _scaleH);
|
2009-05-05 11:34:43 +00:00
|
|
|
glEnd();
|
|
|
|
curTexIdx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
glDisable(GL_SCISSOR_TEST);
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
glDepthMask(GL_TRUE);
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glEnable(GL_LIGHTING);
|
|
|
|
}
|
|
|
|
|
2011-08-14 18:35:49 +02:00
|
|
|
void GfxOpenGL::releaseMovieFrame() {
|
2009-05-05 11:34:43 +00:00
|
|
|
if (_smushNumTex > 0) {
|
|
|
|
glDeleteTextures(_smushNumTex, _smushTexIds);
|
|
|
|
delete[] _smushTexIds;
|
|
|
|
_smushNumTex = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
void GfxOpenGL::loadEmergFont() {
|
2009-05-05 11:34:43 +00:00
|
|
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
|
|
|
|
|
|
|
_emergFont = glGenLists(128);
|
|
|
|
for (int i = 32; i < 127; i++) {
|
|
|
|
glNewList(_emergFont + i, GL_COMPILE);
|
|
|
|
glBitmap(8, 13, 0, 2, 10, 0, Font::emerFont[i - 32]);
|
|
|
|
glEndList();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
void GfxOpenGL::drawEmergString(int x, int y, const char *text, const Color &fgColor) {
|
2009-05-05 11:34:43 +00:00
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPushMatrix();
|
|
|
|
glLoadIdentity();
|
|
|
|
glOrtho(0, _screenWidth, _screenHeight, 0, 0, 1);
|
|
|
|
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
glDisable(GL_LIGHTING);
|
|
|
|
|
|
|
|
glRasterPos2i(x, y);
|
2009-10-14 06:05:14 +00:00
|
|
|
glColor3f(1.0f, 1.0f, 1.0f);
|
2009-05-05 11:34:43 +00:00
|
|
|
|
|
|
|
glListBase(_emergFont);
|
2012-04-03 16:58:04 -07:00
|
|
|
glCallLists(strlen(text), GL_UNSIGNED_BYTE, (const GLubyte *)text);
|
2009-05-05 11:34:43 +00:00
|
|
|
|
|
|
|
glEnable(GL_LIGHTING);
|
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPopMatrix();
|
|
|
|
}
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
Bitmap *GfxOpenGL::getScreenshot(int w, int h) {
|
2012-01-24 18:20:33 +01:00
|
|
|
Graphics::PixelBuffer buffer = Graphics::PixelBuffer::createBuffer<565>(w * h, DisposeAfterUse::YES);
|
|
|
|
Graphics::PixelBuffer src(Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24), _screenWidth * _screenHeight, DisposeAfterUse::YES);
|
|
|
|
glReadPixels(0, 0, _screenWidth, _screenHeight, GL_RGBA, GL_UNSIGNED_BYTE, src.getRawBuffer());
|
2009-05-05 11:34:43 +00:00
|
|
|
|
2012-01-27 20:01:12 +01:00
|
|
|
int i1 = (_screenWidth * w - 1) / _screenWidth + 1;
|
|
|
|
int j1 = (_screenHeight * h - 1) / _screenHeight + 1;
|
|
|
|
|
|
|
|
for (int j = 0; j < j1; j++) {
|
|
|
|
for (int i = 0; i < i1; i++) {
|
|
|
|
int x0 = i * _screenWidth / w;
|
|
|
|
int x1 = ((i + 1) * _screenWidth - 1) / w + 1;
|
|
|
|
int y0 = j * _screenHeight / h;
|
|
|
|
int y1 = ((j + 1) * _screenHeight - 1) / h + 1;
|
|
|
|
uint32 color = 0;
|
|
|
|
for (int y = y0; y < y1; y++) {
|
|
|
|
for (int x = x0; x < x1; x++) {
|
|
|
|
uint8 lr, lg, lb;
|
|
|
|
src.getRGBAt(y * _screenWidth + x, lr, lg, lb);
|
|
|
|
color += (lr + lg + lb) / 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
color /= (x1 - x0) * (y1 - y0);
|
|
|
|
buffer.setPixelAt((h - j - 1) * w + i, color, color, color);
|
2009-05-05 11:34:43 +00:00
|
|
|
}
|
|
|
|
}
|
2009-05-09 17:47:28 +00:00
|
|
|
|
2012-01-24 18:20:33 +01:00
|
|
|
Bitmap *screenshot = new Bitmap(buffer, w, h, "screenshot");
|
2009-05-05 11:34:43 +00:00
|
|
|
return screenshot;
|
|
|
|
}
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
void GfxOpenGL::storeDisplay() {
|
2009-05-05 11:34:43 +00:00
|
|
|
glReadPixels(0, 0, _screenWidth, _screenHeight, GL_RGBA, GL_UNSIGNED_BYTE, _storedDisplay);
|
|
|
|
}
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
void GfxOpenGL::copyStoredToDisplay() {
|
2009-05-05 11:34:43 +00:00
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
|
|
|
glOrtho(0, _screenWidth, _screenHeight, 0, 0, 1);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
|
|
|
|
glDisable(GL_LIGHTING);
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
glDepthMask(GL_FALSE);
|
|
|
|
|
|
|
|
glRasterPos2i(0, _screenHeight - 1);
|
|
|
|
glBitmap(0, 0, 0, 0, 0, -1, NULL);
|
|
|
|
glDrawPixels(_screenWidth, _screenHeight, GL_RGBA, GL_UNSIGNED_BYTE, _storedDisplay);
|
|
|
|
|
|
|
|
glDepthMask(GL_TRUE);
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glEnable(GL_LIGHTING);
|
|
|
|
}
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
void GfxOpenGL::dimScreen() {
|
2009-05-05 11:34:43 +00:00
|
|
|
uint32 *data = (uint32 *)_storedDisplay;
|
|
|
|
for (int l = 0; l < _screenWidth * _screenHeight; l++) {
|
|
|
|
uint32 pixel = data[l];
|
|
|
|
uint8 r = (pixel & 0xFF0000) >> 16;
|
|
|
|
uint8 g = (pixel & 0x00FF00) >> 8;
|
|
|
|
uint8 b = (pixel & 0x0000FF);
|
|
|
|
uint32 color = (r + g + b) / 10;
|
|
|
|
data[l] = ((color & 0xFF) << 16) | ((color & 0xFF) << 8) | (color & 0xFF);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
void GfxOpenGL::dimRegion(int x, int yReal, int w, int h, float level) {
|
2012-01-27 20:01:12 +01:00
|
|
|
x = (int)(x * _scaleW);
|
|
|
|
yReal = (int)(yReal *_scaleH);
|
|
|
|
w = (int)(w * _scaleW);
|
|
|
|
h = (int)(h * _scaleH);
|
2012-03-07 16:12:14 +01:00
|
|
|
int y = _screenHeight - yReal - h;
|
|
|
|
|
|
|
|
#ifdef GL_ARB_fragment_program
|
|
|
|
if (_useDimShader) {
|
|
|
|
GLuint texture;
|
|
|
|
glGenTextures(1, &texture);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
|
|
|
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, 3, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
|
|
|
|
glViewport(0, 0, _screenWidth, _screenHeight);
|
|
|
|
|
|
|
|
// copy the data over to the texture
|
|
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
|
|
|
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, x, y, w, h, 0);
|
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
|
|
|
glOrtho(0, _screenWidth, 0, _screenHeight, 0, 1);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
glMatrixMode(GL_TEXTURE);
|
|
|
|
glLoadIdentity();
|
|
|
|
|
|
|
|
glDisable(GL_LIGHTING);
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
glDisable(GL_ALPHA_TEST);
|
|
|
|
glDepthMask(GL_FALSE);
|
|
|
|
glEnable(GL_SCISSOR_TEST);
|
|
|
|
|
|
|
|
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, _dimFragProgram);
|
|
|
|
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
|
|
|
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, level, 0, 0, 0);
|
|
|
|
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
|
|
|
|
|
|
|
glBegin(GL_QUADS);
|
|
|
|
glTexCoord2f(0, 0);
|
|
|
|
glVertex2f(x, y);
|
|
|
|
glTexCoord2f(1.0f, 0.0f);
|
|
|
|
glVertex2f(x + w, y);
|
|
|
|
glTexCoord2f(1.0f, 1.0f);
|
|
|
|
glVertex2f(x + w, y + h);
|
|
|
|
glTexCoord2f(0.0f, 1.0f);
|
|
|
|
glVertex2f(x, y + h);
|
|
|
|
glEnd();
|
|
|
|
|
|
|
|
glDisable(GL_FRAGMENT_PROGRAM_ARB);
|
|
|
|
|
|
|
|
glDeleteTextures(1, &texture);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-05-05 11:34:43 +00:00
|
|
|
uint32 *data = new uint32[w * h];
|
2012-03-07 16:12:14 +01:00
|
|
|
y = _screenHeight - yReal;
|
2009-05-09 17:47:28 +00:00
|
|
|
|
2009-05-05 11:34:43 +00:00
|
|
|
// collect the requested area and generate the dimmed version
|
|
|
|
glReadPixels(x, y - h, w, h, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
|
|
|
for (int ly = 0; ly < h; ly++) {
|
|
|
|
for (int lx = 0; lx < w; lx++) {
|
|
|
|
uint32 pixel = data[ly * w + lx];
|
|
|
|
uint8 r = (pixel & 0xFF0000) >> 16;
|
|
|
|
uint8 g = (pixel & 0x00FF00) >> 8;
|
|
|
|
uint8 b = (pixel & 0x0000FF);
|
|
|
|
uint32 color = (uint32)(((r + g + b) / 3) * level);
|
|
|
|
data[ly * w + lx] = ((color & 0xFF) << 16) | ((color & 0xFF) << 8) | (color & 0xFF);
|
|
|
|
}
|
|
|
|
}
|
2009-05-09 17:47:28 +00:00
|
|
|
|
2009-05-05 11:34:43 +00:00
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
|
|
|
glOrtho(0, _screenWidth, _screenHeight, 0, 0, 1);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
|
|
|
|
glDisable(GL_LIGHTING);
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
glDepthMask(GL_FALSE);
|
|
|
|
|
|
|
|
// Set the raster position and draw the bitmap
|
|
|
|
glRasterPos2i(x, yReal + h);
|
|
|
|
glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
|
|
|
|
|
|
|
glDepthMask(GL_TRUE);
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glEnable(GL_LIGHTING);
|
|
|
|
|
|
|
|
delete[] data;
|
|
|
|
}
|
2011-07-28 21:36:03 +02:00
|
|
|
|
2012-01-27 17:44:33 +01:00
|
|
|
void GfxOpenGL::irisAroundRegion(int x1, int y1, int x2, int y2) {
|
2011-07-28 01:36:27 +02:00
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
2011-07-28 02:27:48 +02:00
|
|
|
glOrtho(0.0, _screenWidth, _screenHeight, 0.0, 0.0, 1.0);
|
2011-07-28 01:36:27 +02:00
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
2011-07-28 21:36:03 +02:00
|
|
|
|
2011-07-28 01:36:27 +02:00
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
glDisable(GL_LIGHTING);
|
|
|
|
glDepthMask(GL_FALSE);
|
2011-07-28 21:36:03 +02:00
|
|
|
|
2011-07-28 01:36:27 +02:00
|
|
|
glColor3f(0.0f, 0.0f, 0.0f);
|
|
|
|
|
2011-07-28 07:30:37 +02:00
|
|
|
float points[20] = {
|
2011-07-28 02:04:56 +02:00
|
|
|
0.0f, 0.0f,
|
2011-07-29 22:49:08 +02:00
|
|
|
0.0f, y1,
|
2011-07-28 02:04:56 +02:00
|
|
|
_screenWidth, 0.0f,
|
2011-07-29 22:49:08 +02:00
|
|
|
x2, y1,
|
2011-07-28 02:04:56 +02:00
|
|
|
_screenWidth, _screenHeight,
|
2011-07-29 22:49:08 +02:00
|
|
|
x2, y2,
|
2011-07-28 02:04:56 +02:00
|
|
|
0.0f, _screenHeight,
|
2011-07-29 22:49:08 +02:00
|
|
|
x1, y2,
|
|
|
|
0.0f, y1,
|
|
|
|
x1, y1
|
2011-07-28 01:36:27 +02:00
|
|
|
};
|
2011-08-13 11:53:27 +02:00
|
|
|
|
2011-07-28 02:13:02 +02:00
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glVertexPointer(2, GL_FLOAT, 0, points);
|
2011-07-28 07:30:37 +02:00
|
|
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 10);
|
2011-07-28 02:13:02 +02:00
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
2011-07-28 21:36:03 +02:00
|
|
|
|
2011-07-28 02:27:48 +02:00
|
|
|
glColor3f(1.0f, 1.0f, 1.0f);
|
2011-07-28 01:36:27 +02:00
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glEnable(GL_LIGHTING);
|
|
|
|
glDepthMask(GL_TRUE);
|
|
|
|
}
|
2011-07-28 21:36:03 +02:00
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
void GfxOpenGL::drawRectangle(PrimitiveObject *primitive) {
|
2012-01-25 23:02:24 +01:00
|
|
|
float x1 = primitive->getP1().x * _scaleW;
|
|
|
|
float y1 = primitive->getP1().y * _scaleH;
|
|
|
|
float x2 = (primitive->getP2().x+1) * _scaleW;
|
|
|
|
float y2 = (primitive->getP2().y+1) * _scaleH;
|
2009-05-05 11:34:43 +00:00
|
|
|
|
2012-01-27 11:47:28 -08:00
|
|
|
const Color color(primitive->getColor());
|
2009-05-05 11:34:43 +00:00
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
|
|
|
glOrtho(0, _screenWidth, _screenHeight, 0, 0, 1);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
|
|
|
|
glDisable(GL_LIGHTING);
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
glDepthMask(GL_FALSE);
|
|
|
|
|
2011-05-05 10:58:29 +02:00
|
|
|
glColor3f(color.getRed() / 255.0f, color.getGreen() / 255.0f, color.getBlue() / 255.0f);
|
2009-05-05 11:34:43 +00:00
|
|
|
|
|
|
|
if (primitive->isFilled()) {
|
|
|
|
glBegin(GL_QUADS);
|
|
|
|
} else {
|
|
|
|
glBegin(GL_LINE_LOOP);
|
|
|
|
}
|
|
|
|
|
2012-01-25 23:02:24 +01:00
|
|
|
glVertex2f(x1, y1);
|
|
|
|
glVertex2f(x2, y1);
|
|
|
|
glVertex2f(x2, y2);
|
|
|
|
glVertex2f(x1, y2);
|
2009-05-05 11:34:43 +00:00
|
|
|
glEnd();
|
|
|
|
|
|
|
|
glColor3f(1.0f, 1.0f, 1.0f);
|
|
|
|
|
|
|
|
glDepthMask(GL_TRUE);
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glEnable(GL_LIGHTING);
|
|
|
|
}
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
void GfxOpenGL::drawLine(PrimitiveObject *primitive) {
|
2012-01-25 23:02:24 +01:00
|
|
|
float x1 = primitive->getP1().x * _scaleW;
|
|
|
|
float y1 = primitive->getP1().y * _scaleH;
|
|
|
|
float x2 = primitive->getP2().x * _scaleW;
|
|
|
|
float y2 = primitive->getP2().y * _scaleH;
|
2009-05-05 11:34:43 +00:00
|
|
|
|
2012-01-27 11:47:28 -08:00
|
|
|
const Color &color = primitive->getColor();
|
2009-05-05 11:34:43 +00:00
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
|
|
|
glOrtho(0, _screenWidth, _screenHeight, 0, 0, 1);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
|
|
|
|
glDisable(GL_LIGHTING);
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
glDepthMask(GL_FALSE);
|
|
|
|
|
2011-05-05 10:58:29 +02:00
|
|
|
glColor3f(color.getRed() / 255.0f, color.getGreen() / 255.0f, color.getBlue() / 255.0f);
|
2009-05-05 11:34:43 +00:00
|
|
|
|
2012-01-25 23:02:24 +01:00
|
|
|
glLineWidth(_scaleW);
|
|
|
|
|
2009-05-05 11:34:43 +00:00
|
|
|
glBegin(GL_LINES);
|
2012-01-25 23:02:24 +01:00
|
|
|
glVertex2f(x1, y1);
|
|
|
|
glVertex2f(x2, y2);
|
2009-05-05 11:34:43 +00:00
|
|
|
glEnd();
|
|
|
|
|
|
|
|
glColor3f(1.0f, 1.0f, 1.0f);
|
|
|
|
|
|
|
|
glDepthMask(GL_TRUE);
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glEnable(GL_LIGHTING);
|
|
|
|
}
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
void GfxOpenGL::drawPolygon(PrimitiveObject *primitive) {
|
2012-01-25 23:02:24 +01:00
|
|
|
float x1 = primitive->getP1().x * _scaleW;
|
|
|
|
float y1 = primitive->getP1().y * _scaleH;
|
|
|
|
float x2 = primitive->getP2().x * _scaleW;
|
|
|
|
float y2 = primitive->getP2().y * _scaleH;
|
|
|
|
float x3 = primitive->getP3().x * _scaleW;
|
|
|
|
float y3 = primitive->getP3().y * _scaleH;
|
|
|
|
float x4 = primitive->getP4().x * _scaleW;
|
|
|
|
float y4 = primitive->getP4().y * _scaleH;
|
2009-05-05 11:34:43 +00:00
|
|
|
|
2012-01-27 11:47:28 -08:00
|
|
|
const Color &color = primitive->getColor();
|
2009-05-05 11:34:43 +00:00
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
|
|
|
glOrtho(0, _screenWidth, _screenHeight, 0, 0, 1);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
|
|
|
|
glDisable(GL_LIGHTING);
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
glDepthMask(GL_FALSE);
|
|
|
|
|
2011-05-05 10:58:29 +02:00
|
|
|
glColor3f(color.getRed() / 255.0f, color.getGreen() / 255.0f, color.getBlue() / 255.0f);
|
2009-05-05 11:34:43 +00:00
|
|
|
|
|
|
|
glBegin(GL_LINES);
|
2012-01-25 23:02:24 +01:00
|
|
|
glVertex2f(x1, y1);
|
|
|
|
glVertex2f(x2, y2);
|
2009-05-05 11:34:43 +00:00
|
|
|
glEnd();
|
|
|
|
|
|
|
|
glBegin(GL_LINES);
|
2012-01-25 23:02:24 +01:00
|
|
|
glVertex2f(x3, y3);
|
|
|
|
glVertex2f(x4, y4);
|
2009-05-05 11:34:43 +00:00
|
|
|
glEnd();
|
|
|
|
|
|
|
|
glColor3f(1.0f, 1.0f, 1.0f);
|
|
|
|
|
|
|
|
glDepthMask(GL_TRUE);
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glEnable(GL_LIGHTING);
|
|
|
|
}
|
2009-05-07 19:06:31 +00:00
|
|
|
|
2009-05-25 06:49:57 +00:00
|
|
|
} // end of namespace Grim
|
|
|
|
|
2009-05-07 19:06:31 +00:00
|
|
|
#endif
|